Merge tag 'v5.9-rc4' into drm-next
[linux-2.6-microblaze.git] / drivers / gpu / drm / ast / ast_main.c
index 6a9fba0..77066bc 100644 (file)
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_managed.h>
 
 #include "ast_drv.h"
 
@@ -230,11 +232,11 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
                        ast->tx_chip_type = AST_TX_SIL164;
                        break;
                case 0x08:
-                       ast->dp501_fw_addr = kzalloc(32*1024, GFP_KERNEL);
+                       ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL);
                        if (ast->dp501_fw_addr) {
                                /* backup firmware */
                                if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) {
-                                       kfree(ast->dp501_fw_addr);
+                                       drmm_kfree(dev, ast->dp501_fw_addr);
                                        ast->dp501_fw_addr = NULL;
                                }
                        }
@@ -378,24 +380,38 @@ static int ast_get_dram_info(struct drm_device *dev)
        return 0;
 }
 
-int ast_driver_load(struct drm_device *dev, unsigned long flags)
+/*
+ * Run this function as part of the HW device cleanup; not
+ * when the DRM device gets released.
+ */
+static void ast_device_release(void *data)
 {
+       struct ast_private *ast = data;
+
+       /* enable standard VGA decode */
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);
+}
+
+struct ast_private *ast_device_create(struct drm_driver *drv,
+                                     struct pci_dev *pdev,
+                                     unsigned long flags)
+{
+       struct drm_device *dev;
        struct ast_private *ast;
        bool need_post;
        int ret = 0;
 
-       ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL);
-       if (!ast)
-               return -ENOMEM;
+       ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_private, base);
+       if (IS_ERR(ast))
+               return ast;
+       dev = &ast->base;
 
-       dev->dev_private = ast;
-       ast->dev = dev;
+       dev->pdev = pdev;
+       pci_set_drvdata(pdev, dev);
 
        ast->regs = pci_iomap(dev->pdev, 1, 0);
-       if (!ast->regs) {
-               ret = -EIO;
-               goto out_free;
-       }
+       if (!ast->regs)
+               return ERR_PTR(-EIO);
 
        /*
         * If we don't have IO space at all, use MMIO now and
@@ -410,17 +426,16 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
        /* "map" IO regs if the above hasn't done so already */
        if (!ast->ioregs) {
                ast->ioregs = pci_iomap(dev->pdev, 2, 0);
-               if (!ast->ioregs) {
-                       ret = -EIO;
-                       goto out_free;
-               }
+               if (!ast->ioregs)
+                       return ERR_PTR(-EIO);
        }
 
        ast_detect_chip(dev, &need_post);
 
        ret = ast_get_dram_info(dev);
        if (ret)
-               goto out_free;
+               return ERR_PTR(ret);
+
        drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n",
                 ast->mclk, ast->dram_type, ast->dram_bus_width);
 
@@ -429,28 +444,15 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
 
        ret = ast_mm_init(ast);
        if (ret)
-               goto out_free;
+               return ERR_PTR(ret);
 
        ret = ast_mode_config_init(ast);
        if (ret)
-               goto out_free;
+               return ERR_PTR(ret);
 
-       return 0;
-out_free:
-       kfree(ast);
-       dev->dev_private = NULL;
-       return ret;
-}
-
-void ast_driver_unload(struct drm_device *dev)
-{
-       struct ast_private *ast = to_ast_private(dev);
-
-       /* enable standard VGA decode */
-       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);
-
-       ast_release_firmware(dev);
-       kfree(ast->dp501_fw_addr);
+       ret = devm_add_action_or_reset(dev->dev, ast_device_release, ast);
+       if (ret)
+               return ERR_PTR(ret);
 
-       kfree(ast);
+       return ast;
 }