Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Machine driver for AMD Yellow Carp platform using DMIC
0004  *
0005  * Copyright 2021 Advanced Micro Devices, Inc.
0006  */
0007 
0008 #include <sound/soc.h>
0009 #include <sound/soc-dapm.h>
0010 #include <linux/module.h>
0011 #include <sound/pcm.h>
0012 #include <sound/pcm_params.h>
0013 #include <linux/io.h>
0014 #include <linux/dmi.h>
0015 #include <linux/acpi.h>
0016 
0017 #include "acp6x.h"
0018 
0019 #define DRV_NAME "acp_yc_mach"
0020 
0021 SND_SOC_DAILINK_DEF(acp6x_pdm,
0022             DAILINK_COMP_ARRAY(COMP_CPU("acp_yc_pdm_dma.0")));
0023 
0024 SND_SOC_DAILINK_DEF(dmic_codec,
0025             DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0",
0026                           "dmic-hifi")));
0027 
0028 SND_SOC_DAILINK_DEF(pdm_platform,
0029             DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_yc_pdm_dma.0")));
0030 
0031 static struct snd_soc_dai_link acp6x_dai_pdm[] = {
0032     {
0033         .name = "acp6x-dmic-capture",
0034         .stream_name = "DMIC capture",
0035         .capture_only = 1,
0036         SND_SOC_DAILINK_REG(acp6x_pdm, dmic_codec, pdm_platform),
0037     },
0038 };
0039 
0040 static struct snd_soc_card acp6x_card = {
0041     .name = "acp6x",
0042     .owner = THIS_MODULE,
0043     .dai_link = acp6x_dai_pdm,
0044     .num_links = 1,
0045 };
0046 
0047 static const struct dmi_system_id yc_acp_quirk_table[] = {
0048     {
0049         .driver_data = &acp6x_card,
0050         .matches = {
0051             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0052             DMI_MATCH(DMI_PRODUCT_NAME, "21D2"),
0053         }
0054     },
0055     {
0056         .driver_data = &acp6x_card,
0057         .matches = {
0058             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0059             DMI_MATCH(DMI_PRODUCT_NAME, "21D3"),
0060         }
0061     },
0062     {
0063         .driver_data = &acp6x_card,
0064         .matches = {
0065             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0066             DMI_MATCH(DMI_PRODUCT_NAME, "21D4"),
0067         }
0068     },
0069     {
0070         .driver_data = &acp6x_card,
0071         .matches = {
0072             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0073             DMI_MATCH(DMI_PRODUCT_NAME, "21D5"),
0074         }
0075     },
0076     {
0077         .driver_data = &acp6x_card,
0078         .matches = {
0079             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0080             DMI_MATCH(DMI_PRODUCT_NAME, "21CF"),
0081         }
0082     },
0083     {
0084         .driver_data = &acp6x_card,
0085         .matches = {
0086             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0087             DMI_MATCH(DMI_PRODUCT_NAME, "21CG"),
0088         }
0089     },
0090     {
0091         .driver_data = &acp6x_card,
0092         .matches = {
0093             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0094             DMI_MATCH(DMI_PRODUCT_NAME, "21CQ"),
0095         }
0096     },
0097     {
0098         .driver_data = &acp6x_card,
0099         .matches = {
0100             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0101             DMI_MATCH(DMI_PRODUCT_NAME, "21CR"),
0102         }
0103     },
0104     {
0105         .driver_data = &acp6x_card,
0106         .matches = {
0107             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0108             DMI_MATCH(DMI_PRODUCT_NAME, "21CM"),
0109         }
0110     },
0111     {
0112         .driver_data = &acp6x_card,
0113         .matches = {
0114             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0115             DMI_MATCH(DMI_PRODUCT_NAME, "21CN"),
0116         }
0117     },
0118     {
0119         .driver_data = &acp6x_card,
0120         .matches = {
0121             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0122             DMI_MATCH(DMI_PRODUCT_NAME, "21CH"),
0123         }
0124     },
0125     {
0126         .driver_data = &acp6x_card,
0127         .matches = {
0128             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0129             DMI_MATCH(DMI_PRODUCT_NAME, "21CJ"),
0130         }
0131     },
0132     {
0133         .driver_data = &acp6x_card,
0134         .matches = {
0135             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0136             DMI_MATCH(DMI_PRODUCT_NAME, "21CK"),
0137         }
0138     },
0139     {
0140         .driver_data = &acp6x_card,
0141         .matches = {
0142             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0143             DMI_MATCH(DMI_PRODUCT_NAME, "21CL"),
0144         }
0145     },
0146     {
0147         .driver_data = &acp6x_card,
0148         .matches = {
0149             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0150             DMI_MATCH(DMI_PRODUCT_NAME, "21EM"),
0151         }
0152     },
0153     {
0154         .driver_data = &acp6x_card,
0155         .matches = {
0156             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0157             DMI_MATCH(DMI_PRODUCT_NAME, "21EN"),
0158         }
0159     },
0160     {
0161         .driver_data = &acp6x_card,
0162         .matches = {
0163             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0164             DMI_MATCH(DMI_PRODUCT_NAME, "21J5"),
0165         }
0166     },
0167     {
0168         .driver_data = &acp6x_card,
0169         .matches = {
0170             DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
0171             DMI_MATCH(DMI_PRODUCT_NAME, "21J6"),
0172         }
0173     },
0174     {}
0175 };
0176 
0177 static int acp6x_probe(struct platform_device *pdev)
0178 {
0179     const struct dmi_system_id *dmi_id;
0180     struct acp6x_pdm *machine = NULL;
0181     struct snd_soc_card *card;
0182     struct acpi_device *adev;
0183     int ret;
0184 
0185     /* check the parent device's firmware node has _DSD or not */
0186     adev = ACPI_COMPANION(pdev->dev.parent);
0187     if (adev) {
0188         const union acpi_object *obj;
0189 
0190         if (!acpi_dev_get_property(adev, "AcpDmicConnected", ACPI_TYPE_INTEGER, &obj) &&
0191             obj->integer.value == 1)
0192             platform_set_drvdata(pdev, &acp6x_card);
0193     }
0194 
0195     /* check for any DMI overrides */
0196     dmi_id = dmi_first_match(yc_acp_quirk_table);
0197     if (dmi_id)
0198         platform_set_drvdata(pdev, dmi_id->driver_data);
0199 
0200     card = platform_get_drvdata(pdev);
0201     if (!card)
0202         return -ENODEV;
0203     dev_info(&pdev->dev, "Enabling ACP DMIC support via %s", dmi_id ? "DMI" : "ACPI");
0204     acp6x_card.dev = &pdev->dev;
0205 
0206     snd_soc_card_set_drvdata(card, machine);
0207     ret = devm_snd_soc_register_card(&pdev->dev, card);
0208     if (ret) {
0209         return dev_err_probe(&pdev->dev, ret,
0210                 "snd_soc_register_card(%s) failed\n",
0211                 card->name);
0212     }
0213     return 0;
0214 }
0215 
0216 static struct platform_driver acp6x_mach_driver = {
0217     .driver = {
0218         .name = "acp_yc_mach",
0219         .pm = &snd_soc_pm_ops,
0220     },
0221     .probe = acp6x_probe,
0222 };
0223 
0224 module_platform_driver(acp6x_mach_driver);
0225 
0226 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
0227 MODULE_LICENSE("GPL v2");
0228 MODULE_ALIAS("platform:" DRV_NAME);