snd_ac97_compat.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2016 Robert Jarzmik <[email protected]>
  4. */
  5. #include <linux/list.h>
  6. #include <linux/slab.h>
  7. #include <sound/ac97/codec.h>
  8. #include <sound/ac97/compat.h>
  9. #include <sound/ac97/controller.h>
  10. #include <sound/soc.h>
  11. #include "ac97_core.h"
  12. static void compat_ac97_release(struct device *dev)
  13. {
  14. kfree(to_ac97_t(dev));
  15. }
  16. static void compat_ac97_reset(struct snd_ac97 *ac97)
  17. {
  18. struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  19. struct ac97_controller *actrl = adev->ac97_ctrl;
  20. if (actrl->ops->reset)
  21. actrl->ops->reset(actrl);
  22. }
  23. static void compat_ac97_warm_reset(struct snd_ac97 *ac97)
  24. {
  25. struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  26. struct ac97_controller *actrl = adev->ac97_ctrl;
  27. if (actrl->ops->warm_reset)
  28. actrl->ops->warm_reset(actrl);
  29. }
  30. static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
  31. unsigned short val)
  32. {
  33. struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  34. struct ac97_controller *actrl = adev->ac97_ctrl;
  35. actrl->ops->write(actrl, ac97->num, reg, val);
  36. }
  37. static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
  38. unsigned short reg)
  39. {
  40. struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  41. struct ac97_controller *actrl = adev->ac97_ctrl;
  42. return actrl->ops->read(actrl, ac97->num, reg);
  43. }
  44. static const struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
  45. .reset = compat_ac97_reset,
  46. .warm_reset = compat_ac97_warm_reset,
  47. .write = compat_ac97_write,
  48. .read = compat_ac97_read,
  49. };
  50. static struct snd_ac97_bus compat_soc_ac97_bus = {
  51. .ops = &compat_snd_ac97_bus_ops,
  52. };
  53. struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev)
  54. {
  55. struct snd_ac97 *ac97;
  56. int ret;
  57. ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
  58. if (ac97 == NULL)
  59. return ERR_PTR(-ENOMEM);
  60. ac97->private_data = adev;
  61. ac97->bus = &compat_soc_ac97_bus;
  62. ac97->dev.parent = &adev->dev;
  63. ac97->dev.release = compat_ac97_release;
  64. dev_set_name(&ac97->dev, "%s-compat", dev_name(&adev->dev));
  65. ret = device_register(&ac97->dev);
  66. if (ret) {
  67. put_device(&ac97->dev);
  68. return ERR_PTR(ret);
  69. }
  70. return ac97;
  71. }
  72. EXPORT_SYMBOL_GPL(snd_ac97_compat_alloc);
  73. void snd_ac97_compat_release(struct snd_ac97 *ac97)
  74. {
  75. device_unregister(&ac97->dev);
  76. }
  77. EXPORT_SYMBOL_GPL(snd_ac97_compat_release);
  78. int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
  79. unsigned int id_mask)
  80. {
  81. struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  82. struct ac97_controller *actrl = adev->ac97_ctrl;
  83. unsigned int scanned;
  84. if (try_warm) {
  85. compat_ac97_warm_reset(ac97);
  86. scanned = snd_ac97_bus_scan_one(actrl, adev->num);
  87. if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
  88. return 1;
  89. }
  90. compat_ac97_reset(ac97);
  91. compat_ac97_warm_reset(ac97);
  92. scanned = snd_ac97_bus_scan_one(actrl, adev->num);
  93. if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
  94. return 0;
  95. return -ENODEV;
  96. }
  97. EXPORT_SYMBOL_GPL(snd_ac97_reset);