dpu_formats.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
  13. #include <uapi/drm/drm_fourcc.h>
  14. #include "msm_media_info.h"
  15. #include "dpu_kms.h"
  16. #include "dpu_formats.h"
  17. #define DPU_UBWC_META_MACRO_W_H 16
  18. #define DPU_UBWC_META_BLOCK_SIZE 256
  19. #define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096
  20. #define DPU_TILE_HEIGHT_DEFAULT 1
  21. #define DPU_TILE_HEIGHT_TILED 4
  22. #define DPU_TILE_HEIGHT_UBWC 4
  23. #define DPU_TILE_HEIGHT_NV12 8
  24. #define DPU_MAX_IMG_WIDTH 0x3FFF
  25. #define DPU_MAX_IMG_HEIGHT 0x3FFF
  26. /**
  27. * DPU supported format packing, bpp, and other format
  28. * information.
  29. * DPU currently only supports interleaved RGB formats
  30. * UBWC support for a pixel format is indicated by the flag,
  31. * there is additional meta data plane for such formats
  32. */
  33. #define INTERLEAVED_RGB_FMT(fmt, a, r, g, b, e0, e1, e2, e3, uc, alpha, \
  34. bp, flg, fm, np) \
  35. { \
  36. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  37. .fetch_planes = DPU_PLANE_INTERLEAVED, \
  38. .alpha_enable = alpha, \
  39. .element = { (e0), (e1), (e2), (e3) }, \
  40. .bits = { g, b, r, a }, \
  41. .chroma_sample = DPU_CHROMA_RGB, \
  42. .unpack_align_msb = 0, \
  43. .unpack_tight = 1, \
  44. .unpack_count = uc, \
  45. .bpp = bp, \
  46. .fetch_mode = fm, \
  47. .flag = {(flg)}, \
  48. .num_planes = np, \
  49. .tile_height = DPU_TILE_HEIGHT_DEFAULT \
  50. }
  51. #define INTERLEAVED_RGB_FMT_TILED(fmt, a, r, g, b, e0, e1, e2, e3, uc, \
  52. alpha, bp, flg, fm, np, th) \
  53. { \
  54. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  55. .fetch_planes = DPU_PLANE_INTERLEAVED, \
  56. .alpha_enable = alpha, \
  57. .element = { (e0), (e1), (e2), (e3) }, \
  58. .bits = { g, b, r, a }, \
  59. .chroma_sample = DPU_CHROMA_RGB, \
  60. .unpack_align_msb = 0, \
  61. .unpack_tight = 1, \
  62. .unpack_count = uc, \
  63. .bpp = bp, \
  64. .fetch_mode = fm, \
  65. .flag = {(flg)}, \
  66. .num_planes = np, \
  67. .tile_height = th \
  68. }
  69. #define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \
  70. alpha, chroma, count, bp, flg, fm, np) \
  71. { \
  72. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  73. .fetch_planes = DPU_PLANE_INTERLEAVED, \
  74. .alpha_enable = alpha, \
  75. .element = { (e0), (e1), (e2), (e3)}, \
  76. .bits = { g, b, r, a }, \
  77. .chroma_sample = chroma, \
  78. .unpack_align_msb = 0, \
  79. .unpack_tight = 1, \
  80. .unpack_count = count, \
  81. .bpp = bp, \
  82. .fetch_mode = fm, \
  83. .flag = {(flg)}, \
  84. .num_planes = np, \
  85. .tile_height = DPU_TILE_HEIGHT_DEFAULT \
  86. }
  87. #define PSEUDO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np) \
  88. { \
  89. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  90. .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
  91. .alpha_enable = false, \
  92. .element = { (e0), (e1), 0, 0 }, \
  93. .bits = { g, b, r, a }, \
  94. .chroma_sample = chroma, \
  95. .unpack_align_msb = 0, \
  96. .unpack_tight = 1, \
  97. .unpack_count = 2, \
  98. .bpp = 2, \
  99. .fetch_mode = fm, \
  100. .flag = {(flg)}, \
  101. .num_planes = np, \
  102. .tile_height = DPU_TILE_HEIGHT_DEFAULT \
  103. }
  104. #define PSEUDO_YUV_FMT_TILED(fmt, a, r, g, b, e0, e1, chroma, \
  105. flg, fm, np, th) \
  106. { \
  107. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  108. .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
  109. .alpha_enable = false, \
  110. .element = { (e0), (e1), 0, 0 }, \
  111. .bits = { g, b, r, a }, \
  112. .chroma_sample = chroma, \
  113. .unpack_align_msb = 0, \
  114. .unpack_tight = 1, \
  115. .unpack_count = 2, \
  116. .bpp = 2, \
  117. .fetch_mode = fm, \
  118. .flag = {(flg)}, \
  119. .num_planes = np, \
  120. .tile_height = th \
  121. }
  122. #define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\
  123. { \
  124. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  125. .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
  126. .alpha_enable = false, \
  127. .element = { (e0), (e1), 0, 0 }, \
  128. .bits = { g, b, r, a }, \
  129. .chroma_sample = chroma, \
  130. .unpack_align_msb = 1, \
  131. .unpack_tight = 0, \
  132. .unpack_count = 2, \
  133. .bpp = 2, \
  134. .fetch_mode = fm, \
  135. .flag = {(flg)}, \
  136. .num_planes = np, \
  137. .tile_height = DPU_TILE_HEIGHT_DEFAULT \
  138. }
  139. #define PSEUDO_YUV_FMT_LOOSE_TILED(fmt, a, r, g, b, e0, e1, chroma, \
  140. flg, fm, np, th) \
  141. { \
  142. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  143. .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
  144. .alpha_enable = false, \
  145. .element = { (e0), (e1), 0, 0 }, \
  146. .bits = { g, b, r, a }, \
  147. .chroma_sample = chroma, \
  148. .unpack_align_msb = 1, \
  149. .unpack_tight = 0, \
  150. .unpack_count = 2, \
  151. .bpp = 2, \
  152. .fetch_mode = fm, \
  153. .flag = {(flg)}, \
  154. .num_planes = np, \
  155. .tile_height = th \
  156. }
  157. #define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, \
  158. flg, fm, np) \
  159. { \
  160. .base.pixel_format = DRM_FORMAT_ ## fmt, \
  161. .fetch_planes = DPU_PLANE_PLANAR, \
  162. .alpha_enable = alpha, \
  163. .element = { (e0), (e1), (e2), 0 }, \
  164. .bits = { g, b, r, a }, \
  165. .chroma_sample = chroma, \
  166. .unpack_align_msb = 0, \
  167. .unpack_tight = 1, \
  168. .unpack_count = 1, \
  169. .bpp = bp, \
  170. .fetch_mode = fm, \
  171. .flag = {(flg)}, \
  172. .num_planes = np, \
  173. .tile_height = DPU_TILE_HEIGHT_DEFAULT \
  174. }
  175. /*
  176. * struct dpu_media_color_map - maps drm format to media format
  177. * @format: DRM base pixel format
  178. * @color: Media API color related to DRM format
  179. */
  180. struct dpu_media_color_map {
  181. uint32_t format;
  182. uint32_t color;
  183. };
  184. static const struct dpu_format dpu_format_map[] = {
  185. INTERLEAVED_RGB_FMT(ARGB8888,
  186. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  187. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  188. true, 4, 0,
  189. DPU_FETCH_LINEAR, 1),
  190. INTERLEAVED_RGB_FMT(ABGR8888,
  191. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  192. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  193. true, 4, 0,
  194. DPU_FETCH_LINEAR, 1),
  195. INTERLEAVED_RGB_FMT(XBGR8888,
  196. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  197. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  198. false, 4, 0,
  199. DPU_FETCH_LINEAR, 1),
  200. INTERLEAVED_RGB_FMT(RGBA8888,
  201. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  202. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  203. true, 4, 0,
  204. DPU_FETCH_LINEAR, 1),
  205. INTERLEAVED_RGB_FMT(BGRA8888,
  206. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  207. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  208. true, 4, 0,
  209. DPU_FETCH_LINEAR, 1),
  210. INTERLEAVED_RGB_FMT(BGRX8888,
  211. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  212. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  213. false, 4, 0,
  214. DPU_FETCH_LINEAR, 1),
  215. INTERLEAVED_RGB_FMT(XRGB8888,
  216. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  217. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  218. false, 4, 0,
  219. DPU_FETCH_LINEAR, 1),
  220. INTERLEAVED_RGB_FMT(RGBX8888,
  221. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  222. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  223. false, 4, 0,
  224. DPU_FETCH_LINEAR, 1),
  225. INTERLEAVED_RGB_FMT(RGB888,
  226. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  227. C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
  228. false, 3, 0,
  229. DPU_FETCH_LINEAR, 1),
  230. INTERLEAVED_RGB_FMT(BGR888,
  231. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  232. C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
  233. false, 3, 0,
  234. DPU_FETCH_LINEAR, 1),
  235. INTERLEAVED_RGB_FMT(RGB565,
  236. 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
  237. C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
  238. false, 2, 0,
  239. DPU_FETCH_LINEAR, 1),
  240. INTERLEAVED_RGB_FMT(BGR565,
  241. 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
  242. C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
  243. false, 2, 0,
  244. DPU_FETCH_LINEAR, 1),
  245. INTERLEAVED_RGB_FMT(ARGB1555,
  246. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  247. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  248. true, 2, 0,
  249. DPU_FETCH_LINEAR, 1),
  250. INTERLEAVED_RGB_FMT(ABGR1555,
  251. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  252. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  253. true, 2, 0,
  254. DPU_FETCH_LINEAR, 1),
  255. INTERLEAVED_RGB_FMT(RGBA5551,
  256. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  257. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  258. true, 2, 0,
  259. DPU_FETCH_LINEAR, 1),
  260. INTERLEAVED_RGB_FMT(BGRA5551,
  261. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  262. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  263. true, 2, 0,
  264. DPU_FETCH_LINEAR, 1),
  265. INTERLEAVED_RGB_FMT(XRGB1555,
  266. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  267. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  268. false, 2, 0,
  269. DPU_FETCH_LINEAR, 1),
  270. INTERLEAVED_RGB_FMT(XBGR1555,
  271. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  272. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  273. false, 2, 0,
  274. DPU_FETCH_LINEAR, 1),
  275. INTERLEAVED_RGB_FMT(RGBX5551,
  276. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  277. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  278. false, 2, 0,
  279. DPU_FETCH_LINEAR, 1),
  280. INTERLEAVED_RGB_FMT(BGRX5551,
  281. COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
  282. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  283. false, 2, 0,
  284. DPU_FETCH_LINEAR, 1),
  285. INTERLEAVED_RGB_FMT(ARGB4444,
  286. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  287. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  288. true, 2, 0,
  289. DPU_FETCH_LINEAR, 1),
  290. INTERLEAVED_RGB_FMT(ABGR4444,
  291. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  292. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  293. true, 2, 0,
  294. DPU_FETCH_LINEAR, 1),
  295. INTERLEAVED_RGB_FMT(RGBA4444,
  296. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  297. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  298. true, 2, 0,
  299. DPU_FETCH_LINEAR, 1),
  300. INTERLEAVED_RGB_FMT(BGRA4444,
  301. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  302. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  303. true, 2, 0,
  304. DPU_FETCH_LINEAR, 1),
  305. INTERLEAVED_RGB_FMT(XRGB4444,
  306. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  307. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  308. false, 2, 0,
  309. DPU_FETCH_LINEAR, 1),
  310. INTERLEAVED_RGB_FMT(XBGR4444,
  311. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  312. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  313. false, 2, 0,
  314. DPU_FETCH_LINEAR, 1),
  315. INTERLEAVED_RGB_FMT(RGBX4444,
  316. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  317. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  318. false, 2, 0,
  319. DPU_FETCH_LINEAR, 1),
  320. INTERLEAVED_RGB_FMT(BGRX4444,
  321. COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
  322. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  323. false, 2, 0,
  324. DPU_FETCH_LINEAR, 1),
  325. INTERLEAVED_RGB_FMT(BGRA1010102,
  326. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  327. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  328. true, 4, DPU_FORMAT_FLAG_DX,
  329. DPU_FETCH_LINEAR, 1),
  330. INTERLEAVED_RGB_FMT(RGBA1010102,
  331. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  332. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  333. true, 4, DPU_FORMAT_FLAG_DX,
  334. DPU_FETCH_LINEAR, 1),
  335. INTERLEAVED_RGB_FMT(ABGR2101010,
  336. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  337. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  338. true, 4, DPU_FORMAT_FLAG_DX,
  339. DPU_FETCH_LINEAR, 1),
  340. INTERLEAVED_RGB_FMT(ARGB2101010,
  341. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  342. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  343. true, 4, DPU_FORMAT_FLAG_DX,
  344. DPU_FETCH_LINEAR, 1),
  345. INTERLEAVED_RGB_FMT(XRGB2101010,
  346. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  347. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  348. false, 4, DPU_FORMAT_FLAG_DX,
  349. DPU_FETCH_LINEAR, 1),
  350. INTERLEAVED_RGB_FMT(BGRX1010102,
  351. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  352. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  353. false, 4, DPU_FORMAT_FLAG_DX,
  354. DPU_FETCH_LINEAR, 1),
  355. INTERLEAVED_RGB_FMT(XBGR2101010,
  356. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  357. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  358. false, 4, DPU_FORMAT_FLAG_DX,
  359. DPU_FETCH_LINEAR, 1),
  360. INTERLEAVED_RGB_FMT(RGBX1010102,
  361. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  362. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  363. false, 4, DPU_FORMAT_FLAG_DX,
  364. DPU_FETCH_LINEAR, 1),
  365. PSEUDO_YUV_FMT(NV12,
  366. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  367. C1_B_Cb, C2_R_Cr,
  368. DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
  369. DPU_FETCH_LINEAR, 2),
  370. PSEUDO_YUV_FMT(NV21,
  371. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  372. C2_R_Cr, C1_B_Cb,
  373. DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
  374. DPU_FETCH_LINEAR, 2),
  375. PSEUDO_YUV_FMT(NV16,
  376. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  377. C1_B_Cb, C2_R_Cr,
  378. DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
  379. DPU_FETCH_LINEAR, 2),
  380. PSEUDO_YUV_FMT(NV61,
  381. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  382. C2_R_Cr, C1_B_Cb,
  383. DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
  384. DPU_FETCH_LINEAR, 2),
  385. INTERLEAVED_YUV_FMT(VYUY,
  386. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  387. C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y,
  388. false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
  389. DPU_FETCH_LINEAR, 2),
  390. INTERLEAVED_YUV_FMT(UYVY,
  391. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  392. C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y,
  393. false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
  394. DPU_FETCH_LINEAR, 2),
  395. INTERLEAVED_YUV_FMT(YUYV,
  396. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  397. C0_G_Y, C1_B_Cb, C0_G_Y, C2_R_Cr,
  398. false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
  399. DPU_FETCH_LINEAR, 2),
  400. INTERLEAVED_YUV_FMT(YVYU,
  401. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  402. C0_G_Y, C2_R_Cr, C0_G_Y, C1_B_Cb,
  403. false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
  404. DPU_FETCH_LINEAR, 2),
  405. PLANAR_YUV_FMT(YUV420,
  406. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  407. C2_R_Cr, C1_B_Cb, C0_G_Y,
  408. false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV,
  409. DPU_FETCH_LINEAR, 3),
  410. PLANAR_YUV_FMT(YVU420,
  411. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  412. C1_B_Cb, C2_R_Cr, C0_G_Y,
  413. false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV,
  414. DPU_FETCH_LINEAR, 3),
  415. };
  416. /*
  417. * A5x tile formats tables:
  418. * These tables hold the A5x tile formats supported.
  419. */
  420. static const struct dpu_format dpu_format_map_tile[] = {
  421. INTERLEAVED_RGB_FMT_TILED(BGR565,
  422. 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
  423. C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
  424. false, 2, 0,
  425. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  426. INTERLEAVED_RGB_FMT_TILED(ARGB8888,
  427. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  428. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  429. true, 4, 0,
  430. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  431. INTERLEAVED_RGB_FMT_TILED(ABGR8888,
  432. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  433. C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
  434. true, 4, 0,
  435. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  436. INTERLEAVED_RGB_FMT_TILED(XBGR8888,
  437. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  438. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  439. false, 4, 0,
  440. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  441. INTERLEAVED_RGB_FMT_TILED(RGBA8888,
  442. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  443. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  444. true, 4, 0,
  445. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  446. INTERLEAVED_RGB_FMT_TILED(BGRA8888,
  447. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  448. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  449. true, 4, 0,
  450. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  451. INTERLEAVED_RGB_FMT_TILED(BGRX8888,
  452. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  453. C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
  454. false, 4, 0,
  455. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  456. INTERLEAVED_RGB_FMT_TILED(XRGB8888,
  457. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  458. C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
  459. false, 4, 0,
  460. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  461. INTERLEAVED_RGB_FMT_TILED(RGBX8888,
  462. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  463. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  464. false, 4, 0,
  465. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  466. INTERLEAVED_RGB_FMT_TILED(ABGR2101010,
  467. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  468. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  469. true, 4, DPU_FORMAT_FLAG_DX,
  470. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  471. INTERLEAVED_RGB_FMT_TILED(XBGR2101010,
  472. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  473. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  474. true, 4, DPU_FORMAT_FLAG_DX,
  475. DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
  476. PSEUDO_YUV_FMT_TILED(NV12,
  477. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  478. C1_B_Cb, C2_R_Cr,
  479. DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
  480. DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12),
  481. PSEUDO_YUV_FMT_TILED(NV21,
  482. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  483. C2_R_Cr, C1_B_Cb,
  484. DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
  485. DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12),
  486. };
  487. /*
  488. * UBWC formats table:
  489. * This table holds the UBWC formats supported.
  490. * If a compression ratio needs to be used for this or any other format,
  491. * the data will be passed by user-space.
  492. */
  493. static const struct dpu_format dpu_format_map_ubwc[] = {
  494. INTERLEAVED_RGB_FMT_TILED(BGR565,
  495. 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
  496. C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
  497. false, 2, DPU_FORMAT_FLAG_COMPRESSED,
  498. DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
  499. INTERLEAVED_RGB_FMT_TILED(ABGR8888,
  500. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  501. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  502. true, 4, DPU_FORMAT_FLAG_COMPRESSED,
  503. DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
  504. INTERLEAVED_RGB_FMT_TILED(XBGR8888,
  505. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  506. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  507. false, 4, DPU_FORMAT_FLAG_COMPRESSED,
  508. DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
  509. INTERLEAVED_RGB_FMT_TILED(ABGR2101010,
  510. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  511. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  512. true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
  513. DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
  514. INTERLEAVED_RGB_FMT_TILED(XBGR2101010,
  515. COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  516. C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
  517. true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
  518. DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
  519. PSEUDO_YUV_FMT_TILED(NV12,
  520. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  521. C1_B_Cb, C2_R_Cr,
  522. DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV |
  523. DPU_FORMAT_FLAG_COMPRESSED,
  524. DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
  525. };
  526. static const struct dpu_format dpu_format_map_p010[] = {
  527. PSEUDO_YUV_FMT_LOOSE(NV12,
  528. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  529. C1_B_Cb, C2_R_Cr,
  530. DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX),
  531. DPU_FETCH_LINEAR, 2),
  532. };
  533. static const struct dpu_format dpu_format_map_p010_ubwc[] = {
  534. PSEUDO_YUV_FMT_LOOSE_TILED(NV12,
  535. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  536. C1_B_Cb, C2_R_Cr,
  537. DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX |
  538. DPU_FORMAT_FLAG_COMPRESSED),
  539. DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
  540. };
  541. static const struct dpu_format dpu_format_map_tp10_ubwc[] = {
  542. PSEUDO_YUV_FMT_TILED(NV12,
  543. 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
  544. C1_B_Cb, C2_R_Cr,
  545. DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX |
  546. DPU_FORMAT_FLAG_COMPRESSED),
  547. DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
  548. };
  549. /* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
  550. * Note: Not using the drm_format_*_subsampling since we have formats
  551. */
  552. static void _dpu_get_v_h_subsample_rate(
  553. enum dpu_chroma_samp_type chroma_sample,
  554. uint32_t *v_sample,
  555. uint32_t *h_sample)
  556. {
  557. if (!v_sample || !h_sample)
  558. return;
  559. switch (chroma_sample) {
  560. case DPU_CHROMA_H2V1:
  561. *v_sample = 1;
  562. *h_sample = 2;
  563. break;
  564. case DPU_CHROMA_H1V2:
  565. *v_sample = 2;
  566. *h_sample = 1;
  567. break;
  568. case DPU_CHROMA_420:
  569. *v_sample = 2;
  570. *h_sample = 2;
  571. break;
  572. default:
  573. *v_sample = 1;
  574. *h_sample = 1;
  575. break;
  576. }
  577. }
  578. static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt)
  579. {
  580. static const struct dpu_media_color_map dpu_media_ubwc_map[] = {
  581. {DRM_FORMAT_ABGR8888, COLOR_FMT_RGBA8888_UBWC},
  582. {DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
  583. {DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
  584. {DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
  585. {DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
  586. };
  587. int color_fmt = -1;
  588. int i;
  589. if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
  590. if (DPU_FORMAT_IS_DX(fmt)) {
  591. if (fmt->unpack_tight)
  592. color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
  593. else
  594. color_fmt = COLOR_FMT_P010_UBWC;
  595. } else
  596. color_fmt = COLOR_FMT_NV12_UBWC;
  597. return color_fmt;
  598. }
  599. for (i = 0; i < ARRAY_SIZE(dpu_media_ubwc_map); ++i)
  600. if (fmt->base.pixel_format == dpu_media_ubwc_map[i].format) {
  601. color_fmt = dpu_media_ubwc_map[i].color;
  602. break;
  603. }
  604. return color_fmt;
  605. }
  606. static int _dpu_format_get_plane_sizes_ubwc(
  607. const struct dpu_format *fmt,
  608. const uint32_t width,
  609. const uint32_t height,
  610. struct dpu_hw_fmt_layout *layout)
  611. {
  612. int i;
  613. int color;
  614. bool meta = DPU_FORMAT_IS_UBWC(fmt);
  615. memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
  616. layout->format = fmt;
  617. layout->width = width;
  618. layout->height = height;
  619. layout->num_planes = fmt->num_planes;
  620. color = _dpu_format_get_media_color_ubwc(fmt);
  621. if (color < 0) {
  622. DRM_ERROR("UBWC format not supported for fmt: %4.4s\n",
  623. (char *)&fmt->base.pixel_format);
  624. return -EINVAL;
  625. }
  626. if (DPU_FORMAT_IS_YUV(layout->format)) {
  627. uint32_t y_sclines, uv_sclines;
  628. uint32_t y_meta_scanlines = 0;
  629. uint32_t uv_meta_scanlines = 0;
  630. layout->num_planes = 2;
  631. layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
  632. y_sclines = VENUS_Y_SCANLINES(color, height);
  633. layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
  634. y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
  635. layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
  636. uv_sclines = VENUS_UV_SCANLINES(color, height);
  637. layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
  638. uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
  639. if (!meta)
  640. goto done;
  641. layout->num_planes += 2;
  642. layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
  643. y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
  644. layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
  645. y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
  646. layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
  647. uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
  648. layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
  649. uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
  650. } else {
  651. uint32_t rgb_scanlines, rgb_meta_scanlines;
  652. layout->num_planes = 1;
  653. layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
  654. rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
  655. layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
  656. rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
  657. if (!meta)
  658. goto done;
  659. layout->num_planes += 2;
  660. layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
  661. rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
  662. layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
  663. rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
  664. }
  665. done:
  666. for (i = 0; i < DPU_MAX_PLANES; i++)
  667. layout->total_size += layout->plane_size[i];
  668. return 0;
  669. }
  670. static int _dpu_format_get_plane_sizes_linear(
  671. const struct dpu_format *fmt,
  672. const uint32_t width,
  673. const uint32_t height,
  674. struct dpu_hw_fmt_layout *layout,
  675. const uint32_t *pitches)
  676. {
  677. int i;
  678. memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
  679. layout->format = fmt;
  680. layout->width = width;
  681. layout->height = height;
  682. layout->num_planes = fmt->num_planes;
  683. /* Due to memset above, only need to set planes of interest */
  684. if (fmt->fetch_planes == DPU_PLANE_INTERLEAVED) {
  685. layout->num_planes = 1;
  686. layout->plane_size[0] = width * height * layout->format->bpp;
  687. layout->plane_pitch[0] = width * layout->format->bpp;
  688. } else {
  689. uint32_t v_subsample, h_subsample;
  690. uint32_t chroma_samp;
  691. uint32_t bpp = 1;
  692. chroma_samp = fmt->chroma_sample;
  693. _dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
  694. &h_subsample);
  695. if (width % h_subsample || height % v_subsample) {
  696. DRM_ERROR("mismatch in subsample vs dimensions\n");
  697. return -EINVAL;
  698. }
  699. if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
  700. (DPU_FORMAT_IS_DX(fmt)))
  701. bpp = 2;
  702. layout->plane_pitch[0] = width * bpp;
  703. layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
  704. layout->plane_size[0] = layout->plane_pitch[0] * height;
  705. layout->plane_size[1] = layout->plane_pitch[1] *
  706. (height / v_subsample);
  707. if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) {
  708. layout->num_planes = 2;
  709. layout->plane_size[1] *= 2;
  710. layout->plane_pitch[1] *= 2;
  711. } else {
  712. /* planar */
  713. layout->num_planes = 3;
  714. layout->plane_size[2] = layout->plane_size[1];
  715. layout->plane_pitch[2] = layout->plane_pitch[1];
  716. }
  717. }
  718. /*
  719. * linear format: allow user allocated pitches if they are greater than
  720. * the requirement.
  721. * ubwc format: pitch values are computed uniformly across
  722. * all the components based on ubwc specifications.
  723. */
  724. for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) {
  725. if (pitches && layout->plane_pitch[i] < pitches[i])
  726. layout->plane_pitch[i] = pitches[i];
  727. }
  728. for (i = 0; i < DPU_MAX_PLANES; i++)
  729. layout->total_size += layout->plane_size[i];
  730. return 0;
  731. }
  732. static int dpu_format_get_plane_sizes(
  733. const struct dpu_format *fmt,
  734. const uint32_t w,
  735. const uint32_t h,
  736. struct dpu_hw_fmt_layout *layout,
  737. const uint32_t *pitches)
  738. {
  739. if (!layout || !fmt) {
  740. DRM_ERROR("invalid pointer\n");
  741. return -EINVAL;
  742. }
  743. if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
  744. DRM_ERROR("image dimensions outside max range\n");
  745. return -ERANGE;
  746. }
  747. if (DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt))
  748. return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
  749. return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
  750. }
  751. static int _dpu_format_populate_addrs_ubwc(
  752. struct msm_gem_address_space *aspace,
  753. struct drm_framebuffer *fb,
  754. struct dpu_hw_fmt_layout *layout)
  755. {
  756. uint32_t base_addr = 0;
  757. bool meta;
  758. if (!fb || !layout) {
  759. DRM_ERROR("invalid pointers\n");
  760. return -EINVAL;
  761. }
  762. if (aspace)
  763. base_addr = msm_framebuffer_iova(fb, aspace, 0);
  764. if (!base_addr) {
  765. DRM_ERROR("failed to retrieve base addr\n");
  766. return -EFAULT;
  767. }
  768. meta = DPU_FORMAT_IS_UBWC(layout->format);
  769. /* Per-format logic for verifying active planes */
  770. if (DPU_FORMAT_IS_YUV(layout->format)) {
  771. /************************************************/
  772. /* UBWC ** */
  773. /* buffer ** DPU PLANE */
  774. /* format ** */
  775. /************************************************/
  776. /* ------------------- ** -------------------- */
  777. /* | Y meta | ** | Y bitstream | */
  778. /* | data | ** | plane | */
  779. /* ------------------- ** -------------------- */
  780. /* | Y bitstream | ** | CbCr bitstream | */
  781. /* | data | ** | plane | */
  782. /* ------------------- ** -------------------- */
  783. /* | Cbcr metadata | ** | Y meta | */
  784. /* | data | ** | plane | */
  785. /* ------------------- ** -------------------- */
  786. /* | CbCr bitstream | ** | CbCr meta | */
  787. /* | data | ** | plane | */
  788. /* ------------------- ** -------------------- */
  789. /************************************************/
  790. /* configure Y bitstream plane */
  791. layout->plane_addr[0] = base_addr + layout->plane_size[2];
  792. /* configure CbCr bitstream plane */
  793. layout->plane_addr[1] = base_addr + layout->plane_size[0]
  794. + layout->plane_size[2] + layout->plane_size[3];
  795. if (!meta)
  796. goto done;
  797. /* configure Y metadata plane */
  798. layout->plane_addr[2] = base_addr;
  799. /* configure CbCr metadata plane */
  800. layout->plane_addr[3] = base_addr + layout->plane_size[0]
  801. + layout->plane_size[2];
  802. } else {
  803. /************************************************/
  804. /* UBWC ** */
  805. /* buffer ** DPU PLANE */
  806. /* format ** */
  807. /************************************************/
  808. /* ------------------- ** -------------------- */
  809. /* | RGB meta | ** | RGB bitstream | */
  810. /* | data | ** | plane | */
  811. /* ------------------- ** -------------------- */
  812. /* | RGB bitstream | ** | NONE | */
  813. /* | data | ** | | */
  814. /* ------------------- ** -------------------- */
  815. /* ** | RGB meta | */
  816. /* ** | plane | */
  817. /* ** -------------------- */
  818. /************************************************/
  819. layout->plane_addr[0] = base_addr + layout->plane_size[2];
  820. layout->plane_addr[1] = 0;
  821. if (!meta)
  822. goto done;
  823. layout->plane_addr[2] = base_addr;
  824. layout->plane_addr[3] = 0;
  825. }
  826. done:
  827. return 0;
  828. }
  829. static int _dpu_format_populate_addrs_linear(
  830. struct msm_gem_address_space *aspace,
  831. struct drm_framebuffer *fb,
  832. struct dpu_hw_fmt_layout *layout)
  833. {
  834. unsigned int i;
  835. /* Can now check the pitches given vs pitches expected */
  836. for (i = 0; i < layout->num_planes; ++i) {
  837. if (layout->plane_pitch[i] > fb->pitches[i]) {
  838. DRM_ERROR("plane %u expected pitch %u, fb %u\n",
  839. i, layout->plane_pitch[i], fb->pitches[i]);
  840. return -EINVAL;
  841. }
  842. }
  843. /* Populate addresses for simple formats here */
  844. for (i = 0; i < layout->num_planes; ++i) {
  845. if (aspace)
  846. layout->plane_addr[i] =
  847. msm_framebuffer_iova(fb, aspace, i);
  848. if (!layout->plane_addr[i]) {
  849. DRM_ERROR("failed to retrieve base addr\n");
  850. return -EFAULT;
  851. }
  852. }
  853. return 0;
  854. }
  855. int dpu_format_populate_layout(
  856. struct msm_gem_address_space *aspace,
  857. struct drm_framebuffer *fb,
  858. struct dpu_hw_fmt_layout *layout)
  859. {
  860. uint32_t plane_addr[DPU_MAX_PLANES];
  861. int i, ret;
  862. if (!fb || !layout) {
  863. DRM_ERROR("invalid arguments\n");
  864. return -EINVAL;
  865. }
  866. if ((fb->width > DPU_MAX_IMG_WIDTH) ||
  867. (fb->height > DPU_MAX_IMG_HEIGHT)) {
  868. DRM_ERROR("image dimensions outside max range\n");
  869. return -ERANGE;
  870. }
  871. layout->format = to_dpu_format(msm_framebuffer_format(fb));
  872. /* Populate the plane sizes etc via get_format */
  873. ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
  874. layout, fb->pitches);
  875. if (ret)
  876. return ret;
  877. for (i = 0; i < DPU_MAX_PLANES; ++i)
  878. plane_addr[i] = layout->plane_addr[i];
  879. /* Populate the addresses given the fb */
  880. if (DPU_FORMAT_IS_UBWC(layout->format) ||
  881. DPU_FORMAT_IS_TILE(layout->format))
  882. ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
  883. else
  884. ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
  885. /* check if anything changed */
  886. if (!ret && !memcmp(plane_addr, layout->plane_addr, sizeof(plane_addr)))
  887. ret = -EAGAIN;
  888. return ret;
  889. }
  890. int dpu_format_check_modified_format(
  891. const struct msm_kms *kms,
  892. const struct msm_format *msm_fmt,
  893. const struct drm_mode_fb_cmd2 *cmd,
  894. struct drm_gem_object **bos)
  895. {
  896. int ret, i, num_base_fmt_planes;
  897. const struct dpu_format *fmt;
  898. struct dpu_hw_fmt_layout layout;
  899. uint32_t bos_total_size = 0;
  900. if (!msm_fmt || !cmd || !bos) {
  901. DRM_ERROR("invalid arguments\n");
  902. return -EINVAL;
  903. }
  904. fmt = to_dpu_format(msm_fmt);
  905. num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format);
  906. ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
  907. &layout, cmd->pitches);
  908. if (ret)
  909. return ret;
  910. for (i = 0; i < num_base_fmt_planes; i++) {
  911. if (!bos[i]) {
  912. DRM_ERROR("invalid handle for plane %d\n", i);
  913. return -EINVAL;
  914. }
  915. if ((i == 0) || (bos[i] != bos[0]))
  916. bos_total_size += bos[i]->size;
  917. }
  918. if (bos_total_size < layout.total_size) {
  919. DRM_ERROR("buffers total size too small %u expected %u\n",
  920. bos_total_size, layout.total_size);
  921. return -EINVAL;
  922. }
  923. return 0;
  924. }
  925. const struct dpu_format *dpu_get_dpu_format_ext(
  926. const uint32_t format,
  927. const uint64_t modifier)
  928. {
  929. uint32_t i = 0;
  930. const struct dpu_format *fmt = NULL;
  931. const struct dpu_format *map = NULL;
  932. ssize_t map_size = 0;
  933. /*
  934. * Currently only support exactly zero or one modifier.
  935. * All planes use the same modifier.
  936. */
  937. DPU_DEBUG("plane format modifier 0x%llX\n", modifier);
  938. switch (modifier) {
  939. case 0:
  940. map = dpu_format_map;
  941. map_size = ARRAY_SIZE(dpu_format_map);
  942. break;
  943. case DRM_FORMAT_MOD_QCOM_COMPRESSED:
  944. map = dpu_format_map_ubwc;
  945. map_size = ARRAY_SIZE(dpu_format_map_ubwc);
  946. DPU_DEBUG("found fmt: %4.4s DRM_FORMAT_MOD_QCOM_COMPRESSED\n",
  947. (char *)&format);
  948. break;
  949. default:
  950. DPU_ERROR("unsupported format modifier %llX\n", modifier);
  951. return NULL;
  952. }
  953. for (i = 0; i < map_size; i++) {
  954. if (format == map[i].base.pixel_format) {
  955. fmt = &map[i];
  956. break;
  957. }
  958. }
  959. if (fmt == NULL)
  960. DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n",
  961. (char *)&format, modifier);
  962. else
  963. DPU_DEBUG("fmt %4.4s mod 0x%llX ubwc %d yuv %d\n",
  964. (char *)&format, modifier,
  965. DPU_FORMAT_IS_UBWC(fmt),
  966. DPU_FORMAT_IS_YUV(fmt));
  967. return fmt;
  968. }
  969. const struct msm_format *dpu_get_msm_format(
  970. struct msm_kms *kms,
  971. const uint32_t format,
  972. const uint64_t modifiers)
  973. {
  974. const struct dpu_format *fmt = dpu_get_dpu_format_ext(format,
  975. modifiers);
  976. if (fmt)
  977. return &fmt->base;
  978. return NULL;
  979. }
  980. uint32_t dpu_populate_formats(
  981. const struct dpu_format_extended *format_list,
  982. uint32_t *pixel_formats,
  983. uint64_t *pixel_modifiers,
  984. uint32_t pixel_formats_max)
  985. {
  986. uint32_t i, fourcc_format;
  987. if (!format_list || !pixel_formats)
  988. return 0;
  989. for (i = 0, fourcc_format = 0;
  990. format_list->fourcc_format && i < pixel_formats_max;
  991. ++format_list) {
  992. /* verify if listed format is in dpu_format_map? */
  993. /* optionally return modified formats */
  994. if (pixel_modifiers) {
  995. /* assume same modifier for all fb planes */
  996. pixel_formats[i] = format_list->fourcc_format;
  997. pixel_modifiers[i++] = format_list->modifier;
  998. } else {
  999. /* assume base formats grouped together */
  1000. if (fourcc_format != format_list->fourcc_format) {
  1001. fourcc_format = format_list->fourcc_format;
  1002. pixel_formats[i++] = fourcc_format;
  1003. }
  1004. }
  1005. }
  1006. return i;
  1007. }