blob: c5428e79b9332dfc41ec0bfac7e10d08d5d28279 [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) {
123 case DRM_FORMAT_RGB565:
124 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;
129 case DRM_FORMAT_ARGB8888:
130 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;
135 case DRM_FORMAT_XRGB8888:
136 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;
141 case DRM_FORMAT_ABGR8888:
142 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;
147 case DRM_FORMAT_XBGR8888:
148 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;
153 case DRM_FORMAT_RGBA8888:
154 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;
161 case DRM_FORMAT_RGBX8888:
162 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;
169 case DRM_FORMAT_BGRA8888:
170 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;
175 case DRM_FORMAT_BGRX8888:
176 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;
223 case DRM_FORMAT_ARGB2101010:
224 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;
229 case DRM_FORMAT_XRGB2101010:
230 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;
235 case DRM_FORMAT_ABGR2101010:
236 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;
241 case DRM_FORMAT_XBGR2101010:
242 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;
247 case DRM_FORMAT_BGRA1010102:
248 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;
253 case DRM_FORMAT_BGRX1010102:
254 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;
259 case DRM_FORMAT_RGBA1010102:
260 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;
267 case DRM_FORMAT_RGBX1010102:
268 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:
301 *drm_pixfmt = DRM_FORMAT_RGB565;
302 *drm_modifier = 0;
303 break;
304 case SDE_PIX_FMT_RGB_565_UBWC:
305 *drm_pixfmt = DRM_FORMAT_RGB565;
306 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
307 DRM_FORMAT_MOD_QCOM_TILE;
308 break;
309 case SDE_PIX_FMT_RGBA_8888:
310 *drm_pixfmt = DRM_FORMAT_RGBA8888;
311 *drm_modifier = 0;
312 break;
313 case SDE_PIX_FMT_RGBX_8888:
314 *drm_pixfmt = DRM_FORMAT_RGBX8888;
315 *drm_modifier = 0;
316 break;
317 case SDE_PIX_FMT_BGRA_8888:
318 *drm_pixfmt = DRM_FORMAT_BGRA8888;
319 *drm_modifier = 0;
320 break;
321 case SDE_PIX_FMT_BGRX_8888:
322 *drm_pixfmt = DRM_FORMAT_BGRX8888;
323 *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:
335 *drm_pixfmt = DRM_FORMAT_RGBA8888;
336 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
337 DRM_FORMAT_MOD_QCOM_TILE;
338 break;
339 case SDE_PIX_FMT_RGBX_8888_UBWC:
340 *drm_pixfmt = DRM_FORMAT_RGBX8888;
341 *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:
349 *drm_pixfmt = DRM_FORMAT_ARGB8888;
350 *drm_modifier = 0;
351 break;
352 case SDE_PIX_FMT_XRGB_8888:
353 *drm_pixfmt = DRM_FORMAT_XRGB8888;
354 *drm_modifier = 0;
355 break;
356 case SDE_PIX_FMT_ABGR_8888:
357 *drm_pixfmt = DRM_FORMAT_ABGR8888;
358 *drm_modifier = 0;
359 break;
360 case SDE_PIX_FMT_XBGR_8888:
361 *drm_pixfmt = DRM_FORMAT_XBGR8888;
362 *drm_modifier = 0;
363 break;
364 case SDE_PIX_FMT_ARGB_2101010:
365 *drm_pixfmt = DRM_FORMAT_ARGB2101010;
366 *drm_modifier = 0;
367 break;
368 case SDE_PIX_FMT_XRGB_2101010:
369 *drm_pixfmt = DRM_FORMAT_XRGB2101010;
370 *drm_modifier = 0;
371 break;
372 case SDE_PIX_FMT_ABGR_2101010:
373 *drm_pixfmt = DRM_FORMAT_ABGR2101010;
374 *drm_modifier = 0;
375 break;
376 case SDE_PIX_FMT_XBGR_2101010:
377 *drm_pixfmt = DRM_FORMAT_XBGR2101010;
378 *drm_modifier = 0;
379 break;
380 case SDE_PIX_FMT_BGRA_1010102:
381 *drm_pixfmt = DRM_FORMAT_BGRA1010102;
382 *drm_modifier = 0;
383 break;
384 case SDE_PIX_FMT_BGRX_1010102:
385 *drm_pixfmt = DRM_FORMAT_BGRX1010102;
386 *drm_modifier = 0;
387 break;
388 case SDE_PIX_FMT_RGBA_8888_TILE:
389 *drm_pixfmt = DRM_FORMAT_RGBA8888;
390 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
391 break;
392 case SDE_PIX_FMT_RGBX_8888_TILE:
393 *drm_pixfmt = DRM_FORMAT_RGBX8888;
394 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
395 break;
396 case SDE_PIX_FMT_BGRA_8888_TILE:
397 *drm_pixfmt = DRM_FORMAT_BGRA8888;
398 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
399 break;
400 case SDE_PIX_FMT_BGRX_8888_TILE:
401 *drm_pixfmt = DRM_FORMAT_BGRX8888;
402 *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:
413 *drm_pixfmt = DRM_FORMAT_ARGB8888;
414 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
415 break;
416 case SDE_PIX_FMT_XRGB_8888_TILE:
417 *drm_pixfmt = DRM_FORMAT_XRGB8888;
418 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
419 break;
420 case SDE_PIX_FMT_ABGR_8888_TILE:
421 *drm_pixfmt = DRM_FORMAT_ABGR8888;
422 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
423 break;
424 case SDE_PIX_FMT_XBGR_8888_TILE:
425 *drm_pixfmt = DRM_FORMAT_XBGR8888;
426 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
427 break;
428 case SDE_PIX_FMT_ARGB_2101010_TILE:
429 *drm_pixfmt = DRM_FORMAT_ARGB2101010;
430 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
431 break;
432 case SDE_PIX_FMT_XRGB_2101010_TILE:
433 *drm_pixfmt = DRM_FORMAT_XRGB2101010;
434 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
435 break;
436 case SDE_PIX_FMT_ABGR_2101010_TILE:
437 *drm_pixfmt = DRM_FORMAT_ABGR2101010;
438 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
439 break;
440 case SDE_PIX_FMT_XBGR_2101010_TILE:
441 *drm_pixfmt = DRM_FORMAT_XBGR2101010;
442 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
443 break;
444 case SDE_PIX_FMT_BGRA_1010102_TILE:
445 *drm_pixfmt = DRM_FORMAT_BGRA1010102;
446 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
447 break;
448 case SDE_PIX_FMT_BGRX_1010102_TILE:
449 *drm_pixfmt = DRM_FORMAT_BGRX1010102;
450 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
451 break;
452 case SDE_PIX_FMT_Y_CBCR_H2V2_P010:
453 *drm_pixfmt = DRM_FORMAT_NV12;
454 *drm_modifier = DRM_FORMAT_MOD_QCOM_DX;
455 break;
456 case SDE_PIX_FMT_Y_CBCR_H2V2_P010_TILE:
457 *drm_pixfmt = DRM_FORMAT_NV12;
458 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE |
459 DRM_FORMAT_MOD_QCOM_DX;
460 break;
Alan Kwong87847ce2017-02-21 08:34:31 -0800461 case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC:
462 *drm_pixfmt = DRM_FORMAT_NV12;
463 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
464 DRM_FORMAT_MOD_QCOM_TILE |
465 DRM_FORMAT_MOD_QCOM_DX;
466 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800467 case SDE_PIX_FMT_Y_CBCR_H2V2_TP10:
468 *drm_pixfmt = DRM_FORMAT_NV12;
469 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE |
470 DRM_FORMAT_MOD_QCOM_DX |
471 DRM_FORMAT_MOD_QCOM_TIGHT;
472 break;
473 case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC:
474 *drm_pixfmt = DRM_FORMAT_NV12;
475 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
476 DRM_FORMAT_MOD_QCOM_TILE |
477 DRM_FORMAT_MOD_QCOM_DX |
478 DRM_FORMAT_MOD_QCOM_TIGHT;
479 break;
480 default:
481 SDE_DEBUG("invalid v4l2 pixel format %c%c%c%c\n",
482 pixfmt >> 0, pixfmt >> 8,
483 pixfmt >> 16, pixfmt >> 24);
484 rc = -EINVAL;
485 break;
486 }
487
488 return rc;
489}
490
491/**
492 * sde_hw_rot_to_v4l2_buffer - convert drm buffer to v4l2 buffer
493 * @drm_pixfmt: pixel format in drm fourcc
494 * @drm_modifier: pixel format modifier
495 * @drm_addr: drm buffer address per plane
496 * @drm_len: drm buffer length per plane
497 * @drm_planes: drm buffer number of planes
498 * @v4l_addr: v4l2 buffer address per plane
499 * @v4l_len: v4l2 buffer length per plane
500 * @v4l_planes: v4l2 buffer number of planes
501 */
502static void sde_hw_rot_to_v4l2_buffer(u32 drm_pixfmt, u64 drm_modifier,
503 dma_addr_t *drm_addr, u32 *drm_len, u32 *drm_planes,
504 dma_addr_t *v4l_addr, u32 *v4l_len, u32 *v4l_planes)
505{
506 int i, total_size = 0;
507
508 for (i = 0; i < SDE_ROTATOR_INLINE_PLANE_MAX; i++) {
509 v4l_addr[i] = drm_addr[i];
510 v4l_len[i] = drm_len[i];
511 total_size += drm_len[i];
512 SDE_DEBUG("drm[%d]:%pad/%x\n", i, &drm_addr[i], drm_len[i]);
513 }
514
515 if (SDE_MODIFIER_IS_UBWC(drm_modifier)) {
516 /* v4l2 driver uses plane[0] as single ubwc buffer plane */
517 v4l_addr[0] = drm_addr[2];
518 v4l_len[0] = total_size;
519 *v4l_planes = 1;
520 SDE_DEBUG("v4l2[0]:%pad/%x/%d\n", &v4l_addr[0], v4l_len[0],
521 *v4l_planes);
522 } else {
523 *v4l_planes = *drm_planes;
524 }
525}
526
527/**
528 * sde_hw_rot_commit - commit/execute given rotator command
529 * @hw: Pointer to rotator hardware driver
530 * @data: Pointer to command descriptor
531 * @hw_cmd: type of command to be executed
532 * return: 0 if success; error code otherwise
533 */
534static int sde_hw_rot_commit(struct sde_hw_rot *hw, struct sde_hw_rot_cmd *data,
535 enum sde_hw_rot_cmd_type hw_cmd)
536{
537 struct sde_rotator_inline_cmd rot_cmd;
538 enum sde_rotator_inline_cmd_type cmd_type;
539 void *priv_handle = NULL;
540 int rc;
541
542 if (!hw || !data) {
543 SDE_ERROR("invalid parameter\n");
544 return -EINVAL;
545 }
546
547 memset(&rot_cmd, 0, sizeof(struct sde_rotator_inline_cmd));
548
549 switch (hw_cmd) {
550 case SDE_HW_ROT_CMD_VALIDATE:
551 cmd_type = SDE_ROTATOR_INLINE_CMD_VALIDATE;
552 break;
553 case SDE_HW_ROT_CMD_COMMIT:
554 cmd_type = SDE_ROTATOR_INLINE_CMD_COMMIT;
555 break;
556 case SDE_HW_ROT_CMD_CLEANUP:
557 cmd_type = SDE_ROTATOR_INLINE_CMD_CLEANUP;
558 priv_handle = data->priv_handle;
559 break;
560 default:
561 SDE_ERROR("invalid hw rotator command %d\n", hw_cmd);
562 return -EINVAL;
563 }
564
565 rot_cmd.video_mode = data->video_mode;
566 rot_cmd.fps = data->fps;
567 rot_cmd.rot90 = data->rot90;
568 rot_cmd.hflip = data->hflip;
569 rot_cmd.vflip = data->vflip;
570 rot_cmd.secure = data->secure;
571 rot_cmd.clkrate = data->clkrate;
Alan Kwong4aacd532017-02-04 18:51:33 -0800572 rot_cmd.data_bw = 0;
573 rot_cmd.prefill_bw = data->prefill_bw;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800574 rot_cmd.src_width = data->src_width;
575 rot_cmd.src_height = data->src_height;
576 rot_cmd.src_rect_x = data->src_rect_x;
577 rot_cmd.src_rect_y = data->src_rect_y;
578 rot_cmd.src_rect_w = data->src_rect_w;
579 rot_cmd.src_rect_h = data->src_rect_h;
580 rot_cmd.dst_writeback = data->dst_writeback;
581 rot_cmd.dst_rect_x = data->dst_rect_x;
582 rot_cmd.dst_rect_y = data->dst_rect_y;
583 rot_cmd.dst_rect_w = data->dst_rect_w;
584 rot_cmd.dst_rect_h = data->dst_rect_h;
585 rot_cmd.priv_handle = priv_handle;
586
587 rc = sde_hw_rot_to_v4l2_pixfmt(data->src_pixel_format,
588 data->src_modifier, &rot_cmd.src_pixfmt);
589 if (rc) {
590 SDE_ERROR("invalid src format %d\n", rc);
591 return rc;
592 }
593
594 /* calculate preferred output format during validation */
595 if (hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
596 rc = sde_rotator_inline_get_dst_pixfmt(hw->caps->pdev,
597 rot_cmd.src_pixfmt, &rot_cmd.dst_pixfmt);
598 if (rc) {
599 SDE_ERROR("invalid src format %d\n", rc);
600 return rc;
601 }
602
603 rc = sde_hw_rot_to_drm_pixfmt(rot_cmd.dst_pixfmt,
604 &data->dst_pixel_format, &data->dst_modifier);
605 if (rc) {
606 SDE_ERROR("invalid dst format %c%c%c%c\n",
607 rot_cmd.dst_pixfmt >> 0,
608 rot_cmd.dst_pixfmt >> 8,
609 rot_cmd.dst_pixfmt >> 16,
610 rot_cmd.dst_pixfmt >> 24);
611 return rc;
612 }
613
614 data->dst_format = sde_get_sde_format_ext(
615 data->dst_pixel_format, &data->dst_modifier, 1);
616 if (!data->dst_format) {
617 SDE_ERROR("failed to get dst format\n");
618 return -EINVAL;
619 }
620 } else if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
621 rc = sde_hw_rot_to_v4l2_pixfmt(data->dst_pixel_format,
622 data->dst_modifier, &rot_cmd.dst_pixfmt);
623 if (rc) {
624 SDE_ERROR("invalid dst format %d\n", rc);
625 return rc;
626 }
627
628 sde_hw_rot_to_v4l2_buffer(data->src_pixel_format,
629 data->src_modifier,
630 data->src_iova, data->src_len,
631 &data->src_planes,
632 rot_cmd.src_addr, rot_cmd.src_len,
633 &rot_cmd.src_planes);
634
635 sde_hw_rot_to_v4l2_buffer(data->dst_pixel_format,
636 data->dst_modifier,
637 data->dst_iova, data->dst_len,
638 &data->dst_planes,
639 rot_cmd.dst_addr, rot_cmd.dst_len,
640 &rot_cmd.dst_planes);
641 }
642
643 /* only process any command if client is master or for validation */
644 if (data->master || hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
645 SDE_DEBUG("dispatch seq:%d cmd:%d\n", data->sequence_id,
646 hw_cmd);
647
648 rc = sde_rotator_inline_commit(hw->rot_ctx, &rot_cmd, cmd_type);
649 if (rc) {
650 SDE_ERROR("failed to commit inline rotation %d\n", rc);
651 return rc;
652 }
653
654 /* return to caller */
655 data->priv_handle = rot_cmd.priv_handle;
656 } else {
657 SDE_DEBUG("bypass seq:%d cmd:%d\n", data->sequence_id, hw_cmd);
658 }
659
660 return 0;
661}
662
663/**
664 * sde_hw_rot_get_format_caps - get pixel format capability
665 * @hw: Pointer to rotator hardware driver
666 * return: Pointer to pixel format capability array: NULL otherwise
667 */
668static const struct sde_format_extended *sde_hw_rot_get_format_caps(
669 struct sde_hw_rot *hw)
670{
671 int rc, i, j, len;
672 u32 *v4l_pixfmts;
673 struct sde_format_extended *drm_pixfmts;
674 struct platform_device *pdev;
675
676 if (!hw || !hw->caps || !hw->caps->pdev) {
677 SDE_ERROR("invalid rotator hw\n");
678 return NULL;
679 }
680
681 pdev = hw->caps->pdev;
682
683 if (hw->format_caps)
684 return hw->format_caps;
685
686 len = sde_rotator_inline_get_pixfmt_caps(pdev, true, NULL, 0);
687 if (len < 0) {
688 SDE_ERROR("invalid pixfmt caps %d\n", len);
689 return NULL;
690 }
691
692 v4l_pixfmts = kcalloc(len, sizeof(u32), GFP_KERNEL);
693 if (!v4l_pixfmts)
694 goto done;
695
696 sde_rotator_inline_get_pixfmt_caps(pdev, true, v4l_pixfmts, len);
697
698 /* allocate one more to indicate termination */
699 drm_pixfmts = kzalloc((len + 1) * sizeof(struct sde_format_extended),
700 GFP_KERNEL);
701 if (!drm_pixfmts)
702 goto done;
703
704 for (i = 0, j = 0; i < len; i++) {
705 rc = sde_hw_rot_to_drm_pixfmt(v4l_pixfmts[i],
706 &drm_pixfmts[j].fourcc_format,
707 &drm_pixfmts[j].modifier);
708 if (!rc) {
709 SDE_DEBUG("%d: vl42:%c%c%c%c => drm:%c%c%c%c/0x%llx\n",
710 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
711 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24,
712 drm_pixfmts[j].fourcc_format >> 0,
713 drm_pixfmts[j].fourcc_format >> 8,
714 drm_pixfmts[j].fourcc_format >> 16,
715 drm_pixfmts[j].fourcc_format >> 24,
716 drm_pixfmts[j].modifier);
717 j++;
718 } else {
719 SDE_DEBUG("%d: vl42:%c%c%c%c not mapped\n",
720 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
721 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24);
722 }
723 }
724
725 hw->format_caps = drm_pixfmts;
726done:
727 kfree(v4l_pixfmts);
728
729 return hw->format_caps;
730}
731
732/**
733 * sde_hw_rot_get_downscale_caps - get scaling capability string
734 * @hw: Pointer to rotator hardware driver
735 * return: Pointer to capability string: NULL otherwise
736 */
737static const char *sde_hw_rot_get_downscale_caps(struct sde_hw_rot *hw)
738{
739 int len;
740 struct platform_device *pdev;
741
742 if (!hw || !hw->caps || !hw->caps->pdev) {
743 SDE_ERROR("invalid rotator hw\n");
744 return NULL;
745 }
746
747 pdev = hw->caps->pdev;
748
749 if (hw->downscale_caps)
750 return hw->downscale_caps;
751
752 len = sde_rotator_inline_get_downscale_caps(pdev, NULL, 0);
753 if (len < 0) {
754 SDE_ERROR("invalid scaling caps %d\n", len);
755 return NULL;
756 }
757
758 /* add one for ending zero */
759 len += 1;
760 hw->downscale_caps = kzalloc(len, GFP_KERNEL);
761 sde_rotator_inline_get_downscale_caps(pdev, hw->downscale_caps, len);
762
763 return hw->downscale_caps;
764}
765
766/**
767 * sde_hw_rot_get_cache_size - get cache size
768 * @hw: Pointer to rotator hardware driver
769 * return: size of cache
770 */
771static size_t sde_hw_rot_get_cache_size(struct sde_hw_rot *hw)
772{
773 if (!hw || !hw->caps) {
774 SDE_ERROR("invalid rotator hw\n");
775 return 0;
776 }
777
778 return hw->caps->slice_size;
779}
780
781/**
782 * _setup_rot_ops - setup rotator operations
783 * @ops: Pointer to operation table
784 * @features: available feature bitmask
785 * return: none
786 */
787static void _setup_rot_ops(struct sde_hw_rot_ops *ops, unsigned long features)
788{
789 ops->commit = sde_hw_rot_commit;
790 ops->get_format_caps = sde_hw_rot_get_format_caps;
791 ops->get_downscale_caps = sde_hw_rot_get_downscale_caps;
792 ops->get_cache_size = sde_hw_rot_get_cache_size;
793}
794
795/**
Alan Kwong4dd64c82017-02-04 18:41:51 -0800796 * sde_hw_rot_blk_stop - stop rotator block
797 * @hw_blk: Pointer to base hardware block
798 * return: none
799 */
800static void sde_hw_rot_blk_stop(struct sde_hw_blk *hw_blk)
801{
802 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
803
804 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
805
806 sde_hw_rot_stop(hw_rot);
807}
808
809/**
810 * sde_hw_rot_blk_start - art rotator block
811 * @hw_blk: Pointer to base hardware block
812 * return: 0 if success; error code otherwise
813 */
814static int sde_hw_rot_blk_start(struct sde_hw_blk *hw_blk)
815{
816 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
817 int rc = 0;
818
819 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
820
821 rc = sde_hw_rot_start(hw_rot);
822
823 return rc;
824}
825
Alan Kwongcdb2f282017-03-18 13:42:06 -0700826static struct sde_hw_blk_ops sde_hw_rot_ops = {
827 .start = sde_hw_rot_blk_start,
828 .stop = sde_hw_rot_blk_stop,
829};
830
831/**
832 * sde_hw_rot_init - create/initialize given rotator instance
833 * @idx: index of given rotator
834 * @addr: i/o address mapping
835 * @m: Pointer to mdss catalog
836 * return: Pointer to hardware rotator driver of the given instance
837 */
838struct sde_hw_rot *sde_hw_rot_init(enum sde_rot idx,
839 void __iomem *addr,
840 struct sde_mdss_cfg *m)
841{
842 struct sde_hw_rot *c;
843 struct sde_rot_cfg *cfg;
844 int rc;
845
846 c = kzalloc(sizeof(*c), GFP_KERNEL);
847 if (!c)
848 return ERR_PTR(-ENOMEM);
849
850 cfg = _rot_offset(idx, m, addr, &c->hw);
851 if (IS_ERR(cfg)) {
852 WARN(1, "Unable to find rot idx=%d\n", idx);
853 kfree(c);
854 return ERR_PTR(-EINVAL);
855 }
856
857 /* Assign ops */
858 c->idx = idx;
859 c->caps = cfg;
860 _setup_rot_ops(&c->ops, c->caps->features);
861
862 rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_ROT, idx,
863 &sde_hw_rot_ops);
864 if (rc) {
865 SDE_ERROR("failed to init hw blk %d\n", rc);
866 goto blk_init_error;
867 }
868
869 return c;
870
871blk_init_error:
872 kzfree(c);
873
874 return ERR_PTR(rc);
875}
876
877/**
878 * sde_hw_rot_destroy - destroy given hardware rotator driver
879 * @hw_rot: Pointer to hardware rotator driver
880 * return: none
881 */
882void sde_hw_rot_destroy(struct sde_hw_rot *hw_rot)
883{
884 sde_hw_blk_destroy(&hw_rot->base);
885 kfree(hw_rot->downscale_caps);
886 kfree(hw_rot->format_caps);
887 kfree(hw_rot);
888}
889
Alan Kwong4dd64c82017-02-04 18:41:51 -0800890struct sde_hw_rot *sde_hw_rot_get(struct sde_hw_rot *hw_rot)
891{
892 struct sde_hw_blk *hw_blk = sde_hw_blk_get(hw_rot ? &hw_rot->base :
893 NULL, SDE_HW_BLK_ROT, -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800894
Alan Kwongcdb2f282017-03-18 13:42:06 -0700895 return IS_ERR_OR_NULL(hw_blk) ? NULL : to_sde_hw_rot(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800896}
897
898void sde_hw_rot_put(struct sde_hw_rot *hw_rot)
899{
900 struct sde_hw_blk *hw_blk = hw_rot ? &hw_rot->base : NULL;
901
Alan Kwongcdb2f282017-03-18 13:42:06 -0700902 sde_hw_blk_put(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800903}