pcsp_mixer.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * PC-Speaker driver for Linux
  4. *
  5. * Mixer implementation.
  6. * Copyright (C) 2001-2008 Stas Sergeev
  7. */
  8. #include <sound/core.h>
  9. #include <sound/control.h>
  10. #include "pcsp.h"
  11. static int pcsp_enable_info(struct snd_kcontrol *kcontrol,
  12. struct snd_ctl_elem_info *uinfo)
  13. {
  14. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  15. uinfo->count = 1;
  16. uinfo->value.integer.min = 0;
  17. uinfo->value.integer.max = 1;
  18. return 0;
  19. }
  20. static int pcsp_enable_get(struct snd_kcontrol *kcontrol,
  21. struct snd_ctl_elem_value *ucontrol)
  22. {
  23. struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  24. ucontrol->value.integer.value[0] = chip->enable;
  25. return 0;
  26. }
  27. static int pcsp_enable_put(struct snd_kcontrol *kcontrol,
  28. struct snd_ctl_elem_value *ucontrol)
  29. {
  30. struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  31. int changed = 0;
  32. int enab = ucontrol->value.integer.value[0];
  33. if (enab != chip->enable) {
  34. chip->enable = enab;
  35. changed = 1;
  36. }
  37. return changed;
  38. }
  39. static int pcsp_treble_info(struct snd_kcontrol *kcontrol,
  40. struct snd_ctl_elem_info *uinfo)
  41. {
  42. struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  43. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  44. uinfo->count = 1;
  45. uinfo->value.enumerated.items = chip->max_treble + 1;
  46. if (uinfo->value.enumerated.item > chip->max_treble)
  47. uinfo->value.enumerated.item = chip->max_treble;
  48. sprintf(uinfo->value.enumerated.name, "%lu",
  49. (unsigned long)PCSP_CALC_RATE(uinfo->value.enumerated.item));
  50. return 0;
  51. }
  52. static int pcsp_treble_get(struct snd_kcontrol *kcontrol,
  53. struct snd_ctl_elem_value *ucontrol)
  54. {
  55. struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  56. ucontrol->value.enumerated.item[0] = chip->treble;
  57. return 0;
  58. }
  59. static int pcsp_treble_put(struct snd_kcontrol *kcontrol,
  60. struct snd_ctl_elem_value *ucontrol)
  61. {
  62. struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  63. int changed = 0;
  64. int treble = ucontrol->value.enumerated.item[0];
  65. if (treble != chip->treble) {
  66. chip->treble = treble;
  67. #if PCSP_DEBUG
  68. printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE());
  69. #endif
  70. changed = 1;
  71. }
  72. return changed;
  73. }
  74. static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol,
  75. struct snd_ctl_elem_info *uinfo)
  76. {
  77. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  78. uinfo->count = 1;
  79. uinfo->value.integer.min = 0;
  80. uinfo->value.integer.max = 1;
  81. return 0;
  82. }
  83. static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol,
  84. struct snd_ctl_elem_value *ucontrol)
  85. {
  86. struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  87. ucontrol->value.integer.value[0] = chip->pcspkr;
  88. return 0;
  89. }
  90. static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
  91. struct snd_ctl_elem_value *ucontrol)
  92. {
  93. struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  94. int changed = 0;
  95. int spkr = ucontrol->value.integer.value[0];
  96. if (spkr != chip->pcspkr) {
  97. chip->pcspkr = spkr;
  98. changed = 1;
  99. }
  100. return changed;
  101. }
  102. #define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \
  103. { \
  104. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  105. .name = ctl_name, \
  106. .info = pcsp_##ctl_type##_info, \
  107. .get = pcsp_##ctl_type##_get, \
  108. .put = pcsp_##ctl_type##_put, \
  109. }
  110. static struct snd_kcontrol_new snd_pcsp_controls_pcm[] = {
  111. PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
  112. PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
  113. };
  114. static struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
  115. PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
  116. };
  117. static int snd_pcsp_ctls_add(struct snd_pcsp *chip,
  118. struct snd_kcontrol_new *ctls, int num)
  119. {
  120. int i, err;
  121. struct snd_card *card = chip->card;
  122. for (i = 0; i < num; i++) {
  123. err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip));
  124. if (err < 0)
  125. return err;
  126. }
  127. return 0;
  128. }
  129. int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
  130. {
  131. int err;
  132. struct snd_card *card = chip->card;
  133. if (!nopcm) {
  134. err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm,
  135. ARRAY_SIZE(snd_pcsp_controls_pcm));
  136. if (err < 0)
  137. return err;
  138. }
  139. err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_spkr,
  140. ARRAY_SIZE(snd_pcsp_controls_spkr));
  141. if (err < 0)
  142. return err;
  143. strcpy(card->mixername, "PC-Speaker");
  144. return 0;
  145. }