zx_plane.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*
  2. * Copyright 2016 Linaro Ltd.
  3. * Copyright 2016 ZTE Corporation.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. */
  10. #include <drm/drm_atomic.h>
  11. #include <drm/drm_atomic_helper.h>
  12. #include <drm/drm_fb_cma_helper.h>
  13. #include <drm/drm_gem_cma_helper.h>
  14. #include <drm/drm_modeset_helper_vtables.h>
  15. #include <drm/drm_plane_helper.h>
  16. #include <drm/drmP.h>
  17. #include "zx_common_regs.h"
  18. #include "zx_drm_drv.h"
  19. #include "zx_plane.h"
  20. #include "zx_plane_regs.h"
  21. #include "zx_vou.h"
  22. static const uint32_t gl_formats[] = {
  23. DRM_FORMAT_ARGB8888,
  24. DRM_FORMAT_XRGB8888,
  25. DRM_FORMAT_RGB888,
  26. DRM_FORMAT_RGB565,
  27. DRM_FORMAT_ARGB1555,
  28. DRM_FORMAT_ARGB4444,
  29. };
  30. static const uint32_t vl_formats[] = {
  31. DRM_FORMAT_NV12, /* Semi-planar YUV420 */
  32. DRM_FORMAT_YUV420, /* Planar YUV420 */
  33. DRM_FORMAT_YUYV, /* Packed YUV422 */
  34. DRM_FORMAT_YVYU,
  35. DRM_FORMAT_UYVY,
  36. DRM_FORMAT_VYUY,
  37. DRM_FORMAT_YUV444, /* YUV444 8bit */
  38. /*
  39. * TODO: add formats below that HW supports:
  40. * - YUV420 P010
  41. * - YUV420 Hantro
  42. * - YUV444 10bit
  43. */
  44. };
  45. #define FRAC_16_16(mult, div) (((mult) << 16) / (div))
  46. static int zx_vl_plane_atomic_check(struct drm_plane *plane,
  47. struct drm_plane_state *plane_state)
  48. {
  49. struct drm_framebuffer *fb = plane_state->fb;
  50. struct drm_crtc *crtc = plane_state->crtc;
  51. struct drm_crtc_state *crtc_state;
  52. int min_scale = FRAC_16_16(1, 8);
  53. int max_scale = FRAC_16_16(8, 1);
  54. if (!crtc || !fb)
  55. return 0;
  56. crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
  57. crtc);
  58. if (WARN_ON(!crtc_state))
  59. return -EINVAL;
  60. /* nothing to check when disabling or disabled */
  61. if (!crtc_state->enable)
  62. return 0;
  63. /* plane must be enabled */
  64. if (!plane_state->crtc)
  65. return -EINVAL;
  66. return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
  67. min_scale, max_scale,
  68. true, true);
  69. }
  70. static int zx_vl_get_fmt(uint32_t format)
  71. {
  72. switch (format) {
  73. case DRM_FORMAT_NV12:
  74. return VL_FMT_YUV420;
  75. case DRM_FORMAT_YUV420:
  76. return VL_YUV420_PLANAR | VL_FMT_YUV420;
  77. case DRM_FORMAT_YUYV:
  78. return VL_YUV422_YUYV | VL_FMT_YUV422;
  79. case DRM_FORMAT_YVYU:
  80. return VL_YUV422_YVYU | VL_FMT_YUV422;
  81. case DRM_FORMAT_UYVY:
  82. return VL_YUV422_UYVY | VL_FMT_YUV422;
  83. case DRM_FORMAT_VYUY:
  84. return VL_YUV422_VYUY | VL_FMT_YUV422;
  85. case DRM_FORMAT_YUV444:
  86. return VL_FMT_YUV444_8BIT;
  87. default:
  88. WARN_ONCE(1, "invalid pixel format %d\n", format);
  89. return -EINVAL;
  90. }
  91. }
  92. static inline void zx_vl_set_update(struct zx_plane *zplane)
  93. {
  94. void __iomem *layer = zplane->layer;
  95. zx_writel_mask(layer + VL_CTRL0, VL_UPDATE, VL_UPDATE);
  96. }
  97. static inline void zx_vl_rsz_set_update(struct zx_plane *zplane)
  98. {
  99. zx_writel(zplane->rsz + RSZ_VL_ENABLE_CFG, 1);
  100. }
  101. static int zx_vl_rsz_get_fmt(uint32_t format)
  102. {
  103. switch (format) {
  104. case DRM_FORMAT_NV12:
  105. case DRM_FORMAT_YUV420:
  106. return RSZ_VL_FMT_YCBCR420;
  107. case DRM_FORMAT_YUYV:
  108. case DRM_FORMAT_YVYU:
  109. case DRM_FORMAT_UYVY:
  110. case DRM_FORMAT_VYUY:
  111. return RSZ_VL_FMT_YCBCR422;
  112. case DRM_FORMAT_YUV444:
  113. return RSZ_VL_FMT_YCBCR444;
  114. default:
  115. WARN_ONCE(1, "invalid pixel format %d\n", format);
  116. return -EINVAL;
  117. }
  118. }
  119. static inline u32 rsz_step_value(u32 src, u32 dst)
  120. {
  121. u32 val = 0;
  122. if (src == dst)
  123. val = 0;
  124. else if (src < dst)
  125. val = RSZ_PARA_STEP((src << 16) / dst);
  126. else if (src > dst)
  127. val = RSZ_DATA_STEP(src / dst) |
  128. RSZ_PARA_STEP(((src << 16) / dst) & 0xffff);
  129. return val;
  130. }
  131. static void zx_vl_rsz_setup(struct zx_plane *zplane, uint32_t format,
  132. u32 src_w, u32 src_h, u32 dst_w, u32 dst_h)
  133. {
  134. void __iomem *rsz = zplane->rsz;
  135. u32 src_chroma_w = src_w;
  136. u32 src_chroma_h = src_h;
  137. int fmt;
  138. /* Set up source and destination resolution */
  139. zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
  140. zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
  141. /* Configure data format for VL RSZ */
  142. fmt = zx_vl_rsz_get_fmt(format);
  143. if (fmt >= 0)
  144. zx_writel_mask(rsz + RSZ_VL_CTRL_CFG, RSZ_VL_FMT_MASK, fmt);
  145. /* Calculate Chroma height and width */
  146. if (fmt == RSZ_VL_FMT_YCBCR420) {
  147. src_chroma_w = src_w >> 1;
  148. src_chroma_h = src_h >> 1;
  149. } else if (fmt == RSZ_VL_FMT_YCBCR422) {
  150. src_chroma_w = src_w >> 1;
  151. }
  152. /* Set up Luma and Chroma step registers */
  153. zx_writel(rsz + RSZ_VL_LUMA_HOR, rsz_step_value(src_w, dst_w));
  154. zx_writel(rsz + RSZ_VL_LUMA_VER, rsz_step_value(src_h, dst_h));
  155. zx_writel(rsz + RSZ_VL_CHROMA_HOR, rsz_step_value(src_chroma_w, dst_w));
  156. zx_writel(rsz + RSZ_VL_CHROMA_VER, rsz_step_value(src_chroma_h, dst_h));
  157. zx_vl_rsz_set_update(zplane);
  158. }
  159. static void zx_vl_plane_atomic_update(struct drm_plane *plane,
  160. struct drm_plane_state *old_state)
  161. {
  162. struct zx_plane *zplane = to_zx_plane(plane);
  163. struct drm_plane_state *state = plane->state;
  164. struct drm_framebuffer *fb = state->fb;
  165. struct drm_rect *src = &state->src;
  166. struct drm_rect *dst = &state->dst;
  167. struct drm_gem_cma_object *cma_obj;
  168. void __iomem *layer = zplane->layer;
  169. void __iomem *hbsc = zplane->hbsc;
  170. void __iomem *paddr_reg;
  171. dma_addr_t paddr;
  172. u32 src_x, src_y, src_w, src_h;
  173. u32 dst_x, dst_y, dst_w, dst_h;
  174. uint32_t format;
  175. int fmt;
  176. int num_planes;
  177. int i;
  178. if (!fb)
  179. return;
  180. format = fb->format->format;
  181. src_x = src->x1 >> 16;
  182. src_y = src->y1 >> 16;
  183. src_w = drm_rect_width(src) >> 16;
  184. src_h = drm_rect_height(src) >> 16;
  185. dst_x = dst->x1;
  186. dst_y = dst->y1;
  187. dst_w = drm_rect_width(dst);
  188. dst_h = drm_rect_height(dst);
  189. /* Set up data address registers for Y, Cb and Cr planes */
  190. num_planes = drm_format_num_planes(format);
  191. paddr_reg = layer + VL_Y;
  192. for (i = 0; i < num_planes; i++) {
  193. cma_obj = drm_fb_cma_get_gem_obj(fb, i);
  194. paddr = cma_obj->paddr + fb->offsets[i];
  195. paddr += src_y * fb->pitches[i];
  196. paddr += src_x * drm_format_plane_cpp(format, i);
  197. zx_writel(paddr_reg, paddr);
  198. paddr_reg += 4;
  199. }
  200. /* Set up source height/width register */
  201. zx_writel(layer + VL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
  202. /* Set up start position register */
  203. zx_writel(layer + VL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
  204. /* Set up end position register */
  205. zx_writel(layer + VL_POS_END,
  206. GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
  207. /* Strides of Cb and Cr planes should be identical */
  208. zx_writel(layer + VL_STRIDE, LUMA_STRIDE(fb->pitches[0]) |
  209. CHROMA_STRIDE(fb->pitches[1]));
  210. /* Set up video layer data format */
  211. fmt = zx_vl_get_fmt(format);
  212. if (fmt >= 0)
  213. zx_writel(layer + VL_CTRL1, fmt);
  214. /* Always use scaler since it exists (set for not bypass) */
  215. zx_writel_mask(layer + VL_CTRL2, VL_SCALER_BYPASS_MODE,
  216. VL_SCALER_BYPASS_MODE);
  217. zx_vl_rsz_setup(zplane, format, src_w, src_h, dst_w, dst_h);
  218. /* Enable HBSC block */
  219. zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
  220. zx_vou_layer_enable(plane);
  221. zx_vl_set_update(zplane);
  222. }
  223. static void zx_plane_atomic_disable(struct drm_plane *plane,
  224. struct drm_plane_state *old_state)
  225. {
  226. struct zx_plane *zplane = to_zx_plane(plane);
  227. void __iomem *hbsc = zplane->hbsc;
  228. zx_vou_layer_disable(plane);
  229. /* Disable HBSC block */
  230. zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, 0);
  231. }
  232. static const struct drm_plane_helper_funcs zx_vl_plane_helper_funcs = {
  233. .atomic_check = zx_vl_plane_atomic_check,
  234. .atomic_update = zx_vl_plane_atomic_update,
  235. .atomic_disable = zx_plane_atomic_disable,
  236. };
  237. static int zx_gl_plane_atomic_check(struct drm_plane *plane,
  238. struct drm_plane_state *plane_state)
  239. {
  240. struct drm_framebuffer *fb = plane_state->fb;
  241. struct drm_crtc *crtc = plane_state->crtc;
  242. struct drm_crtc_state *crtc_state;
  243. if (!crtc || !fb)
  244. return 0;
  245. crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
  246. crtc);
  247. if (WARN_ON(!crtc_state))
  248. return -EINVAL;
  249. /* nothing to check when disabling or disabled */
  250. if (!crtc_state->enable)
  251. return 0;
  252. /* plane must be enabled */
  253. if (!plane_state->crtc)
  254. return -EINVAL;
  255. return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
  256. DRM_PLANE_HELPER_NO_SCALING,
  257. DRM_PLANE_HELPER_NO_SCALING,
  258. false, true);
  259. }
  260. static int zx_gl_get_fmt(uint32_t format)
  261. {
  262. switch (format) {
  263. case DRM_FORMAT_ARGB8888:
  264. case DRM_FORMAT_XRGB8888:
  265. return GL_FMT_ARGB8888;
  266. case DRM_FORMAT_RGB888:
  267. return GL_FMT_RGB888;
  268. case DRM_FORMAT_RGB565:
  269. return GL_FMT_RGB565;
  270. case DRM_FORMAT_ARGB1555:
  271. return GL_FMT_ARGB1555;
  272. case DRM_FORMAT_ARGB4444:
  273. return GL_FMT_ARGB4444;
  274. default:
  275. WARN_ONCE(1, "invalid pixel format %d\n", format);
  276. return -EINVAL;
  277. }
  278. }
  279. static inline void zx_gl_set_update(struct zx_plane *zplane)
  280. {
  281. void __iomem *layer = zplane->layer;
  282. zx_writel_mask(layer + GL_CTRL0, GL_UPDATE, GL_UPDATE);
  283. }
  284. static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
  285. {
  286. zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
  287. }
  288. static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
  289. u32 dst_w, u32 dst_h)
  290. {
  291. void __iomem *rsz = zplane->rsz;
  292. zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
  293. zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
  294. zx_gl_rsz_set_update(zplane);
  295. }
  296. static void zx_gl_plane_atomic_update(struct drm_plane *plane,
  297. struct drm_plane_state *old_state)
  298. {
  299. struct zx_plane *zplane = to_zx_plane(plane);
  300. struct drm_framebuffer *fb = plane->state->fb;
  301. struct drm_gem_cma_object *cma_obj;
  302. void __iomem *layer = zplane->layer;
  303. void __iomem *csc = zplane->csc;
  304. void __iomem *hbsc = zplane->hbsc;
  305. u32 src_x, src_y, src_w, src_h;
  306. u32 dst_x, dst_y, dst_w, dst_h;
  307. unsigned int bpp;
  308. uint32_t format;
  309. dma_addr_t paddr;
  310. u32 stride;
  311. int fmt;
  312. if (!fb)
  313. return;
  314. format = fb->format->format;
  315. stride = fb->pitches[0];
  316. src_x = plane->state->src_x >> 16;
  317. src_y = plane->state->src_y >> 16;
  318. src_w = plane->state->src_w >> 16;
  319. src_h = plane->state->src_h >> 16;
  320. dst_x = plane->state->crtc_x;
  321. dst_y = plane->state->crtc_y;
  322. dst_w = plane->state->crtc_w;
  323. dst_h = plane->state->crtc_h;
  324. bpp = fb->format->cpp[0];
  325. cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
  326. paddr = cma_obj->paddr + fb->offsets[0];
  327. paddr += src_y * stride + src_x * bpp / 8;
  328. zx_writel(layer + GL_ADDR, paddr);
  329. /* Set up source height/width register */
  330. zx_writel(layer + GL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
  331. /* Set up start position register */
  332. zx_writel(layer + GL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
  333. /* Set up end position register */
  334. zx_writel(layer + GL_POS_END,
  335. GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
  336. /* Set up stride register */
  337. zx_writel(layer + GL_STRIDE, stride & 0xffff);
  338. /* Set up graphic layer data format */
  339. fmt = zx_gl_get_fmt(format);
  340. if (fmt >= 0)
  341. zx_writel_mask(layer + GL_CTRL1, GL_DATA_FMT_MASK,
  342. fmt << GL_DATA_FMT_SHIFT);
  343. /* Initialize global alpha with a sane value */
  344. zx_writel_mask(layer + GL_CTRL2, GL_GLOBAL_ALPHA_MASK,
  345. 0xff << GL_GLOBAL_ALPHA_SHIFT);
  346. /* Setup CSC for the GL */
  347. if (dst_h > 720)
  348. zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
  349. CSC_BT709_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
  350. else
  351. zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
  352. CSC_BT601_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
  353. zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, CSC_WORK_ENABLE);
  354. /* Always use scaler since it exists (set for not bypass) */
  355. zx_writel_mask(layer + GL_CTRL3, GL_SCALER_BYPASS_MODE,
  356. GL_SCALER_BYPASS_MODE);
  357. zx_gl_rsz_setup(zplane, src_w, src_h, dst_w, dst_h);
  358. /* Enable HBSC block */
  359. zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
  360. zx_vou_layer_enable(plane);
  361. zx_gl_set_update(zplane);
  362. }
  363. static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
  364. .atomic_check = zx_gl_plane_atomic_check,
  365. .atomic_update = zx_gl_plane_atomic_update,
  366. .atomic_disable = zx_plane_atomic_disable,
  367. };
  368. static void zx_plane_destroy(struct drm_plane *plane)
  369. {
  370. drm_plane_helper_disable(plane);
  371. drm_plane_cleanup(plane);
  372. }
  373. static const struct drm_plane_funcs zx_plane_funcs = {
  374. .update_plane = drm_atomic_helper_update_plane,
  375. .disable_plane = drm_atomic_helper_disable_plane,
  376. .destroy = zx_plane_destroy,
  377. .reset = drm_atomic_helper_plane_reset,
  378. .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
  379. .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
  380. };
  381. void zx_plane_set_update(struct drm_plane *plane)
  382. {
  383. struct zx_plane *zplane = to_zx_plane(plane);
  384. /* Do nothing if the plane is not enabled */
  385. if (!plane->state->crtc)
  386. return;
  387. switch (plane->type) {
  388. case DRM_PLANE_TYPE_PRIMARY:
  389. zx_gl_rsz_set_update(zplane);
  390. zx_gl_set_update(zplane);
  391. break;
  392. case DRM_PLANE_TYPE_OVERLAY:
  393. zx_vl_rsz_set_update(zplane);
  394. zx_vl_set_update(zplane);
  395. break;
  396. default:
  397. WARN_ONCE(1, "unsupported plane type %d\n", plane->type);
  398. }
  399. }
  400. static void zx_plane_hbsc_init(struct zx_plane *zplane)
  401. {
  402. void __iomem *hbsc = zplane->hbsc;
  403. /*
  404. * Initialize HBSC block with a sane configuration per recommedation
  405. * from ZTE BSP code.
  406. */
  407. zx_writel(hbsc + HBSC_SATURATION, 0x200);
  408. zx_writel(hbsc + HBSC_HUE, 0x0);
  409. zx_writel(hbsc + HBSC_BRIGHT, 0x0);
  410. zx_writel(hbsc + HBSC_CONTRAST, 0x200);
  411. zx_writel(hbsc + HBSC_THRESHOLD_COL1, (0x3ac << 16) | 0x40);
  412. zx_writel(hbsc + HBSC_THRESHOLD_COL2, (0x3c0 << 16) | 0x40);
  413. zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40);
  414. }
  415. int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
  416. enum drm_plane_type type)
  417. {
  418. const struct drm_plane_helper_funcs *helper;
  419. struct drm_plane *plane = &zplane->plane;
  420. struct device *dev = zplane->dev;
  421. const uint32_t *formats;
  422. unsigned int format_count;
  423. int ret;
  424. zx_plane_hbsc_init(zplane);
  425. switch (type) {
  426. case DRM_PLANE_TYPE_PRIMARY:
  427. helper = &zx_gl_plane_helper_funcs;
  428. formats = gl_formats;
  429. format_count = ARRAY_SIZE(gl_formats);
  430. break;
  431. case DRM_PLANE_TYPE_OVERLAY:
  432. helper = &zx_vl_plane_helper_funcs;
  433. formats = vl_formats;
  434. format_count = ARRAY_SIZE(vl_formats);
  435. break;
  436. default:
  437. return -ENODEV;
  438. }
  439. ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
  440. &zx_plane_funcs, formats, format_count,
  441. NULL, type, NULL);
  442. if (ret) {
  443. DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
  444. return ret;
  445. }
  446. drm_plane_helper_add(plane, helper);
  447. return 0;
  448. }