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