blob: 6bb70b6385ed8890955ac998351851b7a14e42c3 [file] [log] [blame]
Rajesh Yadav7f79cb52018-01-22 18:29:06 +05301/*
2 * Copyright 2018 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7#ifdef DRV_MSM
8
Tanmay Shah617ee712018-07-11 16:41:05 -07009#include <errno.h>
10#include <msm_drm.h>
11#include <stdio.h>
12#include <string.h>
13#include <sys/mman.h>
14#include <xf86drm.h>
15
Rajesh Yadav7f79cb52018-01-22 18:29:06 +053016#include "drv_priv.h"
17#include "helpers.h"
18#include "util.h"
19
Tanmay Shah617ee712018-07-11 16:41:05 -070020#define DEFAULT_ALIGNMENT 64
Tanmay Shahc65bd8c2018-11-21 09:14:14 -080021#define BUFFER_SIZE_ALIGN 4096
22
23#define VENUS_STRIDE_ALIGN 128
24#define VENUS_SCANLINE_ALIGN 16
25#define NV12_LINEAR_PADDING (12 * 1024)
Stéphane Marchesin23e006a2018-02-28 16:37:46 -080026
Gurchetan Singhb131c9d2018-08-28 14:17:05 -070027static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
Gurchetan Singh71bc6652018-09-17 17:42:05 -070028 DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
29 DRM_FORMAT_XRGB8888 };
Rajesh Yadav7f79cb52018-01-22 18:29:06 +053030
Tanmay Shah617ee712018-07-11 16:41:05 -070031static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_R8,
32 DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
Alexandre Courbot1805a9b2018-05-21 19:05:10 +090033
Tanmay Shahc65bd8c2018-11-21 09:14:14 -080034static void msm_calculate_linear_layout(struct bo *bo)
35{
36 uint32_t width, height;
37
38 width = bo->width;
39 height = bo->height;
40
41 /* NV12 format requires extra padding with platform
42 * specific alignments for venus driver
43 */
44 if (bo->format == DRM_FORMAT_NV12) {
45 uint32_t y_stride, uv_stride, y_scanline, uv_scanline, y_plane, uv_plane, size;
46 y_stride = ALIGN(width, VENUS_STRIDE_ALIGN);
47 uv_stride = ALIGN(width, VENUS_STRIDE_ALIGN);
48 y_scanline = ALIGN(height, VENUS_SCANLINE_ALIGN * 2);
49 uv_scanline = ALIGN(DIV_ROUND_UP(height, 2), VENUS_SCANLINE_ALIGN);
50 y_plane = y_stride * y_scanline;
51 uv_plane = uv_stride * uv_scanline;
52
53 bo->strides[0] = y_stride;
54 bo->sizes[0] = y_plane;
55 bo->offsets[1] = y_plane;
56 bo->strides[1] = uv_stride;
57 size = y_plane + uv_plane + NV12_LINEAR_PADDING;
58 bo->total_size = ALIGN(size, BUFFER_SIZE_ALIGN);
59 bo->sizes[1] = bo->total_size - bo->sizes[0];
60 } else {
61 uint32_t stride, alignw, alignh;
62
63 alignw = ALIGN(width, DEFAULT_ALIGNMENT);
64
65 /* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned. */
66 if (bo->format == DRM_FORMAT_YVU420_ANDROID) {
67 alignh = height;
68 } else {
69 alignh = ALIGN(height, DEFAULT_ALIGNMENT);
70 }
71
72 stride = drv_stride_from_format(bo->format, alignw, 0);
73
74 /* Calculate size and assign stride, size, offset to each plane based on format */
75 drv_bo_from_format(bo, stride, alignh, bo->format);
76 }
77}
78
Rajesh Yadav7f79cb52018-01-22 18:29:06 +053079static int msm_init(struct driver *drv)
80{
81 drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
82 &LINEAR_METADATA, BO_USE_RENDER_MASK);
83
Tanmay Shah617ee712018-07-11 16:41:05 -070084 drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
Alexandre Courbot1805a9b2018-05-21 19:05:10 +090085 &LINEAR_METADATA, BO_USE_TEXTURE_MASK | BO_USE_HW_VIDEO_DECODER);
86
Gurchetan Singh71bc6652018-09-17 17:42:05 -070087 /* Android CTS tests require this. */
88 drv_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
89
Rajesh Yadav7f79cb52018-01-22 18:29:06 +053090 return drv_modify_linear_combinations(drv);
91}
92
Tanmay Shah617ee712018-07-11 16:41:05 -070093/* msm_bo_create will create linear buffers for now */
Stéphane Marchesin23e006a2018-02-28 16:37:46 -080094static int msm_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
Alistair Strachan0cfaaa52018-03-19 14:03:23 -070095 uint64_t flags)
Stéphane Marchesin23e006a2018-02-28 16:37:46 -080096{
Tanmay Shah617ee712018-07-11 16:41:05 -070097 struct drm_msm_gem_new req;
Tanmay Shah617ee712018-07-11 16:41:05 -070098 int ret;
99 size_t i;
100
Tanmay Shahc65bd8c2018-11-21 09:14:14 -0800101 msm_calculate_linear_layout(bo);
Tanmay Shah617ee712018-07-11 16:41:05 -0700102
103 memset(&req, 0, sizeof(req));
104 req.flags = MSM_BO_WC | MSM_BO_SCANOUT;
105 req.size = bo->total_size;
106
107 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MSM_GEM_NEW, &req);
108 if (ret) {
109 drv_log("DRM_IOCTL_MSM_GEM_NEW failed with %s\n", strerror(errno));
110 return ret;
111 }
112
113 /*
114 * Though we use only one plane, we need to set handle for
115 * all planes to pass kernel checks
116 */
117 for (i = 0; i < bo->num_planes; i++) {
118 bo->handles[i].u32 = req.handle;
119 }
120
121 return 0;
122}
123
124static void *msm_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
125{
126 int ret;
127 struct drm_msm_gem_info req;
128
129 memset(&req, 0, sizeof(req));
130 req.handle = bo->handles[0].u32;
131
132 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MSM_GEM_INFO, &req);
133 if (ret) {
134 drv_log("DRM_IOCLT_MSM_GEM_INFO failed with %s\n", strerror(errno));
135 return MAP_FAILED;
136 }
137 vma->length = bo->total_size;
138
139 return mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
140 req.offset);
Stéphane Marchesin23e006a2018-02-28 16:37:46 -0800141}
142
Rajesh Yadav7f79cb52018-01-22 18:29:06 +0530143const struct backend backend_msm = {
144 .name = "msm",
145 .init = msm_init,
Stéphane Marchesin23e006a2018-02-28 16:37:46 -0800146 .bo_create = msm_bo_create,
Tanmay Shah617ee712018-07-11 16:41:05 -0700147 .bo_destroy = drv_gem_bo_destroy,
Rajesh Yadav7f79cb52018-01-22 18:29:06 +0530148 .bo_import = drv_prime_bo_import,
Tanmay Shah617ee712018-07-11 16:41:05 -0700149 .bo_map = msm_bo_map,
Rajesh Yadav7f79cb52018-01-22 18:29:06 +0530150 .bo_unmap = drv_bo_munmap,
151};
Rajesh Yadav7f79cb52018-01-22 18:29:06 +0530152#endif /* DRV_MSM */