OSDN Git Service

WIP: synchronize gralloc entry points
[android-x86/external-drm_gralloc.git] / gralloc_drm_radeon.c
1 /*
2  * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
3  * Copyright (C) 2010-2011 LunarG Inc.
4  *
5  * Based on xf86-video-ati, which has
6  *
7  * Copyright © 2009 Red Hat, Inc.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  */
27
28 /* XXX This driver assumes evergreen. */
29
30 #define LOG_TAG "GRALLOC-RADEON"
31
32 #include <cutils/log.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <drm.h>
36 #include <radeon_drm.h>
37 #include <radeon_bo_gem.h>
38 #include <radeon_bo.h>
39
40 #include "gralloc_drm.h"
41 #include "gralloc_drm_priv.h"
42
43 #include "radeon/radeon.h"
44 #include "radeon/radeon_chipinfo_gen.h"
45
46 #define RADEON_GPU_PAGE_SIZE 4096
47
48 struct radeon_info {
49         struct gralloc_drm_drv_t base;
50
51         int fd;
52         struct radeon_bo_manager *bufmgr;
53
54         uint32_t chipset;
55         RADEONChipFamily chip_family;
56         int is_mobility;
57         int is_igp;
58
59         uint32_t tile_config;
60         int num_channels;
61         int num_banks;
62         int group_bytes;
63         /* r6xx+ tile config */
64         int have_tiling_info;
65
66         int allow_color_tiling;
67
68         int vram_size;
69         int gart_size;
70 };
71
72 struct radeon_buffer {
73         struct gralloc_drm_bo_t base;
74
75         struct radeon_bo *rbo;
76 };
77
78 /* returns pitch alignment in pixels */
79 static int radeon_get_pitch_align(struct radeon_info *info, int bpe, uint32_t tiling)
80 {
81         int pitch_align = 1;
82
83         if (info->chip_family >= CHIP_FAMILY_R600) {
84                 if (tiling & RADEON_TILING_MACRO) {
85                         /* general surface requirements */
86                         pitch_align = (((info->group_bytes / 8) / bpe) *
87                                         info->num_banks) * 8;
88                         /* further restrictions for scanout */
89                         pitch_align = MAX(info->num_banks * 8, pitch_align);
90                 } else if (tiling & RADEON_TILING_MICRO) {
91                         /* general surface requirements */
92                         pitch_align = MAX(8, (info->group_bytes / (8 * bpe)));
93                         /* further restrictions for scanout */
94                         pitch_align = MAX(info->group_bytes / bpe, pitch_align);
95                 } else {
96                         if (info->have_tiling_info)
97                                 /* linear aligned requirements */
98                                 pitch_align = MAX(64, info->group_bytes / bpe);
99                         else
100                                 /* default to 512 elements if we don't know the real
101                                  * group size otherwise the kernel may reject the CS
102                                  * if the group sizes don't match as the pitch won't
103                                  * be aligned properly.
104                                  */
105                                 pitch_align = 512;
106                 }
107         }
108         else {
109                 /* general surface requirements */
110                 if (tiling)
111                         pitch_align = 256 / bpe;
112                 else
113                         pitch_align = 64;
114         }
115
116         return pitch_align;
117 }
118
119 /* returns height alignment in pixels */
120 static int radeon_get_height_align(struct radeon_info *info, uint32_t tiling)
121 {
122         int height_align = 1;
123
124         if (info->chip_family >= CHIP_FAMILY_R600) {
125                 if (tiling & RADEON_TILING_MACRO)
126                         height_align =  info->num_channels * 8;
127                 else if (tiling & RADEON_TILING_MICRO)
128                         height_align = 8;
129                 else
130                         height_align = 8;
131         }
132         else {
133                 if (tiling)
134                         height_align = 16;
135                 else
136                         height_align = 1;
137         }
138
139         return height_align;
140 }
141
142 /* returns base alignment in bytes */
143 static int radeon_get_base_align(struct radeon_info *info,
144                 int bpe, uint32_t tiling)
145 {
146         int pixel_align = radeon_get_pitch_align(info, bpe, tiling);
147         int height_align = radeon_get_height_align(info, tiling);
148         int base_align = RADEON_GPU_PAGE_SIZE;
149
150         if (info->chip_family >= CHIP_FAMILY_R600) {
151                 if (tiling & RADEON_TILING_MACRO)
152                         base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe,
153                                          pixel_align * bpe * height_align);
154                 else {
155                         if (info->have_tiling_info)
156                                 base_align = info->group_bytes;
157                         else
158                                 /* default to 512 if we don't know the real
159                                  * group size otherwise the kernel may reject the CS
160                                  * if the group sizes don't match as the base won't
161                                  * be aligned properly.
162                                  */
163                                 base_align = 512;
164                 }
165         }
166         return base_align;
167 }
168
169 static uint32_t radeon_get_tiling(struct radeon_info *info,
170                 const struct gralloc_drm_handle_t *handle)
171 {
172         int sw = (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
173
174         if ((handle->usage & sw) && !info->allow_color_tiling)
175                 return 0;
176
177         if (info->chip_family >= CHIP_FAMILY_R600)
178                 return RADEON_TILING_MICRO;
179         else
180                 return RADEON_TILING_MACRO;
181 }
182
183 static struct radeon_bo *radeon_alloc(struct radeon_info *info,
184                 struct gralloc_drm_handle_t *handle)
185 {
186         struct radeon_bo *rbo;
187         int aligned_width, aligned_height;
188         int pitch, size, base_align;
189         uint32_t tiling, domain;
190         int cpp;
191
192         cpp = gralloc_drm_get_bpp(handle->format);
193         if (!cpp) {
194                 ALOGE("unrecognized format 0x%x", handle->format);
195                 return NULL;
196         }
197
198         tiling = radeon_get_tiling(info, handle);
199         domain = RADEON_GEM_DOMAIN_VRAM;
200
201         aligned_width = handle->width;
202         aligned_height = handle->height;
203         gralloc_drm_align_geometry(handle->format,
204                         &aligned_width, &aligned_height);
205
206         if (handle->usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_TEXTURE)) {
207                 aligned_width = ALIGN(aligned_width,
208                                 radeon_get_pitch_align(info, cpp, tiling));
209                 aligned_height = ALIGN(aligned_height,
210                                 radeon_get_height_align(info, tiling));
211         }
212
213         if (!(handle->usage & (GRALLOC_USAGE_HW_FB |
214                                GRALLOC_USAGE_HW_RENDER)) &&
215             (handle->usage & GRALLOC_USAGE_SW_READ_OFTEN))
216                 domain = RADEON_GEM_DOMAIN_GTT;
217
218         pitch = aligned_width * cpp;
219         size = ALIGN(aligned_height * pitch, RADEON_GPU_PAGE_SIZE);
220         base_align = radeon_get_base_align(info, cpp, tiling);
221
222         rbo = radeon_bo_open(info->bufmgr, 0, size, base_align, domain, 0);
223         if (!rbo) {
224                 ALOGE("failed to allocate rbo %dx%dx%d",
225                                 handle->width, handle->height, cpp);
226                 return NULL;
227         }
228
229         if (tiling)
230                 radeon_bo_set_tiling(rbo, tiling, pitch);
231
232         if (radeon_gem_get_kernel_name(rbo,
233                                 (uint32_t *) &handle->name)) {
234                 ALOGE("failed to flink rbo");
235                 radeon_bo_unref(rbo);
236                 return NULL;
237         }
238
239         handle->stride = pitch;
240
241         return rbo;
242 }
243
244 static void radeon_zero(struct radeon_info *info,
245                 struct radeon_bo *rbo)
246 {
247         /* should use HW clear... */
248         if (!radeon_bo_map(rbo, 1)) {
249                 memset(rbo->ptr, 0, rbo->size);
250                 radeon_bo_unmap(rbo);
251         }
252 }
253
254 static struct gralloc_drm_bo_t *
255 drm_gem_radeon_alloc(struct gralloc_drm_drv_t *drv, struct gralloc_drm_handle_t *handle)
256 {
257         struct radeon_info *info = (struct radeon_info *) drv;
258         struct radeon_buffer *rbuf;
259
260         rbuf = calloc(1, sizeof(*rbuf));
261         if (!rbuf)
262                 return NULL;
263
264         if (handle->name) {
265                 rbuf->rbo = radeon_bo_open(info->bufmgr,
266                                 handle->name, 0, 0, 0, 0);
267                 if (!rbuf->rbo) {
268                         ALOGE("failed to create rbo from name %u",
269                                         handle->name);
270                         free(rbuf);
271                         return NULL;
272                 }
273         }
274         else {
275                 rbuf->rbo = radeon_alloc(info, handle);
276                 if (!rbuf->rbo) {
277                         free(rbuf);
278                         return NULL;
279                 }
280
281                 /* Android expects the buffer to be zeroed */
282                 radeon_zero(info, rbuf->rbo);
283         }
284
285         if (handle->usage & GRALLOC_USAGE_HW_FB)
286                 rbuf->base.fb_handle = rbuf->rbo->handle;
287
288         rbuf->base.handle = handle;
289
290         return &rbuf->base;
291 }
292
293 static void drm_gem_radeon_free(struct gralloc_drm_drv_t *drv,
294                 struct gralloc_drm_bo_t *bo)
295 {
296         struct radeon_buffer *rbuf = (struct radeon_buffer *) bo;
297         radeon_bo_unref(rbuf->rbo);
298 }
299
300 static int drm_gem_radeon_map(struct gralloc_drm_drv_t *drv,
301                 struct gralloc_drm_bo_t *bo, int x, int y, int w, int h,
302                 int enable_write, void **addr)
303 {
304         struct radeon_buffer *rbuf = (struct radeon_buffer *) bo;
305         int err;
306
307         err = radeon_bo_map(rbuf->rbo, enable_write);
308         if (!err)
309                 *addr = rbuf->rbo->ptr;
310
311         return err;
312 }
313
314 static void drm_gem_radeon_unmap(struct gralloc_drm_drv_t *drv,
315                 struct gralloc_drm_bo_t *bo)
316 {
317         struct radeon_buffer *rbuf = (struct radeon_buffer *) bo;
318         radeon_bo_unmap(rbuf->rbo);
319 }
320
321 static void drm_gem_radeon_init_kms_features(struct gralloc_drm_drv_t *drv,
322                 struct gralloc_drm_t *drm)
323 {
324         switch (drm->primary.fb_format) {
325         case HAL_PIXEL_FORMAT_BGRA_8888:
326         case HAL_PIXEL_FORMAT_RGB_565:
327                 break;
328         default:
329                 drm->primary.fb_format = HAL_PIXEL_FORMAT_BGRA_8888;
330                 break;
331         }
332
333         drm->mode_quirk_vmwgfx = 0;
334         drm->swap_mode = DRM_SWAP_FLIP;
335         drm->mode_sync_flip = 1;
336         drm->swap_interval = 1;
337         drm->vblank_secondary = 0;
338 }
339
340 static void drm_gem_radeon_destroy(struct gralloc_drm_drv_t *drv)
341 {
342         struct radeon_info *info = (struct radeon_info *) drv;
343
344         radeon_bo_manager_gem_dtor(info->bufmgr);
345         free(info);
346 }
347
348 static int radeon_init_tile_config(struct radeon_info *info)
349 {
350         struct drm_radeon_info ginfo;
351         uint32_t val;
352         int ret;
353
354         memset(&ginfo, 0, sizeof(ginfo));
355         ginfo.request = RADEON_INFO_TILING_CONFIG;
356         ginfo.value = (uintptr_t) &val;
357         ret = drmCommandWriteRead(info->fd, DRM_RADEON_INFO,
358                         &ginfo, sizeof(ginfo));
359         if (ret)
360                 return ret;
361
362         info->tile_config = val;
363
364         if (info->chip_family >= CHIP_FAMILY_CEDAR) {
365                 switch (info->tile_config & 0xf) {
366                 case 0:
367                         info->num_channels = 1;
368                         break;
369                 case 1:
370                         info->num_channels = 2;
371                         break;
372                 case 2:
373                         info->num_channels = 4;
374                         break;
375                 case 3:
376                         info->num_channels = 8;
377                         break;
378                 default:
379                         return -EINVAL;
380                         break;
381                 }
382
383                 switch ((info->tile_config & 0xf0) >> 4) {
384                 case 0:
385                         info->num_banks = 4;
386                         break;
387                 case 1:
388                         info->num_banks = 8;
389                         break;
390                 case 2:
391                         info->num_banks = 16;
392                         break;
393                 default:
394                         return -EINVAL;
395                         break;
396                 }
397
398                 switch ((info->tile_config & 0xf00) >> 8) {
399                 case 0:
400                         info->group_bytes = 256;
401                         break;
402                 case 1:
403                         info->group_bytes = 512;
404                         break;
405                 default:
406                         return -EINVAL;
407                         break;
408                 }
409         }
410         else {
411                 switch ((info->tile_config & 0xe) >> 1) {
412                 case 0:
413                         info->num_channels = 1;
414                         break;
415                 case 1:
416                         info->num_channels = 2;
417                         break;
418                 case 2:
419                         info->num_channels = 4;
420                         break;
421                 case 3:
422                         info->num_channels = 8;
423                         break;
424                 default:
425                         return -EINVAL;
426                         break;
427                 }
428
429                 switch ((info->tile_config & 0x30) >> 4) {
430                 case 0:
431                         info->num_banks = 4;
432                         break;
433                 case 1:
434                         info->num_banks = 8;
435                         break;
436                 default:
437                         return -EINVAL;
438                         break;
439                 }
440
441                 switch ((info->tile_config & 0xc0) >> 6) {
442                 case 0:
443                         info->group_bytes = 256;
444                         break;
445                 case 1:
446                         info->group_bytes = 512;
447                         break;
448                 default:
449                         return -EINVAL;
450                         break;
451                 }
452         }
453
454         info->have_tiling_info = 1;
455
456         return 0;
457 }
458
459 static int radeon_probe(struct radeon_info *info)
460 {
461         struct drm_radeon_info kinfo;
462         struct drm_radeon_gem_info mminfo;
463         unsigned int i;
464         int err;
465
466         memset(&kinfo, 0, sizeof(kinfo));
467         kinfo.request = RADEON_INFO_DEVICE_ID;
468         kinfo.value = (uintptr_t) &info->chipset;
469         err = drmCommandWriteRead(info->fd, DRM_RADEON_INFO, &kinfo, sizeof(kinfo));
470         if (err) {
471                 ALOGE("failed to get device id");
472                 return err;
473         }
474
475         for (i = 0; i < sizeof(RADEONCards) / sizeof(RADEONCards[0]); i++) {
476                 const RADEONCardInfo *card = &RADEONCards[i];
477
478                 if (info->chipset == card->pci_device_id) {
479                         info->chip_family = card->chip_family;
480                         info->is_mobility = card->mobility;
481                         info->is_igp = card->igp;
482                         break;
483                 }
484         }
485
486         if (info->chip_family == CHIP_FAMILY_UNKNOW) {
487                 ALOGE("unknown device id 0x%04x", info->chipset);
488                 return -EINVAL;
489         }
490
491         if (info->chip_family >= CHIP_FAMILY_R600) {
492                 err = radeon_init_tile_config(info);
493                 if (err) {
494                         ALOGE("failed to get tiling config");
495                         return err;
496                 }
497         } else {
498                 /* No tiling config for family older than 06xx */
499                 info->have_tiling_info = 0;
500         }
501
502         /* CPU cannot handle tiled buffers (need scratch buffers) */
503         info->allow_color_tiling = 0;
504
505         memset(&mminfo, 0, sizeof(mminfo));
506         err = drmCommandWriteRead(info->fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo));
507         if (err) {
508                 ALOGE("failed to get gem info");
509                 return err;
510         }
511
512         info->vram_size = mminfo.vram_visible;
513         info->gart_size = mminfo.gart_size;
514
515         ALOGI("detected chipset 0x%04x family 0x%02x (vram size %dMiB, gart size %dMiB)",
516                         info->chipset, info->chip_family,
517                         info->vram_size / 1024 / 1024,
518                         info->gart_size / 1024 / 1024);
519
520         return 0;
521 }
522
523 struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_radeon(int fd)
524 {
525         struct radeon_info *info;
526
527         info = calloc(1, sizeof(*info));
528         if (!info)
529                 return NULL;
530
531         info->fd = fd;
532         if (radeon_probe(info)) {
533                 free(info);
534                 return NULL;
535         }
536
537         info->bufmgr = radeon_bo_manager_gem_ctor(info->fd);
538         if (!info->bufmgr) {
539                 ALOGE("failed to create buffer manager");
540                 free(info);
541                 return NULL;
542         }
543
544         info->base.destroy = drm_gem_radeon_destroy;
545         info->base.init_kms_features = drm_gem_radeon_init_kms_features;
546         info->base.alloc = drm_gem_radeon_alloc;
547         info->base.free = drm_gem_radeon_free;
548         info->base.map = drm_gem_radeon_map;
549         info->base.unmap = drm_gem_radeon_unmap;
550
551         return &info->base;
552 }