ipuv3-plane.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*
  2. * i.MX IPUv3 DP Overlay Planes
  3. *
  4. * Copyright (C) 2013 Philipp Zabel, Pengutronix
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <drm/drmP.h>
  16. #include <drm/drm_fb_cma_helper.h>
  17. #include <drm/drm_gem_cma_helper.h>
  18. #include "video/imx-ipu-v3.h"
  19. #include "ipuv3-plane.h"
  20. #define to_ipu_plane(x) container_of(x, struct ipu_plane, base)
  21. static const uint32_t ipu_plane_formats[] = {
  22. DRM_FORMAT_ARGB1555,
  23. DRM_FORMAT_XRGB1555,
  24. DRM_FORMAT_ABGR1555,
  25. DRM_FORMAT_XBGR1555,
  26. DRM_FORMAT_RGBA5551,
  27. DRM_FORMAT_BGRA5551,
  28. DRM_FORMAT_ARGB4444,
  29. DRM_FORMAT_ARGB8888,
  30. DRM_FORMAT_XRGB8888,
  31. DRM_FORMAT_ABGR8888,
  32. DRM_FORMAT_XBGR8888,
  33. DRM_FORMAT_RGBA8888,
  34. DRM_FORMAT_RGBX8888,
  35. DRM_FORMAT_BGRA8888,
  36. DRM_FORMAT_BGRA8888,
  37. DRM_FORMAT_YUYV,
  38. DRM_FORMAT_YVYU,
  39. DRM_FORMAT_YUV420,
  40. DRM_FORMAT_YVU420,
  41. DRM_FORMAT_RGB565,
  42. };
  43. int ipu_plane_irq(struct ipu_plane *ipu_plane)
  44. {
  45. return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
  46. IPU_IRQ_EOF);
  47. }
  48. static int calc_vref(struct drm_display_mode *mode)
  49. {
  50. unsigned long htotal, vtotal;
  51. htotal = mode->htotal;
  52. vtotal = mode->vtotal;
  53. if (!htotal || !vtotal)
  54. return 60;
  55. return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal);
  56. }
  57. static inline int calc_bandwidth(int width, int height, unsigned int vref)
  58. {
  59. return width * height * vref;
  60. }
  61. int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
  62. int x, int y)
  63. {
  64. struct drm_gem_cma_object *cma_obj[3];
  65. unsigned long eba, ubo, vbo;
  66. int active, i;
  67. for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
  68. cma_obj[i] = drm_fb_cma_get_gem_obj(fb, i);
  69. if (!cma_obj[i]) {
  70. DRM_DEBUG_KMS("plane %d entry is null.\n", i);
  71. return -EFAULT;
  72. }
  73. }
  74. eba = cma_obj[0]->paddr + fb->offsets[0] +
  75. fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
  76. if (eba & 0x7) {
  77. DRM_DEBUG_KMS("base address must be a multiple of 8.\n");
  78. return -EINVAL;
  79. }
  80. if (fb->pitches[0] < 1 || fb->pitches[0] > 16384) {
  81. DRM_DEBUG_KMS("pitches out of range.\n");
  82. return -EINVAL;
  83. }
  84. if (ipu_plane->enabled && fb->pitches[0] != ipu_plane->stride[0]) {
  85. DRM_DEBUG_KMS("pitches must not change while plane is enabled.\n");
  86. return -EINVAL;
  87. }
  88. ipu_plane->stride[0] = fb->pitches[0];
  89. switch (fb->pixel_format) {
  90. case DRM_FORMAT_YUV420:
  91. case DRM_FORMAT_YVU420:
  92. /*
  93. * Multiplanar formats have to meet the following restrictions:
  94. * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
  95. * - EBA, UBO and VBO are a multiple of 8
  96. * - UBO and VBO are unsigned and not larger than 0xfffff8
  97. * - Only EBA may be changed while scanout is active
  98. * - The strides of U and V planes must be identical.
  99. */
  100. ubo = cma_obj[1]->paddr + fb->offsets[1] +
  101. fb->pitches[1] * y / 2 + x / 2 - eba;
  102. vbo = cma_obj[2]->paddr + fb->offsets[2] +
  103. fb->pitches[2] * y / 2 + x / 2 - eba;
  104. if ((ubo & 0x7) || (vbo & 0x7)) {
  105. DRM_DEBUG_KMS("U/V buffer offsets must be a multiple of 8.\n");
  106. return -EINVAL;
  107. }
  108. if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) {
  109. DRM_DEBUG_KMS("U/V buffer offsets must be positive and not larger than 0xfffff8.\n");
  110. return -EINVAL;
  111. }
  112. if (ipu_plane->enabled && ((ipu_plane->u_offset != ubo) ||
  113. (ipu_plane->v_offset != vbo))) {
  114. DRM_DEBUG_KMS("U/V buffer offsets must not change while plane is enabled.\n");
  115. return -EINVAL;
  116. }
  117. if (fb->pitches[1] != fb->pitches[2]) {
  118. DRM_DEBUG_KMS("U/V pitches must be identical.\n");
  119. return -EINVAL;
  120. }
  121. if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) {
  122. DRM_DEBUG_KMS("U/V pitches out of range.\n");
  123. return -EINVAL;
  124. }
  125. if (ipu_plane->enabled &&
  126. (ipu_plane->stride[1] != fb->pitches[1])) {
  127. DRM_DEBUG_KMS("U/V pitches must not change while plane is enabled.\n");
  128. return -EINVAL;
  129. }
  130. ipu_plane->u_offset = ubo;
  131. ipu_plane->v_offset = vbo;
  132. ipu_plane->stride[1] = fb->pitches[1];
  133. dev_dbg(ipu_plane->base.dev->dev,
  134. "phys = %pad %pad %pad, x = %d, y = %d",
  135. &cma_obj[0]->paddr, &cma_obj[1]->paddr,
  136. &cma_obj[2]->paddr, x, y);
  137. break;
  138. default:
  139. dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
  140. &cma_obj[0]->paddr, x, y);
  141. break;
  142. }
  143. if (ipu_plane->enabled) {
  144. active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
  145. ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
  146. ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
  147. } else {
  148. ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
  149. ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
  150. }
  151. /* cache offsets for subsequent pageflips */
  152. ipu_plane->x = x;
  153. ipu_plane->y = y;
  154. return 0;
  155. }
  156. int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
  157. struct drm_display_mode *mode,
  158. struct drm_framebuffer *fb, int crtc_x, int crtc_y,
  159. unsigned int crtc_w, unsigned int crtc_h,
  160. uint32_t src_x, uint32_t src_y,
  161. uint32_t src_w, uint32_t src_h, bool interlaced)
  162. {
  163. struct device *dev = ipu_plane->base.dev->dev;
  164. int ret;
  165. /* no scaling */
  166. if (src_w != crtc_w || src_h != crtc_h)
  167. return -EINVAL;
  168. /* clip to crtc bounds */
  169. if (crtc_x < 0) {
  170. if (-crtc_x > crtc_w)
  171. return -EINVAL;
  172. src_x += -crtc_x;
  173. src_w -= -crtc_x;
  174. crtc_w -= -crtc_x;
  175. crtc_x = 0;
  176. }
  177. if (crtc_y < 0) {
  178. if (-crtc_y > crtc_h)
  179. return -EINVAL;
  180. src_y += -crtc_y;
  181. src_h -= -crtc_y;
  182. crtc_h -= -crtc_y;
  183. crtc_y = 0;
  184. }
  185. if (crtc_x + crtc_w > mode->hdisplay) {
  186. if (crtc_x > mode->hdisplay)
  187. return -EINVAL;
  188. crtc_w = mode->hdisplay - crtc_x;
  189. src_w = crtc_w;
  190. }
  191. if (crtc_y + crtc_h > mode->vdisplay) {
  192. if (crtc_y > mode->vdisplay)
  193. return -EINVAL;
  194. crtc_h = mode->vdisplay - crtc_y;
  195. src_h = crtc_h;
  196. }
  197. /* full plane minimum width is 13 pixels */
  198. if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG))
  199. return -EINVAL;
  200. if (crtc_h < 2)
  201. return -EINVAL;
  202. /*
  203. * since we cannot touch active IDMAC channels, we do not support
  204. * resizing the enabled plane or changing its format
  205. */
  206. if (ipu_plane->enabled) {
  207. if (src_w != ipu_plane->w || src_h != ipu_plane->h ||
  208. fb->pixel_format != ipu_plane->base.fb->pixel_format)
  209. return -EINVAL;
  210. return ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
  211. }
  212. switch (ipu_plane->dp_flow) {
  213. case IPU_DP_FLOW_SYNC_BG:
  214. ret = ipu_dp_setup_channel(ipu_plane->dp,
  215. IPUV3_COLORSPACE_RGB,
  216. IPUV3_COLORSPACE_RGB);
  217. if (ret) {
  218. dev_err(dev,
  219. "initializing display processor failed with %d\n",
  220. ret);
  221. return ret;
  222. }
  223. ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
  224. break;
  225. case IPU_DP_FLOW_SYNC_FG:
  226. ipu_dp_setup_channel(ipu_plane->dp,
  227. ipu_drm_fourcc_to_colorspace(fb->pixel_format),
  228. IPUV3_COLORSPACE_UNKNOWN);
  229. ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
  230. /* Enable local alpha on partial plane */
  231. switch (fb->pixel_format) {
  232. case DRM_FORMAT_ARGB1555:
  233. case DRM_FORMAT_ABGR1555:
  234. case DRM_FORMAT_RGBA5551:
  235. case DRM_FORMAT_BGRA5551:
  236. case DRM_FORMAT_ARGB4444:
  237. case DRM_FORMAT_ARGB8888:
  238. case DRM_FORMAT_ABGR8888:
  239. case DRM_FORMAT_RGBA8888:
  240. case DRM_FORMAT_BGRA8888:
  241. ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
  242. break;
  243. default:
  244. break;
  245. }
  246. }
  247. ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
  248. calc_bandwidth(crtc_w, crtc_h,
  249. calc_vref(mode)), 64);
  250. if (ret) {
  251. dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
  252. return ret;
  253. }
  254. ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w);
  255. ipu_cpmem_zero(ipu_plane->ipu_ch);
  256. ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h);
  257. ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
  258. if (ret < 0) {
  259. dev_err(dev, "unsupported pixel format 0x%08x\n",
  260. fb->pixel_format);
  261. return ret;
  262. }
  263. ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
  264. ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
  265. ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
  266. ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
  267. if (ret < 0)
  268. return ret;
  269. if (interlaced)
  270. ipu_cpmem_interlaced_scan(ipu_plane->ipu_ch, fb->pitches[0]);
  271. if (fb->pixel_format == DRM_FORMAT_YUV420) {
  272. ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
  273. ipu_plane->stride[1],
  274. ipu_plane->u_offset,
  275. ipu_plane->v_offset);
  276. } else if (fb->pixel_format == DRM_FORMAT_YVU420) {
  277. ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
  278. ipu_plane->stride[1],
  279. ipu_plane->v_offset,
  280. ipu_plane->u_offset);
  281. }
  282. ipu_plane->w = src_w;
  283. ipu_plane->h = src_h;
  284. return 0;
  285. }
  286. void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
  287. {
  288. if (!IS_ERR_OR_NULL(ipu_plane->dp))
  289. ipu_dp_put(ipu_plane->dp);
  290. if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
  291. ipu_dmfc_put(ipu_plane->dmfc);
  292. if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
  293. ipu_idmac_put(ipu_plane->ipu_ch);
  294. }
  295. int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
  296. {
  297. int ret;
  298. ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
  299. if (IS_ERR(ipu_plane->ipu_ch)) {
  300. ret = PTR_ERR(ipu_plane->ipu_ch);
  301. DRM_ERROR("failed to get idmac channel: %d\n", ret);
  302. return ret;
  303. }
  304. ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
  305. if (IS_ERR(ipu_plane->dmfc)) {
  306. ret = PTR_ERR(ipu_plane->dmfc);
  307. DRM_ERROR("failed to get dmfc: ret %d\n", ret);
  308. goto err_out;
  309. }
  310. if (ipu_plane->dp_flow >= 0) {
  311. ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
  312. if (IS_ERR(ipu_plane->dp)) {
  313. ret = PTR_ERR(ipu_plane->dp);
  314. DRM_ERROR("failed to get dp flow: %d\n", ret);
  315. goto err_out;
  316. }
  317. }
  318. return 0;
  319. err_out:
  320. ipu_plane_put_resources(ipu_plane);
  321. return ret;
  322. }
  323. void ipu_plane_enable(struct ipu_plane *ipu_plane)
  324. {
  325. if (ipu_plane->dp)
  326. ipu_dp_enable(ipu_plane->ipu);
  327. ipu_dmfc_enable_channel(ipu_plane->dmfc);
  328. ipu_idmac_enable_channel(ipu_plane->ipu_ch);
  329. if (ipu_plane->dp)
  330. ipu_dp_enable_channel(ipu_plane->dp);
  331. ipu_plane->enabled = true;
  332. }
  333. void ipu_plane_disable(struct ipu_plane *ipu_plane)
  334. {
  335. ipu_plane->enabled = false;
  336. ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
  337. if (ipu_plane->dp)
  338. ipu_dp_disable_channel(ipu_plane->dp);
  339. ipu_idmac_disable_channel(ipu_plane->ipu_ch);
  340. ipu_dmfc_disable_channel(ipu_plane->dmfc);
  341. if (ipu_plane->dp)
  342. ipu_dp_disable(ipu_plane->ipu);
  343. }
  344. /*
  345. * drm_plane API
  346. */
  347. static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
  348. struct drm_framebuffer *fb, int crtc_x, int crtc_y,
  349. unsigned int crtc_w, unsigned int crtc_h,
  350. uint32_t src_x, uint32_t src_y,
  351. uint32_t src_w, uint32_t src_h)
  352. {
  353. struct ipu_plane *ipu_plane = to_ipu_plane(plane);
  354. int ret = 0;
  355. DRM_DEBUG_KMS("plane - %p\n", plane);
  356. if (!ipu_plane->enabled)
  357. ret = ipu_plane_get_resources(ipu_plane);
  358. if (ret < 0)
  359. return ret;
  360. ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb,
  361. crtc_x, crtc_y, crtc_w, crtc_h,
  362. src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16,
  363. false);
  364. if (ret < 0) {
  365. ipu_plane_put_resources(ipu_plane);
  366. return ret;
  367. }
  368. if (crtc != plane->crtc)
  369. dev_dbg(plane->dev->dev, "crtc change: %p -> %p\n",
  370. plane->crtc, crtc);
  371. plane->crtc = crtc;
  372. if (!ipu_plane->enabled)
  373. ipu_plane_enable(ipu_plane);
  374. return 0;
  375. }
  376. static int ipu_disable_plane(struct drm_plane *plane)
  377. {
  378. struct ipu_plane *ipu_plane = to_ipu_plane(plane);
  379. DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
  380. if (ipu_plane->enabled)
  381. ipu_plane_disable(ipu_plane);
  382. ipu_plane_put_resources(ipu_plane);
  383. return 0;
  384. }
  385. static void ipu_plane_destroy(struct drm_plane *plane)
  386. {
  387. struct ipu_plane *ipu_plane = to_ipu_plane(plane);
  388. DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
  389. ipu_disable_plane(plane);
  390. drm_plane_cleanup(plane);
  391. kfree(ipu_plane);
  392. }
  393. static struct drm_plane_funcs ipu_plane_funcs = {
  394. .update_plane = ipu_update_plane,
  395. .disable_plane = ipu_disable_plane,
  396. .destroy = ipu_plane_destroy,
  397. };
  398. struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
  399. int dma, int dp, unsigned int possible_crtcs,
  400. enum drm_plane_type type)
  401. {
  402. struct ipu_plane *ipu_plane;
  403. int ret;
  404. DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
  405. dma, dp, possible_crtcs);
  406. ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
  407. if (!ipu_plane) {
  408. DRM_ERROR("failed to allocate plane\n");
  409. return ERR_PTR(-ENOMEM);
  410. }
  411. ipu_plane->ipu = ipu;
  412. ipu_plane->dma = dma;
  413. ipu_plane->dp_flow = dp;
  414. ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
  415. &ipu_plane_funcs, ipu_plane_formats,
  416. ARRAY_SIZE(ipu_plane_formats), type,
  417. NULL);
  418. if (ret) {
  419. DRM_ERROR("failed to initialize plane\n");
  420. kfree(ipu_plane);
  421. return ERR_PTR(ret);
  422. }
  423. return ipu_plane;
  424. }