1/*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24/* This file is based on rgxdefs.h and should only contain function-like macros
25 * and inline functions. Any object-like macros should instead appear in
26 * rogue_hw_defs.h.
27 */
28
29#ifndef ROGUE_HW_UTILS_H
30#define ROGUE_HW_UTILS_H
31
32#include <stdint.h>
33
34#include "pvr_types.h"
35
36#define __pvr_address_type pvr_dev_addr_t
37#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
38/* clang-format off */
39#define __pvr_make_address(addr_u64) PVR_DEV_ADDR(addr_u64)
40/* clang-format on */
41
42#include "csbgen/rogue_cdm.h"
43#include "csbgen/rogue_lls.h"
44
45#undef __pvr_make_address
46#undef __pvr_get_address
47#undef __pvr_address_type
48
49#include "rogue_hw_defs.h"
50#include "pvr_device_info.h"
51#include "util/compiler.h"
52#include "util/macros.h"
53
54static inline void
55rogue_get_isp_samples_per_tile_xy(const struct pvr_device_info *dev_info,
56                                  uint32_t samples,
57                                  uint32_t *const x_out,
58                                  uint32_t *const y_out)
59{
60   const uint32_t tile_size_x =
61      PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 0U);
62   const uint32_t tile_size_y =
63      PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 0U);
64   const uint32_t samples_per_pixel =
65      PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0U);
66
67#if !defined(NDEBUG)
68   switch (samples_per_pixel) {
69   case 1:
70   case 2:
71   case 4:
72      break;
73   default:
74      assert(!"Unsupported ISP samples per pixel");
75   }
76#endif
77
78   *x_out = tile_size_x;
79   *y_out = tile_size_y;
80
81   switch (samples) {
82   case 1:
83      break;
84   case 2:
85      if (samples_per_pixel == 2 || samples_per_pixel == 4)
86         *y_out *= 2;
87
88      break;
89   case 4:
90      if (samples_per_pixel == 2 || samples_per_pixel == 4)
91         *x_out *= 2;
92
93      if (samples_per_pixel == 2)
94         *y_out *= 2;
95
96      break;
97   case 8:
98      *y_out *= 2;
99      break;
100   default:
101      assert(!"Unsupported number of samples");
102   }
103}
104
105static inline uint64_t
106rogue_get_min_free_list_size(const struct pvr_device_info *dev_info)
107{
108   uint64_t min_num_pages;
109
110   if (PVR_HAS_FEATURE(dev_info, roguexe)) {
111      if (PVR_HAS_QUIRK(dev_info, 66011))
112         min_num_pages = 40U;
113      else
114         min_num_pages = 25U;
115   } else {
116      min_num_pages = 50U;
117   }
118
119   return min_num_pages << ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT;
120}
121
122static inline uint32_t
123rogue_get_max_num_vdm_pds_tasks(const struct pvr_device_info *dev_info)
124{
125   /* Default value based on the minimum value found in all existing cores. */
126   uint32_t max_usc_tasks = PVR_GET_FEATURE_VALUE(dev_info, max_usc_tasks, 24U);
127
128   /* FIXME: Where does the 9 come from? */
129   return max_usc_tasks - 9;
130}
131
132static inline uint32_t
133rogue_get_max_output_regs_per_pixel(const struct pvr_device_info *dev_info)
134{
135   if (PVR_HAS_FEATURE(dev_info, eight_output_registers))
136      return 8U;
137
138   return 4U;
139}
140
141static inline void
142rogue_get_num_macrotiles_xy(const struct pvr_device_info *dev_info,
143                            uint32_t *const x_out,
144                            uint32_t *const y_out)
145{
146   uint32_t version;
147
148   if (PVR_FEATURE_VALUE(dev_info, simple_parameter_format_version, &version))
149      version = 0;
150
151   if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) ||
152       version == 2) {
153      *x_out = 4;
154      *y_out = 4;
155   } else {
156      *x_out = 1;
157      *y_out = 1;
158   }
159}
160
161static inline uint32_t
162rogue_get_macrotile_array_size(const struct pvr_device_info *dev_info)
163{
164   uint32_t num_macrotiles_x;
165   uint32_t num_macrotiles_y;
166
167   if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format))
168      return 0;
169
170   rogue_get_num_macrotiles_xy(dev_info, &num_macrotiles_x, &num_macrotiles_y);
171
172   return num_macrotiles_x * num_macrotiles_y * 8U;
173}
174
175/* Region header size in bytes. */
176static inline uint32_t
177rogue_get_region_header_size(const struct pvr_device_info *dev_info)
178{
179   uint32_t version;
180
181   if (PVR_FEATURE_VALUE(dev_info, simple_parameter_format_version, &version))
182      version = 0;
183
184   if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) &&
185       version == 2) {
186      return 6;
187   }
188
189   return 5;
190}
191
192static inline uint32_t
193rogue_get_render_size_max(const struct pvr_device_info *dev_info)
194{
195   if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format))
196      if (!PVR_HAS_FEATURE(dev_info, screen_size8K))
197         return 4096U;
198
199   return 8192U;
200}
201
202#define rogue_get_render_size_max_x(dev_info) \
203   rogue_get_render_size_max(dev_info)
204
205#define rogue_get_render_size_max_y(dev_info) \
206   rogue_get_render_size_max(dev_info)
207
208static inline uint32_t
209rogue_get_slc_cache_line_size(const struct pvr_device_info *dev_info)
210{
211   return PVR_GET_FEATURE_VALUE(dev_info, slc_cache_line_size_bits, 8U) / 8U;
212}
213
214static inline uint32_t pvr_get_max_user_vertex_output_components(
215   const struct pvr_device_info *dev_info)
216{
217   const uint32_t uvs_pba_entries =
218      PVR_GET_FEATURE_VALUE(dev_info, uvs_pba_entries, 0U);
219   const uint32_t uvs_banks = PVR_GET_FEATURE_VALUE(dev_info, uvs_banks, 0U);
220
221   if (uvs_banks <= 8U && uvs_pba_entries == 160U)
222      return 64U;
223
224   return 128U;
225}
226
227static inline uint32_t
228rogue_max_compute_shared_registers(const struct pvr_device_info *dev_info)
229{
230   if (PVR_HAS_FEATURE(dev_info, compute))
231      return 2U * 1024U;
232
233   return 0U;
234}
235
236static inline uint32_t
237rogue_get_cdm_context_resume_buffer_size(const struct pvr_device_info *dev_info)
238{
239   if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) {
240      const uint32_t max_num_cores =
241         PVR_GET_FEATURE_VALUE(dev_info, xpu_max_slaves, 0U) + 1U;
242      const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info);
243      const uint32_t cdm_context_resume_buffer_stride =
244         ALIGN_POT(ROGUE_LLS_CDM_CONTEXT_RESUME_BUFFER_SIZE, cache_line_size);
245
246      return cdm_context_resume_buffer_stride * max_num_cores;
247   }
248
249   return ROGUE_LLS_CDM_CONTEXT_RESUME_BUFFER_SIZE;
250}
251
252static inline uint32_t rogue_get_cdm_context_resume_buffer_alignment(
253   const struct pvr_device_info *dev_info)
254{
255   if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support))
256      return rogue_get_slc_cache_line_size(dev_info);
257
258   return ROGUE_LLS_CDM_CONTEXT_RESUME_BUFFER_ALIGNMENT;
259}
260
261static inline uint32_t
262rogue_get_compute_max_work_group_size(const struct pvr_device_info *dev_info)
263{
264   /* The number of tasks which can be executed per USC - Limited to 16U by the
265    * CDM.
266    */
267   const uint32_t max_tasks_per_usc = 16U;
268
269   if (!PVR_HAS_ERN(dev_info, 35421)) {
270      /* Barriers on work-groups > 32 instances aren't supported. */
271      return ROGUE_MAX_INSTANCES_PER_TASK;
272   }
273
274   return ROGUE_MAX_INSTANCES_PER_TASK * max_tasks_per_usc;
275}
276
277#endif /* ROGUE_HW_UTILS_H */
278