.. | .. |
---|
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 | | - |
---|