root/sound/soc/amd/raven/pci-acp3x.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_acp3x_probe
  2. snd_acp3x_remove

   1 // SPDX-License-Identifier: GPL-2.0+
   2 //
   3 // AMD ACP PCI Driver
   4 //
   5 //Copyright 2016 Advanced Micro Devices, Inc.
   6 
   7 #include <linux/pci.h>
   8 #include <linux/module.h>
   9 #include <linux/io.h>
  10 #include <linux/platform_device.h>
  11 #include <linux/interrupt.h>
  12 
  13 #include "acp3x.h"
  14 
  15 struct acp3x_dev_data {
  16         void __iomem *acp3x_base;
  17         bool acp3x_audio_mode;
  18         struct resource *res;
  19         struct platform_device *pdev;
  20 };
  21 
  22 static int snd_acp3x_probe(struct pci_dev *pci,
  23                            const struct pci_device_id *pci_id)
  24 {
  25         int ret;
  26         u32 addr, val;
  27         struct acp3x_dev_data *adata;
  28         struct platform_device_info pdevinfo;
  29         unsigned int irqflags;
  30 
  31         if (pci_enable_device(pci)) {
  32                 dev_err(&pci->dev, "pci_enable_device failed\n");
  33                 return -ENODEV;
  34         }
  35 
  36         ret = pci_request_regions(pci, "AMD ACP3x audio");
  37         if (ret < 0) {
  38                 dev_err(&pci->dev, "pci_request_regions failed\n");
  39                 goto disable_pci;
  40         }
  41 
  42         adata = devm_kzalloc(&pci->dev, sizeof(struct acp3x_dev_data),
  43                              GFP_KERNEL);
  44         if (!adata) {
  45                 ret = -ENOMEM;
  46                 goto release_regions;
  47         }
  48 
  49         /* check for msi interrupt support */
  50         ret = pci_enable_msi(pci);
  51         if (ret)
  52                 /* msi is not enabled */
  53                 irqflags = IRQF_SHARED;
  54         else
  55                 /* msi is enabled */
  56                 irqflags = 0;
  57 
  58         addr = pci_resource_start(pci, 0);
  59         adata->acp3x_base = ioremap(addr, pci_resource_len(pci, 0));
  60         if (!adata->acp3x_base) {
  61                 ret = -ENOMEM;
  62                 goto release_regions;
  63         }
  64         pci_set_master(pci);
  65         pci_set_drvdata(pci, adata);
  66 
  67         val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
  68         switch (val) {
  69         case I2S_MODE:
  70                 adata->res = devm_kzalloc(&pci->dev,
  71                                           sizeof(struct resource) * 2,
  72                                           GFP_KERNEL);
  73                 if (!adata->res) {
  74                         ret = -ENOMEM;
  75                         goto unmap_mmio;
  76                 }
  77 
  78                 adata->res[0].name = "acp3x_i2s_iomem";
  79                 adata->res[0].flags = IORESOURCE_MEM;
  80                 adata->res[0].start = addr;
  81                 adata->res[0].end = addr + (ACP3x_REG_END - ACP3x_REG_START);
  82 
  83                 adata->res[1].name = "acp3x_i2s_irq";
  84                 adata->res[1].flags = IORESOURCE_IRQ;
  85                 adata->res[1].start = pci->irq;
  86                 adata->res[1].end = pci->irq;
  87 
  88                 adata->acp3x_audio_mode = ACP3x_I2S_MODE;
  89 
  90                 memset(&pdevinfo, 0, sizeof(pdevinfo));
  91                 pdevinfo.name = "acp3x_rv_i2s";
  92                 pdevinfo.id = 0;
  93                 pdevinfo.parent = &pci->dev;
  94                 pdevinfo.num_res = 2;
  95                 pdevinfo.res = adata->res;
  96                 pdevinfo.data = &irqflags;
  97                 pdevinfo.size_data = sizeof(irqflags);
  98 
  99                 adata->pdev = platform_device_register_full(&pdevinfo);
 100                 if (IS_ERR(adata->pdev)) {
 101                         dev_err(&pci->dev, "cannot register %s device\n",
 102                                 pdevinfo.name);
 103                         ret = PTR_ERR(adata->pdev);
 104                         goto unmap_mmio;
 105                 }
 106                 break;
 107         default:
 108                 dev_err(&pci->dev, "Invalid ACP audio mode : %d\n", val);
 109                 ret = -ENODEV;
 110                 goto unmap_mmio;
 111         }
 112         return 0;
 113 
 114 unmap_mmio:
 115         pci_disable_msi(pci);
 116         iounmap(adata->acp3x_base);
 117 release_regions:
 118         pci_release_regions(pci);
 119 disable_pci:
 120         pci_disable_device(pci);
 121 
 122         return ret;
 123 }
 124 
 125 static void snd_acp3x_remove(struct pci_dev *pci)
 126 {
 127         struct acp3x_dev_data *adata = pci_get_drvdata(pci);
 128 
 129         platform_device_unregister(adata->pdev);
 130         iounmap(adata->acp3x_base);
 131 
 132         pci_disable_msi(pci);
 133         pci_release_regions(pci);
 134         pci_disable_device(pci);
 135 }
 136 
 137 static const struct pci_device_id snd_acp3x_ids[] = {
 138         { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2),
 139         .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
 140         .class_mask = 0xffffff },
 141         { 0, },
 142 };
 143 MODULE_DEVICE_TABLE(pci, snd_acp3x_ids);
 144 
 145 static struct pci_driver acp3x_driver  = {
 146         .name = KBUILD_MODNAME,
 147         .id_table = snd_acp3x_ids,
 148         .probe = snd_acp3x_probe,
 149         .remove = snd_acp3x_remove,
 150 };
 151 
 152 module_pci_driver(acp3x_driver);
 153 
 154 MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
 155 MODULE_DESCRIPTION("AMD ACP3x PCI driver");
 156 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */