linux/drivers/gpu/drm/ast/ast_main.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Red Hat Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the
   6 * "Software"), to deal in the Software without restriction, including
   7 * without limitation the rights to use, copy, modify, merge, publish,
   8 * distribute, sub license, and/or sell copies of the Software, and to
   9 * permit persons to whom the Software is furnished to do so, subject to
  10 * the following conditions:
  11 *
  12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  18 * USE OR OTHER DEALINGS IN THE SOFTWARE.
  19 *
  20 * The above copyright notice and this permission notice (including the
  21 * next paragraph) shall be included in all copies or substantial portions
  22 * of the Software.
  23 *
  24 */
  25/*
  26 * Authors: Dave Airlie <airlied@redhat.com>
  27 */
  28#include <drm/drmP.h>
  29#include "ast_drv.h"
  30
  31
  32#include <drm/drm_fb_helper.h>
  33#include <drm/drm_crtc_helper.h>
  34
  35void ast_set_index_reg_mask(struct ast_private *ast,
  36                            uint32_t base, uint8_t index,
  37                            uint8_t mask, uint8_t val)
  38{
  39        u8 tmp;
  40        ast_io_write8(ast, base, index);
  41        tmp = (ast_io_read8(ast, base + 1) & mask) | val;
  42        ast_set_index_reg(ast, base, index, tmp);
  43}
  44
  45uint8_t ast_get_index_reg(struct ast_private *ast,
  46                          uint32_t base, uint8_t index)
  47{
  48        uint8_t ret;
  49        ast_io_write8(ast, base, index);
  50        ret = ast_io_read8(ast, base + 1);
  51        return ret;
  52}
  53
  54uint8_t ast_get_index_reg_mask(struct ast_private *ast,
  55                               uint32_t base, uint8_t index, uint8_t mask)
  56{
  57        uint8_t ret;
  58        ast_io_write8(ast, base, index);
  59        ret = ast_io_read8(ast, base + 1) & mask;
  60        return ret;
  61}
  62
  63static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
  64{
  65        struct device_node *np = dev->pdev->dev.of_node;
  66        struct ast_private *ast = dev->dev_private;
  67        uint32_t data, jregd0, jregd1;
  68
  69        /* Defaults */
  70        ast->config_mode = ast_use_defaults;
  71        *scu_rev = 0xffffffff;
  72
  73        /* Check if we have device-tree properties */
  74        if (np && !of_property_read_u32(np, "aspeed,scu-revision-id",
  75                                        scu_rev)) {
  76                /* We do, disable P2A access */
  77                ast->config_mode = ast_use_dt;
  78                DRM_INFO("Using device-tree for configuration\n");
  79                return;
  80        }
  81
  82        /* Not all families have a P2A bridge */
  83        if (dev->pdev->device != PCI_CHIP_AST2000)
  84                return;
  85
  86        /*
  87         * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
  88         * is disabled. We force using P2A if VGA only mode bit
  89         * is set D[7]
  90         */
  91        jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
  92        jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
  93        if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
  94                /* Double check it's actually working */
  95                data = ast_read32(ast, 0xf004);
  96                if (data != 0xFFFFFFFF) {
  97                        /* P2A works, grab silicon revision */
  98                        ast->config_mode = ast_use_p2a;
  99
 100                        DRM_INFO("Using P2A bridge for configuration\n");
 101
 102                        /* Read SCU7c (silicon revision register) */
 103                        ast_write32(ast, 0xf004, 0x1e6e0000);
 104                        ast_write32(ast, 0xf000, 0x1);
 105                        *scu_rev = ast_read32(ast, 0x1207c);
 106                        return;
 107                }
 108        }
 109
 110        /* We have a P2A bridge but it's disabled */
 111        DRM_INFO("P2A bridge disabled, using default configuration\n");
 112}
 113
 114static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 115{
 116        struct ast_private *ast = dev->dev_private;
 117        uint32_t jreg, scu_rev;
 118
 119        /*
 120         * If VGA isn't enabled, we need to enable now or subsequent
 121         * access to the scratch registers will fail. We also inform
 122         * our caller that it needs to POST the chip
 123         * (Assumption: VGA not enabled -> need to POST)
 124         */
 125        if (!ast_is_vga_enabled(dev)) {
 126                ast_enable_vga(dev);
 127                DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
 128                *need_post = true;
 129        } else
 130                *need_post = false;
 131
 132
 133        /* Enable extended register access */
 134        ast_enable_mmio(dev);
 135        ast_open_key(ast);
 136
 137        /* Find out whether P2A works or whether to use device-tree */
 138        ast_detect_config_mode(dev, &scu_rev);
 139
 140        /* Identify chipset */
 141        if (dev->pdev->device == PCI_CHIP_AST1180) {
 142                ast->chip = AST1100;
 143                DRM_INFO("AST 1180 detected\n");
 144        } else {
 145                if (dev->pdev->revision >= 0x40) {
 146                        ast->chip = AST2500;
 147                        DRM_INFO("AST 2500 detected\n");
 148                } else if (dev->pdev->revision >= 0x30) {
 149                        ast->chip = AST2400;
 150                        DRM_INFO("AST 2400 detected\n");
 151                } else if (dev->pdev->revision >= 0x20) {
 152                        ast->chip = AST2300;
 153                        DRM_INFO("AST 2300 detected\n");
 154                } else if (dev->pdev->revision >= 0x10) {
 155                        switch (scu_rev & 0x0300) {
 156                        case 0x0200:
 157                                ast->chip = AST1100;
 158                                DRM_INFO("AST 1100 detected\n");
 159                                break;
 160                        case 0x0100:
 161                                ast->chip = AST2200;
 162                                DRM_INFO("AST 2200 detected\n");
 163                                break;
 164                        case 0x0000:
 165                                ast->chip = AST2150;
 166                                DRM_INFO("AST 2150 detected\n");
 167                                break;
 168                        default:
 169                                ast->chip = AST2100;
 170                                DRM_INFO("AST 2100 detected\n");
 171                                break;
 172                        }
 173                        ast->vga2_clone = false;
 174                } else {
 175                        ast->chip = AST2000;
 176                        DRM_INFO("AST 2000 detected\n");
 177                }
 178        }
 179
 180        /* Check if we support wide screen */
 181        switch (ast->chip) {
 182        case AST1180:
 183                ast->support_wide_screen = true;
 184                break;
 185        case AST2000:
 186                ast->support_wide_screen = false;
 187                break;
 188        default:
 189                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
 190                if (!(jreg & 0x80))
 191                        ast->support_wide_screen = true;
 192                else if (jreg & 0x01)
 193                        ast->support_wide_screen = true;
 194                else {
 195                        ast->support_wide_screen = false;
 196                        if (ast->chip == AST2300 &&
 197                            (scu_rev & 0x300) == 0x0) /* ast1300 */
 198                                ast->support_wide_screen = true;
 199                        if (ast->chip == AST2400 &&
 200                            (scu_rev & 0x300) == 0x100) /* ast1400 */
 201                                ast->support_wide_screen = true;
 202                        if (ast->chip == AST2500 &&
 203                            scu_rev == 0x100)           /* ast2510 */
 204                                ast->support_wide_screen = true;
 205                }
 206                break;
 207        }
 208
 209        /* Check 3rd Tx option (digital output afaik) */
 210        ast->tx_chip_type = AST_TX_NONE;
 211
 212        /*
 213         * VGACRA3 Enhanced Color Mode Register, check if DVO is already
 214         * enabled, in that case, assume we have a SIL164 TMDS transmitter
 215         *
 216         * Don't make that assumption if we the chip wasn't enabled and
 217         * is at power-on reset, otherwise we'll incorrectly "detect" a
 218         * SIL164 when there is none.
 219         */
 220        if (!*need_post) {
 221                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff);
 222                if (jreg & 0x80)
 223                        ast->tx_chip_type = AST_TX_SIL164;
 224        }
 225
 226        if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
 227                /*
 228                 * On AST2300 and 2400, look the configuration set by the SoC in
 229                 * the SOC scratch register #1 bits 11:8 (interestingly marked
 230                 * as "reserved" in the spec)
 231                 */
 232                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
 233                switch (jreg) {
 234                case 0x04:
 235                        ast->tx_chip_type = AST_TX_SIL164;
 236                        break;
 237                case 0x08:
 238                        ast->dp501_fw_addr = kzalloc(32*1024, GFP_KERNEL);
 239                        if (ast->dp501_fw_addr) {
 240                                /* backup firmware */
 241                                if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) {
 242                                        kfree(ast->dp501_fw_addr);
 243                                        ast->dp501_fw_addr = NULL;
 244                                }
 245                        }
 246                        /* fallthrough */
 247                case 0x0c:
 248                        ast->tx_chip_type = AST_TX_DP501;
 249                }
 250        }
 251
 252        /* Print stuff for diagnostic purposes */
 253        switch(ast->tx_chip_type) {
 254        case AST_TX_SIL164:
 255                DRM_INFO("Using Sil164 TMDS transmitter\n");
 256                break;
 257        case AST_TX_DP501:
 258                DRM_INFO("Using DP501 DisplayPort transmitter\n");
 259                break;
 260        default:
 261                DRM_INFO("Analog VGA only\n");
 262        }
 263        return 0;
 264}
 265
 266static int ast_get_dram_info(struct drm_device *dev)
 267{
 268        struct device_node *np = dev->pdev->dev.of_node;
 269        struct ast_private *ast = dev->dev_private;
 270        uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
 271        uint32_t denum, num, div, ref_pll, dsel;
 272
 273        switch (ast->config_mode) {
 274        case ast_use_dt:
 275                /*
 276                 * If some properties are missing, use reasonable
 277                 * defaults for AST2400
 278                 */
 279                if (of_property_read_u32(np, "aspeed,mcr-configuration",
 280                                         &mcr_cfg))
 281                        mcr_cfg = 0x00000577;
 282                if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
 283                                         &mcr_scu_mpll))
 284                        mcr_scu_mpll = 0x000050C0;
 285                if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
 286                                         &mcr_scu_strap))
 287                        mcr_scu_strap = 0;
 288                break;
 289        case ast_use_p2a:
 290                ast_write32(ast, 0xf004, 0x1e6e0000);
 291                ast_write32(ast, 0xf000, 0x1);
 292                mcr_cfg = ast_read32(ast, 0x10004);
 293                mcr_scu_mpll = ast_read32(ast, 0x10120);
 294                mcr_scu_strap = ast_read32(ast, 0x10170);
 295                break;
 296        case ast_use_defaults:
 297        default:
 298                ast->dram_bus_width = 16;
 299                ast->dram_type = AST_DRAM_1Gx16;
 300                if (ast->chip == AST2500)
 301                        ast->mclk = 800;
 302                else
 303                        ast->mclk = 396;
 304                return 0;
 305        }
 306
 307        if (mcr_cfg & 0x40)
 308                ast->dram_bus_width = 16;
 309        else
 310                ast->dram_bus_width = 32;
 311
 312        if (ast->chip == AST2500) {
 313                switch (mcr_cfg & 0x03) {
 314                case 0:
 315                        ast->dram_type = AST_DRAM_1Gx16;
 316                        break;
 317                default:
 318                case 1:
 319                        ast->dram_type = AST_DRAM_2Gx16;
 320                        break;
 321                case 2:
 322                        ast->dram_type = AST_DRAM_4Gx16;
 323                        break;
 324                case 3:
 325                        ast->dram_type = AST_DRAM_8Gx16;
 326                        break;
 327                }
 328        } else if (ast->chip == AST2300 || ast->chip == AST2400) {
 329                switch (mcr_cfg & 0x03) {
 330                case 0:
 331                        ast->dram_type = AST_DRAM_512Mx16;
 332                        break;
 333                default:
 334                case 1:
 335                        ast->dram_type = AST_DRAM_1Gx16;
 336                        break;
 337                case 2:
 338                        ast->dram_type = AST_DRAM_2Gx16;
 339                        break;
 340                case 3:
 341                        ast->dram_type = AST_DRAM_4Gx16;
 342                        break;
 343                }
 344        } else {
 345                switch (mcr_cfg & 0x0c) {
 346                case 0:
 347                case 4:
 348                        ast->dram_type = AST_DRAM_512Mx16;
 349                        break;
 350                case 8:
 351                        if (mcr_cfg & 0x40)
 352                                ast->dram_type = AST_DRAM_1Gx16;
 353                        else
 354                                ast->dram_type = AST_DRAM_512Mx32;
 355                        break;
 356                case 0xc:
 357                        ast->dram_type = AST_DRAM_1Gx32;
 358                        break;
 359                }
 360        }
 361
 362        if (mcr_scu_strap & 0x2000)
 363                ref_pll = 14318;
 364        else
 365                ref_pll = 12000;
 366
 367        denum = mcr_scu_mpll & 0x1f;
 368        num = (mcr_scu_mpll & 0x3fe0) >> 5;
 369        dsel = (mcr_scu_mpll & 0xc000) >> 14;
 370        switch (dsel) {
 371        case 3:
 372                div = 0x4;
 373                break;
 374        case 2:
 375        case 1:
 376                div = 0x2;
 377                break;
 378        default:
 379                div = 0x1;
 380                break;
 381        }
 382        ast->mclk = ref_pll * (num + 2) / ((denum + 2) * (div * 1000));
 383        return 0;
 384}
 385
 386static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)
 387{
 388        struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
 389
 390        drm_gem_object_put_unlocked(ast_fb->obj);
 391        drm_framebuffer_cleanup(fb);
 392        kfree(ast_fb);
 393}
 394
 395static const struct drm_framebuffer_funcs ast_fb_funcs = {
 396        .destroy = ast_user_framebuffer_destroy,
 397};
 398
 399
 400int ast_framebuffer_init(struct drm_device *dev,
 401                         struct ast_framebuffer *ast_fb,
 402                         const struct drm_mode_fb_cmd2 *mode_cmd,
 403                         struct drm_gem_object *obj)
 404{
 405        int ret;
 406
 407        drm_helper_mode_fill_fb_struct(dev, &ast_fb->base, mode_cmd);
 408        ast_fb->obj = obj;
 409        ret = drm_framebuffer_init(dev, &ast_fb->base, &ast_fb_funcs);
 410        if (ret) {
 411                DRM_ERROR("framebuffer init failed %d\n", ret);
 412                return ret;
 413        }
 414        return 0;
 415}
 416
 417static struct drm_framebuffer *
 418ast_user_framebuffer_create(struct drm_device *dev,
 419               struct drm_file *filp,
 420               const struct drm_mode_fb_cmd2 *mode_cmd)
 421{
 422        struct drm_gem_object *obj;
 423        struct ast_framebuffer *ast_fb;
 424        int ret;
 425
 426        obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
 427        if (obj == NULL)
 428                return ERR_PTR(-ENOENT);
 429
 430        ast_fb = kzalloc(sizeof(*ast_fb), GFP_KERNEL);
 431        if (!ast_fb) {
 432                drm_gem_object_put_unlocked(obj);
 433                return ERR_PTR(-ENOMEM);
 434        }
 435
 436        ret = ast_framebuffer_init(dev, ast_fb, mode_cmd, obj);
 437        if (ret) {
 438                drm_gem_object_put_unlocked(obj);
 439                kfree(ast_fb);
 440                return ERR_PTR(ret);
 441        }
 442        return &ast_fb->base;
 443}
 444
 445static const struct drm_mode_config_funcs ast_mode_funcs = {
 446        .fb_create = ast_user_framebuffer_create,
 447};
 448
 449static u32 ast_get_vram_info(struct drm_device *dev)
 450{
 451        struct ast_private *ast = dev->dev_private;
 452        u8 jreg;
 453        u32 vram_size;
 454        ast_open_key(ast);
 455
 456        vram_size = AST_VIDMEM_DEFAULT_SIZE;
 457        jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff);
 458        switch (jreg & 3) {
 459        case 0: vram_size = AST_VIDMEM_SIZE_8M; break;
 460        case 1: vram_size = AST_VIDMEM_SIZE_16M; break;
 461        case 2: vram_size = AST_VIDMEM_SIZE_32M; break;
 462        case 3: vram_size = AST_VIDMEM_SIZE_64M; break;
 463        }
 464
 465        jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xff);
 466        switch (jreg & 0x03) {
 467        case 1:
 468                vram_size -= 0x100000;
 469                break;
 470        case 2:
 471                vram_size -= 0x200000;
 472                break;
 473        case 3:
 474                vram_size -= 0x400000;
 475                break;
 476        }
 477
 478        return vram_size;
 479}
 480
 481int ast_driver_load(struct drm_device *dev, unsigned long flags)
 482{
 483        struct ast_private *ast;
 484        bool need_post;
 485        int ret = 0;
 486
 487        ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL);
 488        if (!ast)
 489                return -ENOMEM;
 490
 491        dev->dev_private = ast;
 492        ast->dev = dev;
 493
 494        ast->regs = pci_iomap(dev->pdev, 1, 0);
 495        if (!ast->regs) {
 496                ret = -EIO;
 497                goto out_free;
 498        }
 499
 500        /*
 501         * If we don't have IO space at all, use MMIO now and
 502         * assume the chip has MMIO enabled by default (rev 0x20
 503         * and higher).
 504         */
 505        if (!(pci_resource_flags(dev->pdev, 2) & IORESOURCE_IO)) {
 506                DRM_INFO("platform has no IO space, trying MMIO\n");
 507                ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
 508        }
 509
 510        /* "map" IO regs if the above hasn't done so already */
 511        if (!ast->ioregs) {
 512                ast->ioregs = pci_iomap(dev->pdev, 2, 0);
 513                if (!ast->ioregs) {
 514                        ret = -EIO;
 515                        goto out_free;
 516                }
 517        }
 518
 519        ast_detect_chip(dev, &need_post);
 520
 521        if (need_post)
 522                ast_post_gpu(dev);
 523
 524        if (ast->chip != AST1180) {
 525                ret = ast_get_dram_info(dev);
 526                if (ret)
 527                        goto out_free;
 528                ast->vram_size = ast_get_vram_info(dev);
 529                DRM_INFO("dram MCLK=%u Mhz type=%d bus_width=%d size=%08x\n",
 530                         ast->mclk, ast->dram_type,
 531                         ast->dram_bus_width, ast->vram_size);
 532        }
 533
 534        ret = ast_mm_init(ast);
 535        if (ret)
 536                goto out_free;
 537
 538        drm_mode_config_init(dev);
 539
 540        dev->mode_config.funcs = (void *)&ast_mode_funcs;
 541        dev->mode_config.min_width = 0;
 542        dev->mode_config.min_height = 0;
 543        dev->mode_config.preferred_depth = 24;
 544        dev->mode_config.prefer_shadow = 1;
 545        dev->mode_config.fb_base = pci_resource_start(ast->dev->pdev, 0);
 546
 547        if (ast->chip == AST2100 ||
 548            ast->chip == AST2200 ||
 549            ast->chip == AST2300 ||
 550            ast->chip == AST2400 ||
 551            ast->chip == AST2500 ||
 552            ast->chip == AST1180) {
 553                dev->mode_config.max_width = 1920;
 554                dev->mode_config.max_height = 2048;
 555        } else {
 556                dev->mode_config.max_width = 1600;
 557                dev->mode_config.max_height = 1200;
 558        }
 559
 560        ret = ast_mode_init(dev);
 561        if (ret)
 562                goto out_free;
 563
 564        ret = ast_fbdev_init(dev);
 565        if (ret)
 566                goto out_free;
 567
 568        return 0;
 569out_free:
 570        kfree(ast);
 571        dev->dev_private = NULL;
 572        return ret;
 573}
 574
 575void ast_driver_unload(struct drm_device *dev)
 576{
 577        struct ast_private *ast = dev->dev_private;
 578
 579        ast_release_firmware(dev);
 580        kfree(ast->dp501_fw_addr);
 581        ast_mode_fini(dev);
 582        ast_fbdev_fini(dev);
 583        drm_mode_config_cleanup(dev);
 584
 585        ast_mm_fini(ast);
 586        if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET)
 587                pci_iounmap(dev->pdev, ast->ioregs);
 588        pci_iounmap(dev->pdev, ast->regs);
 589        kfree(ast);
 590}
 591
 592int ast_gem_create(struct drm_device *dev,
 593                   u32 size, bool iskernel,
 594                   struct drm_gem_object **obj)
 595{
 596        struct ast_bo *astbo;
 597        int ret;
 598
 599        *obj = NULL;
 600
 601        size = roundup(size, PAGE_SIZE);
 602        if (size == 0)
 603                return -EINVAL;
 604
 605        ret = ast_bo_create(dev, size, 0, 0, &astbo);
 606        if (ret) {
 607                if (ret != -ERESTARTSYS)
 608                        DRM_ERROR("failed to allocate GEM object\n");
 609                return ret;
 610        }
 611        *obj = &astbo->gem;
 612        return 0;
 613}
 614
 615int ast_dumb_create(struct drm_file *file,
 616                    struct drm_device *dev,
 617                    struct drm_mode_create_dumb *args)
 618{
 619        int ret;
 620        struct drm_gem_object *gobj;
 621        u32 handle;
 622
 623        args->pitch = args->width * ((args->bpp + 7) / 8);
 624        args->size = args->pitch * args->height;
 625
 626        ret = ast_gem_create(dev, args->size, false,
 627                             &gobj);
 628        if (ret)
 629                return ret;
 630
 631        ret = drm_gem_handle_create(file, gobj, &handle);
 632        drm_gem_object_put_unlocked(gobj);
 633        if (ret)
 634                return ret;
 635
 636        args->handle = handle;
 637        return 0;
 638}
 639
 640static void ast_bo_unref(struct ast_bo **bo)
 641{
 642        if ((*bo) == NULL)
 643                return;
 644        ttm_bo_put(&((*bo)->bo));
 645        *bo = NULL;
 646}
 647
 648void ast_gem_free_object(struct drm_gem_object *obj)
 649{
 650        struct ast_bo *ast_bo = gem_to_ast_bo(obj);
 651
 652        ast_bo_unref(&ast_bo);
 653}
 654
 655
 656static inline u64 ast_bo_mmap_offset(struct ast_bo *bo)
 657{
 658        return drm_vma_node_offset_addr(&bo->bo.vma_node);
 659}
 660int
 661ast_dumb_mmap_offset(struct drm_file *file,
 662                     struct drm_device *dev,
 663                     uint32_t handle,
 664                     uint64_t *offset)
 665{
 666        struct drm_gem_object *obj;
 667        struct ast_bo *bo;
 668
 669        obj = drm_gem_object_lookup(file, handle);
 670        if (obj == NULL)
 671                return -ENOENT;
 672
 673        bo = gem_to_ast_bo(obj);
 674        *offset = ast_bo_mmap_offset(bo);
 675
 676        drm_gem_object_put_unlocked(obj);
 677
 678        return 0;
 679
 680}
 681
 682