sde_wb.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  5. */
  6. #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
  7. #include <drm/sde_drm.h>
  8. #include <drm/drm_probe_helper.h>
  9. #include <drm/drm_edid.h>
  10. #include "msm_kms.h"
  11. #include "sde_kms.h"
  12. #include "sde_wb.h"
  13. #include "sde_formats.h"
  14. /* maximum display mode resolution if not available from catalog */
  15. #define SDE_WB_MODE_MAX_WIDTH 5120
  16. #define SDE_WB_MODE_MAX_HEIGHT 5120
  17. static const struct drm_display_mode sde_custom_wb_modes[] = {
  18. /* 5120x2160@60Hz */
  19. { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 693264, 5120, 5128,
  20. 5160, 5200, 0, 2160, 2208, 2216, 2222, 0,
  21. DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
  22. { DRM_MODE("2160x5120", DRM_MODE_TYPE_DRIVER, 693264, 2160, 2208,
  23. 2216, 2222, 0, 5120, 5128, 5160, 5200, 0,
  24. DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
  25. { DRM_MODE("5120x2560", DRM_MODE_TYPE_DRIVER, 818064, 5120, 5128,
  26. 5160, 5200, 0, 2560, 2608, 2616, 2622, 0,
  27. DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
  28. };
  29. /* Serialization lock for sde_wb_list */
  30. static DEFINE_MUTEX(sde_wb_list_lock);
  31. /* List of all writeback devices installed */
  32. static LIST_HEAD(sde_wb_list);
  33. /**
  34. * sde_wb_is_format_valid - check if given format/modifier is supported
  35. * @wb_dev: Pointer to writeback device
  36. * @pixel_format: Fourcc pixel format
  37. * @format_modifier: Format modifier
  38. * Returns: true if valid; false otherwise
  39. */
  40. static int sde_wb_is_format_valid(struct sde_wb_device *wb_dev,
  41. u32 pixel_format, u64 format_modifier)
  42. {
  43. const struct sde_format_extended *fmts = wb_dev->wb_cfg->format_list;
  44. int i;
  45. if (!fmts)
  46. return false;
  47. for (i = 0; fmts[i].fourcc_format; i++)
  48. if ((fmts[i].modifier == format_modifier) &&
  49. (fmts[i].fourcc_format == pixel_format))
  50. return true;
  51. return false;
  52. }
  53. enum drm_connector_status
  54. sde_wb_connector_detect(struct drm_connector *connector,
  55. bool force,
  56. void *display)
  57. {
  58. enum drm_connector_status rc = connector_status_unknown;
  59. SDE_DEBUG("\n");
  60. if (display)
  61. rc = ((struct sde_wb_device *)display)->detect_status;
  62. return rc;
  63. }
  64. static int sde_wb_connector_add_custom_modes(struct drm_connector *connector,
  65. u32 hdisplay, u32 vdisplay)
  66. {
  67. int i, num_modes = 0;
  68. struct drm_display_mode *mode;
  69. struct drm_device *dev = connector->dev;
  70. if (!hdisplay || !vdisplay)
  71. return 0;
  72. if (hdisplay > SDE_WB_MODE_MAX_WIDTH)
  73. hdisplay = SDE_WB_MODE_MAX_WIDTH;
  74. if (vdisplay > SDE_WB_MODE_MAX_HEIGHT)
  75. vdisplay = SDE_WB_MODE_MAX_HEIGHT;
  76. for (i = 0; i < ARRAY_SIZE(sde_custom_wb_modes); i++) {
  77. const struct drm_display_mode *ptr = &sde_custom_wb_modes[i];
  78. if (ptr->hdisplay > hdisplay || ptr->vdisplay > vdisplay)
  79. continue;
  80. mode = drm_mode_duplicate(dev, ptr);
  81. if (mode) {
  82. drm_mode_probed_add(connector, mode);
  83. num_modes++;
  84. }
  85. }
  86. return num_modes;
  87. }
  88. int sde_wb_connector_get_modes(struct drm_connector *connector, void *display,
  89. const struct msm_resource_caps_info *avail_res)
  90. {
  91. struct sde_wb_device *wb_dev;
  92. int num_modes = 0;
  93. if (!connector || !display)
  94. return 0;
  95. wb_dev = display;
  96. SDE_DEBUG("\n");
  97. mutex_lock(&wb_dev->wb_lock);
  98. if (wb_dev->count_modes && wb_dev->modes) {
  99. struct drm_display_mode *mode;
  100. int i, ret;
  101. for (i = 0; i < wb_dev->count_modes; i++) {
  102. mode = drm_mode_create(connector->dev);
  103. if (!mode) {
  104. SDE_ERROR("failed to create mode\n");
  105. break;
  106. }
  107. ret = drm_mode_convert_umode(wb_dev->drm_dev, mode,
  108. &wb_dev->modes[i]);
  109. if (ret) {
  110. SDE_ERROR("failed to convert mode %d\n", ret);
  111. break;
  112. }
  113. drm_mode_probed_add(connector, mode);
  114. num_modes++;
  115. }
  116. } else {
  117. u32 max_width = SDE_WB_MODE_MAX_WIDTH;
  118. if (wb_dev->wb_cfg && wb_dev->wb_cfg->sblk)
  119. max_width = max(wb_dev->wb_cfg->sblk->maxlinewidth,
  120. wb_dev->wb_cfg->sblk->maxlinewidth_linear);
  121. num_modes = drm_add_modes_noedid(connector, max_width,
  122. SDE_WB_MODE_MAX_HEIGHT);
  123. num_modes += sde_wb_connector_add_custom_modes(connector, max_width,
  124. SDE_WB_MODE_MAX_HEIGHT);
  125. }
  126. mutex_unlock(&wb_dev->wb_lock);
  127. return num_modes;
  128. }
  129. struct drm_framebuffer *
  130. sde_wb_connector_state_get_output_fb(struct drm_connector_state *state)
  131. {
  132. if (!state || !state->connector ||
  133. (state->connector->connector_type !=
  134. DRM_MODE_CONNECTOR_VIRTUAL)) {
  135. SDE_ERROR("invalid params\n");
  136. return NULL;
  137. }
  138. SDE_DEBUG("\n");
  139. return sde_connector_get_out_fb(state);
  140. }
  141. int sde_wb_connector_state_get_output_roi(struct drm_connector_state *state,
  142. struct sde_rect *roi)
  143. {
  144. if (!state || !roi || !state->connector ||
  145. (state->connector->connector_type !=
  146. DRM_MODE_CONNECTOR_VIRTUAL)) {
  147. SDE_ERROR("invalid params\n");
  148. return -EINVAL;
  149. }
  150. SDE_DEBUG("\n");
  151. roi->x = sde_connector_get_property(state, CONNECTOR_PROP_DST_X);
  152. roi->y = sde_connector_get_property(state, CONNECTOR_PROP_DST_Y);
  153. roi->w = sde_connector_get_property(state, CONNECTOR_PROP_DST_W);
  154. roi->h = sde_connector_get_property(state, CONNECTOR_PROP_DST_H);
  155. return 0;
  156. }
  157. /**
  158. * sde_wb_connector_set_modes - set writeback modes and connection status
  159. * @wb_dev: Pointer to write back device
  160. * @count_modes: Count of modes
  161. * @modes: Pointer to writeback mode requested
  162. * @connected: Connection status requested
  163. * Returns: 0 if success; error code otherwise
  164. */
  165. static
  166. int sde_wb_connector_set_modes(struct sde_wb_device *wb_dev,
  167. u32 count_modes, struct drm_mode_modeinfo __user *modes,
  168. bool connected)
  169. {
  170. struct drm_mode_modeinfo *modeinfo = NULL;
  171. int ret = 0;
  172. int i;
  173. if (!wb_dev || !wb_dev->connector ||
  174. (wb_dev->connector->connector_type !=
  175. DRM_MODE_CONNECTOR_VIRTUAL)) {
  176. SDE_ERROR("invalid params\n");
  177. return -EINVAL;
  178. }
  179. SDE_DEBUG("\n");
  180. if (connected) {
  181. SDE_DEBUG("connect\n");
  182. if (!count_modes || !modes) {
  183. SDE_ERROR("invalid count_modes :%u and modes :%d\n",
  184. count_modes, !modes);
  185. return -EINVAL;
  186. }
  187. modeinfo = kcalloc(count_modes,
  188. sizeof(struct drm_mode_modeinfo),
  189. GFP_KERNEL);
  190. if (!modeinfo) {
  191. SDE_ERROR("invalid params\n");
  192. ret = -ENOMEM;
  193. goto error;
  194. }
  195. if (copy_from_user(modeinfo, modes,
  196. count_modes *
  197. sizeof(struct drm_mode_modeinfo))) {
  198. SDE_ERROR("failed to copy modes\n");
  199. kfree(modeinfo);
  200. ret = -EFAULT;
  201. goto error;
  202. }
  203. for (i = 0; i < count_modes; i++) {
  204. struct drm_display_mode dispmode;
  205. memset(&dispmode, 0, sizeof(dispmode));
  206. ret = drm_mode_convert_umode(wb_dev->drm_dev,
  207. &dispmode, &modeinfo[i]);
  208. if (ret) {
  209. SDE_ERROR(
  210. "failed to convert mode %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x status:%d rc:%d\n",
  211. i,
  212. modeinfo[i].name,
  213. modeinfo[i].vrefresh,
  214. modeinfo[i].clock,
  215. modeinfo[i].hdisplay,
  216. modeinfo[i].hsync_start,
  217. modeinfo[i].hsync_end,
  218. modeinfo[i].htotal,
  219. modeinfo[i].vdisplay,
  220. modeinfo[i].vsync_start,
  221. modeinfo[i].vsync_end,
  222. modeinfo[i].vtotal,
  223. modeinfo[i].type,
  224. modeinfo[i].flags,
  225. dispmode.status,
  226. ret);
  227. kfree(modeinfo);
  228. goto error;
  229. }
  230. }
  231. if (wb_dev->modes) {
  232. wb_dev->count_modes = 0;
  233. kfree(wb_dev->modes);
  234. wb_dev->modes = NULL;
  235. }
  236. wb_dev->count_modes = count_modes;
  237. wb_dev->modes = modeinfo;
  238. wb_dev->detect_status = connector_status_connected;
  239. } else {
  240. SDE_DEBUG("disconnect\n");
  241. if (wb_dev->modes) {
  242. wb_dev->count_modes = 0;
  243. kfree(wb_dev->modes);
  244. wb_dev->modes = NULL;
  245. }
  246. wb_dev->detect_status = connector_status_disconnected;
  247. }
  248. error:
  249. return ret;
  250. }
  251. static void _sde_wb_connector_clear_dnsc_blur(struct drm_connector_state *state)
  252. {
  253. struct sde_connector_state *cstate = to_sde_connector_state(state);
  254. int i;
  255. for (i = 0; i < cstate->dnsc_blur_count; i++)
  256. memset(&cstate->dnsc_blur_cfg[i], 0, sizeof(struct sde_drm_dnsc_blur_cfg));
  257. cstate->dnsc_blur_count = 0;
  258. }
  259. static int _sde_wb_connector_set_dnsc_blur(struct sde_wb_device *wb_dev,
  260. struct drm_connector_state *state, void __user *usr_ptr)
  261. {
  262. struct sde_connector_state *cstate = to_sde_connector_state(state);
  263. struct sde_kms *sde_kms = sde_connector_get_kms(wb_dev->connector);
  264. struct sde_drm_dnsc_blur_cfg *dnsc_blur_cfg = &cstate->dnsc_blur_cfg[0];
  265. u32 copy_count;
  266. int ret = 0, i;
  267. if (!sde_kms || !sde_kms->catalog)
  268. return -EINVAL;
  269. if (!usr_ptr)
  270. goto disable;
  271. /* copy only the first block */
  272. if (copy_from_user(dnsc_blur_cfg, usr_ptr, sizeof(struct sde_drm_dnsc_blur_cfg))) {
  273. SDE_ERROR("failed to copy dnsc_blur block 0 data\n");
  274. ret = -EINVAL;
  275. goto disable;
  276. }
  277. if (dnsc_blur_cfg->num_blocks > sde_kms->catalog->dnsc_blur_count) {
  278. SDE_ERROR("invalid number of dnsc_blur blocks:%d\n", dnsc_blur_cfg->num_blocks);
  279. ret = -EINVAL;
  280. goto disable;
  281. }
  282. /* no further data required */
  283. if (dnsc_blur_cfg->num_blocks <= 1)
  284. goto end;
  285. dnsc_blur_cfg++;
  286. usr_ptr += sizeof(struct sde_drm_dnsc_blur_cfg);
  287. copy_count = dnsc_blur_cfg->num_blocks - 1;
  288. /* copy rest of the blocks */
  289. if ((dnsc_blur_cfg->flags & DNSC_BLUR_INDEPENDENT_BLK_CFG)) {
  290. if (copy_from_user(dnsc_blur_cfg, usr_ptr,
  291. copy_count * sizeof(struct sde_drm_dnsc_blur_cfg))) {
  292. SDE_ERROR("failed to copy dnsc_blur data\n");
  293. ret = -EINVAL;
  294. goto disable;
  295. }
  296. /* duplicate rest of the blocks */
  297. } else if (dnsc_blur_cfg->flags & DNSC_BLUR_MIRROR_BLK_CFG) {
  298. for (i = 0; i < copy_count; i++) {
  299. memcpy(dnsc_blur_cfg, &cstate->dnsc_blur_cfg[0],
  300. sizeof(struct sde_drm_dnsc_blur_cfg));
  301. dnsc_blur_cfg++;
  302. }
  303. }
  304. end:
  305. cstate->dnsc_blur_count = dnsc_blur_cfg->num_blocks;
  306. return 0;
  307. disable:
  308. _sde_wb_connector_clear_dnsc_blur(state);
  309. return ret;
  310. }
  311. static int _sde_wb_connector_set_out_fb(struct sde_wb_device *wb_dev,
  312. struct drm_connector_state *state)
  313. {
  314. struct drm_framebuffer *out_fb;
  315. const struct sde_format *sde_format;
  316. int rc = 0;
  317. out_fb = sde_connector_get_out_fb(state);
  318. if (!out_fb)
  319. goto end;
  320. sde_format = sde_get_sde_format_ext(out_fb->format->format, out_fb->modifier);
  321. if (!sde_format) {
  322. SDE_ERROR("failed to get sde format\n");
  323. rc = -EINVAL;
  324. goto end;
  325. }
  326. if (!sde_wb_is_format_valid(wb_dev, out_fb->format->format, out_fb->modifier)) {
  327. SDE_ERROR("unsupported writeback format 0x%x/0x%llx\n",
  328. out_fb->format->format, out_fb->modifier);
  329. rc = -EINVAL;
  330. goto end;
  331. }
  332. end:
  333. return rc;
  334. }
  335. int sde_wb_connector_set_property(struct drm_connector *connector,
  336. struct drm_connector_state *state, int idx, uint64_t value, void *display)
  337. {
  338. struct sde_wb_device *wb_dev = display;
  339. int rc = 0;
  340. if (!connector || !state || !wb_dev) {
  341. SDE_ERROR("invalid argument(s)\n");
  342. return -EINVAL;
  343. }
  344. switch (idx) {
  345. case CONNECTOR_PROP_OUT_FB:
  346. rc = _sde_wb_connector_set_out_fb(wb_dev, state);
  347. break;
  348. case CONNECTOR_PROP_DNSC_BLUR:
  349. rc = _sde_wb_connector_set_dnsc_blur(wb_dev, state,
  350. (void __user *)(uintptr_t)value);
  351. break;
  352. default:
  353. /* nothing to do */
  354. break;
  355. }
  356. return rc;
  357. }
  358. int sde_wb_get_info(struct drm_connector *connector,
  359. struct msm_display_info *info, void *display)
  360. {
  361. struct sde_wb_device *wb_dev = display;
  362. u32 max_width = SDE_WB_MODE_MAX_WIDTH;
  363. if (!info || !wb_dev) {
  364. pr_err("invalid params\n");
  365. return -EINVAL;
  366. }
  367. if (wb_dev->wb_cfg && wb_dev->wb_cfg->sblk)
  368. max_width = max(wb_dev->wb_cfg->sblk->maxlinewidth,
  369. wb_dev->wb_cfg->sblk->maxlinewidth_linear);
  370. memset(info, 0, sizeof(struct msm_display_info));
  371. info->intf_type = DRM_MODE_CONNECTOR_VIRTUAL;
  372. info->num_of_h_tiles = 1;
  373. info->h_tile_instance[0] = sde_wb_get_index(display);
  374. info->is_connected = true;
  375. info->capabilities = MSM_DISPLAY_CAP_HOT_PLUG | MSM_DISPLAY_CAP_EDID;
  376. info->max_width = max_width;
  377. info->max_height = SDE_WB_MODE_MAX_HEIGHT;
  378. return 0;
  379. }
  380. int sde_wb_get_mode_info(struct drm_connector *connector,
  381. const struct drm_display_mode *drm_mode,
  382. struct msm_sub_mode *sub_mode,
  383. struct msm_mode_info *mode_info,
  384. void *display, const struct msm_resource_caps_info *avail_res)
  385. {
  386. const u32 dual_lm = 2;
  387. const u32 single_lm = 1;
  388. const u32 single_intf = 1;
  389. const u32 no_enc = 0;
  390. struct msm_display_topology *topology;
  391. struct sde_wb_device *wb_dev = display;
  392. u16 hdisplay;
  393. int i;
  394. if (!drm_mode || !mode_info || !avail_res ||
  395. !avail_res->max_mixer_width || !display) {
  396. pr_err("invalid params\n");
  397. return -EINVAL;
  398. }
  399. hdisplay = drm_mode->hdisplay;
  400. /* find maximum display width to support */
  401. for (i = 0; i < wb_dev->count_modes; i++)
  402. hdisplay = max(hdisplay, wb_dev->modes[i].hdisplay);
  403. topology = &mode_info->topology;
  404. topology->num_lm = (avail_res->max_mixer_width <= hdisplay) ?
  405. dual_lm : single_lm;
  406. topology->num_enc = no_enc;
  407. topology->num_intf = single_intf;
  408. mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
  409. mode_info->wide_bus_en = false;
  410. mode_info->comp_info.comp_ratio = MSM_DISPLAY_COMPRESSION_RATIO_NONE;
  411. return 0;
  412. }
  413. int sde_wb_connector_set_info_blob(struct drm_connector *connector,
  414. void *info, void *display, struct msm_mode_info *mode_info)
  415. {
  416. struct sde_wb_device *wb_dev = display;
  417. const struct sde_format_extended *format_list;
  418. struct sde_kms *sde_kms;
  419. struct sde_mdss_cfg *catalog;
  420. int i;
  421. if (!connector || !info || !display || !wb_dev->wb_cfg) {
  422. SDE_ERROR("invalid params\n");
  423. return -EINVAL;
  424. }
  425. sde_kms = sde_connector_get_kms(connector);
  426. if (!sde_kms)
  427. return -EINVAL;
  428. catalog = sde_kms->catalog;
  429. format_list = wb_dev->wb_cfg->format_list;
  430. /* Populate info buffer */
  431. if (format_list) {
  432. sde_kms_info_start(info, "pixel_formats");
  433. while (format_list->fourcc_format) {
  434. sde_kms_info_append_format(info, format_list->fourcc_format,
  435. format_list->modifier);
  436. ++format_list;
  437. }
  438. sde_kms_info_stop(info);
  439. }
  440. /* Populate info buffer with WB rotation output formats */
  441. format_list = wb_dev->wb_cfg->rot_format_list;
  442. if (format_list) {
  443. sde_kms_info_start(info, "rot_output_formats");
  444. while (format_list->fourcc_format) {
  445. sde_kms_info_append_format(info, format_list->fourcc_format,
  446. format_list->modifier);
  447. ++format_list;
  448. }
  449. sde_kms_info_stop(info);
  450. }
  451. sde_kms_info_add_keyint(info, "wb_intf_index", wb_dev->wb_idx - WB_0);
  452. sde_kms_info_add_keyint(info, "maxlinewidth", wb_dev->wb_cfg->sblk->maxlinewidth);
  453. sde_kms_info_add_keyint(info, "maxlinewidth_linear",
  454. wb_dev->wb_cfg->sblk->maxlinewidth_linear);
  455. sde_kms_info_start(info, "features");
  456. if (wb_dev->wb_cfg && (wb_dev->wb_cfg->features & BIT(SDE_WB_UBWC)))
  457. sde_kms_info_append(info, "wb_ubwc");
  458. sde_kms_info_stop(info);
  459. sde_kms_info_add_keyint(info, "has_cwb_dither", test_bit(SDE_FEATURE_CWB_DITHER,
  460. catalog->features));
  461. if (catalog->cdm_count)
  462. sde_kms_info_add_keyint(info, "cdm_count", catalog->cdm_count);
  463. if (catalog->dnsc_blur_count && catalog->dnsc_blur_filters) {
  464. sde_kms_info_add_keyint(info, "dnsc_blur_count", catalog->dnsc_blur_count);
  465. sde_kms_info_start(info, "dnsc_blur_info");
  466. for (i = 0; i < catalog->dnsc_blur_filter_count; i++)
  467. sde_kms_info_append_dnsc_blur_filter_info(info,
  468. &catalog->dnsc_blur_filters[i]);
  469. sde_kms_info_stop(info);
  470. }
  471. return 0;
  472. }
  473. static void _sde_wb_connector_install_dither_property(struct sde_wb_device *wb_dev)
  474. {
  475. struct sde_connector *c_conn = to_sde_connector(wb_dev->connector);
  476. struct sde_kms *sde_kms = sde_connector_get_kms(wb_dev->connector);
  477. struct sde_mdss_cfg *catalog;
  478. char prop_name[DRM_PROP_NAME_LEN];
  479. u32 version = 0;
  480. if (!sde_kms || !sde_kms->catalog)
  481. return;
  482. catalog = sde_kms->catalog;
  483. if (!test_bit(SDE_FEATURE_CWB_DITHER, catalog->features))
  484. return;
  485. version = SDE_COLOR_PROCESS_MAJOR(catalog->pingpong[0].sblk->dither.version);
  486. snprintf(prop_name, ARRAY_SIZE(prop_name), "%s%d", "SDE_PP_CWB_DITHER_V", version);
  487. switch (version) {
  488. case 2:
  489. msm_property_install_blob(&c_conn->property_info, prop_name,
  490. DRM_MODE_PROP_BLOB, CONNECTOR_PROP_PP_CWB_DITHER);
  491. break;
  492. default:
  493. SDE_ERROR("unsupported cwb dither version %d\n", version);
  494. return;
  495. }
  496. }
  497. int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
  498. {
  499. struct sde_connector *c_conn;
  500. struct sde_wb_device *wb_dev = display;
  501. struct msm_drm_private *priv;
  502. struct sde_kms *sde_kms;
  503. struct sde_mdss_cfg *catalog;
  504. static const struct drm_prop_enum_list e_fb_translation_mode[] = {
  505. {SDE_DRM_FB_NON_SEC, "non_sec"},
  506. {SDE_DRM_FB_SEC, "sec"},
  507. };
  508. static const struct drm_prop_enum_list e_cache_state[] = {
  509. {CACHE_STATE_DISABLED, "cache_state_disabled"},
  510. {CACHE_STATE_ENABLED, "cache_state_enabled"},
  511. };
  512. static const struct drm_prop_enum_list e_wb_usage_type[] = {
  513. {WB_USAGE_WFD, "wb_usage_wfd"},
  514. {WB_USAGE_CWB, "wb_usage_cwb"},
  515. {WB_USAGE_OFFLINE_WB, "wb_usage_offline_wb"},
  516. {WB_USAGE_ROT, "wb_usage_rot"},
  517. };
  518. static const struct drm_prop_enum_list e_wb_rotate_type[] = {
  519. {WB_ROT_NONE, "wb_rot_none"},
  520. {WB_ROT_SINGLE, "wb_rot_single"},
  521. {WB_ROT_JOB1, "wb_rot_job1"},
  522. {WB_ROT_JOB2, "wb_rot_job2"},
  523. };
  524. if (!connector || !display || !wb_dev->wb_cfg || !wb_dev->drm_dev->dev_private) {
  525. SDE_ERROR("invalid params\n");
  526. return -EINVAL;
  527. }
  528. priv = wb_dev->drm_dev->dev_private;
  529. sde_kms = to_sde_kms(priv->kms);
  530. if (!sde_kms || !sde_kms->catalog) {
  531. SDE_ERROR("invalid sde_kms\n");
  532. return -EINVAL;
  533. }
  534. catalog = sde_kms->catalog;
  535. c_conn = to_sde_connector(connector);
  536. wb_dev->connector = connector;
  537. wb_dev->detect_status = connector_status_connected;
  538. if (test_bit(SDE_SYS_CACHE_DISP, catalog->sde_sys_cache_type_map)
  539. || test_bit(SDE_SYS_CACHE_DISP_WB, catalog->sde_sys_cache_type_map))
  540. msm_property_install_enum(&c_conn->property_info, "cache_state",
  541. 0x0, 0, e_cache_state, ARRAY_SIZE(e_cache_state),
  542. 0, CONNECTOR_PROP_CACHE_STATE);
  543. /*
  544. * Add extra connector properties
  545. */
  546. msm_property_install_range(&c_conn->property_info, "FB_ID",
  547. 0x0, 0, ~0, 0, CONNECTOR_PROP_OUT_FB);
  548. msm_property_install_range(&c_conn->property_info, "DST_X",
  549. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_X);
  550. msm_property_install_range(&c_conn->property_info, "DST_Y",
  551. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_Y);
  552. msm_property_install_range(&c_conn->property_info, "DST_W",
  553. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_W);
  554. msm_property_install_range(&c_conn->property_info, "DST_H",
  555. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_H);
  556. msm_property_install_enum(&c_conn->property_info,
  557. "fb_translation_mode",
  558. 0x0,
  559. 0, e_fb_translation_mode,
  560. ARRAY_SIZE(e_fb_translation_mode), 0,
  561. CONNECTOR_PROP_FB_TRANSLATION_MODE);
  562. if (wb_dev->wb_cfg->features & BIT(SDE_WB_PROG_LINE))
  563. msm_property_install_range(&c_conn->property_info, "early_fence_line",
  564. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_EARLY_FENCE_LINE);
  565. if (catalog->dnsc_blur_count && catalog->dnsc_blur_filters)
  566. msm_property_install_range(&c_conn->property_info, "dnsc_blur",
  567. 0x0, 0, ~0, 0, CONNECTOR_PROP_DNSC_BLUR);
  568. if (wb_dev->wb_cfg->features & BIT(SDE_WB_LINEAR_ROTATION)) {
  569. msm_property_install_enum(&c_conn->property_info, "wb_rotate_type",
  570. 0x0, 0, e_wb_rotate_type, ARRAY_SIZE(e_wb_rotate_type),
  571. 0, CONNECTOR_PROP_WB_ROT_TYPE);
  572. msm_property_install_range(&c_conn->property_info, "wb_rot_bytes_per_clk",
  573. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK);
  574. }
  575. msm_property_install_enum(&c_conn->property_info, "wb_usage_type",
  576. 0x0, 0, e_wb_usage_type, ARRAY_SIZE(e_wb_usage_type),
  577. 0, CONNECTOR_PROP_WB_USAGE_TYPE);
  578. _sde_wb_connector_install_dither_property(wb_dev);
  579. return 0;
  580. }
  581. struct drm_framebuffer *sde_wb_get_output_fb(struct sde_wb_device *wb_dev)
  582. {
  583. struct drm_framebuffer *fb;
  584. if (!wb_dev || !wb_dev->connector) {
  585. SDE_ERROR("invalid params\n");
  586. return NULL;
  587. }
  588. SDE_DEBUG("\n");
  589. mutex_lock(&wb_dev->wb_lock);
  590. fb = sde_wb_connector_state_get_output_fb(wb_dev->connector->state);
  591. mutex_unlock(&wb_dev->wb_lock);
  592. return fb;
  593. }
  594. int sde_wb_get_output_roi(struct sde_wb_device *wb_dev, struct sde_rect *roi)
  595. {
  596. int rc;
  597. if (!wb_dev || !wb_dev->connector || !roi) {
  598. SDE_ERROR("invalid params\n");
  599. return -EINVAL;
  600. }
  601. SDE_DEBUG("\n");
  602. mutex_lock(&wb_dev->wb_lock);
  603. rc = sde_wb_connector_state_get_output_roi(
  604. wb_dev->connector->state, roi);
  605. mutex_unlock(&wb_dev->wb_lock);
  606. return rc;
  607. }
  608. u32 sde_wb_get_num_of_displays(void)
  609. {
  610. u32 count = 0;
  611. struct sde_wb_device *wb_dev;
  612. SDE_DEBUG("\n");
  613. mutex_lock(&sde_wb_list_lock);
  614. list_for_each_entry(wb_dev, &sde_wb_list, wb_list) {
  615. count++;
  616. }
  617. mutex_unlock(&sde_wb_list_lock);
  618. return count;
  619. }
  620. int wb_display_get_displays(void **display_array, u32 max_display_count)
  621. {
  622. struct sde_wb_device *curr;
  623. int i = 0;
  624. SDE_DEBUG("\n");
  625. if (!display_array || !max_display_count) {
  626. if (!display_array)
  627. SDE_ERROR("invalid param\n");
  628. return 0;
  629. }
  630. mutex_lock(&sde_wb_list_lock);
  631. list_for_each_entry(curr, &sde_wb_list, wb_list) {
  632. if (i >= max_display_count)
  633. break;
  634. display_array[i++] = curr;
  635. }
  636. mutex_unlock(&sde_wb_list_lock);
  637. return i;
  638. }
  639. int sde_wb_config(struct drm_device *drm_dev, void *data,
  640. struct drm_file *file_priv)
  641. {
  642. struct sde_drm_wb_cfg *config = data;
  643. struct msm_drm_private *priv;
  644. struct sde_wb_device *wb_dev = NULL;
  645. struct sde_wb_device *curr;
  646. struct drm_connector *connector;
  647. uint32_t flags;
  648. uint32_t connector_id;
  649. uint32_t count_modes;
  650. uint64_t modes;
  651. int rc;
  652. if (!drm_dev || !data) {
  653. SDE_ERROR("invalid params\n");
  654. return -EINVAL;
  655. }
  656. SDE_DEBUG("\n");
  657. flags = config->flags;
  658. connector_id = config->connector_id;
  659. count_modes = config->count_modes;
  660. modes = config->modes;
  661. priv = drm_dev->dev_private;
  662. connector = drm_connector_lookup(drm_dev, file_priv, connector_id);
  663. if (!connector) {
  664. SDE_ERROR("failed to find connector\n");
  665. rc = -ENOENT;
  666. goto fail;
  667. }
  668. mutex_lock(&sde_wb_list_lock);
  669. list_for_each_entry(curr, &sde_wb_list, wb_list) {
  670. if (curr->connector == connector) {
  671. wb_dev = curr;
  672. break;
  673. }
  674. }
  675. mutex_unlock(&sde_wb_list_lock);
  676. if (!wb_dev) {
  677. SDE_ERROR("failed to find wb device\n");
  678. rc = -ENOENT;
  679. goto fail;
  680. }
  681. mutex_lock(&wb_dev->wb_lock);
  682. rc = sde_wb_connector_set_modes(wb_dev, count_modes,
  683. (struct drm_mode_modeinfo __user *) (uintptr_t) modes,
  684. (flags & SDE_DRM_WB_CFG_FLAGS_CONNECTED) ? true : false);
  685. mutex_unlock(&wb_dev->wb_lock);
  686. drm_helper_hpd_irq_event(drm_dev);
  687. fail:
  688. return rc;
  689. }
  690. /**
  691. * _sde_wb_dev_init - perform device initialization
  692. * @wb_dev: Pointer to writeback device
  693. */
  694. static int _sde_wb_dev_init(struct sde_wb_device *wb_dev)
  695. {
  696. int rc = 0;
  697. if (!wb_dev) {
  698. SDE_ERROR("invalid params\n");
  699. return -EINVAL;
  700. }
  701. SDE_DEBUG("\n");
  702. return rc;
  703. }
  704. /**
  705. * _sde_wb_dev_deinit - perform device de-initialization
  706. * @wb_dev: Pointer to writeback device
  707. */
  708. static int _sde_wb_dev_deinit(struct sde_wb_device *wb_dev)
  709. {
  710. int rc = 0;
  711. if (!wb_dev) {
  712. SDE_ERROR("invalid params\n");
  713. return -EINVAL;
  714. }
  715. SDE_DEBUG("\n");
  716. return rc;
  717. }
  718. /**
  719. * sde_wb_bind - bind writeback device with controlling device
  720. * @dev: Pointer to base of platform device
  721. * @master: Pointer to container of drm device
  722. * @data: Pointer to private data
  723. * Returns: Zero on success
  724. */
  725. static int sde_wb_bind(struct device *dev, struct device *master, void *data)
  726. {
  727. struct sde_wb_device *wb_dev;
  728. if (!dev || !master) {
  729. SDE_ERROR("invalid params\n");
  730. return -EINVAL;
  731. }
  732. wb_dev = platform_get_drvdata(to_platform_device(dev));
  733. if (!wb_dev) {
  734. SDE_ERROR("invalid wb device\n");
  735. return -EINVAL;
  736. }
  737. SDE_DEBUG("\n");
  738. mutex_lock(&wb_dev->wb_lock);
  739. wb_dev->drm_dev = dev_get_drvdata(master);
  740. mutex_unlock(&wb_dev->wb_lock);
  741. return 0;
  742. }
  743. /**
  744. * sde_wb_unbind - unbind writeback from controlling device
  745. * @dev: Pointer to base of platform device
  746. * @master: Pointer to container of drm device
  747. * @data: Pointer to private data
  748. */
  749. static void sde_wb_unbind(struct device *dev,
  750. struct device *master, void *data)
  751. {
  752. struct sde_wb_device *wb_dev;
  753. if (!dev) {
  754. SDE_ERROR("invalid params\n");
  755. return;
  756. }
  757. wb_dev = platform_get_drvdata(to_platform_device(dev));
  758. if (!wb_dev) {
  759. SDE_ERROR("invalid wb device\n");
  760. return;
  761. }
  762. SDE_DEBUG("\n");
  763. mutex_lock(&wb_dev->wb_lock);
  764. wb_dev->drm_dev = NULL;
  765. mutex_unlock(&wb_dev->wb_lock);
  766. }
  767. static const struct component_ops sde_wb_comp_ops = {
  768. .bind = sde_wb_bind,
  769. .unbind = sde_wb_unbind,
  770. };
  771. /**
  772. * sde_wb_drm_init - perform DRM initialization
  773. * @wb_dev: Pointer to writeback device
  774. * @encoder: Pointer to associated encoder
  775. */
  776. int sde_wb_drm_init(struct sde_wb_device *wb_dev, struct drm_encoder *encoder)
  777. {
  778. int rc = 0;
  779. if (!wb_dev || !wb_dev->drm_dev || !encoder) {
  780. SDE_ERROR("invalid params\n");
  781. return -EINVAL;
  782. }
  783. SDE_DEBUG("\n");
  784. mutex_lock(&wb_dev->wb_lock);
  785. if (wb_dev->drm_dev->dev_private) {
  786. struct msm_drm_private *priv = wb_dev->drm_dev->dev_private;
  787. struct sde_kms *sde_kms = to_sde_kms(priv->kms);
  788. if (wb_dev->index < sde_kms->catalog->wb_count) {
  789. wb_dev->wb_idx = sde_kms->catalog->wb[wb_dev->index].id;
  790. wb_dev->wb_cfg = &sde_kms->catalog->wb[wb_dev->index];
  791. }
  792. }
  793. wb_dev->drm_dev = encoder->dev;
  794. wb_dev->encoder = encoder;
  795. mutex_unlock(&wb_dev->wb_lock);
  796. return rc;
  797. }
  798. int sde_wb_drm_deinit(struct sde_wb_device *wb_dev)
  799. {
  800. int rc = 0;
  801. if (!wb_dev) {
  802. SDE_ERROR("invalid params\n");
  803. return -EINVAL;
  804. }
  805. SDE_DEBUG("\n");
  806. return rc;
  807. }
  808. /**
  809. * sde_wb_probe - load writeback module
  810. * @pdev: Pointer to platform device
  811. */
  812. static int sde_wb_probe(struct platform_device *pdev)
  813. {
  814. struct sde_wb_device *wb_dev;
  815. int ret;
  816. wb_dev = devm_kzalloc(&pdev->dev, sizeof(*wb_dev), GFP_KERNEL);
  817. if (!wb_dev)
  818. return -ENOMEM;
  819. SDE_DEBUG("\n");
  820. ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
  821. &wb_dev->index);
  822. if (ret) {
  823. SDE_DEBUG("cell index not set, default to 0\n");
  824. wb_dev->index = 0;
  825. }
  826. wb_dev->name = of_get_property(pdev->dev.of_node, "label", NULL);
  827. if (!wb_dev->name) {
  828. SDE_DEBUG("label not set, default to unknown\n");
  829. wb_dev->name = "unknown";
  830. }
  831. wb_dev->wb_idx = SDE_NONE;
  832. mutex_init(&wb_dev->wb_lock);
  833. platform_set_drvdata(pdev, wb_dev);
  834. mutex_lock(&sde_wb_list_lock);
  835. list_add_tail(&wb_dev->wb_list, &sde_wb_list);
  836. mutex_unlock(&sde_wb_list_lock);
  837. if (!_sde_wb_dev_init(wb_dev)) {
  838. ret = component_add(&pdev->dev, &sde_wb_comp_ops);
  839. if (ret)
  840. pr_err("component add failed\n");
  841. }
  842. return ret;
  843. }
  844. /**
  845. * sde_wb_remove - unload writeback module
  846. * @pdev: Pointer to platform device
  847. */
  848. static int sde_wb_remove(struct platform_device *pdev)
  849. {
  850. struct sde_wb_device *wb_dev;
  851. struct sde_wb_device *curr, *next;
  852. wb_dev = platform_get_drvdata(pdev);
  853. if (!wb_dev)
  854. return 0;
  855. SDE_DEBUG("\n");
  856. (void)_sde_wb_dev_deinit(wb_dev);
  857. mutex_lock(&sde_wb_list_lock);
  858. list_for_each_entry_safe(curr, next, &sde_wb_list, wb_list) {
  859. if (curr == wb_dev) {
  860. list_del(&wb_dev->wb_list);
  861. break;
  862. }
  863. }
  864. mutex_unlock(&sde_wb_list_lock);
  865. kfree(wb_dev->modes);
  866. mutex_destroy(&wb_dev->wb_lock);
  867. platform_set_drvdata(pdev, NULL);
  868. devm_kfree(&pdev->dev, wb_dev);
  869. return 0;
  870. }
  871. static const struct of_device_id dt_match[] = {
  872. { .compatible = "qcom,wb-display"},
  873. {}
  874. };
  875. static struct platform_driver sde_wb_driver = {
  876. .probe = sde_wb_probe,
  877. .remove = sde_wb_remove,
  878. .driver = {
  879. .name = "sde_wb",
  880. .of_match_table = dt_match,
  881. .suppress_bind_attrs = true,
  882. },
  883. };
  884. void __init sde_wb_register(void)
  885. {
  886. platform_driver_register(&sde_wb_driver);
  887. }
  888. void __exit sde_wb_unregister(void)
  889. {
  890. platform_driver_unregister(&sde_wb_driver);
  891. }