hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2020 Intel Corporation. All rights reserved.
#include <linux/string.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
#include <uapi/sound/asound.h>
#include "sof_maxim_common.h"
 
#define MAX_98373_PIN_NAME 16
 
const struct snd_soc_dapm_route max_98373_dapm_routes[] = {
   /* speaker */
   { "Left Spk", NULL, "Left BE_OUT" },
   { "Right Spk", NULL, "Right BE_OUT" },
};
 
static struct snd_soc_codec_conf max_98373_codec_conf[] = {
   {
       .dlc = COMP_CODEC_CONF(MAX_98373_DEV0_NAME),
       .name_prefix = "Right",
   },
   {
       .dlc = COMP_CODEC_CONF(MAX_98373_DEV1_NAME),
       .name_prefix = "Left",
   },
};
 
struct snd_soc_dai_link_component max_98373_components[] = {
   {  /* For Right */
       .name = MAX_98373_DEV0_NAME,
       .dai_name = MAX_98373_CODEC_DAI,
   },
   {  /* For Left */
       .name = MAX_98373_DEV1_NAME,
       .dai_name = MAX_98373_CODEC_DAI,
   },
};
 
static int max98373_hw_params(struct snd_pcm_substream *substream,
                 struct snd_pcm_hw_params *params)
{
   struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
   struct snd_soc_dai *codec_dai;
   int j;
 
   for_each_rtd_codec_dais(rtd, j, codec_dai) {
       if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) {
           /* DEV0 tdm slot configuration */
           snd_soc_dai_set_tdm_slot(codec_dai, 0x03, 3, 8, 32);
       }
       if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) {
           /* DEV1 tdm slot configuration */
           snd_soc_dai_set_tdm_slot(codec_dai, 0x0C, 3, 8, 32);
       }
   }
   return 0;
}
 
int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
{
   struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
   struct snd_soc_dai *codec_dai;
   int j;
   int ret = 0;
 
   /* set spk pin by playback only */
   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
       return 0;
 
   for_each_rtd_codec_dais(rtd, j, codec_dai) {
       struct snd_soc_component *component = codec_dai->component;
       struct snd_soc_dapm_context *dapm =
               snd_soc_component_get_dapm(component);
       char pin_name[MAX_98373_PIN_NAME];
 
       snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk",
            codec_dai->component->name_prefix);
 
       switch (cmd) {
       case SNDRV_PCM_TRIGGER_START:
       case SNDRV_PCM_TRIGGER_RESUME:
       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
           ret = snd_soc_dapm_enable_pin(dapm, pin_name);
           if (!ret)
               snd_soc_dapm_sync(dapm);
           break;
       case SNDRV_PCM_TRIGGER_STOP:
       case SNDRV_PCM_TRIGGER_SUSPEND:
       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
           ret = snd_soc_dapm_disable_pin(dapm, pin_name);
           if (!ret)
               snd_soc_dapm_sync(dapm);
           break;
       default:
           break;
       }
   }
 
   return ret;
}
 
struct snd_soc_ops max_98373_ops = {
   .hw_params = max98373_hw_params,
   .trigger = max98373_trigger,
};
 
int max98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd)
{
   struct snd_soc_card *card = rtd->card;
   int ret;
 
   ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes,
                     ARRAY_SIZE(max_98373_dapm_routes));
   if (ret)
       dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
   return ret;
}
 
void sof_max98373_codec_conf(struct snd_soc_card *card)
{
   card->codec_conf = max_98373_codec_conf;
   card->num_configs = ARRAY_SIZE(max_98373_codec_conf);
}