0285-drm-vc4-Add-support-for-YUV-planes.patch 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. From 4760d384fa61412cfff7ac9e4166610cff125f53 Mon Sep 17 00:00:00 2001
  2. From: Eric Anholt <eric@anholt.net>
  3. Date: Wed, 30 Dec 2015 12:25:44 -0800
  4. Subject: [PATCH 285/381] drm/vc4: Add support for YUV planes.
  5. This supports 420 and 422 subsampling with 2 or 3 planes, tested with
  6. modetest. It doesn't set up chroma subsampling position (which it
  7. appears KMS doesn't deal with yet).
  8. The LBM memory is overallocated in many cases, but apparently the docs
  9. aren't quite correct and I'll probably need to look at the hardware
  10. source to really figure it out.
  11. Signed-off-by: Eric Anholt <eric@anholt.net>
  12. (cherry picked from commit fc04023fafecf19ebd09278d8d67dc5ed1f68b46)
  13. ---
  14. drivers/gpu/drm/vc4/vc4_plane.c | 256 +++++++++++++++++++++++++++++++---------
  15. drivers/gpu/drm/vc4/vc4_regs.h | 56 ++++++++-
  16. 2 files changed, 253 insertions(+), 59 deletions(-)
  17. --- a/drivers/gpu/drm/vc4/vc4_plane.c
  18. +++ b/drivers/gpu/drm/vc4/vc4_plane.c
  19. @@ -54,15 +54,19 @@ struct vc4_plane_state {
  20. /* Clipped coordinates of the plane on the display. */
  21. int crtc_x, crtc_y, crtc_w, crtc_h;
  22. /* Clipped area being scanned from in the FB. */
  23. - u32 src_x, src_y, src_w, src_h;
  24. + u32 src_x, src_y;
  25. - enum vc4_scaling_mode x_scaling, y_scaling;
  26. + u32 src_w[2], src_h[2];
  27. +
  28. + /* Scaling selection for the RGB/Y plane and the Cb/Cr planes. */
  29. + enum vc4_scaling_mode x_scaling[2], y_scaling[2];
  30. bool is_unity;
  31. + bool is_yuv;
  32. /* Offset to start scanning out from the start of the plane's
  33. * BO.
  34. */
  35. - u32 offset;
  36. + u32 offsets[3];
  37. /* Our allocation in LBM for temporary storage during scaling. */
  38. struct drm_mm_node lbm;
  39. @@ -79,6 +83,7 @@ static const struct hvs_format {
  40. u32 hvs; /* HVS_FORMAT_* */
  41. u32 pixel_order;
  42. bool has_alpha;
  43. + bool flip_cbcr;
  44. } hvs_formats[] = {
  45. {
  46. .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
  47. @@ -104,6 +109,32 @@ static const struct hvs_format {
  48. .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
  49. .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false,
  50. },
  51. + {
  52. + .drm = DRM_FORMAT_YUV422,
  53. + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
  54. + },
  55. + {
  56. + .drm = DRM_FORMAT_YVU422,
  57. + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
  58. + .flip_cbcr = true,
  59. + },
  60. + {
  61. + .drm = DRM_FORMAT_YUV420,
  62. + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
  63. + },
  64. + {
  65. + .drm = DRM_FORMAT_YVU420,
  66. + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
  67. + .flip_cbcr = true,
  68. + },
  69. + {
  70. + .drm = DRM_FORMAT_NV12,
  71. + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
  72. + },
  73. + {
  74. + .drm = DRM_FORMAT_NV16,
  75. + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
  76. + },
  77. };
  78. static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
  79. @@ -219,11 +250,11 @@ static void vc4_dlist_write(struct vc4_p
  80. *
  81. * This is a replication of a table from the spec.
  82. */
  83. -static u32 vc4_get_scl_field(struct drm_plane_state *state)
  84. +static u32 vc4_get_scl_field(struct drm_plane_state *state, int plane)
  85. {
  86. struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
  87. - switch (vc4_state->x_scaling << 2 | vc4_state->y_scaling) {
  88. + switch (vc4_state->x_scaling[plane] << 2 | vc4_state->y_scaling[plane]) {
  89. case VC4_SCALING_PPF << 2 | VC4_SCALING_PPF:
  90. return SCALER_CTL0_SCL_H_PPF_V_PPF;
  91. case VC4_SCALING_TPZ << 2 | VC4_SCALING_PPF:
  92. @@ -254,9 +285,16 @@ static int vc4_plane_setup_clipping_and_
  93. struct drm_plane *plane = state->plane;
  94. struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
  95. struct drm_framebuffer *fb = state->fb;
  96. + struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
  97. u32 subpixel_src_mask = (1 << 16) - 1;
  98. + u32 format = fb->pixel_format;
  99. + int num_planes = drm_format_num_planes(format);
  100. + u32 h_subsample = 1;
  101. + u32 v_subsample = 1;
  102. + int i;
  103. - vc4_state->offset = fb->offsets[0];
  104. + for (i = 0; i < num_planes; i++)
  105. + vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
  106. /* We don't support subpixel source positioning for scaling. */
  107. if ((state->src_x & subpixel_src_mask) ||
  108. @@ -268,20 +306,48 @@ static int vc4_plane_setup_clipping_and_
  109. vc4_state->src_x = state->src_x >> 16;
  110. vc4_state->src_y = state->src_y >> 16;
  111. - vc4_state->src_w = state->src_w >> 16;
  112. - vc4_state->src_h = state->src_h >> 16;
  113. + vc4_state->src_w[0] = state->src_w >> 16;
  114. + vc4_state->src_h[0] = state->src_h >> 16;
  115. vc4_state->crtc_x = state->crtc_x;
  116. vc4_state->crtc_y = state->crtc_y;
  117. vc4_state->crtc_w = state->crtc_w;
  118. vc4_state->crtc_h = state->crtc_h;
  119. - vc4_state->x_scaling = vc4_get_scaling_mode(vc4_state->src_w,
  120. - vc4_state->crtc_w);
  121. - vc4_state->y_scaling = vc4_get_scaling_mode(vc4_state->src_h,
  122. - vc4_state->crtc_h);
  123. - vc4_state->is_unity = (vc4_state->x_scaling == VC4_SCALING_NONE &&
  124. - vc4_state->y_scaling == VC4_SCALING_NONE);
  125. + vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0],
  126. + vc4_state->crtc_w);
  127. + vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0],
  128. + vc4_state->crtc_h);
  129. +
  130. + if (num_planes > 1) {
  131. + vc4_state->is_yuv = true;
  132. +
  133. + h_subsample = drm_format_horz_chroma_subsampling(format);
  134. + v_subsample = drm_format_vert_chroma_subsampling(format);
  135. + vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample;
  136. + vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample;
  137. +
  138. + vc4_state->x_scaling[1] =
  139. + vc4_get_scaling_mode(vc4_state->src_w[1],
  140. + vc4_state->crtc_w);
  141. + vc4_state->y_scaling[1] =
  142. + vc4_get_scaling_mode(vc4_state->src_h[1],
  143. + vc4_state->crtc_h);
  144. +
  145. + /* YUV conversion requires that scaling be enabled,
  146. + * even on a plane that's otherwise 1:1. Choose TPZ
  147. + * for simplicity.
  148. + */
  149. + if (vc4_state->x_scaling[0] == VC4_SCALING_NONE)
  150. + vc4_state->x_scaling[0] = VC4_SCALING_TPZ;
  151. + if (vc4_state->y_scaling[0] == VC4_SCALING_NONE)
  152. + vc4_state->y_scaling[0] = VC4_SCALING_TPZ;
  153. + }
  154. +
  155. + vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE &&
  156. + vc4_state->y_scaling[0] == VC4_SCALING_NONE &&
  157. + vc4_state->x_scaling[1] == VC4_SCALING_NONE &&
  158. + vc4_state->y_scaling[1] == VC4_SCALING_NONE);
  159. /* No configuring scaling on the cursor plane, since it gets
  160. non-vblank-synced updates, and scaling requires requires
  161. @@ -294,16 +360,27 @@ static int vc4_plane_setup_clipping_and_
  162. * support negative y, and negative x wastes bandwidth.
  163. */
  164. if (vc4_state->crtc_x < 0) {
  165. - vc4_state->offset += (drm_format_plane_cpp(fb->pixel_format,
  166. - 0) *
  167. - -vc4_state->crtc_x);
  168. - vc4_state->src_w += vc4_state->crtc_x;
  169. + for (i = 0; i < num_planes; i++) {
  170. + u32 cpp = drm_format_plane_cpp(fb->pixel_format, i);
  171. + u32 subs = ((i == 0) ? 1 : h_subsample);
  172. +
  173. + vc4_state->offsets[i] += (cpp *
  174. + (-vc4_state->crtc_x) / subs);
  175. + }
  176. + vc4_state->src_w[0] += vc4_state->crtc_x;
  177. + vc4_state->src_w[1] += vc4_state->crtc_x / h_subsample;
  178. vc4_state->crtc_x = 0;
  179. }
  180. if (vc4_state->crtc_y < 0) {
  181. - vc4_state->offset += fb->pitches[0] * -vc4_state->crtc_y;
  182. - vc4_state->src_h += vc4_state->crtc_y;
  183. + for (i = 0; i < num_planes; i++) {
  184. + u32 subs = ((i == 0) ? 1 : v_subsample);
  185. +
  186. + vc4_state->offsets[i] += (fb->pitches[i] *
  187. + (-vc4_state->crtc_y) / subs);
  188. + }
  189. + vc4_state->src_h[0] += vc4_state->crtc_y;
  190. + vc4_state->src_h[1] += vc4_state->crtc_y / v_subsample;
  191. vc4_state->crtc_y = 0;
  192. }
  193. @@ -344,15 +421,23 @@ static u32 vc4_lbm_size(struct drm_plane
  194. /* This is the worst case number. One of the two sizes will
  195. * be used depending on the scaling configuration.
  196. */
  197. - u32 pix_per_line = max(vc4_state->src_w, (u32)vc4_state->crtc_w);
  198. + u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w);
  199. u32 lbm;
  200. - if (vc4_state->is_unity)
  201. - return 0;
  202. - else if (vc4_state->y_scaling == VC4_SCALING_TPZ)
  203. - lbm = pix_per_line * 8;
  204. - else {
  205. - /* In special cases, this multiplier might be 12. */
  206. + if (!vc4_state->is_yuv) {
  207. + if (vc4_state->is_unity)
  208. + return 0;
  209. + else if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
  210. + lbm = pix_per_line * 8;
  211. + else {
  212. + /* In special cases, this multiplier might be 12. */
  213. + lbm = pix_per_line * 16;
  214. + }
  215. + } else {
  216. + /* There are cases for this going down to a multiplier
  217. + * of 2, but according to the firmware source, the
  218. + * table in the docs is somewhat wrong.
  219. + */
  220. lbm = pix_per_line * 16;
  221. }
  222. @@ -361,33 +446,34 @@ static u32 vc4_lbm_size(struct drm_plane
  223. return lbm;
  224. }
  225. -static void vc4_write_scaling_parameters(struct drm_plane_state *state)
  226. +static void vc4_write_scaling_parameters(struct drm_plane_state *state,
  227. + int channel)
  228. {
  229. struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
  230. /* Ch0 H-PPF Word 0: Scaling Parameters */
  231. - if (vc4_state->x_scaling == VC4_SCALING_PPF) {
  232. + if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) {
  233. vc4_write_ppf(vc4_state,
  234. - vc4_state->src_w, vc4_state->crtc_w);
  235. + vc4_state->src_w[channel], vc4_state->crtc_w);
  236. }
  237. /* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */
  238. - if (vc4_state->y_scaling == VC4_SCALING_PPF) {
  239. + if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) {
  240. vc4_write_ppf(vc4_state,
  241. - vc4_state->src_h, vc4_state->crtc_h);
  242. + vc4_state->src_h[channel], vc4_state->crtc_h);
  243. vc4_dlist_write(vc4_state, 0xc0c0c0c0);
  244. }
  245. /* Ch0 H-TPZ Words 0-1: Scaling Parameters, Recip */
  246. - if (vc4_state->x_scaling == VC4_SCALING_TPZ) {
  247. + if (vc4_state->x_scaling[channel] == VC4_SCALING_TPZ) {
  248. vc4_write_tpz(vc4_state,
  249. - vc4_state->src_w, vc4_state->crtc_w);
  250. + vc4_state->src_w[channel], vc4_state->crtc_w);
  251. }
  252. /* Ch0 V-TPZ Words 0-2: Scaling Parameters, Recip, Context */
  253. - if (vc4_state->y_scaling == VC4_SCALING_TPZ) {
  254. + if (vc4_state->y_scaling[channel] == VC4_SCALING_TPZ) {
  255. vc4_write_tpz(vc4_state,
  256. - vc4_state->src_h, vc4_state->crtc_h);
  257. + vc4_state->src_h[channel], vc4_state->crtc_h);
  258. vc4_dlist_write(vc4_state, 0xc0c0c0c0);
  259. }
  260. }
  261. @@ -401,13 +487,13 @@ static int vc4_plane_mode_set(struct drm
  262. struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
  263. struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
  264. struct drm_framebuffer *fb = state->fb;
  265. - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
  266. u32 ctl0_offset = vc4_state->dlist_count;
  267. const struct hvs_format *format = vc4_get_hvs_format(fb->pixel_format);
  268. - u32 scl;
  269. + int num_planes = drm_format_num_planes(format->drm);
  270. + u32 scl0, scl1;
  271. u32 lbm_size;
  272. unsigned long irqflags;
  273. - int ret;
  274. + int ret, i;
  275. ret = vc4_plane_setup_clipping_and_scaling(state);
  276. if (ret)
  277. @@ -432,7 +518,19 @@ static int vc4_plane_mode_set(struct drm
  278. if (ret)
  279. return ret;
  280. - scl = vc4_get_scl_field(state);
  281. + /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB
  282. + * and 4:4:4, scl1 should be set to scl0 so both channels of
  283. + * the scaler do the same thing. For YUV, the Y plane needs
  284. + * to be put in channel 1 and Cb/Cr in channel 0, so we swap
  285. + * the scl fields here.
  286. + */
  287. + if (num_planes == 1) {
  288. + scl0 = vc4_get_scl_field(state, 1);
  289. + scl1 = scl0;
  290. + } else {
  291. + scl0 = vc4_get_scl_field(state, 1);
  292. + scl1 = vc4_get_scl_field(state, 0);
  293. + }
  294. /* Control word */
  295. vc4_dlist_write(vc4_state,
  296. @@ -440,8 +538,8 @@ static int vc4_plane_mode_set(struct drm
  297. (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
  298. (format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
  299. (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
  300. - VC4_SET_FIELD(scl, SCALER_CTL0_SCL0) |
  301. - VC4_SET_FIELD(scl, SCALER_CTL0_SCL1));
  302. + VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
  303. + VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
  304. /* Position Word 0: Image Positions and Alpha Value */
  305. vc4_state->pos0_offset = vc4_state->dlist_count;
  306. @@ -466,35 +564,68 @@ static int vc4_plane_mode_set(struct drm
  307. SCALER_POS2_ALPHA_MODE_PIPELINE :
  308. SCALER_POS2_ALPHA_MODE_FIXED,
  309. SCALER_POS2_ALPHA_MODE) |
  310. - VC4_SET_FIELD(vc4_state->src_w, SCALER_POS2_WIDTH) |
  311. - VC4_SET_FIELD(vc4_state->src_h, SCALER_POS2_HEIGHT));
  312. + VC4_SET_FIELD(vc4_state->src_w[0], SCALER_POS2_WIDTH) |
  313. + VC4_SET_FIELD(vc4_state->src_h[0], SCALER_POS2_HEIGHT));
  314. /* Position Word 3: Context. Written by the HVS. */
  315. vc4_dlist_write(vc4_state, 0xc0c0c0c0);
  316. - /* Pointer Word 0: RGB / Y Pointer */
  317. +
  318. + /* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers
  319. + *
  320. + * The pointers may be any byte address.
  321. + */
  322. vc4_state->ptr0_offset = vc4_state->dlist_count;
  323. - vc4_dlist_write(vc4_state, bo->paddr + vc4_state->offset);
  324. + if (!format->flip_cbcr) {
  325. + for (i = 0; i < num_planes; i++)
  326. + vc4_dlist_write(vc4_state, vc4_state->offsets[i]);
  327. + } else {
  328. + WARN_ON_ONCE(num_planes != 3);
  329. + vc4_dlist_write(vc4_state, vc4_state->offsets[0]);
  330. + vc4_dlist_write(vc4_state, vc4_state->offsets[2]);
  331. + vc4_dlist_write(vc4_state, vc4_state->offsets[1]);
  332. + }
  333. - /* Pointer Context Word 0: Written by the HVS */
  334. - vc4_dlist_write(vc4_state, 0xc0c0c0c0);
  335. + /* Pointer Context Word 0/1/2: Written by the HVS */
  336. + for (i = 0; i < num_planes; i++)
  337. + vc4_dlist_write(vc4_state, 0xc0c0c0c0);
  338. - /* Pitch word 0: Pointer 0 Pitch */
  339. - vc4_dlist_write(vc4_state,
  340. - VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH));
  341. + /* Pitch word 0/1/2 */
  342. + for (i = 0; i < num_planes; i++) {
  343. + vc4_dlist_write(vc4_state,
  344. + VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH));
  345. + }
  346. +
  347. + /* Colorspace conversion words */
  348. + if (vc4_state->is_yuv) {
  349. + vc4_dlist_write(vc4_state, SCALER_CSC0_ITR_R_601_5);
  350. + vc4_dlist_write(vc4_state, SCALER_CSC1_ITR_R_601_5);
  351. + vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5);
  352. + }
  353. if (!vc4_state->is_unity) {
  354. /* LBM Base Address. */
  355. - if (vc4_state->y_scaling != VC4_SCALING_NONE)
  356. + if (vc4_state->y_scaling[0] != VC4_SCALING_NONE ||
  357. + vc4_state->y_scaling[1] != VC4_SCALING_NONE) {
  358. vc4_dlist_write(vc4_state, vc4_state->lbm.start);
  359. + }
  360. - vc4_write_scaling_parameters(state);
  361. + if (num_planes > 1) {
  362. + /* Emit Cb/Cr as channel 0 and Y as channel
  363. + * 1. This matches how we set up scl0/scl1
  364. + * above.
  365. + */
  366. + vc4_write_scaling_parameters(state, 1);
  367. + }
  368. + vc4_write_scaling_parameters(state, 0);
  369. /* If any PPF setup was done, then all the kernel
  370. * pointers get uploaded.
  371. */
  372. - if (vc4_state->x_scaling == VC4_SCALING_PPF ||
  373. - vc4_state->y_scaling == VC4_SCALING_PPF) {
  374. + if (vc4_state->x_scaling[0] == VC4_SCALING_PPF ||
  375. + vc4_state->y_scaling[0] == VC4_SCALING_PPF ||
  376. + vc4_state->x_scaling[1] == VC4_SCALING_PPF ||
  377. + vc4_state->y_scaling[1] == VC4_SCALING_PPF) {
  378. u32 kernel = VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start,
  379. SCALER_PPF_KERNEL_OFFSET);
  380. @@ -698,6 +829,7 @@ struct drm_plane *vc4_plane_init(struct
  381. struct drm_plane *plane = NULL;
  382. struct vc4_plane *vc4_plane;
  383. u32 formats[ARRAY_SIZE(hvs_formats)];
  384. + u32 num_formats = 0;
  385. int ret = 0;
  386. unsigned i;
  387. @@ -708,12 +840,20 @@ struct drm_plane *vc4_plane_init(struct
  388. goto fail;
  389. }
  390. - for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
  391. - formats[i] = hvs_formats[i].drm;
  392. + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
  393. + /* Don't allow YUV in cursor planes, since that means
  394. + * tuning on the scaler, which we don't allow for the
  395. + * cursor.
  396. + */
  397. + if (type != DRM_PLANE_TYPE_CURSOR ||
  398. + hvs_formats[i].hvs < HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE) {
  399. + formats[num_formats++] = hvs_formats[i].drm;
  400. + }
  401. + }
  402. plane = &vc4_plane->base;
  403. ret = drm_universal_plane_init(dev, plane, 0xff,
  404. &vc4_plane_funcs,
  405. - formats, ARRAY_SIZE(formats),
  406. + formats, num_formats,
  407. type);
  408. drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
  409. --- a/drivers/gpu/drm/vc4/vc4_regs.h
  410. +++ b/drivers/gpu/drm/vc4/vc4_regs.h
  411. @@ -503,7 +503,12 @@ enum hvs_pixel_format {
  412. HVS_PIXEL_FORMAT_RGB888 = 5,
  413. HVS_PIXEL_FORMAT_RGBA6666 = 6,
  414. /* 32bpp */
  415. - HVS_PIXEL_FORMAT_RGBA8888 = 7
  416. + HVS_PIXEL_FORMAT_RGBA8888 = 7,
  417. +
  418. + HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE = 8,
  419. + HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE = 9,
  420. + HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE = 10,
  421. + HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE = 11,
  422. };
  423. /* Note: the LSB is the rightmost character shown. Only valid for
  424. @@ -585,6 +590,55 @@ enum hvs_pixel_format {
  425. #define SCALER_POS2_WIDTH_MASK VC4_MASK(11, 0)
  426. #define SCALER_POS2_WIDTH_SHIFT 0
  427. +/* Color Space Conversion words. Some values are S2.8 signed
  428. + * integers, except that the 2 integer bits map as {0x0: 0, 0x1: 1,
  429. + * 0x2: 2, 0x3: -1}
  430. + */
  431. +/* bottom 8 bits of S2.8 contribution of Cr to Blue */
  432. +#define SCALER_CSC0_COEF_CR_BLU_MASK VC4_MASK(31, 24)
  433. +#define SCALER_CSC0_COEF_CR_BLU_SHIFT 24
  434. +/* Signed offset to apply to Y before CSC. (Y' = Y + YY_OFS) */
  435. +#define SCALER_CSC0_COEF_YY_OFS_MASK VC4_MASK(23, 16)
  436. +#define SCALER_CSC0_COEF_YY_OFS_SHIFT 16
  437. +/* Signed offset to apply to CB before CSC (Cb' = Cb - 128 + CB_OFS). */
  438. +#define SCALER_CSC0_COEF_CB_OFS_MASK VC4_MASK(15, 8)
  439. +#define SCALER_CSC0_COEF_CB_OFS_SHIFT 8
  440. +/* Signed offset to apply to CB before CSC (Cr' = Cr - 128 + CR_OFS). */
  441. +#define SCALER_CSC0_COEF_CR_OFS_MASK VC4_MASK(7, 0)
  442. +#define SCALER_CSC0_COEF_CR_OFS_SHIFT 0
  443. +#define SCALER_CSC0_ITR_R_601_5 0x00f00000
  444. +#define SCALER_CSC0_ITR_R_709_3 0x00f00000
  445. +#define SCALER_CSC0_JPEG_JFIF 0x00000000
  446. +
  447. +/* S2.8 contribution of Cb to Green */
  448. +#define SCALER_CSC1_COEF_CB_GRN_MASK VC4_MASK(31, 22)
  449. +#define SCALER_CSC1_COEF_CB_GRN_SHIFT 22
  450. +/* S2.8 contribution of Cr to Green */
  451. +#define SCALER_CSC1_COEF_CR_GRN_MASK VC4_MASK(21, 12)
  452. +#define SCALER_CSC1_COEF_CR_GRN_SHIFT 12
  453. +/* S2.8 contribution of Y to all of RGB */
  454. +#define SCALER_CSC1_COEF_YY_ALL_MASK VC4_MASK(11, 2)
  455. +#define SCALER_CSC1_COEF_YY_ALL_SHIFT 2
  456. +/* top 2 bits of S2.8 contribution of Cr to Blue */
  457. +#define SCALER_CSC1_COEF_CR_BLU_MASK VC4_MASK(1, 0)
  458. +#define SCALER_CSC1_COEF_CR_BLU_SHIFT 0
  459. +#define SCALER_CSC1_ITR_R_601_5 0xe73304a8
  460. +#define SCALER_CSC1_ITR_R_709_3 0xf2b784a8
  461. +#define SCALER_CSC1_JPEG_JFIF 0xea34a400
  462. +
  463. +/* S2.8 contribution of Cb to Red */
  464. +#define SCALER_CSC2_COEF_CB_RED_MASK VC4_MASK(29, 20)
  465. +#define SCALER_CSC2_COEF_CB_RED_SHIFT 20
  466. +/* S2.8 contribution of Cr to Red */
  467. +#define SCALER_CSC2_COEF_CR_RED_MASK VC4_MASK(19, 10)
  468. +#define SCALER_CSC2_COEF_CR_RED_SHIFT 10
  469. +/* S2.8 contribution of Cb to Blue */
  470. +#define SCALER_CSC2_COEF_CB_BLU_MASK VC4_MASK(19, 10)
  471. +#define SCALER_CSC2_COEF_CB_BLU_SHIFT 10
  472. +#define SCALER_CSC2_ITR_R_601_5 0x00066204
  473. +#define SCALER_CSC2_ITR_R_709_3 0x00072a1c
  474. +#define SCALER_CSC2_JPEG_JFIF 0x000599c5
  475. +
  476. #define SCALER_TPZ0_VERT_RECALC BIT(31)
  477. #define SCALER_TPZ0_SCALE_MASK VC4_MASK(28, 8)
  478. #define SCALER_TPZ0_SCALE_SHIFT 8