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
  35#include "ast_dram_tables.h"
  36
  37void ast_set_index_reg_mask(struct ast_private *ast,
  38                            uint32_t base, uint8_t index,
  39                            uint8_t mask, uint8_t val)
  40{
  41        u8 tmp;
  42        ast_io_write8(ast, base, index);
  43        tmp = (ast_io_read8(ast, base + 1) & mask) | val;
  44        ast_set_index_reg(ast, base, index, tmp);
  45}
  46
  47uint8_t ast_get_index_reg(struct ast_private *ast,
  48                          uint32_t base, uint8_t index)
  49{
  50        uint8_t ret;
  51        ast_io_write8(ast, base, index);
  52        ret = ast_io_read8(ast, base + 1);
  53        return ret;
  54}
  55
  56uint8_t ast_get_index_reg_mask(struct ast_private *ast,
  57                               uint32_t base, uint8_t index, uint8_t mask)
  58{
  59        uint8_t ret;
  60        ast_io_write8(ast, base, index);
  61        ret = ast_io_read8(ast, base + 1) & mask;
  62        return ret;
  63}
  64
  65
  66static int ast_detect_chip(struct drm_device *dev)
  67{
  68        struct ast_private *ast = dev->dev_private;
  69
  70        if (dev->pdev->device == PCI_CHIP_AST1180) {
  71                ast->chip = AST1100;
  72                DRM_INFO("AST 1180 detected\n");
  73        } else {
  74                if (dev->pdev->revision >= 0x20) {
  75                        ast->chip = AST2300;
  76                        DRM_INFO("AST 2300 detected\n");
  77                } else if (dev->pdev->revision >= 0x10) {
  78                        uint32_t data;
  79                        ast_write32(ast, 0xf004, 0x1e6e0000);
  80                        ast_write32(ast, 0xf000, 0x1);
  81
  82                        data = ast_read32(ast, 0x1207c);
  83                        switch (data & 0x0300) {
  84                        case 0x0200:
  85                                ast->chip = AST1100;
  86                                DRM_INFO("AST 1100 detected\n");
  87                                break;
  88                        case 0x0100:
  89                                ast->chip = AST2200;
  90                                DRM_INFO("AST 2200 detected\n");
  91                                break;
  92                        case 0x0000:
  93                                ast->chip = AST2150;
  94                                DRM_INFO("AST 2150 detected\n");
  95                                break;
  96                        default:
  97                                ast->chip = AST2100;
  98                                DRM_INFO("AST 2100 detected\n");
  99                                break;
 100                        }
 101                        ast->vga2_clone = false;
 102                } else {
 103                        ast->chip = 2000;
 104                        DRM_INFO("AST 2000 detected\n");
 105                }
 106        }
 107        return 0;
 108}
 109
 110static int ast_get_dram_info(struct drm_device *dev)
 111{
 112        struct ast_private *ast = dev->dev_private;
 113        uint32_t data, data2;
 114        uint32_t denum, num, div, ref_pll;
 115
 116        ast_write32(ast, 0xf004, 0x1e6e0000);
 117        ast_write32(ast, 0xf000, 0x1);
 118
 119
 120        ast_write32(ast, 0x10000, 0xfc600309);
 121
 122        do {
 123                ;
 124        } while (ast_read32(ast, 0x10000) != 0x01);
 125        data = ast_read32(ast, 0x10004);
 126
 127        if (data & 0x400)
 128                ast->dram_bus_width = 16;
 129        else
 130                ast->dram_bus_width = 32;
 131
 132        if (ast->chip == AST2300) {
 133                switch (data & 0x03) {
 134                case 0:
 135                        ast->dram_type = AST_DRAM_512Mx16;
 136                        break;
 137                default:
 138                case 1:
 139                        ast->dram_type = AST_DRAM_1Gx16;
 140                        break;
 141                case 2:
 142                        ast->dram_type = AST_DRAM_2Gx16;
 143                        break;
 144                case 3:
 145                        ast->dram_type = AST_DRAM_4Gx16;
 146                        break;
 147                }
 148        } else {
 149                switch (data & 0x0c) {
 150                case 0:
 151                case 4:
 152                        ast->dram_type = AST_DRAM_512Mx16;
 153                        break;
 154                case 8:
 155                        if (data & 0x40)
 156                                ast->dram_type = AST_DRAM_1Gx16;
 157                        else
 158                                ast->dram_type = AST_DRAM_512Mx32;
 159                        break;
 160                case 0xc:
 161                        ast->dram_type = AST_DRAM_1Gx32;
 162                        break;
 163                }
 164        }
 165
 166        data = ast_read32(ast, 0x10120);
 167        data2 = ast_read32(ast, 0x10170);
 168        if (data2 & 0x2000)
 169                ref_pll = 14318;
 170        else
 171                ref_pll = 12000;
 172
 173        denum = data & 0x1f;
 174        num = (data & 0x3fe0) >> 5;
 175        data = (data & 0xc000) >> 14;
 176        switch (data) {
 177        case 3:
 178                div = 0x4;
 179                break;
 180        case 2:
 181        case 1:
 182                div = 0x2;
 183                break;
 184        default:
 185                div = 0x1;
 186                break;
 187        }
 188        ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
 189        return 0;
 190}
 191
 192uint32_t ast_get_max_dclk(struct drm_device *dev, int bpp)
 193{
 194        struct ast_private *ast = dev->dev_private;
 195        uint32_t dclk, jreg;
 196        uint32_t dram_bus_width, mclk, dram_bandwidth, actual_dram_bandwidth, dram_efficency = 500;
 197
 198        dram_bus_width = ast->dram_bus_width;
 199        mclk = ast->mclk;
 200
 201        if (ast->chip == AST2100 ||
 202            ast->chip == AST1100 ||
 203            ast->chip == AST2200 ||
 204            ast->chip == AST2150 ||
 205            ast->dram_bus_width == 16)
 206                dram_efficency = 600;
 207        else if (ast->chip == AST2300)
 208                dram_efficency = 400;
 209
 210        dram_bandwidth = mclk * dram_bus_width * 2 / 8;
 211        actual_dram_bandwidth = dram_bandwidth * dram_efficency / 1000;
 212
 213        if (ast->chip == AST1180)
 214                dclk = actual_dram_bandwidth / ((bpp + 1) / 8);
 215        else {
 216                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
 217                if ((jreg & 0x08) && (ast->chip == AST2000))
 218                        dclk = actual_dram_bandwidth / ((bpp + 1 + 16) / 8);
 219                else if ((jreg & 0x08) && (bpp == 8))
 220                        dclk = actual_dram_bandwidth / ((bpp + 1 + 24) / 8);
 221                else
 222                        dclk = actual_dram_bandwidth / ((bpp + 1) / 8);
 223        }
 224
 225        if (ast->chip == AST2100 ||
 226            ast->chip == AST2200 ||
 227            ast->chip == AST2300 ||
 228            ast->chip == AST1180) {
 229                if (dclk > 200)
 230                        dclk = 200;
 231        } else {
 232                if (dclk > 165)
 233                        dclk = 165;
 234        }
 235
 236        return dclk;
 237}
 238
 239static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)
 240{
 241        struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
 242        if (ast_fb->obj)
 243                drm_gem_object_unreference_unlocked(ast_fb->obj);
 244
 245        drm_framebuffer_cleanup(fb);
 246        kfree(fb);
 247}
 248
 249static const struct drm_framebuffer_funcs ast_fb_funcs = {
 250        .destroy = ast_user_framebuffer_destroy,
 251};
 252
 253
 254int ast_framebuffer_init(struct drm_device *dev,
 255                         struct ast_framebuffer *ast_fb,
 256                         struct drm_mode_fb_cmd2 *mode_cmd,
 257                         struct drm_gem_object *obj)
 258{
 259        int ret;
 260
 261        drm_helper_mode_fill_fb_struct(&ast_fb->base, mode_cmd);
 262        ast_fb->obj = obj;
 263        ret = drm_framebuffer_init(dev, &ast_fb->base, &ast_fb_funcs);
 264        if (ret) {
 265                DRM_ERROR("framebuffer init failed %d\n", ret);
 266                return ret;
 267        }
 268        return 0;
 269}
 270
 271static struct drm_framebuffer *
 272ast_user_framebuffer_create(struct drm_device *dev,
 273               struct drm_file *filp,
 274               struct drm_mode_fb_cmd2 *mode_cmd)
 275{
 276        struct drm_gem_object *obj;
 277        struct ast_framebuffer *ast_fb;
 278        int ret;
 279
 280        obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
 281        if (obj == NULL)
 282                return ERR_PTR(-ENOENT);
 283
 284        ast_fb = kzalloc(sizeof(*ast_fb), GFP_KERNEL);
 285        if (!ast_fb) {
 286                drm_gem_object_unreference_unlocked(obj);
 287                return ERR_PTR(-ENOMEM);
 288        }
 289
 290        ret = ast_framebuffer_init(dev, ast_fb, mode_cmd, obj);
 291        if (ret) {
 292                drm_gem_object_unreference_unlocked(obj);
 293                kfree(ast_fb);
 294                return ERR_PTR(ret);
 295        }
 296        return &ast_fb->base;
 297}
 298
 299static const struct drm_mode_config_funcs ast_mode_funcs = {
 300        .fb_create = ast_user_framebuffer_create,
 301};
 302
 303static u32 ast_get_vram_info(struct drm_device *dev)
 304{
 305        struct ast_private *ast = dev->dev_private;
 306        u8 jreg;
 307
 308        ast_open_key(ast);
 309
 310        jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff);
 311        switch (jreg & 3) {
 312        case 0: return AST_VIDMEM_SIZE_8M;
 313        case 1: return AST_VIDMEM_SIZE_16M;
 314        case 2: return AST_VIDMEM_SIZE_32M;
 315        case 3: return AST_VIDMEM_SIZE_64M;
 316        }
 317        return AST_VIDMEM_DEFAULT_SIZE;
 318}
 319
 320int ast_driver_load(struct drm_device *dev, unsigned long flags)
 321{
 322        struct ast_private *ast;
 323        int ret = 0;
 324
 325        ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL);
 326        if (!ast)
 327                return -ENOMEM;
 328
 329        dev->dev_private = ast;
 330        ast->dev = dev;
 331
 332        ast->regs = pci_iomap(dev->pdev, 1, 0);
 333        if (!ast->regs) {
 334                ret = -EIO;
 335                goto out_free;
 336        }
 337        ast->ioregs = pci_iomap(dev->pdev, 2, 0);
 338        if (!ast->ioregs) {
 339                ret = -EIO;
 340                goto out_free;
 341        }
 342
 343        ast_detect_chip(dev);
 344
 345        if (ast->chip != AST1180) {
 346                ast_get_dram_info(dev);
 347                ast->vram_size = ast_get_vram_info(dev);
 348                DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
 349        }
 350
 351        ret = ast_mm_init(ast);
 352        if (ret)
 353                goto out_free;
 354
 355        drm_mode_config_init(dev);
 356
 357        dev->mode_config.funcs = (void *)&ast_mode_funcs;
 358        dev->mode_config.min_width = 0;
 359        dev->mode_config.min_height = 0;
 360        dev->mode_config.preferred_depth = 24;
 361        dev->mode_config.prefer_shadow = 1;
 362
 363        if (ast->chip == AST2100 ||
 364            ast->chip == AST2200 ||
 365            ast->chip == AST2300 ||
 366            ast->chip == AST1180) {
 367                dev->mode_config.max_width = 1920;
 368                dev->mode_config.max_height = 2048;
 369        } else {
 370                dev->mode_config.max_width = 1600;
 371                dev->mode_config.max_height = 1200;
 372        }
 373
 374        ret = ast_mode_init(dev);
 375        if (ret)
 376                goto out_free;
 377
 378        ret = ast_fbdev_init(dev);
 379        if (ret)
 380                goto out_free;
 381
 382        return 0;
 383out_free:
 384        kfree(ast);
 385        dev->dev_private = NULL;
 386        return ret;
 387}
 388
 389int ast_driver_unload(struct drm_device *dev)
 390{
 391        struct ast_private *ast = dev->dev_private;
 392
 393        ast_mode_fini(dev);
 394        ast_fbdev_fini(dev);
 395        drm_mode_config_cleanup(dev);
 396
 397        ast_mm_fini(ast);
 398        pci_iounmap(dev->pdev, ast->ioregs);
 399        pci_iounmap(dev->pdev, ast->regs);
 400        kfree(ast);
 401        return 0;
 402}
 403
 404int ast_gem_create(struct drm_device *dev,
 405                   u32 size, bool iskernel,
 406                   struct drm_gem_object **obj)
 407{
 408        struct ast_bo *astbo;
 409        int ret;
 410
 411        *obj = NULL;
 412
 413        size = roundup(size, PAGE_SIZE);
 414        if (size == 0)
 415                return -EINVAL;
 416
 417        ret = ast_bo_create(dev, size, 0, 0, &astbo);
 418        if (ret) {
 419                if (ret != -ERESTARTSYS)
 420                        DRM_ERROR("failed to allocate GEM object\n");
 421                return ret;
 422        }
 423        *obj = &astbo->gem;
 424        return 0;
 425}
 426
 427int ast_dumb_create(struct drm_file *file,
 428                    struct drm_device *dev,
 429                    struct drm_mode_create_dumb *args)
 430{
 431        int ret;
 432        struct drm_gem_object *gobj;
 433        u32 handle;
 434
 435        args->pitch = args->width * ((args->bpp + 7) / 8);
 436        args->size = args->pitch * args->height;
 437
 438        ret = ast_gem_create(dev, args->size, false,
 439                             &gobj);
 440        if (ret)
 441                return ret;
 442
 443        ret = drm_gem_handle_create(file, gobj, &handle);
 444        drm_gem_object_unreference_unlocked(gobj);
 445        if (ret)
 446                return ret;
 447
 448        args->handle = handle;
 449        return 0;
 450}
 451
 452int ast_dumb_destroy(struct drm_file *file,
 453                     struct drm_device *dev,
 454                     uint32_t handle)
 455{
 456        return drm_gem_handle_delete(file, handle);
 457}
 458
 459int ast_gem_init_object(struct drm_gem_object *obj)
 460{
 461        BUG();
 462        return 0;
 463}
 464
 465void ast_bo_unref(struct ast_bo **bo)
 466{
 467        struct ttm_buffer_object *tbo;
 468
 469        if ((*bo) == NULL)
 470                return;
 471
 472        tbo = &((*bo)->bo);
 473        ttm_bo_unref(&tbo);
 474        if (tbo == NULL)
 475                *bo = NULL;
 476
 477}
 478void ast_gem_free_object(struct drm_gem_object *obj)
 479{
 480        struct ast_bo *ast_bo = gem_to_ast_bo(obj);
 481
 482        if (!ast_bo)
 483                return;
 484        ast_bo_unref(&ast_bo);
 485}
 486
 487
 488static inline u64 ast_bo_mmap_offset(struct ast_bo *bo)
 489{
 490        return bo->bo.addr_space_offset;
 491}
 492int
 493ast_dumb_mmap_offset(struct drm_file *file,
 494                     struct drm_device *dev,
 495                     uint32_t handle,
 496                     uint64_t *offset)
 497{
 498        struct drm_gem_object *obj;
 499        int ret;
 500        struct ast_bo *bo;
 501
 502        mutex_lock(&dev->struct_mutex);
 503        obj = drm_gem_object_lookup(dev, file, handle);
 504        if (obj == NULL) {
 505                ret = -ENOENT;
 506                goto out_unlock;
 507        }
 508
 509        bo = gem_to_ast_bo(obj);
 510        *offset = ast_bo_mmap_offset(bo);
 511
 512        drm_gem_object_unreference(obj);
 513        ret = 0;
 514out_unlock:
 515        mutex_unlock(&dev->struct_mutex);
 516        return ret;
 517
 518}
 519
 520