sde_wb.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021-2023 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. if (!drm_mode || !mode_info || !avail_res ||
  392. !avail_res->max_mixer_width || !display) {
  393. pr_err("invalid params\n");
  394. return -EINVAL;
  395. }
  396. topology = &mode_info->topology;
  397. topology->num_lm = (avail_res->max_mixer_width <= drm_mode->hdisplay) ?
  398. dual_lm : single_lm;
  399. topology->num_enc = no_enc;
  400. topology->num_intf = single_intf;
  401. if (topology->num_lm == dual_lm && (drm_mode->hdisplay % 4)) {
  402. SDE_ERROR("invalid mode settings for 3d-merge, hdisplay:%d\n", drm_mode->hdisplay);
  403. return -EINVAL;
  404. }
  405. mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
  406. mode_info->wide_bus_en = false;
  407. mode_info->comp_info.comp_ratio = MSM_DISPLAY_COMPRESSION_RATIO_NONE;
  408. return 0;
  409. }
  410. int sde_wb_connector_set_info_blob(struct drm_connector *connector,
  411. void *info, void *display, struct msm_mode_info *mode_info)
  412. {
  413. struct sde_wb_device *wb_dev = display;
  414. const struct sde_format_extended *format_list;
  415. struct sde_kms *sde_kms;
  416. struct sde_mdss_cfg *catalog;
  417. int i;
  418. if (!connector || !info || !display || !wb_dev->wb_cfg) {
  419. SDE_ERROR("invalid params\n");
  420. return -EINVAL;
  421. }
  422. sde_kms = sde_connector_get_kms(connector);
  423. if (!sde_kms)
  424. return -EINVAL;
  425. catalog = sde_kms->catalog;
  426. format_list = wb_dev->wb_cfg->format_list;
  427. /* Populate info buffer */
  428. if (format_list) {
  429. sde_kms_info_start(info, "pixel_formats");
  430. while (format_list->fourcc_format) {
  431. sde_kms_info_append_format(info, format_list->fourcc_format,
  432. format_list->modifier);
  433. ++format_list;
  434. }
  435. sde_kms_info_stop(info);
  436. }
  437. /* Populate info buffer with WB rotation output formats */
  438. format_list = wb_dev->wb_cfg->rot_format_list;
  439. if (format_list) {
  440. sde_kms_info_start(info, "rot_output_formats");
  441. while (format_list->fourcc_format) {
  442. sde_kms_info_append_format(info, format_list->fourcc_format,
  443. format_list->modifier);
  444. ++format_list;
  445. }
  446. sde_kms_info_stop(info);
  447. }
  448. sde_kms_info_add_keyint(info, "wb_intf_index", wb_dev->wb_idx - WB_0);
  449. sde_kms_info_add_keyint(info, "maxlinewidth", wb_dev->wb_cfg->sblk->maxlinewidth);
  450. sde_kms_info_add_keyint(info, "maxlinewidth_linear",
  451. wb_dev->wb_cfg->sblk->maxlinewidth_linear);
  452. sde_kms_info_start(info, "features");
  453. if (wb_dev->wb_cfg && (wb_dev->wb_cfg->features & BIT(SDE_WB_UBWC)))
  454. sde_kms_info_append(info, "wb_ubwc");
  455. sde_kms_info_stop(info);
  456. sde_kms_info_add_keyint(info, "has_cwb_dither", test_bit(SDE_FEATURE_CWB_DITHER,
  457. catalog->features));
  458. if (catalog->cdm_count)
  459. sde_kms_info_add_keyint(info, "cdm_count", catalog->cdm_count);
  460. if (catalog->dnsc_blur_count && catalog->dnsc_blur_filters) {
  461. sde_kms_info_add_keyint(info, "dnsc_blur_count", catalog->dnsc_blur_count);
  462. sde_kms_info_start(info, "dnsc_blur_info");
  463. for (i = 0; i < catalog->dnsc_blur_filter_count; i++)
  464. sde_kms_info_append_dnsc_blur_filter_info(info,
  465. &catalog->dnsc_blur_filters[i]);
  466. sde_kms_info_stop(info);
  467. }
  468. return 0;
  469. }
  470. static void _sde_wb_connector_install_dither_property(struct sde_wb_device *wb_dev)
  471. {
  472. struct sde_connector *c_conn = to_sde_connector(wb_dev->connector);
  473. struct sde_kms *sde_kms = sde_connector_get_kms(wb_dev->connector);
  474. struct sde_mdss_cfg *catalog;
  475. char prop_name[DRM_PROP_NAME_LEN];
  476. u32 version = 0;
  477. if (!sde_kms || !sde_kms->catalog)
  478. return;
  479. catalog = sde_kms->catalog;
  480. if (!test_bit(SDE_FEATURE_CWB_DITHER, catalog->features))
  481. return;
  482. version = SDE_COLOR_PROCESS_MAJOR(catalog->pingpong[0].sblk->dither.version);
  483. snprintf(prop_name, ARRAY_SIZE(prop_name), "%s%d", "SDE_PP_CWB_DITHER_V", version);
  484. switch (version) {
  485. case 2:
  486. msm_property_install_blob(&c_conn->property_info, prop_name,
  487. DRM_MODE_PROP_BLOB, CONNECTOR_PROP_PP_CWB_DITHER);
  488. break;
  489. default:
  490. SDE_ERROR("unsupported cwb dither version %d\n", version);
  491. return;
  492. }
  493. }
  494. int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
  495. {
  496. struct sde_connector *c_conn;
  497. struct sde_wb_device *wb_dev = display;
  498. struct msm_drm_private *priv;
  499. struct sde_kms *sde_kms;
  500. struct sde_mdss_cfg *catalog;
  501. static const struct drm_prop_enum_list e_fb_translation_mode[] = {
  502. {SDE_DRM_FB_NON_SEC, "non_sec"},
  503. {SDE_DRM_FB_SEC, "sec"},
  504. };
  505. static const struct drm_prop_enum_list e_cache_state[] = {
  506. {CACHE_STATE_DISABLED, "cache_state_disabled"},
  507. {CACHE_STATE_ENABLED, "cache_state_enabled"},
  508. };
  509. static const struct drm_prop_enum_list e_wb_usage_type[] = {
  510. {WB_USAGE_WFD, "wb_usage_wfd"},
  511. {WB_USAGE_CWB, "wb_usage_cwb"},
  512. {WB_USAGE_OFFLINE_WB, "wb_usage_offline_wb"},
  513. {WB_USAGE_ROT, "wb_usage_rot"},
  514. };
  515. static const struct drm_prop_enum_list e_wb_rotate_type[] = {
  516. {WB_ROT_NONE, "wb_rot_none"},
  517. {WB_ROT_SINGLE, "wb_rot_single"},
  518. {WB_ROT_JOB1, "wb_rot_job1"},
  519. {WB_ROT_JOB2, "wb_rot_job2"},
  520. };
  521. if (!connector || !display || !wb_dev->wb_cfg || !wb_dev->drm_dev->dev_private) {
  522. SDE_ERROR("invalid params\n");
  523. return -EINVAL;
  524. }
  525. priv = wb_dev->drm_dev->dev_private;
  526. sde_kms = to_sde_kms(priv->kms);
  527. if (!sde_kms || !sde_kms->catalog) {
  528. SDE_ERROR("invalid sde_kms\n");
  529. return -EINVAL;
  530. }
  531. catalog = sde_kms->catalog;
  532. c_conn = to_sde_connector(connector);
  533. wb_dev->connector = connector;
  534. wb_dev->detect_status = connector_status_connected;
  535. if (test_bit(SDE_SYS_CACHE_DISP, catalog->sde_sys_cache_type_map)
  536. || test_bit(SDE_SYS_CACHE_DISP_WB, catalog->sde_sys_cache_type_map))
  537. msm_property_install_enum(&c_conn->property_info, "cache_state",
  538. 0x0, 0, e_cache_state, ARRAY_SIZE(e_cache_state),
  539. 0, CONNECTOR_PROP_CACHE_STATE);
  540. /*
  541. * Add extra connector properties
  542. */
  543. msm_property_install_range(&c_conn->property_info, "FB_ID",
  544. 0x0, 0, ~0, 0, CONNECTOR_PROP_OUT_FB);
  545. msm_property_install_range(&c_conn->property_info, "DST_X",
  546. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_X);
  547. msm_property_install_range(&c_conn->property_info, "DST_Y",
  548. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_Y);
  549. msm_property_install_range(&c_conn->property_info, "DST_W",
  550. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_W);
  551. msm_property_install_range(&c_conn->property_info, "DST_H",
  552. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_H);
  553. msm_property_install_enum(&c_conn->property_info,
  554. "fb_translation_mode",
  555. 0x0,
  556. 0, e_fb_translation_mode,
  557. ARRAY_SIZE(e_fb_translation_mode), 0,
  558. CONNECTOR_PROP_FB_TRANSLATION_MODE);
  559. if (wb_dev->wb_cfg->features & BIT(SDE_WB_PROG_LINE))
  560. msm_property_install_range(&c_conn->property_info, "early_fence_line",
  561. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_EARLY_FENCE_LINE);
  562. if (catalog->dnsc_blur_count && catalog->dnsc_blur_filters)
  563. msm_property_install_range(&c_conn->property_info, "dnsc_blur",
  564. 0x0, 0, ~0, 0, CONNECTOR_PROP_DNSC_BLUR);
  565. if (wb_dev->wb_cfg->features & BIT(SDE_WB_LINEAR_ROTATION)) {
  566. msm_property_install_enum(&c_conn->property_info, "wb_rotate_type",
  567. 0x0, 0, e_wb_rotate_type, ARRAY_SIZE(e_wb_rotate_type),
  568. 0, CONNECTOR_PROP_WB_ROT_TYPE);
  569. msm_property_install_range(&c_conn->property_info, "wb_rot_bytes_per_clk",
  570. 0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK);
  571. }
  572. msm_property_install_enum(&c_conn->property_info, "wb_usage_type",
  573. 0x0, 0, e_wb_usage_type, ARRAY_SIZE(e_wb_usage_type),
  574. 0, CONNECTOR_PROP_WB_USAGE_TYPE);
  575. _sde_wb_connector_install_dither_property(wb_dev);
  576. return 0;
  577. }
  578. struct drm_framebuffer *sde_wb_get_output_fb(struct sde_wb_device *wb_dev)
  579. {
  580. struct drm_framebuffer *fb;
  581. if (!wb_dev || !wb_dev->connector) {
  582. SDE_ERROR("invalid params\n");
  583. return NULL;
  584. }
  585. SDE_DEBUG("\n");
  586. mutex_lock(&wb_dev->wb_lock);
  587. fb = sde_wb_connector_state_get_output_fb(wb_dev->connector->state);
  588. mutex_unlock(&wb_dev->wb_lock);
  589. return fb;
  590. }
  591. int sde_wb_get_output_roi(struct sde_wb_device *wb_dev, struct sde_rect *roi)
  592. {
  593. int rc;
  594. if (!wb_dev || !wb_dev->connector || !roi) {
  595. SDE_ERROR("invalid params\n");
  596. return -EINVAL;
  597. }
  598. SDE_DEBUG("\n");
  599. mutex_lock(&wb_dev->wb_lock);
  600. rc = sde_wb_connector_state_get_output_roi(
  601. wb_dev->connector->state, roi);
  602. mutex_unlock(&wb_dev->wb_lock);
  603. return rc;
  604. }
  605. u32 sde_wb_get_num_of_displays(void)
  606. {
  607. u32 count = 0;
  608. struct sde_wb_device *wb_dev;
  609. SDE_DEBUG("\n");
  610. mutex_lock(&sde_wb_list_lock);
  611. list_for_each_entry(wb_dev, &sde_wb_list, wb_list) {
  612. count++;
  613. }
  614. mutex_unlock(&sde_wb_list_lock);
  615. return count;
  616. }
  617. int wb_display_get_displays(void **display_array, u32 max_display_count)
  618. {
  619. struct sde_wb_device *curr;
  620. int i = 0;
  621. SDE_DEBUG("\n");
  622. if (!display_array || !max_display_count) {
  623. if (!display_array)
  624. SDE_ERROR("invalid param\n");
  625. return 0;
  626. }
  627. mutex_lock(&sde_wb_list_lock);
  628. list_for_each_entry(curr, &sde_wb_list, wb_list) {
  629. if (i >= max_display_count)
  630. break;
  631. display_array[i++] = curr;
  632. }
  633. mutex_unlock(&sde_wb_list_lock);
  634. return i;
  635. }
  636. int sde_wb_config(struct drm_device *drm_dev, void *data,
  637. struct drm_file *file_priv)
  638. {
  639. struct sde_drm_wb_cfg *config = data;
  640. struct msm_drm_private *priv;
  641. struct sde_wb_device *wb_dev = NULL;
  642. struct sde_wb_device *curr;
  643. struct drm_connector *connector;
  644. uint32_t flags;
  645. uint32_t connector_id;
  646. uint32_t count_modes;
  647. uint64_t modes;
  648. int rc;
  649. if (!drm_dev || !data) {
  650. SDE_ERROR("invalid params\n");
  651. return -EINVAL;
  652. }
  653. SDE_DEBUG("\n");
  654. flags = config->flags;
  655. connector_id = config->connector_id;
  656. count_modes = config->count_modes;
  657. modes = config->modes;
  658. priv = drm_dev->dev_private;
  659. connector = drm_connector_lookup(drm_dev, file_priv, connector_id);
  660. if (!connector) {
  661. SDE_ERROR("failed to find connector\n");
  662. rc = -ENOENT;
  663. goto fail;
  664. }
  665. mutex_lock(&sde_wb_list_lock);
  666. list_for_each_entry(curr, &sde_wb_list, wb_list) {
  667. if (curr->connector == connector) {
  668. wb_dev = curr;
  669. break;
  670. }
  671. }
  672. mutex_unlock(&sde_wb_list_lock);
  673. if (!wb_dev) {
  674. SDE_ERROR("failed to find wb device\n");
  675. rc = -ENOENT;
  676. goto fail;
  677. }
  678. mutex_lock(&wb_dev->wb_lock);
  679. rc = sde_wb_connector_set_modes(wb_dev, count_modes,
  680. (struct drm_mode_modeinfo __user *) (uintptr_t) modes,
  681. (flags & SDE_DRM_WB_CFG_FLAGS_CONNECTED) ? true : false);
  682. mutex_unlock(&wb_dev->wb_lock);
  683. drm_helper_hpd_irq_event(drm_dev);
  684. fail:
  685. return rc;
  686. }
  687. /**
  688. * _sde_wb_dev_init - perform device initialization
  689. * @wb_dev: Pointer to writeback device
  690. */
  691. static int _sde_wb_dev_init(struct sde_wb_device *wb_dev)
  692. {
  693. int rc = 0;
  694. if (!wb_dev) {
  695. SDE_ERROR("invalid params\n");
  696. return -EINVAL;
  697. }
  698. SDE_DEBUG("\n");
  699. return rc;
  700. }
  701. /**
  702. * _sde_wb_dev_deinit - perform device de-initialization
  703. * @wb_dev: Pointer to writeback device
  704. */
  705. static int _sde_wb_dev_deinit(struct sde_wb_device *wb_dev)
  706. {
  707. int rc = 0;
  708. if (!wb_dev) {
  709. SDE_ERROR("invalid params\n");
  710. return -EINVAL;
  711. }
  712. SDE_DEBUG("\n");
  713. return rc;
  714. }
  715. /**
  716. * sde_wb_bind - bind writeback device with controlling device
  717. * @dev: Pointer to base of platform device
  718. * @master: Pointer to container of drm device
  719. * @data: Pointer to private data
  720. * Returns: Zero on success
  721. */
  722. static int sde_wb_bind(struct device *dev, struct device *master, void *data)
  723. {
  724. struct sde_wb_device *wb_dev;
  725. if (!dev || !master) {
  726. SDE_ERROR("invalid params\n");
  727. return -EINVAL;
  728. }
  729. wb_dev = platform_get_drvdata(to_platform_device(dev));
  730. if (!wb_dev) {
  731. SDE_ERROR("invalid wb device\n");
  732. return -EINVAL;
  733. }
  734. SDE_DEBUG("\n");
  735. mutex_lock(&wb_dev->wb_lock);
  736. wb_dev->drm_dev = dev_get_drvdata(master);
  737. mutex_unlock(&wb_dev->wb_lock);
  738. return 0;
  739. }
  740. /**
  741. * sde_wb_unbind - unbind writeback from controlling device
  742. * @dev: Pointer to base of platform device
  743. * @master: Pointer to container of drm device
  744. * @data: Pointer to private data
  745. */
  746. static void sde_wb_unbind(struct device *dev,
  747. struct device *master, void *data)
  748. {
  749. struct sde_wb_device *wb_dev;
  750. if (!dev) {
  751. SDE_ERROR("invalid params\n");
  752. return;
  753. }
  754. wb_dev = platform_get_drvdata(to_platform_device(dev));
  755. if (!wb_dev) {
  756. SDE_ERROR("invalid wb device\n");
  757. return;
  758. }
  759. SDE_DEBUG("\n");
  760. mutex_lock(&wb_dev->wb_lock);
  761. wb_dev->drm_dev = NULL;
  762. mutex_unlock(&wb_dev->wb_lock);
  763. }
  764. static const struct component_ops sde_wb_comp_ops = {
  765. .bind = sde_wb_bind,
  766. .unbind = sde_wb_unbind,
  767. };
  768. /**
  769. * sde_wb_drm_init - perform DRM initialization
  770. * @wb_dev: Pointer to writeback device
  771. * @encoder: Pointer to associated encoder
  772. */
  773. int sde_wb_drm_init(struct sde_wb_device *wb_dev, struct drm_encoder *encoder)
  774. {
  775. int rc = 0;
  776. if (!wb_dev || !wb_dev->drm_dev || !encoder) {
  777. SDE_ERROR("invalid params\n");
  778. return -EINVAL;
  779. }
  780. SDE_DEBUG("\n");
  781. mutex_lock(&wb_dev->wb_lock);
  782. if (wb_dev->drm_dev->dev_private) {
  783. struct msm_drm_private *priv = wb_dev->drm_dev->dev_private;
  784. struct sde_kms *sde_kms = to_sde_kms(priv->kms);
  785. if (wb_dev->index < sde_kms->catalog->wb_count) {
  786. wb_dev->wb_idx = sde_kms->catalog->wb[wb_dev->index].id;
  787. wb_dev->wb_cfg = &sde_kms->catalog->wb[wb_dev->index];
  788. }
  789. }
  790. wb_dev->drm_dev = encoder->dev;
  791. wb_dev->encoder = encoder;
  792. mutex_unlock(&wb_dev->wb_lock);
  793. return rc;
  794. }
  795. int sde_wb_drm_deinit(struct sde_wb_device *wb_dev)
  796. {
  797. int rc = 0;
  798. if (!wb_dev) {
  799. SDE_ERROR("invalid params\n");
  800. return -EINVAL;
  801. }
  802. SDE_DEBUG("\n");
  803. return rc;
  804. }
  805. /**
  806. * sde_wb_probe - load writeback module
  807. * @pdev: Pointer to platform device
  808. */
  809. static int sde_wb_probe(struct platform_device *pdev)
  810. {
  811. struct sde_wb_device *wb_dev;
  812. int ret;
  813. wb_dev = devm_kzalloc(&pdev->dev, sizeof(*wb_dev), GFP_KERNEL);
  814. if (!wb_dev)
  815. return -ENOMEM;
  816. SDE_DEBUG("\n");
  817. ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
  818. &wb_dev->index);
  819. if (ret) {
  820. SDE_DEBUG("cell index not set, default to 0\n");
  821. wb_dev->index = 0;
  822. }
  823. wb_dev->name = of_get_property(pdev->dev.of_node, "label", NULL);
  824. if (!wb_dev->name) {
  825. SDE_DEBUG("label not set, default to unknown\n");
  826. wb_dev->name = "unknown";
  827. }
  828. wb_dev->wb_idx = SDE_NONE;
  829. mutex_init(&wb_dev->wb_lock);
  830. platform_set_drvdata(pdev, wb_dev);
  831. mutex_lock(&sde_wb_list_lock);
  832. list_add_tail(&wb_dev->wb_list, &sde_wb_list);
  833. mutex_unlock(&sde_wb_list_lock);
  834. if (!_sde_wb_dev_init(wb_dev)) {
  835. ret = component_add(&pdev->dev, &sde_wb_comp_ops);
  836. if (ret)
  837. pr_err("component add failed\n");
  838. }
  839. return ret;
  840. }
  841. /**
  842. * sde_wb_remove - unload writeback module
  843. * @pdev: Pointer to platform device
  844. */
  845. static int sde_wb_remove(struct platform_device *pdev)
  846. {
  847. struct sde_wb_device *wb_dev;
  848. struct sde_wb_device *curr, *next;
  849. wb_dev = platform_get_drvdata(pdev);
  850. if (!wb_dev)
  851. return 0;
  852. SDE_DEBUG("\n");
  853. (void)_sde_wb_dev_deinit(wb_dev);
  854. mutex_lock(&sde_wb_list_lock);
  855. list_for_each_entry_safe(curr, next, &sde_wb_list, wb_list) {
  856. if (curr == wb_dev) {
  857. list_del(&wb_dev->wb_list);
  858. break;
  859. }
  860. }
  861. mutex_unlock(&sde_wb_list_lock);
  862. kfree(wb_dev->modes);
  863. mutex_destroy(&wb_dev->wb_lock);
  864. platform_set_drvdata(pdev, NULL);
  865. devm_kfree(&pdev->dev, wb_dev);
  866. return 0;
  867. }
  868. static const struct of_device_id dt_match[] = {
  869. { .compatible = "qcom,wb-display"},
  870. {}
  871. };
  872. static struct platform_driver sde_wb_driver = {
  873. .probe = sde_wb_probe,
  874. .remove = sde_wb_remove,
  875. .driver = {
  876. .name = "sde_wb",
  877. .of_match_table = dt_match,
  878. .suppress_bind_attrs = true,
  879. },
  880. };
  881. void __init sde_wb_register(void)
  882. {
  883. platform_driver_register(&sde_wb_driver);
  884. }
  885. void __exit sde_wb_unregister(void)
  886. {
  887. platform_driver_unregister(&sde_wb_driver);
  888. }