dc-crtc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2024 NXP
  4. */
  5. #include <linux/completion.h>
  6. #include <linux/container_of.h>
  7. #include <linux/interrupt.h>
  8. #include <linux/irqreturn.h>
  9. #include <linux/pm_runtime.h>
  10. #include <linux/spinlock.h>
  11. #include <drm/drm_atomic.h>
  12. #include <drm/drm_atomic_helper.h>
  13. #include <drm/drm_atomic_state_helper.h>
  14. #include <drm/drm_crtc.h>
  15. #include <drm/drm_device.h>
  16. #include <drm/drm_drv.h>
  17. #include <drm/drm_modes.h>
  18. #include <drm/drm_modeset_helper_vtables.h>
  19. #include <drm/drm_plane.h>
  20. #include <drm/drm_print.h>
  21. #include <drm/drm_vblank.h>
  22. #include "dc-de.h"
  23. #include "dc-drv.h"
  24. #include "dc-kms.h"
  25. #include "dc-pe.h"
  26. #define dc_crtc_dbg(crtc, fmt, ...) \
  27. do { \
  28. struct drm_crtc *_crtc = (crtc); \
  29. drm_dbg_kms(_crtc->dev, "[CRTC:%d:%s] " fmt, \
  30. _crtc->base.id, _crtc->name, ##__VA_ARGS__); \
  31. } while (0)
  32. #define dc_crtc_err(crtc, fmt, ...) \
  33. do { \
  34. struct drm_crtc *_crtc = (crtc); \
  35. drm_err(_crtc->dev, "[CRTC:%d:%s] " fmt, \
  36. _crtc->base.id, _crtc->name, ##__VA_ARGS__); \
  37. } while (0)
  38. #define DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(c) \
  39. do { \
  40. unsigned long ret; \
  41. ret = wait_for_completion_timeout(&dc_crtc->c, HZ); \
  42. if (ret == 0) \
  43. dc_crtc_err(crtc, "%s: wait for " #c " timeout\n", \
  44. __func__); \
  45. } while (0)
  46. #define DC_CRTC_CHECK_FRAMEGEN_FIFO(fg) \
  47. do { \
  48. struct dc_fg *_fg = (fg); \
  49. if (dc_fg_secondary_requests_to_read_empty_fifo(_fg)) { \
  50. dc_fg_secondary_clear_channel_status(_fg); \
  51. dc_crtc_err(crtc, "%s: FrameGen FIFO empty\n", \
  52. __func__); \
  53. } \
  54. } while (0)
  55. #define DC_CRTC_WAIT_FOR_FRAMEGEN_SECONDARY_SYNCUP(fg) \
  56. do { \
  57. if (dc_fg_wait_for_secondary_syncup(fg)) \
  58. dc_crtc_err(crtc, \
  59. "%s: FrameGen secondary channel isn't syncup\n",\
  60. __func__); \
  61. } while (0)
  62. static inline struct dc_crtc *to_dc_crtc(struct drm_crtc *crtc)
  63. {
  64. return container_of(crtc, struct dc_crtc, base);
  65. }
  66. static u32 dc_crtc_get_vblank_counter(struct drm_crtc *crtc)
  67. {
  68. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  69. return dc_fg_get_frame_index(dc_crtc->fg);
  70. }
  71. static int dc_crtc_enable_vblank(struct drm_crtc *crtc)
  72. {
  73. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  74. enable_irq(dc_crtc->irq_dec_framecomplete);
  75. return 0;
  76. }
  77. static void dc_crtc_disable_vblank(struct drm_crtc *crtc)
  78. {
  79. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  80. /* nosync due to atomic context */
  81. disable_irq_nosync(dc_crtc->irq_dec_framecomplete);
  82. }
  83. static const struct drm_crtc_funcs dc_crtc_funcs = {
  84. .reset = drm_atomic_helper_crtc_reset,
  85. .destroy = drm_crtc_cleanup,
  86. .set_config = drm_atomic_helper_set_config,
  87. .page_flip = drm_atomic_helper_page_flip,
  88. .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
  89. .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
  90. .get_vblank_counter = dc_crtc_get_vblank_counter,
  91. .enable_vblank = dc_crtc_enable_vblank,
  92. .disable_vblank = dc_crtc_disable_vblank,
  93. .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
  94. };
  95. static void dc_crtc_queue_state_event(struct drm_crtc_state *crtc_state)
  96. {
  97. struct drm_crtc *crtc = crtc_state->crtc;
  98. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  99. spin_lock_irq(&crtc->dev->event_lock);
  100. if (crtc_state->event) {
  101. WARN_ON(drm_crtc_vblank_get(crtc));
  102. WARN_ON(dc_crtc->event);
  103. dc_crtc->event = crtc_state->event;
  104. crtc_state->event = NULL;
  105. }
  106. spin_unlock_irq(&crtc->dev->event_lock);
  107. }
  108. static inline enum drm_mode_status
  109. dc_crtc_check_clock(struct dc_crtc *dc_crtc, int clk_khz)
  110. {
  111. return dc_fg_check_clock(dc_crtc->fg, clk_khz);
  112. }
  113. static enum drm_mode_status
  114. dc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
  115. {
  116. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  117. enum drm_mode_status status;
  118. status = dc_crtc_check_clock(dc_crtc, mode->clock);
  119. if (status != MODE_OK)
  120. return status;
  121. if (mode->crtc_clock > DC_FRAMEGEN_MAX_CLOCK_KHZ)
  122. return MODE_CLOCK_HIGH;
  123. return MODE_OK;
  124. }
  125. static int
  126. dc_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
  127. {
  128. struct drm_crtc_state *new_crtc_state =
  129. drm_atomic_get_new_crtc_state(state, crtc);
  130. struct drm_display_mode *adj = &new_crtc_state->adjusted_mode;
  131. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  132. enum drm_mode_status status;
  133. status = dc_crtc_check_clock(dc_crtc, adj->clock);
  134. if (status != MODE_OK)
  135. return -EINVAL;
  136. return 0;
  137. }
  138. static void
  139. dc_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state)
  140. {
  141. struct drm_crtc_state *new_crtc_state =
  142. drm_atomic_get_new_crtc_state(state, crtc);
  143. struct dc_drm_device *dc_drm = to_dc_drm_device(crtc->dev);
  144. int idx, ret;
  145. if (!drm_atomic_crtc_needs_modeset(new_crtc_state) ||
  146. !new_crtc_state->active)
  147. return;
  148. if (!drm_dev_enter(crtc->dev, &idx))
  149. return;
  150. /* request pixel engine power-on when CRTC starts to be active */
  151. ret = pm_runtime_resume_and_get(dc_drm->pe->dev);
  152. if (ret)
  153. dc_crtc_err(crtc, "failed to get DC pixel engine RPM: %d\n",
  154. ret);
  155. drm_dev_exit(idx);
  156. }
  157. static void
  158. dc_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state)
  159. {
  160. struct drm_crtc_state *old_crtc_state =
  161. drm_atomic_get_old_crtc_state(state, crtc);
  162. struct drm_crtc_state *new_crtc_state =
  163. drm_atomic_get_new_crtc_state(state, crtc);
  164. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  165. int idx;
  166. if (drm_atomic_crtc_needs_modeset(new_crtc_state) ||
  167. (!old_crtc_state->active && !new_crtc_state->active))
  168. return;
  169. if (!drm_dev_enter(crtc->dev, &idx))
  170. goto out;
  171. enable_irq(dc_crtc->irq_ed_cont_shdload);
  172. /* flush plane update out to display */
  173. dc_ed_pec_sync_trigger(dc_crtc->ed_cont);
  174. DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(ed_cont_shdload_done);
  175. disable_irq(dc_crtc->irq_ed_cont_shdload);
  176. DC_CRTC_CHECK_FRAMEGEN_FIFO(dc_crtc->fg);
  177. drm_dev_exit(idx);
  178. out:
  179. dc_crtc_queue_state_event(new_crtc_state);
  180. }
  181. static void
  182. dc_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
  183. {
  184. struct drm_crtc_state *new_crtc_state =
  185. drm_atomic_get_new_crtc_state(state, crtc);
  186. struct drm_display_mode *adj = &new_crtc_state->adjusted_mode;
  187. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  188. enum dc_link_id cf_link;
  189. int idx, ret;
  190. dc_crtc_dbg(crtc, "mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(adj));
  191. drm_crtc_vblank_on(crtc);
  192. if (!drm_dev_enter(crtc->dev, &idx))
  193. goto out;
  194. /* request display engine power-on when CRTC is enabled */
  195. ret = pm_runtime_resume_and_get(dc_crtc->de->dev);
  196. if (ret < 0)
  197. dc_crtc_err(crtc, "failed to get DC display engine RPM: %d\n",
  198. ret);
  199. enable_irq(dc_crtc->irq_dec_shdload);
  200. enable_irq(dc_crtc->irq_ed_cont_shdload);
  201. enable_irq(dc_crtc->irq_ed_safe_shdload);
  202. dc_fg_cfg_videomode(dc_crtc->fg, adj);
  203. dc_cf_framedimensions(dc_crtc->cf_cont,
  204. adj->crtc_hdisplay, adj->crtc_vdisplay);
  205. dc_cf_framedimensions(dc_crtc->cf_safe,
  206. adj->crtc_hdisplay, adj->crtc_vdisplay);
  207. /* constframe in safety stream shows blue frame */
  208. dc_cf_constantcolor_blue(dc_crtc->cf_safe);
  209. cf_link = dc_cf_get_link_id(dc_crtc->cf_safe);
  210. dc_ed_pec_src_sel(dc_crtc->ed_safe, cf_link);
  211. /* show CRTC background if no plane is enabled */
  212. if (new_crtc_state->plane_mask == 0) {
  213. /* constframe in content stream shows black frame */
  214. dc_cf_constantcolor_black(dc_crtc->cf_cont);
  215. cf_link = dc_cf_get_link_id(dc_crtc->cf_cont);
  216. dc_ed_pec_src_sel(dc_crtc->ed_cont, cf_link);
  217. }
  218. dc_fg_enable_clock(dc_crtc->fg);
  219. dc_ed_pec_sync_trigger(dc_crtc->ed_cont);
  220. dc_ed_pec_sync_trigger(dc_crtc->ed_safe);
  221. dc_fg_shdtokgen(dc_crtc->fg);
  222. dc_fg_enable(dc_crtc->fg);
  223. DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(ed_safe_shdload_done);
  224. DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(ed_cont_shdload_done);
  225. DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(dec_shdload_done);
  226. disable_irq(dc_crtc->irq_ed_safe_shdload);
  227. disable_irq(dc_crtc->irq_ed_cont_shdload);
  228. disable_irq(dc_crtc->irq_dec_shdload);
  229. DC_CRTC_WAIT_FOR_FRAMEGEN_SECONDARY_SYNCUP(dc_crtc->fg);
  230. DC_CRTC_CHECK_FRAMEGEN_FIFO(dc_crtc->fg);
  231. drm_dev_exit(idx);
  232. out:
  233. dc_crtc_queue_state_event(new_crtc_state);
  234. }
  235. static void
  236. dc_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
  237. {
  238. struct drm_crtc_state *new_crtc_state =
  239. drm_atomic_get_new_crtc_state(state, crtc);
  240. struct dc_drm_device *dc_drm = to_dc_drm_device(crtc->dev);
  241. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  242. int idx;
  243. if (!drm_dev_enter(crtc->dev, &idx))
  244. goto out;
  245. enable_irq(dc_crtc->irq_dec_seqcomplete);
  246. dc_fg_disable(dc_crtc->fg);
  247. DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(dec_seqcomplete_done);
  248. disable_irq(dc_crtc->irq_dec_seqcomplete);
  249. dc_fg_disable_clock(dc_crtc->fg);
  250. /* request pixel engine power-off as plane is off too */
  251. pm_runtime_put(dc_drm->pe->dev);
  252. /* request display engine power-off when CRTC is disabled */
  253. pm_runtime_put(dc_crtc->de->dev);
  254. drm_dev_exit(idx);
  255. out:
  256. drm_crtc_vblank_off(crtc);
  257. spin_lock_irq(&crtc->dev->event_lock);
  258. if (new_crtc_state->event && !new_crtc_state->active) {
  259. drm_crtc_send_vblank_event(crtc, new_crtc_state->event);
  260. new_crtc_state->event = NULL;
  261. }
  262. spin_unlock_irq(&crtc->dev->event_lock);
  263. }
  264. static bool dc_crtc_get_scanout_position(struct drm_crtc *crtc,
  265. bool in_vblank_irq,
  266. int *vpos, int *hpos,
  267. ktime_t *stime, ktime_t *etime,
  268. const struct drm_display_mode *mode)
  269. {
  270. struct dc_crtc *dc_crtc = to_dc_crtc(crtc);
  271. int vdisplay = mode->crtc_vdisplay;
  272. int vtotal = mode->crtc_vtotal;
  273. bool reliable;
  274. int line;
  275. int idx;
  276. if (stime)
  277. *stime = ktime_get();
  278. if (!drm_dev_enter(crtc->dev, &idx)) {
  279. reliable = false;
  280. *vpos = 0;
  281. *hpos = 0;
  282. goto out;
  283. }
  284. /* line index starts with 0 for the first active output line */
  285. line = dc_fg_get_line_index(dc_crtc->fg);
  286. if (line < vdisplay)
  287. /* active scanout area - positive */
  288. *vpos = line + 1;
  289. else
  290. /* inside vblank - negative */
  291. *vpos = line - (vtotal - 1);
  292. *hpos = 0;
  293. reliable = true;
  294. drm_dev_exit(idx);
  295. out:
  296. if (etime)
  297. *etime = ktime_get();
  298. return reliable;
  299. }
  300. static const struct drm_crtc_helper_funcs dc_helper_funcs = {
  301. .mode_valid = dc_crtc_mode_valid,
  302. .atomic_check = dc_crtc_atomic_check,
  303. .atomic_begin = dc_crtc_atomic_begin,
  304. .atomic_flush = dc_crtc_atomic_flush,
  305. .atomic_enable = dc_crtc_atomic_enable,
  306. .atomic_disable = dc_crtc_atomic_disable,
  307. .get_scanout_position = dc_crtc_get_scanout_position,
  308. };
  309. static irqreturn_t dc_crtc_irq_handler_dec_framecomplete(int irq, void *dev_id)
  310. {
  311. struct dc_crtc *dc_crtc = dev_id;
  312. struct drm_crtc *crtc = &dc_crtc->base;
  313. unsigned long flags;
  314. drm_crtc_handle_vblank(crtc);
  315. spin_lock_irqsave(&crtc->dev->event_lock, flags);
  316. if (dc_crtc->event) {
  317. drm_crtc_send_vblank_event(crtc, dc_crtc->event);
  318. dc_crtc->event = NULL;
  319. drm_crtc_vblank_put(crtc);
  320. }
  321. spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
  322. return IRQ_HANDLED;
  323. }
  324. static irqreturn_t
  325. dc_crtc_irq_handler_dec_seqcomplete_done(int irq, void *dev_id)
  326. {
  327. struct dc_crtc *dc_crtc = dev_id;
  328. complete(&dc_crtc->dec_seqcomplete_done);
  329. return IRQ_HANDLED;
  330. }
  331. static irqreturn_t dc_crtc_irq_handler_dec_shdload_done(int irq, void *dev_id)
  332. {
  333. struct dc_crtc *dc_crtc = dev_id;
  334. complete(&dc_crtc->dec_shdload_done);
  335. return IRQ_HANDLED;
  336. }
  337. static irqreturn_t
  338. dc_crtc_irq_handler_ed_cont_shdload_done(int irq, void *dev_id)
  339. {
  340. struct dc_crtc *dc_crtc = dev_id;
  341. complete(&dc_crtc->ed_cont_shdload_done);
  342. return IRQ_HANDLED;
  343. }
  344. static irqreturn_t
  345. dc_crtc_irq_handler_ed_safe_shdload_done(int irq, void *dev_id)
  346. {
  347. struct dc_crtc *dc_crtc = dev_id;
  348. complete(&dc_crtc->ed_safe_shdload_done);
  349. return IRQ_HANDLED;
  350. }
  351. static int dc_crtc_request_irqs(struct drm_device *drm, struct dc_crtc *dc_crtc)
  352. {
  353. struct {
  354. struct device *dev;
  355. unsigned int irq;
  356. irqreturn_t (*irq_handler)(int irq, void *dev_id);
  357. } irqs[DC_CRTC_IRQS] = {
  358. {
  359. dc_crtc->de->dev,
  360. dc_crtc->irq_dec_framecomplete,
  361. dc_crtc_irq_handler_dec_framecomplete,
  362. }, {
  363. dc_crtc->de->dev,
  364. dc_crtc->irq_dec_seqcomplete,
  365. dc_crtc_irq_handler_dec_seqcomplete_done,
  366. }, {
  367. dc_crtc->de->dev,
  368. dc_crtc->irq_dec_shdload,
  369. dc_crtc_irq_handler_dec_shdload_done,
  370. }, {
  371. dc_crtc->ed_cont->dev,
  372. dc_crtc->irq_ed_cont_shdload,
  373. dc_crtc_irq_handler_ed_cont_shdload_done,
  374. }, {
  375. dc_crtc->ed_safe->dev,
  376. dc_crtc->irq_ed_safe_shdload,
  377. dc_crtc_irq_handler_ed_safe_shdload_done,
  378. },
  379. };
  380. int i, ret;
  381. for (i = 0; i < DC_CRTC_IRQS; i++) {
  382. struct dc_crtc_irq *irq = &dc_crtc->irqs[i];
  383. ret = devm_request_irq(irqs[i].dev, irqs[i].irq,
  384. irqs[i].irq_handler, IRQF_NO_AUTOEN,
  385. dev_name(irqs[i].dev), dc_crtc);
  386. if (ret) {
  387. dev_err(irqs[i].dev, "failed to request irq(%u): %d\n",
  388. irqs[i].irq, ret);
  389. return ret;
  390. }
  391. irq->dc_crtc = dc_crtc;
  392. irq->irq = irqs[i].irq;
  393. }
  394. return 0;
  395. }
  396. int dc_crtc_init(struct dc_drm_device *dc_drm, int crtc_index)
  397. {
  398. struct dc_crtc *dc_crtc = &dc_drm->dc_crtc[crtc_index];
  399. struct drm_device *drm = &dc_drm->base;
  400. struct dc_de *de = dc_drm->de[crtc_index];
  401. struct dc_pe *pe = dc_drm->pe;
  402. struct dc_plane *dc_primary;
  403. int ret;
  404. dc_crtc->de = de;
  405. init_completion(&dc_crtc->dec_seqcomplete_done);
  406. init_completion(&dc_crtc->dec_shdload_done);
  407. init_completion(&dc_crtc->ed_cont_shdload_done);
  408. init_completion(&dc_crtc->ed_safe_shdload_done);
  409. dc_crtc->cf_cont = pe->cf_cont[crtc_index];
  410. dc_crtc->cf_safe = pe->cf_safe[crtc_index];
  411. dc_crtc->ed_cont = pe->ed_cont[crtc_index];
  412. dc_crtc->ed_safe = pe->ed_safe[crtc_index];
  413. dc_crtc->fg = de->fg;
  414. dc_crtc->irq_dec_framecomplete = de->irq_framecomplete;
  415. dc_crtc->irq_dec_seqcomplete = de->irq_seqcomplete;
  416. dc_crtc->irq_dec_shdload = de->irq_shdload;
  417. dc_crtc->irq_ed_safe_shdload = dc_crtc->ed_safe->irq_shdload;
  418. dc_crtc->irq_ed_cont_shdload = dc_crtc->ed_cont->irq_shdload;
  419. dc_primary = &dc_drm->dc_primary[crtc_index];
  420. ret = dc_plane_init(dc_drm, dc_primary);
  421. if (ret) {
  422. dev_err(de->dev, "failed to initialize primary plane: %d\n",
  423. ret);
  424. return ret;
  425. }
  426. drm_crtc_helper_add(&dc_crtc->base, &dc_helper_funcs);
  427. ret = drm_crtc_init_with_planes(drm, &dc_crtc->base, &dc_primary->base,
  428. NULL, &dc_crtc_funcs, NULL);
  429. if (ret)
  430. dev_err(de->dev, "failed to add CRTC: %d\n", ret);
  431. return ret;
  432. }
  433. int dc_crtc_post_init(struct dc_drm_device *dc_drm, int crtc_index)
  434. {
  435. struct dc_crtc *dc_crtc = &dc_drm->dc_crtc[crtc_index];
  436. struct drm_device *drm = &dc_drm->base;
  437. return dc_crtc_request_irqs(drm, dc_crtc);
  438. }