linux/sound/soc/fsl/pcm030-audio-fabric.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Phytec pcm030 driver for the PSC of the Freescale MPC52xx
   4// configured as AC97 interface
   5//
   6// Copyright 2008 Jon Smirl, Digispeaker
   7// Author: Jon Smirl <jonsmirl@gmail.com>
   8
   9#include <linux/init.h>
  10#include <linux/module.h>
  11#include <linux/device.h>
  12#include <linux/of_device.h>
  13#include <linux/of_platform.h>
  14
  15#include <sound/soc.h>
  16
  17#include "mpc5200_dma.h"
  18
  19#define DRV_NAME "pcm030-audio-fabric"
  20
  21struct pcm030_audio_data {
  22        struct snd_soc_card *card;
  23        struct platform_device *codec_device;
  24};
  25
  26SND_SOC_DAILINK_DEFS(analog,
  27        DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")),
  28        DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")),
  29        DAILINK_COMP_ARRAY(COMP_EMPTY()));
  30
  31SND_SOC_DAILINK_DEFS(iec958,
  32        DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")),
  33        DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")),
  34        DAILINK_COMP_ARRAY(COMP_EMPTY()));
  35
  36static struct snd_soc_dai_link pcm030_fabric_dai[] = {
  37{
  38        .name = "AC97.0",
  39        .stream_name = "AC97 Analog",
  40        SND_SOC_DAILINK_REG(analog),
  41},
  42{
  43        .name = "AC97.1",
  44        .stream_name = "AC97 IEC958",
  45        SND_SOC_DAILINK_REG(iec958),
  46},
  47};
  48
  49static struct snd_soc_card pcm030_card = {
  50        .name = "pcm030",
  51        .owner = THIS_MODULE,
  52        .dai_link = pcm030_fabric_dai,
  53        .num_links = ARRAY_SIZE(pcm030_fabric_dai),
  54};
  55
  56static int pcm030_fabric_probe(struct platform_device *op)
  57{
  58        struct device_node *np = op->dev.of_node;
  59        struct device_node *platform_np;
  60        struct snd_soc_card *card = &pcm030_card;
  61        struct pcm030_audio_data *pdata;
  62        struct snd_soc_dai_link *dai_link;
  63        int ret;
  64        int i;
  65
  66        if (!of_machine_is_compatible("phytec,pcm030"))
  67                return -ENODEV;
  68
  69        pdata = devm_kzalloc(&op->dev, sizeof(struct pcm030_audio_data),
  70                             GFP_KERNEL);
  71        if (!pdata)
  72                return -ENOMEM;
  73
  74        card->dev = &op->dev;
  75
  76        pdata->card = card;
  77
  78        platform_np = of_parse_phandle(np, "asoc-platform", 0);
  79        if (!platform_np) {
  80                dev_err(&op->dev, "ac97 not registered\n");
  81                return -ENODEV;
  82        }
  83
  84        for_each_card_prelinks(card, i, dai_link)
  85                dai_link->platforms->of_node = platform_np;
  86
  87        ret = request_module("snd-soc-wm9712");
  88        if (ret)
  89                dev_err(&op->dev, "request_module returned: %d\n", ret);
  90
  91        pdata->codec_device = platform_device_alloc("wm9712-codec", -1);
  92        if (!pdata->codec_device)
  93                dev_err(&op->dev, "platform_device_alloc() failed\n");
  94
  95        ret = platform_device_add(pdata->codec_device);
  96        if (ret)
  97                dev_err(&op->dev, "platform_device_add() failed: %d\n", ret);
  98
  99        ret = snd_soc_register_card(card);
 100        if (ret)
 101                dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
 102
 103        platform_set_drvdata(op, pdata);
 104
 105        return ret;
 106}
 107
 108static int pcm030_fabric_remove(struct platform_device *op)
 109{
 110        struct pcm030_audio_data *pdata = platform_get_drvdata(op);
 111        int ret;
 112
 113        ret = snd_soc_unregister_card(pdata->card);
 114        platform_device_unregister(pdata->codec_device);
 115
 116        return ret;
 117}
 118
 119static const struct of_device_id pcm030_audio_match[] = {
 120        { .compatible = "phytec,pcm030-audio-fabric", },
 121        {}
 122};
 123MODULE_DEVICE_TABLE(of, pcm030_audio_match);
 124
 125static struct platform_driver pcm030_fabric_driver = {
 126        .probe          = pcm030_fabric_probe,
 127        .remove         = pcm030_fabric_remove,
 128        .driver         = {
 129                .name   = DRV_NAME,
 130                .of_match_table    = pcm030_audio_match,
 131        },
 132};
 133
 134module_platform_driver(pcm030_fabric_driver);
 135
 136
 137MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
 138MODULE_DESCRIPTION(DRV_NAME ": mpc5200 pcm030 fabric driver");
 139MODULE_LICENSE("GPL");
 140
 141