1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // Analog Devices SSM2305 Amplifier Driver |
4 | // |
5 | // Copyright (C) 2018 Pengutronix, Marco Felsch <kernel@pengutronix.de> |
6 | // |
7 | |
8 | #include <linux/gpio/consumer.h> |
9 | #include <linux/module.h> |
10 | #include <sound/soc.h> |
11 | |
12 | #define DRV_NAME "ssm2305" |
13 | |
14 | struct ssm2305 { |
15 | /* shutdown gpio */ |
16 | struct gpio_desc *gpiod_shutdown; |
17 | }; |
18 | |
19 | static int ssm2305_power_event(struct snd_soc_dapm_widget *w, |
20 | struct snd_kcontrol *kctrl, int event) |
21 | { |
22 | struct snd_soc_component *c = snd_soc_dapm_to_component(dapm: w->dapm); |
23 | struct ssm2305 *data = snd_soc_component_get_drvdata(c); |
24 | |
25 | gpiod_set_value_cansleep(desc: data->gpiod_shutdown, |
26 | SND_SOC_DAPM_EVENT_ON(event)); |
27 | |
28 | return 0; |
29 | } |
30 | |
31 | static const struct snd_soc_dapm_widget ssm2305_dapm_widgets[] = { |
32 | /* Stereo input/output */ |
33 | SND_SOC_DAPM_INPUT("L_IN" ), |
34 | SND_SOC_DAPM_INPUT("R_IN" ), |
35 | SND_SOC_DAPM_OUTPUT("L_OUT" ), |
36 | SND_SOC_DAPM_OUTPUT("R_OUT" ), |
37 | |
38 | SND_SOC_DAPM_SUPPLY("Power" , SND_SOC_NOPM, 0, 0, ssm2305_power_event, |
39 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
40 | }; |
41 | |
42 | static const struct snd_soc_dapm_route ssm2305_dapm_routes[] = { |
43 | { "L_OUT" , NULL, "L_IN" }, |
44 | { "R_OUT" , NULL, "R_IN" }, |
45 | { "L_IN" , NULL, "Power" }, |
46 | { "R_IN" , NULL, "Power" }, |
47 | }; |
48 | |
49 | static const struct snd_soc_component_driver ssm2305_component_driver = { |
50 | .dapm_widgets = ssm2305_dapm_widgets, |
51 | .num_dapm_widgets = ARRAY_SIZE(ssm2305_dapm_widgets), |
52 | .dapm_routes = ssm2305_dapm_routes, |
53 | .num_dapm_routes = ARRAY_SIZE(ssm2305_dapm_routes), |
54 | }; |
55 | |
56 | static int ssm2305_probe(struct platform_device *pdev) |
57 | { |
58 | struct device *dev = &pdev->dev; |
59 | struct ssm2305 *priv; |
60 | |
61 | /* Allocate the private data */ |
62 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
63 | if (!priv) |
64 | return -ENOMEM; |
65 | |
66 | platform_set_drvdata(pdev, data: priv); |
67 | |
68 | /* Get shutdown gpio */ |
69 | priv->gpiod_shutdown = devm_gpiod_get(dev, con_id: "shutdown" , |
70 | flags: GPIOD_OUT_LOW); |
71 | if (IS_ERR(ptr: priv->gpiod_shutdown)) |
72 | return dev_err_probe(dev, err: PTR_ERR(ptr: priv->gpiod_shutdown), |
73 | fmt: "Failed to get 'shutdown' gpio\n" ); |
74 | |
75 | return devm_snd_soc_register_component(dev, component_driver: &ssm2305_component_driver, |
76 | NULL, num_dai: 0); |
77 | } |
78 | |
79 | #ifdef CONFIG_OF |
80 | static const struct of_device_id ssm2305_of_match[] = { |
81 | { .compatible = "adi,ssm2305" , }, |
82 | { } |
83 | }; |
84 | MODULE_DEVICE_TABLE(of, ssm2305_of_match); |
85 | #endif |
86 | |
87 | static struct platform_driver ssm2305_driver = { |
88 | .driver = { |
89 | .name = DRV_NAME, |
90 | .of_match_table = of_match_ptr(ssm2305_of_match), |
91 | }, |
92 | .probe = ssm2305_probe, |
93 | }; |
94 | |
95 | module_platform_driver(ssm2305_driver); |
96 | |
97 | MODULE_DESCRIPTION("ASoC SSM2305 amplifier driver" ); |
98 | MODULE_AUTHOR("Marco Felsch <m.felsch@pengutronix.de>" ); |
99 | MODULE_LICENSE("GPL v2" ); |
100 | |