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