blob: 8d386a8c0cad1b2a7d0c310518a8406dd3e88777 [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/**
Alan Kwongaa53e682017-07-31 18:21:15 -040065 * _sde_hw_rot_reg_dump - perform register dump
66 * @ptr: private pointer to rotator platform device
67 * return: None
68 */
69static void _sde_hw_rot_reg_dump(void *ptr)
70{
71 sde_rotator_inline_reg_dump((struct platform_device *) ptr);
72}
73
74/**
Alan Kwong4dd64c82017-02-04 18:41:51 -080075 * sde_hw_rot_start - start rotator before any commit
76 * @hw: Pointer to rotator hardware driver
77 * return: 0 if success; error code otherwise
78 */
79static int sde_hw_rot_start(struct sde_hw_rot *hw)
80{
81 struct platform_device *pdev;
82 int rc;
83
84 if (!hw || !hw->caps || !hw->caps->pdev) {
85 SDE_ERROR("invalid parameters\n");
86 return -EINVAL;
87 }
88
89 pdev = hw->caps->pdev;
90
Alan Kwongaa53e682017-07-31 18:21:15 -040091 rc = sde_dbg_reg_register_cb(hw->name, _sde_hw_rot_reg_dump, pdev);
92 if (rc)
93 SDE_ERROR("failed to register debug dump %d\n", rc);
94
Alan Kwong4dd64c82017-02-04 18:41:51 -080095 hw->rot_ctx = sde_rotator_inline_open(pdev);
96 if (IS_ERR_OR_NULL(hw->rot_ctx)) {
97 rc = PTR_ERR(hw->rot_ctx);
98 hw->rot_ctx = NULL;
99 return rc;
100 }
101
102 return 0;
103}
104
105/**
106 * sde_hw_rot_stop - stop rotator after final commit
107 * @hw: Pointer to rotator hardware driver
108 * return: none
109 */
110static void sde_hw_rot_stop(struct sde_hw_rot *hw)
111{
Alan Kwongaa53e682017-07-31 18:21:15 -0400112 if (!hw || !hw->caps || !hw->caps->pdev) {
Alan Kwong4dd64c82017-02-04 18:41:51 -0800113 SDE_ERROR("invalid parameter\n");
114 return;
115 }
116
117 sde_rotator_inline_release(hw->rot_ctx);
118 hw->rot_ctx = NULL;
Alan Kwongaa53e682017-07-31 18:21:15 -0400119
120 sde_dbg_reg_unregister_cb(hw->name, _sde_hw_rot_reg_dump,
121 hw->caps->pdev);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800122}
123
124/**
125 * sde_hw_rot_to_v4l2_pixfmt - convert drm pixel format to v4l2 pixel format
126 * @drm_pixfmt: drm fourcc pixel format
127 * @drm_modifier: drm pixel format modifier
128 * @pixfmt: Pointer to v4l2 fourcc pixel format (output)
129 * return: 0 if success; error code otherwise
130 */
131static int sde_hw_rot_to_v4l2_pixfmt(u32 drm_pixfmt, u64 drm_modifier,
132 u32 *pixfmt)
133{
134 u32 rc = 0;
135
136 if (!pixfmt)
137 return -EINVAL;
138
139 switch (drm_pixfmt) {
Alan Kwong75316d92017-03-31 14:12:05 -0700140 case DRM_FORMAT_BGR565:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800141 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
142 *pixfmt = SDE_PIX_FMT_RGB_565_UBWC;
143 else
144 *pixfmt = SDE_PIX_FMT_RGB_565;
145 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700146 case DRM_FORMAT_BGRA8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800147 if (SDE_MODIFIER_IS_TILE(drm_modifier))
148 *pixfmt = SDE_PIX_FMT_ARGB_8888_TILE;
149 else
150 *pixfmt = SDE_PIX_FMT_ARGB_8888;
151 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700152 case DRM_FORMAT_BGRX8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800153 if (SDE_MODIFIER_IS_TILE(drm_modifier))
154 *pixfmt = SDE_PIX_FMT_XRGB_8888_TILE;
155 else
156 *pixfmt = SDE_PIX_FMT_XRGB_8888;
157 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700158 case DRM_FORMAT_RGBA8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800159 if (SDE_MODIFIER_IS_TILE(drm_modifier))
160 *pixfmt = SDE_PIX_FMT_ABGR_8888_TILE;
161 else
162 *pixfmt = SDE_PIX_FMT_ABGR_8888;
163 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700164 case DRM_FORMAT_RGBX8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800165 if (SDE_MODIFIER_IS_TILE(drm_modifier))
166 *pixfmt = SDE_PIX_FMT_XBGR_8888_TILE;
167 else
168 *pixfmt = SDE_PIX_FMT_XBGR_8888;
169 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700170 case DRM_FORMAT_ABGR8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800171 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
172 *pixfmt = SDE_PIX_FMT_RGBA_8888_UBWC;
173 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
174 *pixfmt = SDE_PIX_FMT_RGBA_8888_TILE;
175 else
176 *pixfmt = SDE_PIX_FMT_RGBA_8888;
177 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700178 case DRM_FORMAT_XBGR8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800179 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
180 *pixfmt = SDE_PIX_FMT_RGBX_8888_UBWC;
181 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
182 *pixfmt = SDE_PIX_FMT_RGBX_8888_TILE;
183 else
184 *pixfmt = SDE_PIX_FMT_RGBX_8888;
185 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700186 case DRM_FORMAT_ARGB8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800187 if (SDE_MODIFIER_IS_TILE(drm_modifier))
188 *pixfmt = SDE_PIX_FMT_BGRA_8888_TILE;
189 else
190 *pixfmt = SDE_PIX_FMT_BGRA_8888;
191 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700192 case DRM_FORMAT_XRGB8888:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800193 if (SDE_MODIFIER_IS_TILE(drm_modifier))
194 *pixfmt = SDE_PIX_FMT_BGRX_8888_TILE;
195 else
196 *pixfmt = SDE_PIX_FMT_BGRX_8888;
197 break;
198 case DRM_FORMAT_NV12:
199 if (SDE_MODIFIER_IS_UBWC(drm_modifier)) {
Alan Kwong87847ce2017-02-21 08:34:31 -0800200 if (SDE_MODIFIER_IS_10B(drm_modifier)) {
201 if (SDE_MODIFIER_IS_TIGHT(drm_modifier))
202 *pixfmt =
203 SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC;
204 else
205 *pixfmt =
206 SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC;
207 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -0800208 *pixfmt = SDE_PIX_FMT_Y_CBCR_H2V2_UBWC;
Alan Kwong87847ce2017-02-21 08:34:31 -0800209 }
Alan Kwong4dd64c82017-02-04 18:41:51 -0800210 } else if (SDE_MODIFIER_IS_TILE(drm_modifier)) {
211 if (SDE_MODIFIER_IS_10B(drm_modifier)) {
212 if (SDE_MODIFIER_IS_TIGHT(drm_modifier))
213 *pixfmt =
214 SDE_PIX_FMT_Y_CBCR_H2V2_TP10;
215 else
216 *pixfmt =
217 SDE_PIX_FMT_Y_CBCR_H2V2_P010_TILE;
218 } else {
219 *pixfmt = SDE_PIX_FMT_Y_CBCR_H2V2_TILE;
220 }
221 } else {
222 if (SDE_MODIFIER_IS_10B(drm_modifier)) {
223 if (SDE_MODIFIER_IS_TIGHT(drm_modifier))
224 *pixfmt =
225 SDE_PIX_FMT_Y_CBCR_H2V2_TP10;
226 else
227 *pixfmt =
228 SDE_PIX_FMT_Y_CBCR_H2V2_P010;
229 } else {
230 *pixfmt = SDE_PIX_FMT_Y_CBCR_H2V2;
231 }
232 }
233 break;
234 case DRM_FORMAT_NV21:
235 if (SDE_MODIFIER_IS_TILE(drm_modifier))
236 *pixfmt = SDE_PIX_FMT_Y_CRCB_H2V2_TILE;
237 else
238 *pixfmt = SDE_PIX_FMT_Y_CRCB_H2V2;
239 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700240 case DRM_FORMAT_BGRA1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800241 if (SDE_MODIFIER_IS_TILE(drm_modifier))
242 *pixfmt = SDE_PIX_FMT_ARGB_2101010_TILE;
243 else
244 *pixfmt = SDE_PIX_FMT_ARGB_2101010;
245 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700246 case DRM_FORMAT_BGRX1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800247 if (SDE_MODIFIER_IS_TILE(drm_modifier))
248 *pixfmt = SDE_PIX_FMT_XRGB_2101010_TILE;
249 else
250 *pixfmt = SDE_PIX_FMT_XRGB_2101010;
251 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700252 case DRM_FORMAT_RGBA1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800253 if (SDE_MODIFIER_IS_TILE(drm_modifier))
254 *pixfmt = SDE_PIX_FMT_ABGR_2101010_TILE;
255 else
256 *pixfmt = SDE_PIX_FMT_ABGR_2101010;
257 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700258 case DRM_FORMAT_RGBX1010102:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800259 if (SDE_MODIFIER_IS_TILE(drm_modifier))
260 *pixfmt = SDE_PIX_FMT_XBGR_2101010_TILE;
261 else
262 *pixfmt = SDE_PIX_FMT_XBGR_2101010;
263 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700264 case DRM_FORMAT_ARGB2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800265 if (SDE_MODIFIER_IS_TILE(drm_modifier))
266 *pixfmt = SDE_PIX_FMT_BGRA_1010102_TILE;
267 else
268 *pixfmt = SDE_PIX_FMT_BGRA_1010102;
269 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700270 case DRM_FORMAT_XRGB2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800271 if (SDE_MODIFIER_IS_TILE(drm_modifier))
272 *pixfmt = SDE_PIX_FMT_BGRX_1010102_TILE;
273 else
274 *pixfmt = SDE_PIX_FMT_BGRX_1010102;
275 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700276 case DRM_FORMAT_ABGR2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800277 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
278 *pixfmt = SDE_PIX_FMT_RGBA_1010102_UBWC;
279 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
280 *pixfmt = SDE_PIX_FMT_RGBA_1010102_TILE;
281 else
282 *pixfmt = SDE_PIX_FMT_RGBA_1010102;
283 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700284 case DRM_FORMAT_XBGR2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800285 if (SDE_MODIFIER_IS_UBWC(drm_modifier))
286 *pixfmt = SDE_PIX_FMT_RGBX_1010102_UBWC;
287 else if (SDE_MODIFIER_IS_TILE(drm_modifier))
288 *pixfmt = SDE_PIX_FMT_RGBX_1010102_TILE;
289 else
290 *pixfmt = SDE_PIX_FMT_RGBX_1010102;
291 break;
292 default:
293 SDE_ERROR("invalid drm pixel format %c%c%c%c/%llx\n",
294 drm_pixfmt >> 0, drm_pixfmt >> 8,
295 drm_pixfmt >> 16, drm_pixfmt >> 24,
296 drm_modifier);
297 rc = -EINVAL;
298 break;
299 }
300
301 return rc;
302}
303
304/**
305 * sde_hw_rot_to_drm_pixfmt - convert v4l2 pixel format to drm pixel format
306 * @pixfmt: v4l2 fourcc pixel format
307 * @drm_pixfmt: Pointer to drm forucc pixel format (output)
308 * @drm_modifier: Pointer to drm pixel format modifier (output)
309 * return: 0 if success; error code otherwise
310 */
311static int sde_hw_rot_to_drm_pixfmt(u32 pixfmt, u32 *drm_pixfmt,
312 u64 *drm_modifier)
313{
314 u32 rc = 0;
315
316 switch (pixfmt) {
317 case SDE_PIX_FMT_RGB_565:
Alan Kwong75316d92017-03-31 14:12:05 -0700318 *drm_pixfmt = DRM_FORMAT_BGR565;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800319 *drm_modifier = 0;
320 break;
321 case SDE_PIX_FMT_RGB_565_UBWC:
Alan Kwong75316d92017-03-31 14:12:05 -0700322 *drm_pixfmt = DRM_FORMAT_BGR565;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800323 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
324 DRM_FORMAT_MOD_QCOM_TILE;
325 break;
326 case SDE_PIX_FMT_RGBA_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700327 *drm_pixfmt = DRM_FORMAT_ABGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800328 *drm_modifier = 0;
329 break;
330 case SDE_PIX_FMT_RGBX_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700331 *drm_pixfmt = DRM_FORMAT_XBGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800332 *drm_modifier = 0;
333 break;
334 case SDE_PIX_FMT_BGRA_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700335 *drm_pixfmt = DRM_FORMAT_ARGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800336 *drm_modifier = 0;
337 break;
338 case SDE_PIX_FMT_BGRX_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700339 *drm_pixfmt = DRM_FORMAT_XRGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800340 *drm_modifier = 0;
341 break;
342 case SDE_PIX_FMT_Y_CBCR_H2V2_UBWC:
343 *drm_pixfmt = DRM_FORMAT_NV12;
344 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
345 DRM_FORMAT_MOD_QCOM_TILE;
346 break;
347 case SDE_PIX_FMT_Y_CRCB_H2V2:
348 *drm_pixfmt = DRM_FORMAT_NV21;
349 *drm_modifier = 0;
350 break;
351 case SDE_PIX_FMT_RGBA_8888_UBWC:
Alan Kwong75316d92017-03-31 14:12:05 -0700352 *drm_pixfmt = DRM_FORMAT_ABGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800353 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
354 DRM_FORMAT_MOD_QCOM_TILE;
355 break;
356 case SDE_PIX_FMT_RGBX_8888_UBWC:
Alan Kwong75316d92017-03-31 14:12:05 -0700357 *drm_pixfmt = DRM_FORMAT_XBGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800358 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
359 DRM_FORMAT_MOD_QCOM_TILE;
360 break;
361 case SDE_PIX_FMT_Y_CBCR_H2V2:
362 *drm_pixfmt = DRM_FORMAT_NV12;
363 *drm_modifier = 0;
364 break;
365 case SDE_PIX_FMT_ARGB_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700366 *drm_pixfmt = DRM_FORMAT_BGRA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800367 *drm_modifier = 0;
368 break;
369 case SDE_PIX_FMT_XRGB_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700370 *drm_pixfmt = DRM_FORMAT_BGRX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800371 *drm_modifier = 0;
372 break;
373 case SDE_PIX_FMT_ABGR_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700374 *drm_pixfmt = DRM_FORMAT_RGBA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800375 *drm_modifier = 0;
376 break;
377 case SDE_PIX_FMT_XBGR_8888:
Alan Kwong75316d92017-03-31 14:12:05 -0700378 *drm_pixfmt = DRM_FORMAT_RGBX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800379 *drm_modifier = 0;
380 break;
381 case SDE_PIX_FMT_ARGB_2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800382 *drm_pixfmt = DRM_FORMAT_BGRA1010102;
383 *drm_modifier = 0;
384 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700385 case SDE_PIX_FMT_XRGB_2101010:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800386 *drm_pixfmt = DRM_FORMAT_BGRX1010102;
387 *drm_modifier = 0;
388 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700389 case SDE_PIX_FMT_ABGR_2101010:
390 *drm_pixfmt = DRM_FORMAT_RGBA1010102;
391 *drm_modifier = 0;
392 break;
393 case SDE_PIX_FMT_XBGR_2101010:
394 *drm_pixfmt = DRM_FORMAT_RGBX1010102;
395 *drm_modifier = 0;
396 break;
397 case SDE_PIX_FMT_BGRA_1010102:
398 *drm_pixfmt = DRM_FORMAT_ARGB2101010;
399 *drm_modifier = 0;
400 break;
401 case SDE_PIX_FMT_BGRX_1010102:
402 *drm_pixfmt = DRM_FORMAT_XRGB2101010;
403 *drm_modifier = 0;
404 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800405 case SDE_PIX_FMT_RGBA_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700406 *drm_pixfmt = DRM_FORMAT_ABGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800407 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
408 break;
409 case SDE_PIX_FMT_RGBX_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700410 *drm_pixfmt = DRM_FORMAT_XBGR8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800411 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
412 break;
413 case SDE_PIX_FMT_BGRA_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700414 *drm_pixfmt = DRM_FORMAT_ARGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800415 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
416 break;
417 case SDE_PIX_FMT_BGRX_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700418 *drm_pixfmt = DRM_FORMAT_XRGB8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800419 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
420 break;
421 case SDE_PIX_FMT_Y_CRCB_H2V2_TILE:
422 *drm_pixfmt = DRM_FORMAT_NV21;
423 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
424 break;
425 case SDE_PIX_FMT_Y_CBCR_H2V2_TILE:
426 *drm_pixfmt = DRM_FORMAT_NV12;
427 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
428 break;
429 case SDE_PIX_FMT_ARGB_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700430 *drm_pixfmt = DRM_FORMAT_BGRA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800431 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
432 break;
433 case SDE_PIX_FMT_XRGB_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700434 *drm_pixfmt = DRM_FORMAT_BGRX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800435 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
436 break;
437 case SDE_PIX_FMT_ABGR_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700438 *drm_pixfmt = DRM_FORMAT_RGBA8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800439 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
440 break;
441 case SDE_PIX_FMT_XBGR_8888_TILE:
Alan Kwong75316d92017-03-31 14:12:05 -0700442 *drm_pixfmt = DRM_FORMAT_RGBX8888;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800443 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
444 break;
445 case SDE_PIX_FMT_ARGB_2101010_TILE:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800446 *drm_pixfmt = DRM_FORMAT_BGRA1010102;
447 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
448 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700449 case SDE_PIX_FMT_XRGB_2101010_TILE:
Alan Kwong4dd64c82017-02-04 18:41:51 -0800450 *drm_pixfmt = DRM_FORMAT_BGRX1010102;
451 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
452 break;
Alan Kwong75316d92017-03-31 14:12:05 -0700453 case SDE_PIX_FMT_ABGR_2101010_TILE:
454 *drm_pixfmt = DRM_FORMAT_RGBA1010102;
455 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
456 break;
457 case SDE_PIX_FMT_XBGR_2101010_TILE:
458 *drm_pixfmt = DRM_FORMAT_RGBX1010102;
459 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
460 break;
461 case SDE_PIX_FMT_BGRA_1010102_TILE:
462 *drm_pixfmt = DRM_FORMAT_ARGB2101010;
463 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
464 break;
465 case SDE_PIX_FMT_BGRX_1010102_TILE:
466 *drm_pixfmt = DRM_FORMAT_XRGB2101010;
467 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE;
468 break;
469 case SDE_PIX_FMT_RGBA_1010102_UBWC:
470 *drm_pixfmt = DRM_FORMAT_ABGR2101010;
471 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
472 DRM_FORMAT_MOD_QCOM_TILE;
473 break;
474 case SDE_PIX_FMT_RGBX_1010102_UBWC:
475 *drm_pixfmt = DRM_FORMAT_XBGR2101010;
476 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
477 DRM_FORMAT_MOD_QCOM_TILE;
478 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800479 case SDE_PIX_FMT_Y_CBCR_H2V2_P010:
480 *drm_pixfmt = DRM_FORMAT_NV12;
481 *drm_modifier = DRM_FORMAT_MOD_QCOM_DX;
482 break;
483 case SDE_PIX_FMT_Y_CBCR_H2V2_P010_TILE:
484 *drm_pixfmt = DRM_FORMAT_NV12;
485 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE |
486 DRM_FORMAT_MOD_QCOM_DX;
487 break;
Alan Kwong87847ce2017-02-21 08:34:31 -0800488 case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC:
489 *drm_pixfmt = DRM_FORMAT_NV12;
490 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
491 DRM_FORMAT_MOD_QCOM_TILE |
492 DRM_FORMAT_MOD_QCOM_DX;
493 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800494 case SDE_PIX_FMT_Y_CBCR_H2V2_TP10:
495 *drm_pixfmt = DRM_FORMAT_NV12;
496 *drm_modifier = DRM_FORMAT_MOD_QCOM_TILE |
497 DRM_FORMAT_MOD_QCOM_DX |
498 DRM_FORMAT_MOD_QCOM_TIGHT;
499 break;
500 case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC:
501 *drm_pixfmt = DRM_FORMAT_NV12;
502 *drm_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
503 DRM_FORMAT_MOD_QCOM_TILE |
504 DRM_FORMAT_MOD_QCOM_DX |
505 DRM_FORMAT_MOD_QCOM_TIGHT;
506 break;
507 default:
508 SDE_DEBUG("invalid v4l2 pixel format %c%c%c%c\n",
509 pixfmt >> 0, pixfmt >> 8,
510 pixfmt >> 16, pixfmt >> 24);
511 rc = -EINVAL;
512 break;
513 }
514
515 return rc;
516}
517
518/**
519 * sde_hw_rot_to_v4l2_buffer - convert drm buffer to v4l2 buffer
520 * @drm_pixfmt: pixel format in drm fourcc
521 * @drm_modifier: pixel format modifier
522 * @drm_addr: drm buffer address per plane
523 * @drm_len: drm buffer length per plane
524 * @drm_planes: drm buffer number of planes
525 * @v4l_addr: v4l2 buffer address per plane
526 * @v4l_len: v4l2 buffer length per plane
527 * @v4l_planes: v4l2 buffer number of planes
528 */
529static void sde_hw_rot_to_v4l2_buffer(u32 drm_pixfmt, u64 drm_modifier,
530 dma_addr_t *drm_addr, u32 *drm_len, u32 *drm_planes,
531 dma_addr_t *v4l_addr, u32 *v4l_len, u32 *v4l_planes)
532{
533 int i, total_size = 0;
534
535 for (i = 0; i < SDE_ROTATOR_INLINE_PLANE_MAX; i++) {
536 v4l_addr[i] = drm_addr[i];
537 v4l_len[i] = drm_len[i];
538 total_size += drm_len[i];
539 SDE_DEBUG("drm[%d]:%pad/%x\n", i, &drm_addr[i], drm_len[i]);
540 }
541
542 if (SDE_MODIFIER_IS_UBWC(drm_modifier)) {
543 /* v4l2 driver uses plane[0] as single ubwc buffer plane */
544 v4l_addr[0] = drm_addr[2];
545 v4l_len[0] = total_size;
546 *v4l_planes = 1;
547 SDE_DEBUG("v4l2[0]:%pad/%x/%d\n", &v4l_addr[0], v4l_len[0],
548 *v4l_planes);
549 } else {
550 *v4l_planes = *drm_planes;
551 }
552}
553
554/**
555 * sde_hw_rot_commit - commit/execute given rotator command
556 * @hw: Pointer to rotator hardware driver
557 * @data: Pointer to command descriptor
558 * @hw_cmd: type of command to be executed
559 * return: 0 if success; error code otherwise
560 */
561static int sde_hw_rot_commit(struct sde_hw_rot *hw, struct sde_hw_rot_cmd *data,
562 enum sde_hw_rot_cmd_type hw_cmd)
563{
564 struct sde_rotator_inline_cmd rot_cmd;
565 enum sde_rotator_inline_cmd_type cmd_type;
566 void *priv_handle = NULL;
567 int rc;
568
569 if (!hw || !data) {
570 SDE_ERROR("invalid parameter\n");
571 return -EINVAL;
572 }
573
574 memset(&rot_cmd, 0, sizeof(struct sde_rotator_inline_cmd));
575
576 switch (hw_cmd) {
577 case SDE_HW_ROT_CMD_VALIDATE:
578 cmd_type = SDE_ROTATOR_INLINE_CMD_VALIDATE;
579 break;
580 case SDE_HW_ROT_CMD_COMMIT:
581 cmd_type = SDE_ROTATOR_INLINE_CMD_COMMIT;
582 break;
Clarence Ipddbf7752017-05-21 18:07:30 -0400583 case SDE_HW_ROT_CMD_START:
584 cmd_type = SDE_ROTATOR_INLINE_CMD_START;
585 priv_handle = data->priv_handle;
586 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800587 case SDE_HW_ROT_CMD_CLEANUP:
588 cmd_type = SDE_ROTATOR_INLINE_CMD_CLEANUP;
589 priv_handle = data->priv_handle;
590 break;
Clarence Ip2606dd62017-10-14 21:11:14 -0400591 case SDE_HW_ROT_CMD_RESET:
592 cmd_type = SDE_ROTATOR_INLINE_CMD_ABORT;
593 priv_handle = data->priv_handle;
594 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800595 default:
596 SDE_ERROR("invalid hw rotator command %d\n", hw_cmd);
597 return -EINVAL;
598 }
599
Alan Kwongaa53e682017-07-31 18:21:15 -0400600 rot_cmd.sequence_id = data->sequence_id;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800601 rot_cmd.video_mode = data->video_mode;
602 rot_cmd.fps = data->fps;
Alan Kwong120b1642017-05-01 12:36:13 -0700603
604 /*
605 * DRM rotation property is specified in counter clockwise direction
606 * whereas rotator h/w rotates in clockwise direction.
607 * Convert rotation property to clockwise 90 by toggling h/v flip
608 */
Alan Kwong4dd64c82017-02-04 18:41:51 -0800609 rot_cmd.rot90 = data->rot90;
Alan Kwong120b1642017-05-01 12:36:13 -0700610 rot_cmd.hflip = data->rot90 ? !data->hflip : data->hflip;
611 rot_cmd.vflip = data->rot90 ? !data->vflip : data->vflip;
612
Alan Kwong4dd64c82017-02-04 18:41:51 -0800613 rot_cmd.secure = data->secure;
614 rot_cmd.clkrate = data->clkrate;
Alan Kwong4aacd532017-02-04 18:51:33 -0800615 rot_cmd.data_bw = 0;
616 rot_cmd.prefill_bw = data->prefill_bw;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800617 rot_cmd.src_width = data->src_width;
618 rot_cmd.src_height = data->src_height;
619 rot_cmd.src_rect_x = data->src_rect_x;
620 rot_cmd.src_rect_y = data->src_rect_y;
621 rot_cmd.src_rect_w = data->src_rect_w;
622 rot_cmd.src_rect_h = data->src_rect_h;
623 rot_cmd.dst_writeback = data->dst_writeback;
624 rot_cmd.dst_rect_x = data->dst_rect_x;
625 rot_cmd.dst_rect_y = data->dst_rect_y;
626 rot_cmd.dst_rect_w = data->dst_rect_w;
627 rot_cmd.dst_rect_h = data->dst_rect_h;
628 rot_cmd.priv_handle = priv_handle;
629
630 rc = sde_hw_rot_to_v4l2_pixfmt(data->src_pixel_format,
631 data->src_modifier, &rot_cmd.src_pixfmt);
632 if (rc) {
633 SDE_ERROR("invalid src format %d\n", rc);
634 return rc;
635 }
636
637 /* calculate preferred output format during validation */
638 if (hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
639 rc = sde_rotator_inline_get_dst_pixfmt(hw->caps->pdev,
640 rot_cmd.src_pixfmt, &rot_cmd.dst_pixfmt);
641 if (rc) {
642 SDE_ERROR("invalid src format %d\n", rc);
643 return rc;
644 }
645
646 rc = sde_hw_rot_to_drm_pixfmt(rot_cmd.dst_pixfmt,
647 &data->dst_pixel_format, &data->dst_modifier);
648 if (rc) {
649 SDE_ERROR("invalid dst format %c%c%c%c\n",
650 rot_cmd.dst_pixfmt >> 0,
651 rot_cmd.dst_pixfmt >> 8,
652 rot_cmd.dst_pixfmt >> 16,
653 rot_cmd.dst_pixfmt >> 24);
654 return rc;
655 }
656
657 data->dst_format = sde_get_sde_format_ext(
658 data->dst_pixel_format, &data->dst_modifier, 1);
659 if (!data->dst_format) {
660 SDE_ERROR("failed to get dst format\n");
661 return -EINVAL;
662 }
Alan Kwongd2681812017-08-27 21:24:43 -0400663 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -0800664 rc = sde_hw_rot_to_v4l2_pixfmt(data->dst_pixel_format,
665 data->dst_modifier, &rot_cmd.dst_pixfmt);
666 if (rc) {
667 SDE_ERROR("invalid dst format %d\n", rc);
668 return rc;
669 }
670
671 sde_hw_rot_to_v4l2_buffer(data->src_pixel_format,
672 data->src_modifier,
673 data->src_iova, data->src_len,
674 &data->src_planes,
675 rot_cmd.src_addr, rot_cmd.src_len,
676 &rot_cmd.src_planes);
677
678 sde_hw_rot_to_v4l2_buffer(data->dst_pixel_format,
679 data->dst_modifier,
680 data->dst_iova, data->dst_len,
681 &data->dst_planes,
682 rot_cmd.dst_addr, rot_cmd.dst_len,
683 &rot_cmd.dst_planes);
684 }
685
686 /* only process any command if client is master or for validation */
687 if (data->master || hw_cmd == SDE_HW_ROT_CMD_VALIDATE) {
688 SDE_DEBUG("dispatch seq:%d cmd:%d\n", data->sequence_id,
689 hw_cmd);
690
691 rc = sde_rotator_inline_commit(hw->rot_ctx, &rot_cmd, cmd_type);
Alan Kwong05109752017-08-12 20:26:45 -0400692 if (rc)
Alan Kwong4dd64c82017-02-04 18:41:51 -0800693 return rc;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800694
695 /* return to caller */
696 data->priv_handle = rot_cmd.priv_handle;
697 } else {
698 SDE_DEBUG("bypass seq:%d cmd:%d\n", data->sequence_id, hw_cmd);
699 }
700
701 return 0;
702}
703
704/**
705 * sde_hw_rot_get_format_caps - get pixel format capability
706 * @hw: Pointer to rotator hardware driver
707 * return: Pointer to pixel format capability array: NULL otherwise
708 */
709static const struct sde_format_extended *sde_hw_rot_get_format_caps(
710 struct sde_hw_rot *hw)
711{
712 int rc, i, j, len;
713 u32 *v4l_pixfmts;
714 struct sde_format_extended *drm_pixfmts;
715 struct platform_device *pdev;
716
717 if (!hw || !hw->caps || !hw->caps->pdev) {
718 SDE_ERROR("invalid rotator hw\n");
719 return NULL;
720 }
721
722 pdev = hw->caps->pdev;
723
724 if (hw->format_caps)
725 return hw->format_caps;
726
727 len = sde_rotator_inline_get_pixfmt_caps(pdev, true, NULL, 0);
728 if (len < 0) {
729 SDE_ERROR("invalid pixfmt caps %d\n", len);
730 return NULL;
731 }
732
733 v4l_pixfmts = kcalloc(len, sizeof(u32), GFP_KERNEL);
734 if (!v4l_pixfmts)
735 goto done;
736
737 sde_rotator_inline_get_pixfmt_caps(pdev, true, v4l_pixfmts, len);
738
739 /* allocate one more to indicate termination */
740 drm_pixfmts = kzalloc((len + 1) * sizeof(struct sde_format_extended),
741 GFP_KERNEL);
742 if (!drm_pixfmts)
743 goto done;
744
745 for (i = 0, j = 0; i < len; i++) {
746 rc = sde_hw_rot_to_drm_pixfmt(v4l_pixfmts[i],
747 &drm_pixfmts[j].fourcc_format,
748 &drm_pixfmts[j].modifier);
749 if (!rc) {
750 SDE_DEBUG("%d: vl42:%c%c%c%c => drm:%c%c%c%c/0x%llx\n",
751 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
752 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24,
753 drm_pixfmts[j].fourcc_format >> 0,
754 drm_pixfmts[j].fourcc_format >> 8,
755 drm_pixfmts[j].fourcc_format >> 16,
756 drm_pixfmts[j].fourcc_format >> 24,
757 drm_pixfmts[j].modifier);
758 j++;
759 } else {
760 SDE_DEBUG("%d: vl42:%c%c%c%c not mapped\n",
761 i, v4l_pixfmts[i] >> 0, v4l_pixfmts[i] >> 8,
762 v4l_pixfmts[i] >> 16, v4l_pixfmts[i] >> 24);
763 }
764 }
765
766 hw->format_caps = drm_pixfmts;
767done:
768 kfree(v4l_pixfmts);
769
770 return hw->format_caps;
771}
772
773/**
774 * sde_hw_rot_get_downscale_caps - get scaling capability string
775 * @hw: Pointer to rotator hardware driver
776 * return: Pointer to capability string: NULL otherwise
777 */
778static const char *sde_hw_rot_get_downscale_caps(struct sde_hw_rot *hw)
779{
780 int len;
781 struct platform_device *pdev;
782
783 if (!hw || !hw->caps || !hw->caps->pdev) {
784 SDE_ERROR("invalid rotator hw\n");
785 return NULL;
786 }
787
788 pdev = hw->caps->pdev;
789
790 if (hw->downscale_caps)
791 return hw->downscale_caps;
792
793 len = sde_rotator_inline_get_downscale_caps(pdev, NULL, 0);
794 if (len < 0) {
795 SDE_ERROR("invalid scaling caps %d\n", len);
796 return NULL;
797 }
798
799 /* add one for ending zero */
800 len += 1;
801 hw->downscale_caps = kzalloc(len, GFP_KERNEL);
802 sde_rotator_inline_get_downscale_caps(pdev, hw->downscale_caps, len);
803
804 return hw->downscale_caps;
805}
806
807/**
808 * sde_hw_rot_get_cache_size - get cache size
809 * @hw: Pointer to rotator hardware driver
810 * return: size of cache
811 */
812static size_t sde_hw_rot_get_cache_size(struct sde_hw_rot *hw)
813{
814 if (!hw || !hw->caps) {
815 SDE_ERROR("invalid rotator hw\n");
816 return 0;
817 }
818
819 return hw->caps->slice_size;
820}
821
822/**
Alan Kwong1a915802017-03-31 12:55:46 -0700823 * sde_hw_rot_get_maxlinewidth - get maximum line width of rotator
824 * @hw: Pointer to rotator hardware driver
825 * return: maximum line width
826 */
827static int sde_hw_rot_get_maxlinewidth(struct sde_hw_rot *hw)
828{
829 struct platform_device *pdev;
830
831 if (!hw || !hw->caps || !hw->caps->pdev) {
832 SDE_ERROR("invalid rotator hw\n");
833 return 0;
834 }
835
836 pdev = hw->caps->pdev;
837
838 return sde_rotator_inline_get_maxlinewidth(pdev);
839}
840
841/**
Alan Kwong4dd64c82017-02-04 18:41:51 -0800842 * _setup_rot_ops - setup rotator operations
843 * @ops: Pointer to operation table
844 * @features: available feature bitmask
845 * return: none
846 */
847static void _setup_rot_ops(struct sde_hw_rot_ops *ops, unsigned long features)
848{
849 ops->commit = sde_hw_rot_commit;
850 ops->get_format_caps = sde_hw_rot_get_format_caps;
851 ops->get_downscale_caps = sde_hw_rot_get_downscale_caps;
852 ops->get_cache_size = sde_hw_rot_get_cache_size;
Alan Kwong1a915802017-03-31 12:55:46 -0700853 ops->get_maxlinewidth = sde_hw_rot_get_maxlinewidth;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800854}
855
856/**
Alan Kwong4dd64c82017-02-04 18:41:51 -0800857 * sde_hw_rot_blk_stop - stop rotator block
858 * @hw_blk: Pointer to base hardware block
859 * return: none
860 */
861static void sde_hw_rot_blk_stop(struct sde_hw_blk *hw_blk)
862{
863 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
864
865 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
866
867 sde_hw_rot_stop(hw_rot);
868}
869
870/**
871 * sde_hw_rot_blk_start - art rotator block
872 * @hw_blk: Pointer to base hardware block
873 * return: 0 if success; error code otherwise
874 */
875static int sde_hw_rot_blk_start(struct sde_hw_blk *hw_blk)
876{
877 struct sde_hw_rot *hw_rot = to_sde_hw_rot(hw_blk);
878 int rc = 0;
879
880 SDE_DEBUG("type:%d id:%d\n", hw_blk->type, hw_blk->id);
881
882 rc = sde_hw_rot_start(hw_rot);
883
884 return rc;
885}
886
Alan Kwongcdb2f282017-03-18 13:42:06 -0700887static struct sde_hw_blk_ops sde_hw_rot_ops = {
888 .start = sde_hw_rot_blk_start,
889 .stop = sde_hw_rot_blk_stop,
890};
891
892/**
893 * sde_hw_rot_init - create/initialize given rotator instance
894 * @idx: index of given rotator
895 * @addr: i/o address mapping
896 * @m: Pointer to mdss catalog
897 * return: Pointer to hardware rotator driver of the given instance
898 */
899struct sde_hw_rot *sde_hw_rot_init(enum sde_rot idx,
900 void __iomem *addr,
901 struct sde_mdss_cfg *m)
902{
903 struct sde_hw_rot *c;
904 struct sde_rot_cfg *cfg;
905 int rc;
906
907 c = kzalloc(sizeof(*c), GFP_KERNEL);
908 if (!c)
909 return ERR_PTR(-ENOMEM);
910
911 cfg = _rot_offset(idx, m, addr, &c->hw);
912 if (IS_ERR(cfg)) {
913 WARN(1, "Unable to find rot idx=%d\n", idx);
914 kfree(c);
915 return ERR_PTR(-EINVAL);
916 }
917
918 /* Assign ops */
919 c->idx = idx;
920 c->caps = cfg;
921 _setup_rot_ops(&c->ops, c->caps->features);
Alan Kwongaa53e682017-07-31 18:21:15 -0400922 snprintf(c->name, ARRAY_SIZE(c->name), "sde_rot_%d", idx - ROT_0);
Alan Kwongcdb2f282017-03-18 13:42:06 -0700923
Lloyd Atkinson652e59b2017-05-03 11:20:30 -0400924 rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_ROT, idx, &sde_hw_rot_ops);
Alan Kwongcdb2f282017-03-18 13:42:06 -0700925 if (rc) {
926 SDE_ERROR("failed to init hw blk %d\n", rc);
927 goto blk_init_error;
928 }
929
930 return c;
931
932blk_init_error:
933 kzfree(c);
934
935 return ERR_PTR(rc);
936}
937
938/**
939 * sde_hw_rot_destroy - destroy given hardware rotator driver
940 * @hw_rot: Pointer to hardware rotator driver
941 * return: none
942 */
943void sde_hw_rot_destroy(struct sde_hw_rot *hw_rot)
944{
Lloyd Atkinson652e59b2017-05-03 11:20:30 -0400945 if (hw_rot) {
946 sde_hw_blk_destroy(&hw_rot->base);
947 kfree(hw_rot->downscale_caps);
948 kfree(hw_rot->format_caps);
949 }
Alan Kwongcdb2f282017-03-18 13:42:06 -0700950 kfree(hw_rot);
951}
952
Alan Kwong4dd64c82017-02-04 18:41:51 -0800953struct sde_hw_rot *sde_hw_rot_get(struct sde_hw_rot *hw_rot)
954{
955 struct sde_hw_blk *hw_blk = sde_hw_blk_get(hw_rot ? &hw_rot->base :
956 NULL, SDE_HW_BLK_ROT, -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800957
Alan Kwongcdb2f282017-03-18 13:42:06 -0700958 return IS_ERR_OR_NULL(hw_blk) ? NULL : to_sde_hw_rot(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800959}
960
961void sde_hw_rot_put(struct sde_hw_rot *hw_rot)
962{
963 struct sde_hw_blk *hw_blk = hw_rot ? &hw_rot->base : NULL;
964
Alan Kwongcdb2f282017-03-18 13:42:06 -0700965 sde_hw_blk_put(hw_blk);
Alan Kwong4dd64c82017-02-04 18:41:51 -0800966}