| .. | .. |
|---|
| 25 | 25 | /* |
|---|
| 26 | 26 | * Authors: Dave Airlie <airlied@redhat.com> |
|---|
| 27 | 27 | */ |
|---|
| 28 | | -#include <drm/drmP.h> |
|---|
| 29 | | -#include "ast_drv.h" |
|---|
| 30 | 28 | |
|---|
| 29 | +#include <linux/pci.h> |
|---|
| 31 | 30 | |
|---|
| 32 | | -#include <drm/drm_fb_helper.h> |
|---|
| 31 | +#include <drm/drm_atomic_helper.h> |
|---|
| 33 | 32 | #include <drm/drm_crtc_helper.h> |
|---|
| 33 | +#include <drm/drm_drv.h> |
|---|
| 34 | +#include <drm/drm_gem.h> |
|---|
| 35 | +#include <drm/drm_gem_vram_helper.h> |
|---|
| 36 | +#include <drm/drm_managed.h> |
|---|
| 37 | + |
|---|
| 38 | +#include "ast_drv.h" |
|---|
| 34 | 39 | |
|---|
| 35 | 40 | void ast_set_index_reg_mask(struct ast_private *ast, |
|---|
| 36 | 41 | uint32_t base, uint8_t index, |
|---|
| .. | .. |
|---|
| 63 | 68 | static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) |
|---|
| 64 | 69 | { |
|---|
| 65 | 70 | struct device_node *np = dev->pdev->dev.of_node; |
|---|
| 66 | | - struct ast_private *ast = dev->dev_private; |
|---|
| 71 | + struct ast_private *ast = to_ast_private(dev); |
|---|
| 67 | 72 | uint32_t data, jregd0, jregd1; |
|---|
| 68 | 73 | |
|---|
| 69 | 74 | /* Defaults */ |
|---|
| .. | .. |
|---|
| 75 | 80 | scu_rev)) { |
|---|
| 76 | 81 | /* We do, disable P2A access */ |
|---|
| 77 | 82 | ast->config_mode = ast_use_dt; |
|---|
| 78 | | - DRM_INFO("Using device-tree for configuration\n"); |
|---|
| 83 | + drm_info(dev, "Using device-tree for configuration\n"); |
|---|
| 79 | 84 | return; |
|---|
| 80 | 85 | } |
|---|
| 81 | 86 | |
|---|
| .. | .. |
|---|
| 93 | 98 | if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { |
|---|
| 94 | 99 | /* Double check it's actually working */ |
|---|
| 95 | 100 | data = ast_read32(ast, 0xf004); |
|---|
| 96 | | - if (data != 0xFFFFFFFF) { |
|---|
| 101 | + if ((data != 0xFFFFFFFF) && (data != 0x00)) { |
|---|
| 97 | 102 | /* P2A works, grab silicon revision */ |
|---|
| 98 | 103 | ast->config_mode = ast_use_p2a; |
|---|
| 99 | 104 | |
|---|
| 100 | | - DRM_INFO("Using P2A bridge for configuration\n"); |
|---|
| 105 | + drm_info(dev, "Using P2A bridge for configuration\n"); |
|---|
| 101 | 106 | |
|---|
| 102 | 107 | /* Read SCU7c (silicon revision register) */ |
|---|
| 103 | 108 | ast_write32(ast, 0xf004, 0x1e6e0000); |
|---|
| .. | .. |
|---|
| 108 | 113 | } |
|---|
| 109 | 114 | |
|---|
| 110 | 115 | /* We have a P2A bridge but it's disabled */ |
|---|
| 111 | | - DRM_INFO("P2A bridge disabled, using default configuration\n"); |
|---|
| 116 | + drm_info(dev, "P2A bridge disabled, using default configuration\n"); |
|---|
| 112 | 117 | } |
|---|
| 113 | 118 | |
|---|
| 114 | 119 | static int ast_detect_chip(struct drm_device *dev, bool *need_post) |
|---|
| 115 | 120 | { |
|---|
| 116 | | - struct ast_private *ast = dev->dev_private; |
|---|
| 121 | + struct ast_private *ast = to_ast_private(dev); |
|---|
| 117 | 122 | uint32_t jreg, scu_rev; |
|---|
| 118 | 123 | |
|---|
| 119 | 124 | /* |
|---|
| .. | .. |
|---|
| 124 | 129 | */ |
|---|
| 125 | 130 | if (!ast_is_vga_enabled(dev)) { |
|---|
| 126 | 131 | ast_enable_vga(dev); |
|---|
| 127 | | - DRM_INFO("VGA not enabled on entry, requesting chip POST\n"); |
|---|
| 132 | + drm_info(dev, "VGA not enabled on entry, requesting chip POST\n"); |
|---|
| 128 | 133 | *need_post = true; |
|---|
| 129 | 134 | } else |
|---|
| 130 | 135 | *need_post = false; |
|---|
| .. | .. |
|---|
| 138 | 143 | ast_detect_config_mode(dev, &scu_rev); |
|---|
| 139 | 144 | |
|---|
| 140 | 145 | /* 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"); |
|---|
| 146 | + if (dev->pdev->revision >= 0x40) { |
|---|
| 147 | + ast->chip = AST2500; |
|---|
| 148 | + drm_info(dev, "AST 2500 detected\n"); |
|---|
| 149 | + } else if (dev->pdev->revision >= 0x30) { |
|---|
| 150 | + ast->chip = AST2400; |
|---|
| 151 | + drm_info(dev, "AST 2400 detected\n"); |
|---|
| 152 | + } else if (dev->pdev->revision >= 0x20) { |
|---|
| 153 | + ast->chip = AST2300; |
|---|
| 154 | + drm_info(dev, "AST 2300 detected\n"); |
|---|
| 155 | + } else if (dev->pdev->revision >= 0x10) { |
|---|
| 156 | + switch (scu_rev & 0x0300) { |
|---|
| 157 | + case 0x0200: |
|---|
| 158 | + ast->chip = AST1100; |
|---|
| 159 | + drm_info(dev, "AST 1100 detected\n"); |
|---|
| 160 | + break; |
|---|
| 161 | + case 0x0100: |
|---|
| 162 | + ast->chip = AST2200; |
|---|
| 163 | + drm_info(dev, "AST 2200 detected\n"); |
|---|
| 164 | + break; |
|---|
| 165 | + case 0x0000: |
|---|
| 166 | + ast->chip = AST2150; |
|---|
| 167 | + drm_info(dev, "AST 2150 detected\n"); |
|---|
| 168 | + break; |
|---|
| 169 | + default: |
|---|
| 170 | + ast->chip = AST2100; |
|---|
| 171 | + drm_info(dev, "AST 2100 detected\n"); |
|---|
| 172 | + break; |
|---|
| 177 | 173 | } |
|---|
| 174 | + ast->vga2_clone = false; |
|---|
| 175 | + } else { |
|---|
| 176 | + ast->chip = AST2000; |
|---|
| 177 | + drm_info(dev, "AST 2000 detected\n"); |
|---|
| 178 | 178 | } |
|---|
| 179 | 179 | |
|---|
| 180 | 180 | /* Check if we support wide screen */ |
|---|
| 181 | 181 | switch (ast->chip) { |
|---|
| 182 | | - case AST1180: |
|---|
| 183 | | - ast->support_wide_screen = true; |
|---|
| 184 | | - break; |
|---|
| 185 | 182 | case AST2000: |
|---|
| 186 | 183 | ast->support_wide_screen = false; |
|---|
| 187 | 184 | break; |
|---|
| .. | .. |
|---|
| 235 | 232 | ast->tx_chip_type = AST_TX_SIL164; |
|---|
| 236 | 233 | break; |
|---|
| 237 | 234 | case 0x08: |
|---|
| 238 | | - ast->dp501_fw_addr = kzalloc(32*1024, GFP_KERNEL); |
|---|
| 235 | + ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL); |
|---|
| 239 | 236 | if (ast->dp501_fw_addr) { |
|---|
| 240 | 237 | /* backup firmware */ |
|---|
| 241 | 238 | if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) { |
|---|
| 242 | | - kfree(ast->dp501_fw_addr); |
|---|
| 239 | + drmm_kfree(dev, ast->dp501_fw_addr); |
|---|
| 243 | 240 | ast->dp501_fw_addr = NULL; |
|---|
| 244 | 241 | } |
|---|
| 245 | 242 | } |
|---|
| 246 | | - /* fallthrough */ |
|---|
| 243 | + fallthrough; |
|---|
| 247 | 244 | case 0x0c: |
|---|
| 248 | 245 | ast->tx_chip_type = AST_TX_DP501; |
|---|
| 249 | 246 | } |
|---|
| .. | .. |
|---|
| 252 | 249 | /* Print stuff for diagnostic purposes */ |
|---|
| 253 | 250 | switch(ast->tx_chip_type) { |
|---|
| 254 | 251 | case AST_TX_SIL164: |
|---|
| 255 | | - DRM_INFO("Using Sil164 TMDS transmitter\n"); |
|---|
| 252 | + drm_info(dev, "Using Sil164 TMDS transmitter\n"); |
|---|
| 256 | 253 | break; |
|---|
| 257 | 254 | case AST_TX_DP501: |
|---|
| 258 | | - DRM_INFO("Using DP501 DisplayPort transmitter\n"); |
|---|
| 255 | + drm_info(dev, "Using DP501 DisplayPort transmitter\n"); |
|---|
| 259 | 256 | break; |
|---|
| 260 | 257 | default: |
|---|
| 261 | | - DRM_INFO("Analog VGA only\n"); |
|---|
| 258 | + drm_info(dev, "Analog VGA only\n"); |
|---|
| 262 | 259 | } |
|---|
| 263 | 260 | return 0; |
|---|
| 264 | 261 | } |
|---|
| .. | .. |
|---|
| 266 | 263 | static int ast_get_dram_info(struct drm_device *dev) |
|---|
| 267 | 264 | { |
|---|
| 268 | 265 | struct device_node *np = dev->pdev->dev.of_node; |
|---|
| 269 | | - struct ast_private *ast = dev->dev_private; |
|---|
| 266 | + struct ast_private *ast = to_ast_private(dev); |
|---|
| 270 | 267 | uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap; |
|---|
| 271 | 268 | uint32_t denum, num, div, ref_pll, dsel; |
|---|
| 272 | 269 | |
|---|
| .. | .. |
|---|
| 383 | 380 | return 0; |
|---|
| 384 | 381 | } |
|---|
| 385 | 382 | |
|---|
| 386 | | -static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb) |
|---|
| 383 | +/* |
|---|
| 384 | + * Run this function as part of the HW device cleanup; not |
|---|
| 385 | + * when the DRM device gets released. |
|---|
| 386 | + */ |
|---|
| 387 | +static void ast_device_release(void *data) |
|---|
| 387 | 388 | { |
|---|
| 388 | | - struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb); |
|---|
| 389 | + struct ast_private *ast = data; |
|---|
| 389 | 390 | |
|---|
| 390 | | - drm_gem_object_put_unlocked(ast_fb->obj); |
|---|
| 391 | | - drm_framebuffer_cleanup(fb); |
|---|
| 392 | | - kfree(ast_fb); |
|---|
| 391 | + /* enable standard VGA decode */ |
|---|
| 392 | + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); |
|---|
| 393 | 393 | } |
|---|
| 394 | 394 | |
|---|
| 395 | | -static const struct drm_framebuffer_funcs ast_fb_funcs = { |
|---|
| 396 | | - .destroy = ast_user_framebuffer_destroy, |
|---|
| 397 | | -}; |
|---|
| 398 | | - |
|---|
| 399 | | - |
|---|
| 400 | | -int 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) |
|---|
| 395 | +struct ast_private *ast_device_create(struct drm_driver *drv, |
|---|
| 396 | + struct pci_dev *pdev, |
|---|
| 397 | + unsigned long flags) |
|---|
| 404 | 398 | { |
|---|
| 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 | | - |
|---|
| 417 | | -static struct drm_framebuffer * |
|---|
| 418 | | -ast_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 | | - |
|---|
| 445 | | -static const struct drm_mode_config_funcs ast_mode_funcs = { |
|---|
| 446 | | - .fb_create = ast_user_framebuffer_create, |
|---|
| 447 | | -}; |
|---|
| 448 | | - |
|---|
| 449 | | -static 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 | | - |
|---|
| 481 | | -int ast_driver_load(struct drm_device *dev, unsigned long flags) |
|---|
| 482 | | -{ |
|---|
| 399 | + struct drm_device *dev; |
|---|
| 483 | 400 | struct ast_private *ast; |
|---|
| 484 | 401 | bool need_post; |
|---|
| 485 | 402 | int ret = 0; |
|---|
| 486 | 403 | |
|---|
| 487 | | - ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL); |
|---|
| 488 | | - if (!ast) |
|---|
| 489 | | - return -ENOMEM; |
|---|
| 404 | + ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_private, base); |
|---|
| 405 | + if (IS_ERR(ast)) |
|---|
| 406 | + return ast; |
|---|
| 407 | + dev = &ast->base; |
|---|
| 490 | 408 | |
|---|
| 491 | | - dev->dev_private = ast; |
|---|
| 492 | | - ast->dev = dev; |
|---|
| 409 | + dev->pdev = pdev; |
|---|
| 410 | + pci_set_drvdata(pdev, dev); |
|---|
| 493 | 411 | |
|---|
| 494 | | - ast->regs = pci_iomap(dev->pdev, 1, 0); |
|---|
| 495 | | - if (!ast->regs) { |
|---|
| 496 | | - ret = -EIO; |
|---|
| 497 | | - goto out_free; |
|---|
| 498 | | - } |
|---|
| 412 | + ast->regs = pcim_iomap(pdev, 1, 0); |
|---|
| 413 | + if (!ast->regs) |
|---|
| 414 | + return ERR_PTR(-EIO); |
|---|
| 499 | 415 | |
|---|
| 500 | 416 | /* |
|---|
| 501 | 417 | * If we don't have IO space at all, use MMIO now and |
|---|
| .. | .. |
|---|
| 503 | 419 | * and higher). |
|---|
| 504 | 420 | */ |
|---|
| 505 | 421 | if (!(pci_resource_flags(dev->pdev, 2) & IORESOURCE_IO)) { |
|---|
| 506 | | - DRM_INFO("platform has no IO space, trying MMIO\n"); |
|---|
| 422 | + drm_info(dev, "platform has no IO space, trying MMIO\n"); |
|---|
| 507 | 423 | ast->ioregs = ast->regs + AST_IO_MM_OFFSET; |
|---|
| 508 | 424 | } |
|---|
| 509 | 425 | |
|---|
| 510 | 426 | /* "map" IO regs if the above hasn't done so already */ |
|---|
| 511 | 427 | if (!ast->ioregs) { |
|---|
| 512 | | - ast->ioregs = pci_iomap(dev->pdev, 2, 0); |
|---|
| 513 | | - if (!ast->ioregs) { |
|---|
| 514 | | - ret = -EIO; |
|---|
| 515 | | - goto out_free; |
|---|
| 516 | | - } |
|---|
| 428 | + ast->ioregs = pcim_iomap(pdev, 2, 0); |
|---|
| 429 | + if (!ast->ioregs) |
|---|
| 430 | + return ERR_PTR(-EIO); |
|---|
| 517 | 431 | } |
|---|
| 518 | 432 | |
|---|
| 519 | 433 | ast_detect_chip(dev, &need_post); |
|---|
| 520 | 434 | |
|---|
| 435 | + ret = ast_get_dram_info(dev); |
|---|
| 436 | + if (ret) |
|---|
| 437 | + return ERR_PTR(ret); |
|---|
| 438 | + |
|---|
| 439 | + drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n", |
|---|
| 440 | + ast->mclk, ast->dram_type, ast->dram_bus_width); |
|---|
| 441 | + |
|---|
| 521 | 442 | if (need_post) |
|---|
| 522 | 443 | ast_post_gpu(dev); |
|---|
| 523 | 444 | |
|---|
| 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 | 445 | ret = ast_mm_init(ast); |
|---|
| 535 | 446 | if (ret) |
|---|
| 536 | | - goto out_free; |
|---|
| 447 | + return ERR_PTR(ret); |
|---|
| 537 | 448 | |
|---|
| 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; |
|---|
| 449 | + /* map reserved buffer */ |
|---|
| 450 | + ast->dp501_fw_buf = NULL; |
|---|
| 451 | + if (dev->vram_mm->vram_size < pci_resource_len(dev->pdev, 0)) { |
|---|
| 452 | + ast->dp501_fw_buf = pci_iomap_range(dev->pdev, 0, dev->vram_mm->vram_size, 0); |
|---|
| 453 | + if (!ast->dp501_fw_buf) |
|---|
| 454 | + drm_info(dev, "failed to map reserved buffer!\n"); |
|---|
| 558 | 455 | } |
|---|
| 559 | 456 | |
|---|
| 560 | | - ret = ast_mode_init(dev); |
|---|
| 457 | + ret = ast_mode_config_init(ast); |
|---|
| 561 | 458 | if (ret) |
|---|
| 562 | | - goto out_free; |
|---|
| 459 | + return ERR_PTR(ret); |
|---|
| 563 | 460 | |
|---|
| 564 | | - ret = ast_fbdev_init(dev); |
|---|
| 461 | + ret = devm_add_action_or_reset(dev->dev, ast_device_release, ast); |
|---|
| 565 | 462 | if (ret) |
|---|
| 566 | | - goto out_free; |
|---|
| 463 | + return ERR_PTR(ret); |
|---|
| 567 | 464 | |
|---|
| 568 | | - return 0; |
|---|
| 569 | | -out_free: |
|---|
| 570 | | - kfree(ast); |
|---|
| 571 | | - dev->dev_private = NULL; |
|---|
| 572 | | - return ret; |
|---|
| 465 | + return ast; |
|---|
| 573 | 466 | } |
|---|
| 574 | | - |
|---|
| 575 | | -void ast_driver_unload(struct drm_device *dev) |
|---|
| 576 | | -{ |
|---|
| 577 | | - struct ast_private *ast = dev->dev_private; |
|---|
| 578 | | - |
|---|
| 579 | | - /* enable standard VGA decode */ |
|---|
| 580 | | - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); |
|---|
| 581 | | - |
|---|
| 582 | | - ast_release_firmware(dev); |
|---|
| 583 | | - kfree(ast->dp501_fw_addr); |
|---|
| 584 | | - ast_mode_fini(dev); |
|---|
| 585 | | - ast_fbdev_fini(dev); |
|---|
| 586 | | - drm_mode_config_cleanup(dev); |
|---|
| 587 | | - |
|---|
| 588 | | - ast_mm_fini(ast); |
|---|
| 589 | | - if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET) |
|---|
| 590 | | - pci_iounmap(dev->pdev, ast->ioregs); |
|---|
| 591 | | - pci_iounmap(dev->pdev, ast->regs); |
|---|
| 592 | | - kfree(ast); |
|---|
| 593 | | -} |
|---|
| 594 | | - |
|---|
| 595 | | -int ast_gem_create(struct drm_device *dev, |
|---|
| 596 | | - u32 size, bool iskernel, |
|---|
| 597 | | - struct drm_gem_object **obj) |
|---|
| 598 | | -{ |
|---|
| 599 | | - struct ast_bo *astbo; |
|---|
| 600 | | - int ret; |
|---|
| 601 | | - |
|---|
| 602 | | - *obj = NULL; |
|---|
| 603 | | - |
|---|
| 604 | | - size = roundup(size, PAGE_SIZE); |
|---|
| 605 | | - if (size == 0) |
|---|
| 606 | | - return -EINVAL; |
|---|
| 607 | | - |
|---|
| 608 | | - ret = ast_bo_create(dev, size, 0, 0, &astbo); |
|---|
| 609 | | - if (ret) { |
|---|
| 610 | | - if (ret != -ERESTARTSYS) |
|---|
| 611 | | - DRM_ERROR("failed to allocate GEM object\n"); |
|---|
| 612 | | - return ret; |
|---|
| 613 | | - } |
|---|
| 614 | | - *obj = &astbo->gem; |
|---|
| 615 | | - return 0; |
|---|
| 616 | | -} |
|---|
| 617 | | - |
|---|
| 618 | | -int ast_dumb_create(struct drm_file *file, |
|---|
| 619 | | - struct drm_device *dev, |
|---|
| 620 | | - struct drm_mode_create_dumb *args) |
|---|
| 621 | | -{ |
|---|
| 622 | | - int ret; |
|---|
| 623 | | - struct drm_gem_object *gobj; |
|---|
| 624 | | - u32 handle; |
|---|
| 625 | | - |
|---|
| 626 | | - args->pitch = args->width * ((args->bpp + 7) / 8); |
|---|
| 627 | | - args->size = args->pitch * args->height; |
|---|
| 628 | | - |
|---|
| 629 | | - ret = ast_gem_create(dev, args->size, false, |
|---|
| 630 | | - &gobj); |
|---|
| 631 | | - if (ret) |
|---|
| 632 | | - return ret; |
|---|
| 633 | | - |
|---|
| 634 | | - ret = drm_gem_handle_create(file, gobj, &handle); |
|---|
| 635 | | - drm_gem_object_put_unlocked(gobj); |
|---|
| 636 | | - if (ret) |
|---|
| 637 | | - return ret; |
|---|
| 638 | | - |
|---|
| 639 | | - args->handle = handle; |
|---|
| 640 | | - return 0; |
|---|
| 641 | | -} |
|---|
| 642 | | - |
|---|
| 643 | | -static void ast_bo_unref(struct ast_bo **bo) |
|---|
| 644 | | -{ |
|---|
| 645 | | - struct ttm_buffer_object *tbo; |
|---|
| 646 | | - |
|---|
| 647 | | - if ((*bo) == NULL) |
|---|
| 648 | | - return; |
|---|
| 649 | | - |
|---|
| 650 | | - tbo = &((*bo)->bo); |
|---|
| 651 | | - ttm_bo_unref(&tbo); |
|---|
| 652 | | - *bo = NULL; |
|---|
| 653 | | -} |
|---|
| 654 | | - |
|---|
| 655 | | -void ast_gem_free_object(struct drm_gem_object *obj) |
|---|
| 656 | | -{ |
|---|
| 657 | | - struct ast_bo *ast_bo = gem_to_ast_bo(obj); |
|---|
| 658 | | - |
|---|
| 659 | | - ast_bo_unref(&ast_bo); |
|---|
| 660 | | -} |
|---|
| 661 | | - |
|---|
| 662 | | - |
|---|
| 663 | | -static inline u64 ast_bo_mmap_offset(struct ast_bo *bo) |
|---|
| 664 | | -{ |
|---|
| 665 | | - return drm_vma_node_offset_addr(&bo->bo.vma_node); |
|---|
| 666 | | -} |
|---|
| 667 | | -int |
|---|
| 668 | | -ast_dumb_mmap_offset(struct drm_file *file, |
|---|
| 669 | | - struct drm_device *dev, |
|---|
| 670 | | - uint32_t handle, |
|---|
| 671 | | - uint64_t *offset) |
|---|
| 672 | | -{ |
|---|
| 673 | | - struct drm_gem_object *obj; |
|---|
| 674 | | - struct ast_bo *bo; |
|---|
| 675 | | - |
|---|
| 676 | | - obj = drm_gem_object_lookup(file, handle); |
|---|
| 677 | | - if (obj == NULL) |
|---|
| 678 | | - return -ENOENT; |
|---|
| 679 | | - |
|---|
| 680 | | - bo = gem_to_ast_bo(obj); |
|---|
| 681 | | - *offset = ast_bo_mmap_offset(bo); |
|---|
| 682 | | - |
|---|
| 683 | | - drm_gem_object_put_unlocked(obj); |
|---|
| 684 | | - |
|---|
| 685 | | - return 0; |
|---|
| 686 | | - |
|---|
| 687 | | -} |
|---|
| 688 | | - |
|---|