27588ed066c9d6efefeb3503d9a9941d00bfa73f
[linux] / sound / soc / amd / raven / pci-acp3x.c
1 /*
2  * AMD ALSA SoC PCM Driver
3  *
4  * Copyright 2016 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  */
15
16 #include <linux/pci.h>
17 #include <linux/module.h>
18 #include <linux/io.h>
19
20 #include "acp3x.h"
21
22 struct acp3x_dev_data {
23         void __iomem *acp3x_base;
24 };
25
26 static int snd_acp3x_probe(struct pci_dev *pci,
27                            const struct pci_device_id *pci_id)
28 {
29         int ret;
30         u32 addr;
31         struct acp3x_dev_data *adata;
32
33         if (pci_enable_device(pci)) {
34                 dev_err(&pci->dev, "pci_enable_device failed\n");
35                 return -ENODEV;
36         }
37
38         ret = pci_request_regions(pci, "AMD ACP3x audio");
39         if (ret < 0) {
40                 dev_err(&pci->dev, "pci_request_regions failed\n");
41                 goto disable_pci;
42         }
43
44         adata = devm_kzalloc(&pci->dev, sizeof(struct acp3x_dev_data),
45                              GFP_KERNEL);
46         if (!adata) {
47                 ret = -ENOMEM;
48                 goto release_regions;
49         }
50
51         addr = pci_resource_start(pci, 0);
52         adata->acp3x_base = ioremap(addr, pci_resource_len(pci, 0));
53         if (!adata->acp3x_base) {
54                 ret = -ENOMEM;
55                 goto release_regions;
56         }
57         pci_set_master(pci);
58         pci_set_drvdata(pci, adata);
59         return 0;
60
61 release_regions:
62         pci_release_regions(pci);
63 disable_pci:
64         pci_disable_device(pci);
65
66         return ret;
67 }
68
69 static void snd_acp3x_remove(struct pci_dev *pci)
70 {
71         struct acp3x_dev_data *adata = pci_get_drvdata(pci);
72
73         iounmap(adata->acp3x_base);
74         pci_release_regions(pci);
75         pci_disable_device(pci);
76 }
77
78 static const struct pci_device_id snd_acp3x_ids[] = {
79         { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2),
80         .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
81         .class_mask = 0xffffff },
82         { 0, },
83 };
84 MODULE_DEVICE_TABLE(pci, snd_acp3x_ids);
85
86 static struct pci_driver acp3x_driver  = {
87         .name = KBUILD_MODNAME,
88         .id_table = snd_acp3x_ids,
89         .probe = snd_acp3x_probe,
90         .remove = snd_acp3x_remove,
91 };
92
93 module_pci_driver(acp3x_driver);
94
95 MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
96 MODULE_DESCRIPTION("AMD ACP3x PCI driver");
97 MODULE_LICENSE("GPL v2");