blob: d5f03a6a7f24b795dbc81be66b4aa6df219414f9 [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;
Clarence Ipddbf7752017-05-21 18:07:30 -0400566 case SDE_HW_ROT_CMD_START:
567 cmd_type = SDE_ROTATOR_INLINE_CMD_START;
568 priv_handle = data->priv_handle;
569 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800570 case SDE_HW_ROT_CMD_CLEANUP:
571 cmd_type = SDE_ROTATOR_INLINE_CMD_CLEANUP;
572 priv_handle = data->priv_handle;
573 break;
574 default:
575 SDE_ERROR("invalid hw rotator command %d\n", hw_cmd);
576 return -EINVAL;
577 }
578
579 rot_cmd.video_mode = data->video_mode;
580 rot_cmd.fps = data->fps;
Alan Kwong120b1642017-05-01 12:36:13 -0700581
582 /*
583 * DRM rotation property is specified in counter clockwise direction
584 * whereas rotator h/w rotates in clockwise direction.
585 * Convert rotation property to clockwise 90 by toggling h/v flip
586 */
Alan Kwong4dd64c82017-02-04 18:41:51 -0800587 rot_cmd.rot90 = data->rot90;
Alan Kwong120b1642017-05-01 12:36:13 -0700588 rot_cmd.hflip = data->rot90 ? !data->hflip : data->hflip;
589 rot_cmd.vflip = data->rot90 ? !data->vflip : data->vflip;
590
Alan Kwong4dd64c82017-02-04 18:41:51 -0800591 rot_cmd.secure = data->secure;
592 rot_cmd.clkrate = data->clkrate;
Alan Kwong4aacd532017-02-04 18:51:33 -0800593 rot_cmd.data_bw = 0;
594 rot_cmd.prefill_bw = data->prefill_bw;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800595 rot_cmd.src_width = data->src_width;
596 rot_cmd.src_height = data->src_height;
597 rot_cmd.src_rect_x = data->src_rect_x;
598 rot_cmd.src_rect_y = data->src_rect_y;
599 rot_cmd.src_rect_w = data->src_rect_w;
600 rot_cmd.src_rect_h = data->src_rect_h;
601 rot_cmd.dst_writeback = data->dst_writeback;
602 rot_cmd.dst_rect_x = data->dst_rect_x;
603 rot_cmd.dst_rect_y = data->dst_rect_y;
604 rot_cmd.dst_rect_w = data->dst_rect_w;
605 rot_cmd.dst_rect_h = data->dst_rect_h;
606 rot_cmd.priv_handle = priv_handle;
607
608 rc = sde_hw_rot_to_v4l2_pixfmt(data->src_pixel_format,
609 data->src_modifier, &rot_cmd.src_pixfmt);
610 if (rc) {
611 SDE_ERROR("invalid src format %d\n", rc);
612 return rc;
613 }
614
615 /* calculate preferred output format during validation */
616 if (hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
617 rc = sde_rotator_inline_get_dst_pixfmt(hw->caps->pdev,
618 rot_cmd.src_pixfmt, &rot_cmd.dst_pixfmt);
619 if (rc) {
620 SDE_ERROR("invalid src format %d\n", rc);
621 return rc;
622 }
623
624 rc = sde_hw_rot_to_drm_pixfmt(rot_cmd.dst_pixfmt,
625 &data->dst_pixel_format, &data->dst_modifier);
626 if (rc) {
627 SDE_ERROR("invalid dst format %c%c%c%c\n",
628 rot_cmd.dst_pixfmt >> 0,
629 rot_cmd.dst_pixfmt >> 8,
630 rot_cmd.dst_pixfmt >> 16,
631 rot_cmd.dst_pixfmt >> 24);
632 return rc;
633 }
634
635 data->dst_format = sde_get_sde_format_ext(
636 data->dst_pixel_format, &data->dst_modifier, 1);
637 if (!data->dst_format) {
638 SDE_ERROR("failed to get dst format\n");
639 return -EINVAL;
640 }
641 } else if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
642 rc = sde_hw_rot_to_v4l2_pixfmt(data->dst_pixel_format,
643 data->dst_modifier, &rot_cmd.dst_pixfmt);
644 if (rc) {
645 SDE_ERROR("invalid dst format %d\n", rc);
646 return rc;
647 }
648
649 sde_hw_rot_to_v4l2_buffer(data->src_pixel_format,
650 data->src_modifier,
651 data->src_iova, data->src_len,
652 &data->src_planes,
653 rot_cmd.src_addr, rot_cmd.src_len,
654 &rot_cmd.src_planes);
655
656 sde_hw_rot_to_v4l2_buffer(data->dst_pixel_format,
657 data->dst_modifier,
658 data->dst_iova, data->dst_len,
659 &data->dst_planes,
660 rot_cmd.dst_addr, rot_cmd.dst_len,
661 &rot_cmd.dst_planes);
662 }
663
664 /* only process any command if client is master or for validation */
665 if (data->master || hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
666 SDE_DEBUG("dispatch seq:%d cmd:%d\n", data->sequence_id,
667 hw_cmd);
668
669 rc = sde_rotator_inline_commit(hw->rot_ctx, &rot_cmd, cmd_type);
670 if (rc) {
671 SDE_ERROR("failed to commit inline rotation %d\n", rc);
672 return rc;
673 }
674
675 /* return to caller */
676 data->priv_handle = rot_cmd.priv_handle;
677 } else {
678 SDE_DEBUG("bypass seq:%d cmd:%d\n", data->sequence_id, hw_cmd);
679 }
680
681 return 0;
682}
683
684/**
685 * sde_hw_rot_get_format_caps - get pixel format capability
686 * @hw: Pointer to rotator hardware driver
687 * return: Pointer to pixel format capability array: NULL otherwise
688 */
689static const struct sde_format_extended *sde_hw_rot_get_format_caps(
690 struct sde_hw_rot *hw)
691{
692 int rc, i, j, len;
693 u32 *v4l_pixfmts;
694 struct sde_format_extended *drm_pixfmts;
695 struct platform_device *pdev;
696
697 if (!hw || !hw->caps || !hw->caps->pdev) {
698 SDE_ERROR("invalid rotator hw\n");
699 return NULL;
700 }
701
702 pdev = hw->caps->pdev;
703
704 if (hw->format_caps)
705 return hw->format_caps;
706
707 len = sde_rotator_inline_get_pixfmt_caps(pdev, true, NULL, 0);
708 if (len < 0) {
709 SDE_ERROR("invalid pixfmt caps %d\n", len);
710 return NULL;
711 }
712
713 v4l_pixfmts = kcalloc(len, sizeof(u32), GFP_KERNEL);
714 if (!v4l_pixfmts)
715 goto done;
716
717 sde_rotator_inline_get_pixfmt_caps(pdev, true, v4l_pixfmts, len);
718
719 /* allocate one more to indicate termination */
720 drm_pixfmts = kzalloc((len + 1) * sizeof(struct sde_format_extended),
721 GFP_KERNEL);
722 if (!drm_pixfmts)
723 goto done;
724
725 for (i = 0, j = 0; i < len; i++) {
726 rc = sde_hw_rot_to_drm_pixfmt(v4l_pixfmts[i],
727 &drm_pixfmts[j].fourcc_format,
728 &drm_pixfmts[j].modifier);
729 if (!rc) {
730 SDE_DEBUG("%d: vl42:%c%c%c%c => drm:%c%c%c%c/0x%llx\n",
731 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
732 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24,
733 drm_pixfmts[j].fourcc_format >> 0,
734 drm_pixfmts[j].fourcc_format >> 8,
735 drm_pixfmts[j].fourcc_format >> 16,
736 drm_pixfmts[j].fourcc_format >> 24,
737 drm_pixfmts[j].modifier);
738 j++;
739 } else {
740 SDE_DEBUG("%d: vl42:%c%c%c%c not mapped\n",
741 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
742 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24);
743 }
744 }
745
746 hw->format_caps = drm_pixfmts;
747done:
748 kfree(v4l_pixfmts);
749
750 return hw->format_caps;
751}
752
753/**
754 * sde_hw_rot_get_downscale_caps - get scaling capability string
755 * @hw: Pointer to rotator hardware driver
756 * return: Pointer to capability string: NULL otherwise
757 */
758static const char *sde_hw_rot_get_downscale_caps(struct sde_hw_rot *hw)
759{
760 int len;
761 struct platform_device *pdev;
762
763 if (!hw || !hw->caps || !hw->caps->pdev) {
764 SDE_ERROR("invalid rotator hw\n");
765 return NULL;
766 }
767
768 pdev = hw->caps->pdev;
769
770 if (hw->downscale_caps)
771 return hw->downscale_caps;
772
773 len = sde_rotator_inline_get_downscale_caps(pdev, NULL, 0);
774 if (len < 0) {
775 SDE_ERROR("invalid scaling caps %d\n", len);
776 return NULL;
777 }
778
779 /* add one for ending zero */
780 len += 1;
781 hw->downscale_caps = kzalloc(len, GFP_KERNEL);
782 sde_rotator_inline_get_downscale_caps(pdev, hw->downscale_caps, len);
783
784 return hw->downscale_caps;
785}
786
787/**
788 * sde_hw_rot_get_cache_size - get cache size
789 * @hw: Pointer to rotator hardware driver
790 * return: size of cache
791 */
792static size_t sde_hw_rot_get_cache_size(struct sde_hw_rot *hw)
793{
794 if (!hw || !hw->caps) {
795 SDE_ERROR("invalid rotator hw\n");
796 return 0;
797 }
798
799 return hw->caps->slice_size;
800}
801
802/**
Alan Kwong1a915802017-03-31 12:55:46 -0700803 * sde_hw_rot_get_maxlinewidth - get maximum line width of rotator
804 * @hw: Pointer to rotator hardware driver
805 * return: maximum line width
806 */
807static int sde_hw_rot_get_maxlinewidth(struct sde_hw_rot *hw)
808{
809 struct platform_device *pdev;
810
811 if (!hw || !hw->caps || !hw->caps->pdev) {
812 SDE_ERROR("invalid rotator hw\n");
813 return 0;
814 }
815
816 pdev = hw->caps->pdev;
817
818 return sde_rotator_inline_get_maxlinewidth(pdev);
819}
820
821/**
Alan Kwong4dd64c82017-02-04 18:41:51 -0800822 * _setup_rot_ops - setup rotator operations
823 * @ops: Pointer to operation table
824 * @features: available feature bitmask
825 * return: none
826 */
827static void _setup_rot_ops(struct sde_hw_rot_ops *ops, unsigned long features)
828{
829 ops->commit = sde_hw_rot_commit;
830 ops->get_format_caps = sde_hw_rot_get_format_caps;
831 ops->get_downscale_caps = sde_hw_rot_get_downscale_caps;
832 ops->get_cache_size = sde_hw_rot_get_cache_size;
Alan Kwong1a915802017-03-31 12:55:46 -0700833 ops->get_maxlinewidth = sde_hw_rot_get_maxlinewidth;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800834}
835
836/**
Alan Kwong4dd64c82017-02-04 18:41:51 -0800837 * sde_hw_rot_blk_stop - stop rotator block
838 * @hw_blk: Pointer to base hardware block
839 * return: none
840 */
841static void sde_hw_rot_blk_stop(struct sde_hw_blk *hw_blk)
842{
843 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
844
845 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
846
847 sde_hw_rot_stop(hw_rot);
848}
849
850/**
851 * sde_hw_rot_blk_start - art rotator block
852 * @hw_blk: Pointer to base hardware block
853 * return: 0 if success; error code otherwise
854 */
855static int sde_hw_rot_blk_start(struct sde_hw_blk *hw_blk)
856{
857 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
858 int rc = 0;
859
860 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
861
862 rc = sde_hw_rot_start(hw_rot);
863
864 return rc;
865}
866
Alan Kwongcdb2f282017-03-18 13:42:06 -0700867static struct sde_hw_blk_ops sde_hw_rot_ops = {
868 .start = sde_hw_rot_blk_start,
869 .stop = sde_hw_rot_blk_stop,
870};
871
872/**
873 * sde_hw_rot_init - create/initialize given rotator instance
874 * @idx: index of given rotator
875 * @addr: i/o address mapping
876 * @m: Pointer to mdss catalog
877 * return: Pointer to hardware rotator driver of the given instance
878 */
879struct sde_hw_rot *sde_hw_rot_init(enum sde_rot idx,
880 void __iomem *addr,
881 struct sde_mdss_cfg *m)
882{
883 struct sde_hw_rot *c;
884 struct sde_rot_cfg *cfg;
885 int rc;
886
887 c = kzalloc(sizeof(*c), GFP_KERNEL);
888 if (!c)
889 return ERR_PTR(-ENOMEM);
890
891 cfg = _rot_offset(idx, m, addr, &c->hw);
892 if (IS_ERR(cfg)) {
893 WARN(1, "Unable to find rot idx=%d\n", idx);
894 kfree(c);
895 return ERR_PTR(-EINVAL);
896 }
897
898 /* Assign ops */
899 c->idx = idx;
900 c->caps = cfg;
901 _setup_rot_ops(&c->ops, c->caps->features);
902
903 rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_ROT, idx,
904 &sde_hw_rot_ops);
905 if (rc) {
906 SDE_ERROR("failed to init hw blk %d\n", rc);
907 goto blk_init_error;
908 }
909
910 return c;
911
912blk_init_error:
913 kzfree(c);
914
915 return ERR_PTR(rc);
916}
917
918/**
919 * sde_hw_rot_destroy - destroy given hardware rotator driver
920 * @hw_rot: Pointer to hardware rotator driver
921 * return: none
922 */
923void sde_hw_rot_destroy(struct sde_hw_rot *hw_rot)
924{
925 sde_hw_blk_destroy(&hw_rot->base);
926 kfree(hw_rot->downscale_caps);
927 kfree(hw_rot->format_caps);
928 kfree(hw_rot);
929}
930
Alan Kwong4dd64c82017-02-04 18:41:51 -0800931struct sde_hw_rot *sde_hw_rot_get(struct sde_hw_rot *hw_rot)
932{
933 struct sde_hw_blk *hw_blk = sde_hw_blk_get(hw_rot ? &hw_rot->base :
934 NULL, SDE_HW_BLK_ROT, -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800935
Alan Kwongcdb2f282017-03-18 13:42:06 -0700936 return IS_ERR_OR_NULL(hw_blk) ? NULL : to_sde_hw_rot(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800937}
938
939void sde_hw_rot_put(struct sde_hw_rot *hw_rot)
940{
941 struct sde_hw_blk *hw_blk = hw_rot ? &hw_rot->base : NULL;
942
Alan Kwongcdb2f282017-03-18 13:42:06 -0700943 sde_hw_blk_put(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800944}