forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/tegra/plane.c
....@@ -1,13 +1,14 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
74 */
5
+
6
+#include <linux/iommu.h>
87
98 #include <drm/drm_atomic.h>
109 #include <drm/drm_atomic_helper.h>
10
+#include <drm/drm_fourcc.h>
11
+#include <drm/drm_gem_framebuffer_helper.h>
1112 #include <drm/drm_plane_helper.h>
1213
1314 #include "dc.h"
....@@ -25,6 +26,7 @@
2526 {
2627 struct tegra_plane *p = to_tegra_plane(plane);
2728 struct tegra_plane_state *state;
29
+ unsigned int i;
2830
2931 if (plane->state)
3032 __drm_atomic_helper_plane_destroy_state(plane->state);
....@@ -38,6 +40,9 @@
3840 plane->state->plane = plane;
3941 plane->state->zpos = p->index;
4042 plane->state->normalized_zpos = p->index;
43
+
44
+ for (i = 0; i < 3; i++)
45
+ state->iova[i] = DMA_MAPPING_ERROR;
4146 }
4247 }
4348
....@@ -56,11 +61,17 @@
5661 copy->tiling = state->tiling;
5762 copy->format = state->format;
5863 copy->swap = state->swap;
59
- copy->bottom_up = state->bottom_up;
64
+ copy->reflect_x = state->reflect_x;
65
+ copy->reflect_y = state->reflect_y;
6066 copy->opaque = state->opaque;
6167
6268 for (i = 0; i < 2; i++)
6369 copy->blending[i] = state->blending[i];
70
+
71
+ for (i = 0; i < 3; i++) {
72
+ copy->iova[i] = DMA_MAPPING_ERROR;
73
+ copy->sgt[i] = NULL;
74
+ }
6475
6576 return &copy->base;
6677 }
....@@ -97,6 +108,110 @@
97108 .format_mod_supported = tegra_plane_format_mod_supported,
98109 };
99110
111
+static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state)
112
+{
113
+ struct iommu_domain *domain = iommu_get_domain_for_dev(dc->dev);
114
+ unsigned int i;
115
+ int err;
116
+
117
+ for (i = 0; i < state->base.fb->format->num_planes; i++) {
118
+ struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
119
+ dma_addr_t phys_addr, *phys;
120
+ struct sg_table *sgt;
121
+
122
+ if (!domain || dc->client.group)
123
+ phys = &phys_addr;
124
+ else
125
+ phys = NULL;
126
+
127
+ sgt = host1x_bo_pin(dc->dev, &bo->base, phys);
128
+ if (IS_ERR(sgt)) {
129
+ err = PTR_ERR(sgt);
130
+ goto unpin;
131
+ }
132
+
133
+ if (sgt) {
134
+ err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
135
+ if (err)
136
+ goto unpin;
137
+
138
+ /*
139
+ * The display controller needs contiguous memory, so
140
+ * fail if the buffer is discontiguous and we fail to
141
+ * map its SG table to a single contiguous chunk of
142
+ * I/O virtual memory.
143
+ */
144
+ if (sgt->nents > 1) {
145
+ err = -EINVAL;
146
+ goto unpin;
147
+ }
148
+
149
+ state->iova[i] = sg_dma_address(sgt->sgl);
150
+ state->sgt[i] = sgt;
151
+ } else {
152
+ state->iova[i] = phys_addr;
153
+ }
154
+ }
155
+
156
+ return 0;
157
+
158
+unpin:
159
+ dev_err(dc->dev, "failed to map plane %u: %d\n", i, err);
160
+
161
+ while (i--) {
162
+ struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
163
+ struct sg_table *sgt = state->sgt[i];
164
+
165
+ if (sgt)
166
+ dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
167
+
168
+ host1x_bo_unpin(dc->dev, &bo->base, sgt);
169
+ state->iova[i] = DMA_MAPPING_ERROR;
170
+ state->sgt[i] = NULL;
171
+ }
172
+
173
+ return err;
174
+}
175
+
176
+static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state)
177
+{
178
+ unsigned int i;
179
+
180
+ for (i = 0; i < state->base.fb->format->num_planes; i++) {
181
+ struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
182
+ struct sg_table *sgt = state->sgt[i];
183
+
184
+ if (sgt)
185
+ dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
186
+
187
+ host1x_bo_unpin(dc->dev, &bo->base, sgt);
188
+ state->iova[i] = DMA_MAPPING_ERROR;
189
+ state->sgt[i] = NULL;
190
+ }
191
+}
192
+
193
+int tegra_plane_prepare_fb(struct drm_plane *plane,
194
+ struct drm_plane_state *state)
195
+{
196
+ struct tegra_dc *dc = to_tegra_dc(state->crtc);
197
+
198
+ if (!state->fb)
199
+ return 0;
200
+
201
+ drm_gem_fb_prepare_fb(plane, state);
202
+
203
+ return tegra_dc_pin(dc, to_tegra_plane_state(state));
204
+}
205
+
206
+void tegra_plane_cleanup_fb(struct drm_plane *plane,
207
+ struct drm_plane_state *state)
208
+{
209
+ struct tegra_dc *dc = to_tegra_dc(state->crtc);
210
+
211
+ if (dc)
212
+ tegra_dc_unpin(dc, to_tegra_plane_state(state));
213
+}
214
+
100215 int tegra_plane_state_add(struct tegra_plane *plane,
101216 struct drm_plane_state *state)
102217 {