aw8738.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/gpio/consumer.h>
  3. #include <linux/module.h>
  4. #include <linux/regulator/consumer.h>
  5. #include <sound/soc.h>
  6. struct aw8738_priv {
  7. struct gpio_desc *gpiod_mode;
  8. unsigned int mode;
  9. };
  10. static int aw8738_drv_event(struct snd_soc_dapm_widget *w,
  11. struct snd_kcontrol *kcontrol, int event)
  12. {
  13. struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
  14. struct aw8738_priv *aw = snd_soc_component_get_drvdata(c);
  15. int i;
  16. switch (event) {
  17. case SND_SOC_DAPM_POST_PMU:
  18. for (i = 0; i < aw->mode; i++) {
  19. gpiod_set_value_cansleep(aw->gpiod_mode, 0);
  20. udelay(2);
  21. gpiod_set_value_cansleep(aw->gpiod_mode, 1);
  22. udelay(2);
  23. }
  24. msleep(40);
  25. break;
  26. case SND_SOC_DAPM_PRE_PMD:
  27. gpiod_set_value_cansleep(aw->gpiod_mode, 0);
  28. usleep_range(1000, 2000);
  29. break;
  30. default:
  31. WARN(1, "Unexpected event");
  32. return -EINVAL;
  33. }
  34. return 0;
  35. }
  36. static const struct snd_soc_dapm_widget aw8738_dapm_widgets[] = {
  37. SND_SOC_DAPM_INPUT("IN"),
  38. SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, aw8738_drv_event,
  39. SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  40. SND_SOC_DAPM_OUTPUT("OUT"),
  41. };
  42. static const struct snd_soc_dapm_route aw8738_dapm_routes[] = {
  43. { "DRV", NULL, "IN" },
  44. { "OUT", NULL, "DRV" },
  45. };
  46. static const struct snd_soc_component_driver aw8738_component_driver = {
  47. .dapm_widgets = aw8738_dapm_widgets,
  48. .num_dapm_widgets = ARRAY_SIZE(aw8738_dapm_widgets),
  49. .dapm_routes = aw8738_dapm_routes,
  50. .num_dapm_routes = ARRAY_SIZE(aw8738_dapm_routes),
  51. };
  52. static int aw8738_probe(struct platform_device *pdev)
  53. {
  54. struct device *dev = &pdev->dev;
  55. struct aw8738_priv *aw;
  56. int ret;
  57. aw = devm_kzalloc(dev, sizeof(*aw), GFP_KERNEL);
  58. if (!aw)
  59. return -ENOMEM;
  60. platform_set_drvdata(pdev, aw);
  61. aw->gpiod_mode = devm_gpiod_get(dev, "mode", GPIOD_OUT_LOW);
  62. if (IS_ERR(aw->gpiod_mode))
  63. return dev_err_probe(dev, PTR_ERR(aw->gpiod_mode),
  64. "Failed to get 'mode' gpio");
  65. ret = device_property_read_u32(dev, "awinic,mode", &aw->mode);
  66. if (ret)
  67. return -EINVAL;
  68. return devm_snd_soc_register_component(&pdev->dev,
  69. &aw8738_component_driver,
  70. NULL, 0);
  71. }
  72. #ifdef CONFIG_OF
  73. static const struct of_device_id aw8738_of_match[] = {
  74. { .compatible = "awinic,aw8738" },
  75. { }
  76. };
  77. MODULE_DEVICE_TABLE(of, aw8738_of_match);
  78. #endif
  79. static struct platform_driver aw8738_driver = {
  80. .probe = aw8738_probe,
  81. .driver = {
  82. .name = "aw8738",
  83. .of_match_table = of_match_ptr(aw8738_of_match),
  84. },
  85. };
  86. module_platform_driver(aw8738_driver);
  87. MODULE_DESCRIPTION("Awinic AW8738 Amplifier Driver");
  88. MODULE_LICENSE("GPL v2");