linux/sound/soc/intel/boards/sof_sdw_rt1316.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2// Copyright (c) 2020 Intel Corporation
   3
   4/*
   5 *  sof_sdw_rt1316 - Helpers to handle RT1316 from generic machine driver
   6 */
   7
   8#include <linux/device.h>
   9#include <linux/errno.h>
  10#include <sound/control.h>
  11#include <sound/soc.h>
  12#include <sound/soc-acpi.h>
  13#include <sound/soc-dapm.h>
  14#include "sof_sdw_common.h"
  15
  16static const struct snd_soc_dapm_widget rt1316_widgets[] = {
  17        SND_SOC_DAPM_SPK("Speaker", NULL),
  18};
  19
  20/*
  21 * dapm routes for rt1316 will be registered dynamically according
  22 * to the number of rt1316 used. The first two entries will be registered
  23 * for one codec case, and the last two entries are also registered
  24 * if two 1316s are used.
  25 */
  26static const struct snd_soc_dapm_route rt1316_map[] = {
  27        { "Speaker", NULL, "rt1316-1 SPOL" },
  28        { "Speaker", NULL, "rt1316-1 SPOR" },
  29        { "Speaker", NULL, "rt1316-2 SPOL" },
  30        { "Speaker", NULL, "rt1316-2 SPOR" },
  31};
  32
  33static const struct snd_kcontrol_new rt1316_controls[] = {
  34        SOC_DAPM_PIN_SWITCH("Speaker"),
  35};
  36
  37static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
  38{
  39        struct snd_soc_card *card = rtd->card;
  40        int ret;
  41
  42        card->components = devm_kasprintf(card->dev, GFP_KERNEL,
  43                                          "%s spk:rt1316",
  44                                          card->components);
  45        if (!card->components)
  46                return -ENOMEM;
  47
  48        ret = snd_soc_add_card_controls(card, rt1316_controls,
  49                                        ARRAY_SIZE(rt1316_controls));
  50        if (ret) {
  51                dev_err(card->dev, "rt1316 controls addition failed: %d\n", ret);
  52                return ret;
  53        }
  54
  55        ret = snd_soc_dapm_new_controls(&card->dapm, rt1316_widgets,
  56                                        ARRAY_SIZE(rt1316_widgets));
  57        if (ret) {
  58                dev_err(card->dev, "rt1316 widgets addition failed: %d\n", ret);
  59                return ret;
  60        }
  61
  62        ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map, 2);
  63        if (ret)
  64                dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret);
  65
  66        return ret;
  67}
  68
  69static int second_spk_init(struct snd_soc_pcm_runtime *rtd)
  70{
  71        struct snd_soc_card *card = rtd->card;
  72        int ret;
  73
  74        ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map + 2, 2);
  75        if (ret)
  76                dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret);
  77
  78        return ret;
  79}
  80
  81static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
  82{
  83        int ret;
  84
  85        ret = first_spk_init(rtd);
  86        if (ret)
  87                return ret;
  88
  89        return second_spk_init(rtd);
  90}
  91
  92int sof_sdw_rt1316_init(struct snd_soc_card *card,
  93                        const struct snd_soc_acpi_link_adr *link,
  94                        struct snd_soc_dai_link *dai_links,
  95                        struct sof_sdw_codec_info *info,
  96                        bool playback)
  97{
  98        /* Count amp number and do init on playback link only. */
  99        if (!playback)
 100                return 0;
 101
 102        info->amp_num++;
 103        if (info->amp_num == 1)
 104                dai_links->init = first_spk_init;
 105
 106        if (info->amp_num == 2) {
 107                /*
 108                 * if two 1316s are in one dai link, the init function
 109                 * in this dai link will be first set for the first speaker,
 110                 * and it should be reset to initialize all speakers when
 111                 * the second speaker is found.
 112                 */
 113                if (dai_links->init)
 114                        dai_links->init = all_spk_init;
 115                else
 116                        dai_links->init = second_spk_init;
 117        }
 118
 119        return 0;
 120}
 121