blob: 01fe3c8f451374230d2d99e01ee0ddc191d0b3b8 [file] [log] [blame]
Alan Kwong4dd64c82017-02-04 18:41:51 -08001/* Copyright (c) 2017, 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
13#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
14
15#include <linux/mutex.h>
16#include <linux/platform_device.h>
17
18#include "sde_kms.h"
19#include "sde_hw_mdss.h"
20#include "sde_hwio.h"
21#include "sde_hw_catalog.h"
22#include "sde_hw_rot.h"
23#include "sde_formats.h"
24#include "sde_rotator_inline.h"
25
26#define SDE_MODIFLER(_modifier_) ((_modifier_) & 0x00ffffffffffffffULL)
27#define SDE_MODIFIER_IS_TILE(_modifier_) \
28 SDE_MODIFLER((_modifier_) & DRM_FORMAT_MOD_QCOM_TILE)
29#define SDE_MODIFIER_IS_UBWC(_modifier_) \
30 SDE_MODIFLER((_modifier_) & DRM_FORMAT_MOD_QCOM_COMPRESSED)
31#define SDE_MODIFIER_IS_10B(_modifier_) \
32 SDE_MODIFLER((_modifier_) & DRM_FORMAT_MOD_QCOM_DX)
33#define SDE_MODIFIER_IS_TIGHT(_modifier_) \
34 SDE_MODIFLER((_modifier_) & DRM_FORMAT_MOD_QCOM_TIGHT)
35
36/**
37 * _rot_offset - update register map of the given rotator instance
38 * @rot: rotator identifier
39 * @m: Pointer to mdss catalog
40 * @addr: i/o address mapping
41 * @b: Pointer to register block mapping structure
42 * return: Pointer to rotator configuration of the given instance
43 */
44static struct sde_rot_cfg *_rot_offset(enum sde_rot rot,
45 struct sde_mdss_cfg *m,
46 void __iomem *addr,
47 struct sde_hw_blk_reg_map *b)
48{
49 int i;
50
51 for (i = 0; i < m->rot_count; i++) {
52 if (rot == m->rot[i].id) {
53 b->base_off = addr;
54 b->blk_off = m->rot[i].base;
55 b->hwversion = m->hwversion;
56 b->log_mask = SDE_DBG_MASK_ROT;
57 return &m->rot[i];
58 }
59 }
60
61 return ERR_PTR(-EINVAL);
62}
63
64/**
65 * sde_hw_rot_start - start rotator before any commit
66 * @hw: Pointer to rotator hardware driver
67 * return: 0 if success; error code otherwise
68 */
69static int sde_hw_rot_start(struct sde_hw_rot *hw)
70{
71 struct platform_device *pdev;
72 int rc;
73
74 if (!hw || !hw->caps || !hw->caps->pdev) {
75 SDE_ERROR("invalid parameters\n");
76 return -EINVAL;
77 }
78
79 pdev = hw->caps->pdev;
80
81 hw->rot_ctx = sde_rotator_inline_open(pdev);
82 if (IS_ERR_OR_NULL(hw->rot_ctx)) {
83 rc = PTR_ERR(hw->rot_ctx);
84 hw->rot_ctx = NULL;
85 return rc;
86 }
87
88 return 0;
89}
90
91/**
92 * sde_hw_rot_stop - stop rotator after final commit
93 * @hw: Pointer to rotator hardware driver
94 * return: none
95 */
96static void sde_hw_rot_stop(struct sde_hw_rot *hw)
97{
98 if (!hw) {
99 SDE_ERROR("invalid parameter\n");
100 return;
101 }
102
103 sde_rotator_inline_release(hw->rot_ctx);
104 hw->rot_ctx = NULL;
105}
106
107/**
108 * sde_hw_rot_to_v4l2_pixfmt - convert drm pixel format to v4l2 pixel format
109 * @drm_pixfmt: drm fourcc pixel format
110 * @drm_modifier: drm pixel format modifier
111 * @pixfmt: Pointer to v4l2 fourcc pixel format (output)
112 * return: 0 if success; error code otherwise
113 */
114static int sde_hw_rot_to_v4l2_pixfmt(u32 drm_pixfmt, u64 drm_modifier,
115 u32 *pixfmt)
116{
117 u32 rc = 0;
118
119 if (!pixfmt)
120 return -EINVAL;
121
122 switch (drm_pixfmt) {
Alan Kwong75316d92017-03-31 14:12:05 -0700123 case DRM_FORMAT_BGR565:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800124 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
125 *pixfmt = SDE_PIX_FMT_RGB_565_UBWC;
126 else
127 *pixfmt = SDE_PIX_FMT_RGB_565;
128 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700129 case DRM_FORMAT_BGRA8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800130 if (SDE_MODIFIER_IS_TILE(drm_modifier))
131 *pixfmt = SDE_PIX_FMT_ARGB_8888_TILE;
132 else
133 *pixfmt = SDE_PIX_FMT_ARGB_8888;
134 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700135 case DRM_FORMAT_BGRX8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800136 if (SDE_MODIFIER_IS_TILE(drm_modifier))
137 *pixfmt = SDE_PIX_FMT_XRGB_8888_TILE;
138 else
139 *pixfmt = SDE_PIX_FMT_XRGB_8888;
140 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700141 case DRM_FORMAT_RGBA8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800142 if (SDE_MODIFIER_IS_TILE(drm_modifier))
143 *pixfmt = SDE_PIX_FMT_ABGR_8888_TILE;
144 else
145 *pixfmt = SDE_PIX_FMT_ABGR_8888;
146 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700147 case DRM_FORMAT_RGBX8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800148 if (SDE_MODIFIER_IS_TILE(drm_modifier))
149 *pixfmt = SDE_PIX_FMT_XBGR_8888_TILE;
150 else
151 *pixfmt = SDE_PIX_FMT_XBGR_8888;
152 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700153 case DRM_FORMAT_ABGR8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800154 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
155 *pixfmt = SDE_PIX_FMT_RGBA_8888_UBWC;
156 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
157 *pixfmt = SDE_PIX_FMT_RGBA_8888_TILE;
158 else
159 *pixfmt = SDE_PIX_FMT_RGBA_8888;
160 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700161 case DRM_FORMAT_XBGR8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800162 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
163 *pixfmt = SDE_PIX_FMT_RGBX_8888_UBWC;
164 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
165 *pixfmt = SDE_PIX_FMT_RGBX_8888_TILE;
166 else
167 *pixfmt = SDE_PIX_FMT_RGBX_8888;
168 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700169 case DRM_FORMAT_ARGB8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800170 if (SDE_MODIFIER_IS_TILE(drm_modifier))
171 *pixfmt = SDE_PIX_FMT_BGRA_8888_TILE;
172 else
173 *pixfmt = SDE_PIX_FMT_BGRA_8888;
174 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700175 case DRM_FORMAT_XRGB8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800176 if (SDE_MODIFIER_IS_TILE(drm_modifier))
177 *pixfmt = SDE_PIX_FMT_BGRX_8888_TILE;
178 else
179 *pixfmt = SDE_PIX_FMT_BGRX_8888;
180 break;
181 case DRM_FORMAT_NV12:
182 if (SDE_MODIFIER_IS_UBWC(drm_modifier)) {
Alan Kwong87847ce2017-02-21 08:34:31 -0800183 if (SDE_MODIFIER_IS_10B(drm_modifier)) {
184 if (SDE_MODIFIER_IS_TIGHT(drm_modifier))
185 *pixfmt =
186 SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC;
187 else
188 *pixfmt =
189 SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC;
190 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -0800191 *pixfmt = SDE_PIX_FMT_Y_CBCR_H2V2_UBWC;
Alan Kwong87847ce2017-02-21 08:34:31 -0800192 }
Alan Kwong4dd64c82017-02-04 18:41:51 -0800193 } else if (SDE_MODIFIER_IS_TILE(drm_modifier)) {
194 if (SDE_MODIFIER_IS_10B(drm_modifier)) {
195 if (SDE_MODIFIER_IS_TIGHT(drm_modifier))
196 *pixfmt =
197 SDE_PIX_FMT_Y_CBCR_H2V2_TP10;
198 else
199 *pixfmt =
200 SDE_PIX_FMT_Y_CBCR_H2V2_P010_TILE;
201 } else {
202 *pixfmt = SDE_PIX_FMT_Y_CBCR_H2V2_TILE;
203 }
204 } else {
205 if (SDE_MODIFIER_IS_10B(drm_modifier)) {
206 if (SDE_MODIFIER_IS_TIGHT(drm_modifier))
207 *pixfmt =
208 SDE_PIX_FMT_Y_CBCR_H2V2_TP10;
209 else
210 *pixfmt =
211 SDE_PIX_FMT_Y_CBCR_H2V2_P010;
212 } else {
213 *pixfmt = SDE_PIX_FMT_Y_CBCR_H2V2;
214 }
215 }
216 break;
217 case DRM_FORMAT_NV21:
218 if (SDE_MODIFIER_IS_TILE(drm_modifier))
219 *pixfmt = SDE_PIX_FMT_Y_CRCB_H2V2_TILE;
220 else
221 *pixfmt = SDE_PIX_FMT_Y_CRCB_H2V2;
222 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700223 case DRM_FORMAT_BGRA1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800224 if (SDE_MODIFIER_IS_TILE(drm_modifier))
225 *pixfmt = SDE_PIX_FMT_ARGB_2101010_TILE;
226 else
227 *pixfmt = SDE_PIX_FMT_ARGB_2101010;
228 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700229 case DRM_FORMAT_BGRX1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800230 if (SDE_MODIFIER_IS_TILE(drm_modifier))
231 *pixfmt = SDE_PIX_FMT_XRGB_2101010_TILE;
232 else
233 *pixfmt = SDE_PIX_FMT_XRGB_2101010;
234 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700235 case DRM_FORMAT_RGBA1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800236 if (SDE_MODIFIER_IS_TILE(drm_modifier))
237 *pixfmt = SDE_PIX_FMT_ABGR_2101010_TILE;
238 else
239 *pixfmt = SDE_PIX_FMT_ABGR_2101010;
240 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700241 case DRM_FORMAT_RGBX1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800242 if (SDE_MODIFIER_IS_TILE(drm_modifier))
243 *pixfmt = SDE_PIX_FMT_XBGR_2101010_TILE;
244 else
245 *pixfmt = SDE_PIX_FMT_XBGR_2101010;
246 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700247 case DRM_FORMAT_ARGB2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800248 if (SDE_MODIFIER_IS_TILE(drm_modifier))
249 *pixfmt = SDE_PIX_FMT_BGRA_1010102_TILE;
250 else
251 *pixfmt = SDE_PIX_FMT_BGRA_1010102;
252 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700253 case DRM_FORMAT_XRGB2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800254 if (SDE_MODIFIER_IS_TILE(drm_modifier))
255 *pixfmt = SDE_PIX_FMT_BGRX_1010102_TILE;
256 else
257 *pixfmt = SDE_PIX_FMT_BGRX_1010102;
258 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700259 case DRM_FORMAT_ABGR2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800260 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
261 *pixfmt = SDE_PIX_FMT_RGBA_1010102_UBWC;
262 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
263 *pixfmt = SDE_PIX_FMT_RGBA_1010102_TILE;
264 else
265 *pixfmt = SDE_PIX_FMT_RGBA_1010102;
266 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700267 case DRM_FORMAT_XBGR2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800268 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
269 *pixfmt = SDE_PIX_FMT_RGBX_1010102_UBWC;
270 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
271 *pixfmt = SDE_PIX_FMT_RGBX_1010102_TILE;
272 else
273 *pixfmt = SDE_PIX_FMT_RGBX_1010102;
274 break;
275 default:
276 SDE_ERROR("invalid drm pixel format %c%c%c%c/%llx\n",
277 drm_pixfmt >> 0, drm_pixfmt >> 8,
278 drm_pixfmt >> 16, drm_pixfmt >> 24,
279 drm_modifier);
280 rc = -EINVAL;
281 break;
282 }
283
284 return rc;
285}
286
287/**
288 * sde_hw_rot_to_drm_pixfmt - convert v4l2 pixel format to drm pixel format
289 * @pixfmt: v4l2 fourcc pixel format
290 * @drm_pixfmt: Pointer to drm forucc pixel format (output)
291 * @drm_modifier: Pointer to drm pixel format modifier (output)
292 * return: 0 if success; error code otherwise
293 */
294static int sde_hw_rot_to_drm_pixfmt(u32 pixfmt, u32 *drm_pixfmt,
295 u64 *drm_modifier)
296{
297 u32 rc = 0;
298
299 switch (pixfmt) {
300 case SDE_PIX_FMT_RGB_565:
Alan Kwong75316d92017-03-31 14:12:05 -0700301 *drm_pixfmt = DRM_FORMAT_BGR565;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800302 *drm_modifier = 0;
303 break;
304 case SDE_PIX_FMT_RGB_565_UBWC:
Alan Kwong75316d92017-03-31 14:12:05 -0700305 *drm_pixfmt = DRM_FORMAT_BGR565;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800306 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
307 DRM_FORMAT_MOD_QCOM_TILE;
308 break;
309 case SDE_PIX_FMT_RGBA_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700310 *drm_pixfmt = DRM_FORMAT_ABGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800311 *drm_modifier = 0;
312 break;
313 case SDE_PIX_FMT_RGBX_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700314 *drm_pixfmt = DRM_FORMAT_XBGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800315 *drm_modifier = 0;
316 break;
317 case SDE_PIX_FMT_BGRA_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700318 *drm_pixfmt = DRM_FORMAT_ARGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800319 *drm_modifier = 0;
320 break;
321 case SDE_PIX_FMT_BGRX_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700322 *drm_pixfmt = DRM_FORMAT_XRGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800323 *drm_modifier = 0;
324 break;
325 case SDE_PIX_FMT_Y_CBCR_H2V2_UBWC:
326 *drm_pixfmt = DRM_FORMAT_NV12;
327 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
328 DRM_FORMAT_MOD_QCOM_TILE;
329 break;
330 case SDE_PIX_FMT_Y_CRCB_H2V2:
331 *drm_pixfmt = DRM_FORMAT_NV21;
332 *drm_modifier = 0;
333 break;
334 case SDE_PIX_FMT_RGBA_8888_UBWC:
Alan Kwong75316d92017-03-31 14:12:05 -0700335 *drm_pixfmt = DRM_FORMAT_ABGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800336 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
337 DRM_FORMAT_MOD_QCOM_TILE;
338 break;
339 case SDE_PIX_FMT_RGBX_8888_UBWC:
Alan Kwong75316d92017-03-31 14:12:05 -0700340 *drm_pixfmt = DRM_FORMAT_XBGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800341 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
342 DRM_FORMAT_MOD_QCOM_TILE;
343 break;
344 case SDE_PIX_FMT_Y_CBCR_H2V2:
345 *drm_pixfmt = DRM_FORMAT_NV12;
346 *drm_modifier = 0;
347 break;
348 case SDE_PIX_FMT_ARGB_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700349 *drm_pixfmt = DRM_FORMAT_BGRA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800350 *drm_modifier = 0;
351 break;
352 case SDE_PIX_FMT_XRGB_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700353 *drm_pixfmt = DRM_FORMAT_BGRX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800354 *drm_modifier = 0;
355 break;
356 case SDE_PIX_FMT_ABGR_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700357 *drm_pixfmt = DRM_FORMAT_RGBA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800358 *drm_modifier = 0;
359 break;
360 case SDE_PIX_FMT_XBGR_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700361 *drm_pixfmt = DRM_FORMAT_RGBX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800362 *drm_modifier = 0;
363 break;
364 case SDE_PIX_FMT_ARGB_2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800365 *drm_pixfmt = DRM_FORMAT_BGRA1010102;
366 *drm_modifier = 0;
367 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700368 case SDE_PIX_FMT_XRGB_2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800369 *drm_pixfmt = DRM_FORMAT_BGRX1010102;
370 *drm_modifier = 0;
371 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700372 case SDE_PIX_FMT_ABGR_2101010:
373 *drm_pixfmt = DRM_FORMAT_RGBA1010102;
374 *drm_modifier = 0;
375 break;
376 case SDE_PIX_FMT_XBGR_2101010:
377 *drm_pixfmt = DRM_FORMAT_RGBX1010102;
378 *drm_modifier = 0;
379 break;
380 case SDE_PIX_FMT_BGRA_1010102:
381 *drm_pixfmt = DRM_FORMAT_ARGB2101010;
382 *drm_modifier = 0;
383 break;
384 case SDE_PIX_FMT_BGRX_1010102:
385 *drm_pixfmt = DRM_FORMAT_XRGB2101010;
386 *drm_modifier = 0;
387 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800388 case SDE_PIX_FMT_RGBA_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700389 *drm_pixfmt = DRM_FORMAT_ABGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800390 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
391 break;
392 case SDE_PIX_FMT_RGBX_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700393 *drm_pixfmt = DRM_FORMAT_XBGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800394 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
395 break;
396 case SDE_PIX_FMT_BGRA_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700397 *drm_pixfmt = DRM_FORMAT_ARGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800398 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
399 break;
400 case SDE_PIX_FMT_BGRX_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700401 *drm_pixfmt = DRM_FORMAT_XRGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800402 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
403 break;
404 case SDE_PIX_FMT_Y_CRCB_H2V2_TILE:
405 *drm_pixfmt = DRM_FORMAT_NV21;
406 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
407 break;
408 case SDE_PIX_FMT_Y_CBCR_H2V2_TILE:
409 *drm_pixfmt = DRM_FORMAT_NV12;
410 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
411 break;
412 case SDE_PIX_FMT_ARGB_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700413 *drm_pixfmt = DRM_FORMAT_BGRA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800414 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
415 break;
416 case SDE_PIX_FMT_XRGB_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700417 *drm_pixfmt = DRM_FORMAT_BGRX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800418 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
419 break;
420 case SDE_PIX_FMT_ABGR_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700421 *drm_pixfmt = DRM_FORMAT_RGBA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800422 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
423 break;
424 case SDE_PIX_FMT_XBGR_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700425 *drm_pixfmt = DRM_FORMAT_RGBX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800426 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
427 break;
428 case SDE_PIX_FMT_ARGB_2101010_TILE:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800429 *drm_pixfmt = DRM_FORMAT_BGRA1010102;
430 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
431 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700432 case SDE_PIX_FMT_XRGB_2101010_TILE:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800433 *drm_pixfmt = DRM_FORMAT_BGRX1010102;
434 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
435 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700436 case SDE_PIX_FMT_ABGR_2101010_TILE:
437 *drm_pixfmt = DRM_FORMAT_RGBA1010102;
438 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
439 break;
440 case SDE_PIX_FMT_XBGR_2101010_TILE:
441 *drm_pixfmt = DRM_FORMAT_RGBX1010102;
442 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
443 break;
444 case SDE_PIX_FMT_BGRA_1010102_TILE:
445 *drm_pixfmt = DRM_FORMAT_ARGB2101010;
446 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
447 break;
448 case SDE_PIX_FMT_BGRX_1010102_TILE:
449 *drm_pixfmt = DRM_FORMAT_XRGB2101010;
450 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
451 break;
452 case SDE_PIX_FMT_RGBA_1010102_UBWC:
453 *drm_pixfmt = DRM_FORMAT_ABGR2101010;
454 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
455 DRM_FORMAT_MOD_QCOM_TILE;
456 break;
457 case SDE_PIX_FMT_RGBX_1010102_UBWC:
458 *drm_pixfmt = DRM_FORMAT_XBGR2101010;
459 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
460 DRM_FORMAT_MOD_QCOM_TILE;
461 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800462 case SDE_PIX_FMT_Y_CBCR_H2V2_P010:
463 *drm_pixfmt = DRM_FORMAT_NV12;
464 *drm_modifier = DRM_FORMAT_MOD_QCOM_DX;
465 break;
466 case SDE_PIX_FMT_Y_CBCR_H2V2_P010_TILE:
467 *drm_pixfmt = DRM_FORMAT_NV12;
468 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE |
469 DRM_FORMAT_MOD_QCOM_DX;
470 break;
Alan Kwong87847ce2017-02-21 08:34:31 -0800471 case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC:
472 *drm_pixfmt = DRM_FORMAT_NV12;
473 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
474 DRM_FORMAT_MOD_QCOM_TILE |
475 DRM_FORMAT_MOD_QCOM_DX;
476 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800477 case SDE_PIX_FMT_Y_CBCR_H2V2_TP10:
478 *drm_pixfmt = DRM_FORMAT_NV12;
479 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE |
480 DRM_FORMAT_MOD_QCOM_DX |
481 DRM_FORMAT_MOD_QCOM_TIGHT;
482 break;
483 case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC:
484 *drm_pixfmt = DRM_FORMAT_NV12;
485 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
486 DRM_FORMAT_MOD_QCOM_TILE |
487 DRM_FORMAT_MOD_QCOM_DX |
488 DRM_FORMAT_MOD_QCOM_TIGHT;
489 break;
490 default:
491 SDE_DEBUG("invalid v4l2 pixel format %c%c%c%c\n",
492 pixfmt >> 0, pixfmt >> 8,
493 pixfmt >> 16, pixfmt >> 24);
494 rc = -EINVAL;
495 break;
496 }
497
498 return rc;
499}
500
501/**
502 * sde_hw_rot_to_v4l2_buffer - convert drm buffer to v4l2 buffer
503 * @drm_pixfmt: pixel format in drm fourcc
504 * @drm_modifier: pixel format modifier
505 * @drm_addr: drm buffer address per plane
506 * @drm_len: drm buffer length per plane
507 * @drm_planes: drm buffer number of planes
508 * @v4l_addr: v4l2 buffer address per plane
509 * @v4l_len: v4l2 buffer length per plane
510 * @v4l_planes: v4l2 buffer number of planes
511 */
512static void sde_hw_rot_to_v4l2_buffer(u32 drm_pixfmt, u64 drm_modifier,
513 dma_addr_t *drm_addr, u32 *drm_len, u32 *drm_planes,
514 dma_addr_t *v4l_addr, u32 *v4l_len, u32 *v4l_planes)
515{
516 int i, total_size = 0;
517
518 for (i = 0; i < SDE_ROTATOR_INLINE_PLANE_MAX; i++) {
519 v4l_addr[i] = drm_addr[i];
520 v4l_len[i] = drm_len[i];
521 total_size += drm_len[i];
522 SDE_DEBUG("drm[%d]:%pad/%x\n", i, &drm_addr[i], drm_len[i]);
523 }
524
525 if (SDE_MODIFIER_IS_UBWC(drm_modifier)) {
526 /* v4l2 driver uses plane[0] as single ubwc buffer plane */
527 v4l_addr[0] = drm_addr[2];
528 v4l_len[0] = total_size;
529 *v4l_planes = 1;
530 SDE_DEBUG("v4l2[0]:%pad/%x/%d\n", &v4l_addr[0], v4l_len[0],
531 *v4l_planes);
532 } else {
533 *v4l_planes = *drm_planes;
534 }
535}
536
537/**
538 * sde_hw_rot_commit - commit/execute given rotator command
539 * @hw: Pointer to rotator hardware driver
540 * @data: Pointer to command descriptor
541 * @hw_cmd: type of command to be executed
542 * return: 0 if success; error code otherwise
543 */
544static int sde_hw_rot_commit(struct sde_hw_rot *hw, struct sde_hw_rot_cmd *data,
545 enum sde_hw_rot_cmd_type hw_cmd)
546{
547 struct sde_rotator_inline_cmd rot_cmd;
548 enum sde_rotator_inline_cmd_type cmd_type;
549 void *priv_handle = NULL;
550 int rc;
551
552 if (!hw || !data) {
553 SDE_ERROR("invalid parameter\n");
554 return -EINVAL;
555 }
556
557 memset(&rot_cmd, 0, sizeof(struct sde_rotator_inline_cmd));
558
559 switch (hw_cmd) {
560 case SDE_HW_ROT_CMD_VALIDATE:
561 cmd_type = SDE_ROTATOR_INLINE_CMD_VALIDATE;
562 break;
563 case SDE_HW_ROT_CMD_COMMIT:
564 cmd_type = SDE_ROTATOR_INLINE_CMD_COMMIT;
565 break;
566 case SDE_HW_ROT_CMD_CLEANUP:
567 cmd_type = SDE_ROTATOR_INLINE_CMD_CLEANUP;
568 priv_handle = data->priv_handle;
569 break;
570 default:
571 SDE_ERROR("invalid hw rotator command %d\n", hw_cmd);
572 return -EINVAL;
573 }
574
575 rot_cmd.video_mode = data->video_mode;
576 rot_cmd.fps = data->fps;
577 rot_cmd.rot90 = data->rot90;
578 rot_cmd.hflip = data->hflip;
579 rot_cmd.vflip = data->vflip;
580 rot_cmd.secure = data->secure;
581 rot_cmd.clkrate = data->clkrate;
Alan Kwong4aacd532017-02-04 18:51:33 -0800582 rot_cmd.data_bw = 0;
583 rot_cmd.prefill_bw = data->prefill_bw;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800584 rot_cmd.src_width = data->src_width;
585 rot_cmd.src_height = data->src_height;
586 rot_cmd.src_rect_x = data->src_rect_x;
587 rot_cmd.src_rect_y = data->src_rect_y;
588 rot_cmd.src_rect_w = data->src_rect_w;
589 rot_cmd.src_rect_h = data->src_rect_h;
590 rot_cmd.dst_writeback = data->dst_writeback;
591 rot_cmd.dst_rect_x = data->dst_rect_x;
592 rot_cmd.dst_rect_y = data->dst_rect_y;
593 rot_cmd.dst_rect_w = data->dst_rect_w;
594 rot_cmd.dst_rect_h = data->dst_rect_h;
595 rot_cmd.priv_handle = priv_handle;
596
597 rc = sde_hw_rot_to_v4l2_pixfmt(data->src_pixel_format,
598 data->src_modifier, &rot_cmd.src_pixfmt);
599 if (rc) {
600 SDE_ERROR("invalid src format %d\n", rc);
601 return rc;
602 }
603
604 /* calculate preferred output format during validation */
605 if (hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
606 rc = sde_rotator_inline_get_dst_pixfmt(hw->caps->pdev,
607 rot_cmd.src_pixfmt, &rot_cmd.dst_pixfmt);
608 if (rc) {
609 SDE_ERROR("invalid src format %d\n", rc);
610 return rc;
611 }
612
613 rc = sde_hw_rot_to_drm_pixfmt(rot_cmd.dst_pixfmt,
614 &data->dst_pixel_format, &data->dst_modifier);
615 if (rc) {
616 SDE_ERROR("invalid dst format %c%c%c%c\n",
617 rot_cmd.dst_pixfmt >> 0,
618 rot_cmd.dst_pixfmt >> 8,
619 rot_cmd.dst_pixfmt >> 16,
620 rot_cmd.dst_pixfmt >> 24);
621 return rc;
622 }
623
624 data->dst_format = sde_get_sde_format_ext(
625 data->dst_pixel_format, &data->dst_modifier, 1);
626 if (!data->dst_format) {
627 SDE_ERROR("failed to get dst format\n");
628 return -EINVAL;
629 }
630 } else if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
631 rc = sde_hw_rot_to_v4l2_pixfmt(data->dst_pixel_format,
632 data->dst_modifier, &rot_cmd.dst_pixfmt);
633 if (rc) {
634 SDE_ERROR("invalid dst format %d\n", rc);
635 return rc;
636 }
637
638 sde_hw_rot_to_v4l2_buffer(data->src_pixel_format,
639 data->src_modifier,
640 data->src_iova, data->src_len,
641 &data->src_planes,
642 rot_cmd.src_addr, rot_cmd.src_len,
643 &rot_cmd.src_planes);
644
645 sde_hw_rot_to_v4l2_buffer(data->dst_pixel_format,
646 data->dst_modifier,
647 data->dst_iova, data->dst_len,
648 &data->dst_planes,
649 rot_cmd.dst_addr, rot_cmd.dst_len,
650 &rot_cmd.dst_planes);
651 }
652
653 /* only process any command if client is master or for validation */
654 if (data->master || hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
655 SDE_DEBUG("dispatch seq:%d cmd:%d\n", data->sequence_id,
656 hw_cmd);
657
658 rc = sde_rotator_inline_commit(hw->rot_ctx, &rot_cmd, cmd_type);
659 if (rc) {
660 SDE_ERROR("failed to commit inline rotation %d\n", rc);
661 return rc;
662 }
663
664 /* return to caller */
665 data->priv_handle = rot_cmd.priv_handle;
666 } else {
667 SDE_DEBUG("bypass seq:%d cmd:%d\n", data->sequence_id, hw_cmd);
668 }
669
670 return 0;
671}
672
673/**
674 * sde_hw_rot_get_format_caps - get pixel format capability
675 * @hw: Pointer to rotator hardware driver
676 * return: Pointer to pixel format capability array: NULL otherwise
677 */
678static const struct sde_format_extended *sde_hw_rot_get_format_caps(
679 struct sde_hw_rot *hw)
680{
681 int rc, i, j, len;
682 u32 *v4l_pixfmts;
683 struct sde_format_extended *drm_pixfmts;
684 struct platform_device *pdev;
685
686 if (!hw || !hw->caps || !hw->caps->pdev) {
687 SDE_ERROR("invalid rotator hw\n");
688 return NULL;
689 }
690
691 pdev = hw->caps->pdev;
692
693 if (hw->format_caps)
694 return hw->format_caps;
695
696 len = sde_rotator_inline_get_pixfmt_caps(pdev, true, NULL, 0);
697 if (len < 0) {
698 SDE_ERROR("invalid pixfmt caps %d\n", len);
699 return NULL;
700 }
701
702 v4l_pixfmts = kcalloc(len, sizeof(u32), GFP_KERNEL);
703 if (!v4l_pixfmts)
704 goto done;
705
706 sde_rotator_inline_get_pixfmt_caps(pdev, true, v4l_pixfmts, len);
707
708 /* allocate one more to indicate termination */
709 drm_pixfmts = kzalloc((len + 1) * sizeof(struct sde_format_extended),
710 GFP_KERNEL);
711 if (!drm_pixfmts)
712 goto done;
713
714 for (i = 0, j = 0; i < len; i++) {
715 rc = sde_hw_rot_to_drm_pixfmt(v4l_pixfmts[i],
716 &drm_pixfmts[j].fourcc_format,
717 &drm_pixfmts[j].modifier);
718 if (!rc) {
719 SDE_DEBUG("%d: vl42:%c%c%c%c => drm:%c%c%c%c/0x%llx\n",
720 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
721 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24,
722 drm_pixfmts[j].fourcc_format >> 0,
723 drm_pixfmts[j].fourcc_format >> 8,
724 drm_pixfmts[j].fourcc_format >> 16,
725 drm_pixfmts[j].fourcc_format >> 24,
726 drm_pixfmts[j].modifier);
727 j++;
728 } else {
729 SDE_DEBUG("%d: vl42:%c%c%c%c not mapped\n",
730 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
731 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24);
732 }
733 }
734
735 hw->format_caps = drm_pixfmts;
736done:
737 kfree(v4l_pixfmts);
738
739 return hw->format_caps;
740}
741
742/**
743 * sde_hw_rot_get_downscale_caps - get scaling capability string
744 * @hw: Pointer to rotator hardware driver
745 * return: Pointer to capability string: NULL otherwise
746 */
747static const char *sde_hw_rot_get_downscale_caps(struct sde_hw_rot *hw)
748{
749 int len;
750 struct platform_device *pdev;
751
752 if (!hw || !hw->caps || !hw->caps->pdev) {
753 SDE_ERROR("invalid rotator hw\n");
754 return NULL;
755 }
756
757 pdev = hw->caps->pdev;
758
759 if (hw->downscale_caps)
760 return hw->downscale_caps;
761
762 len = sde_rotator_inline_get_downscale_caps(pdev, NULL, 0);
763 if (len < 0) {
764 SDE_ERROR("invalid scaling caps %d\n", len);
765 return NULL;
766 }
767
768 /* add one for ending zero */
769 len += 1;
770 hw->downscale_caps = kzalloc(len, GFP_KERNEL);
771 sde_rotator_inline_get_downscale_caps(pdev, hw->downscale_caps, len);
772
773 return hw->downscale_caps;
774}
775
776/**
777 * sde_hw_rot_get_cache_size - get cache size
778 * @hw: Pointer to rotator hardware driver
779 * return: size of cache
780 */
781static size_t sde_hw_rot_get_cache_size(struct sde_hw_rot *hw)
782{
783 if (!hw || !hw->caps) {
784 SDE_ERROR("invalid rotator hw\n");
785 return 0;
786 }
787
788 return hw->caps->slice_size;
789}
790
791/**
Alan Kwong1a915802017-03-31 12:55:46 -0700792 * sde_hw_rot_get_maxlinewidth - get maximum line width of rotator
793 * @hw: Pointer to rotator hardware driver
794 * return: maximum line width
795 */
796static int sde_hw_rot_get_maxlinewidth(struct sde_hw_rot *hw)
797{
798 struct platform_device *pdev;
799
800 if (!hw || !hw->caps || !hw->caps->pdev) {
801 SDE_ERROR("invalid rotator hw\n");
802 return 0;
803 }
804
805 pdev = hw->caps->pdev;
806
807 return sde_rotator_inline_get_maxlinewidth(pdev);
808}
809
810/**
Alan Kwong4dd64c82017-02-04 18:41:51 -0800811 * _setup_rot_ops - setup rotator operations
812 * @ops: Pointer to operation table
813 * @features: available feature bitmask
814 * return: none
815 */
816static void _setup_rot_ops(struct sde_hw_rot_ops *ops, unsigned long features)
817{
818 ops->commit = sde_hw_rot_commit;
819 ops->get_format_caps = sde_hw_rot_get_format_caps;
820 ops->get_downscale_caps = sde_hw_rot_get_downscale_caps;
821 ops->get_cache_size = sde_hw_rot_get_cache_size;
Alan Kwong1a915802017-03-31 12:55:46 -0700822 ops->get_maxlinewidth = sde_hw_rot_get_maxlinewidth;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800823}
824
825/**
Alan Kwong4dd64c82017-02-04 18:41:51 -0800826 * sde_hw_rot_blk_stop - stop rotator block
827 * @hw_blk: Pointer to base hardware block
828 * return: none
829 */
830static void sde_hw_rot_blk_stop(struct sde_hw_blk *hw_blk)
831{
832 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
833
834 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
835
836 sde_hw_rot_stop(hw_rot);
837}
838
839/**
840 * sde_hw_rot_blk_start - art rotator block
841 * @hw_blk: Pointer to base hardware block
842 * return: 0 if success; error code otherwise
843 */
844static int sde_hw_rot_blk_start(struct sde_hw_blk *hw_blk)
845{
846 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
847 int rc = 0;
848
849 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
850
851 rc = sde_hw_rot_start(hw_rot);
852
853 return rc;
854}
855
Alan Kwongcdb2f282017-03-18 13:42:06 -0700856static struct sde_hw_blk_ops sde_hw_rot_ops = {
857 .start = sde_hw_rot_blk_start,
858 .stop = sde_hw_rot_blk_stop,
859};
860
861/**
862 * sde_hw_rot_init - create/initialize given rotator instance
863 * @idx: index of given rotator
864 * @addr: i/o address mapping
865 * @m: Pointer to mdss catalog
866 * return: Pointer to hardware rotator driver of the given instance
867 */
868struct sde_hw_rot *sde_hw_rot_init(enum sde_rot idx,
869 void __iomem *addr,
870 struct sde_mdss_cfg *m)
871{
872 struct sde_hw_rot *c;
873 struct sde_rot_cfg *cfg;
874 int rc;
875
876 c = kzalloc(sizeof(*c), GFP_KERNEL);
877 if (!c)
878 return ERR_PTR(-ENOMEM);
879
880 cfg = _rot_offset(idx, m, addr, &c->hw);
881 if (IS_ERR(cfg)) {
882 WARN(1, "Unable to find rot idx=%d\n", idx);
883 kfree(c);
884 return ERR_PTR(-EINVAL);
885 }
886
887 /* Assign ops */
888 c->idx = idx;
889 c->caps = cfg;
890 _setup_rot_ops(&c->ops, c->caps->features);
891
892 rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_ROT, idx,
893 &sde_hw_rot_ops);
894 if (rc) {
895 SDE_ERROR("failed to init hw blk %d\n", rc);
896 goto blk_init_error;
897 }
898
899 return c;
900
901blk_init_error:
902 kzfree(c);
903
904 return ERR_PTR(rc);
905}
906
907/**
908 * sde_hw_rot_destroy - destroy given hardware rotator driver
909 * @hw_rot: Pointer to hardware rotator driver
910 * return: none
911 */
912void sde_hw_rot_destroy(struct sde_hw_rot *hw_rot)
913{
914 sde_hw_blk_destroy(&hw_rot->base);
915 kfree(hw_rot->downscale_caps);
916 kfree(hw_rot->format_caps);
917 kfree(hw_rot);
918}
919
Alan Kwong4dd64c82017-02-04 18:41:51 -0800920struct sde_hw_rot *sde_hw_rot_get(struct sde_hw_rot *hw_rot)
921{
922 struct sde_hw_blk *hw_blk = sde_hw_blk_get(hw_rot ? &hw_rot->base :
923 NULL, SDE_HW_BLK_ROT, -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800924
Alan Kwongcdb2f282017-03-18 13:42:06 -0700925 return IS_ERR_OR_NULL(hw_blk) ? NULL : to_sde_hw_rot(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800926}
927
928void sde_hw_rot_put(struct sde_hw_rot *hw_rot)
929{
930 struct sde_hw_blk *hw_blk = hw_rot ? &hw_rot->base : NULL;
931
Alan Kwongcdb2f282017-03-18 13:42:06 -0700932 sde_hw_blk_put(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800933}