sde_wb.c 27 KB

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