se6x.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * C-Media CMI8787 driver for the Studio Evolution SE6X
  3. *
  4. * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5. *
  6. * This driver is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License, version 2.
  8. *
  9. * This driver is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this driver; if not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /*
  18. * CMI8787:
  19. *
  20. * SPI -> microcontroller (not actually used)
  21. * GPIO 0 -> do.
  22. * GPIO 2 -> do.
  23. *
  24. * DAC0 -> both PCM1792A (L+R, each in mono mode)
  25. * ADC1 <- 1st PCM1804
  26. * ADC2 <- 2nd PCM1804
  27. * ADC3 <- 3rd PCM1804
  28. */
  29. #include <linux/pci.h>
  30. #include <linux/module.h>
  31. #include <sound/core.h>
  32. #include <sound/control.h>
  33. #include <sound/initval.h>
  34. #include <sound/pcm.h>
  35. #include "oxygen.h"
  36. MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  37. MODULE_DESCRIPTION("Studio Evolution SE6X driver");
  38. MODULE_LICENSE("GPL v2");
  39. MODULE_SUPPORTED_DEVICE("{{Studio Evolution,SE6X}}");
  40. static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
  41. static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
  42. static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
  43. module_param_array(index, int, NULL, 0444);
  44. MODULE_PARM_DESC(index, "card index");
  45. module_param_array(id, charp, NULL, 0444);
  46. MODULE_PARM_DESC(id, "ID string");
  47. module_param_array(enable, bool, NULL, 0444);
  48. MODULE_PARM_DESC(enable, "enable card");
  49. static const struct pci_device_id se6x_ids[] = {
  50. { OXYGEN_PCI_SUBID(0x13f6, 0x8788) },
  51. { }
  52. };
  53. MODULE_DEVICE_TABLE(pci, se6x_ids);
  54. static void se6x_init(struct oxygen *chip)
  55. {
  56. oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 0x005);
  57. snd_component_add(chip->card, "PCM1792A");
  58. snd_component_add(chip->card, "PCM1804");
  59. }
  60. static int se6x_control_filter(struct snd_kcontrol_new *template)
  61. {
  62. /* no DAC volume/mute */
  63. if (!strncmp(template->name, "Master Playback ", 16))
  64. return 1;
  65. return 0;
  66. }
  67. static void se6x_cleanup(struct oxygen *chip)
  68. {
  69. }
  70. static void set_pcm1792a_params(struct oxygen *chip,
  71. struct snd_pcm_hw_params *params)
  72. {
  73. /* nothing to do (the microcontroller monitors DAC_LRCK) */
  74. }
  75. static void set_pcm1804_params(struct oxygen *chip,
  76. struct snd_pcm_hw_params *params)
  77. {
  78. }
  79. static unsigned int se6x_adjust_dac_routing(struct oxygen *chip,
  80. unsigned int play_routing)
  81. {
  82. /* route the same stereo pair to DAC0 and DAC1 */
  83. return ( play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
  84. ((play_routing << 2) & OXYGEN_PLAY_DAC1_SOURCE_MASK);
  85. }
  86. static const struct oxygen_model model_se6x = {
  87. .shortname = "Studio Evolution SE6X",
  88. .longname = "C-Media Oxygen HD Audio",
  89. .chip = "CMI8787",
  90. .init = se6x_init,
  91. .control_filter = se6x_control_filter,
  92. .cleanup = se6x_cleanup,
  93. .set_dac_params = set_pcm1792a_params,
  94. .set_adc_params = set_pcm1804_params,
  95. .adjust_dac_routing = se6x_adjust_dac_routing,
  96. .device_config = PLAYBACK_0_TO_I2S |
  97. CAPTURE_0_FROM_I2S_1 |
  98. CAPTURE_2_FROM_I2S_2 |
  99. CAPTURE_3_FROM_I2S_3,
  100. .dac_channels_pcm = 2,
  101. .function_flags = OXYGEN_FUNCTION_SPI,
  102. .dac_mclks = OXYGEN_MCLKS(256, 128, 128),
  103. .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
  104. .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
  105. .adc_i2s_format = OXYGEN_I2S_FORMAT_I2S,
  106. };
  107. static int se6x_get_model(struct oxygen *chip,
  108. const struct pci_device_id *pci_id)
  109. {
  110. chip->model = model_se6x;
  111. return 0;
  112. }
  113. static int se6x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
  114. {
  115. static int dev;
  116. int err;
  117. if (dev >= SNDRV_CARDS)
  118. return -ENODEV;
  119. if (!enable[dev]) {
  120. ++dev;
  121. return -ENOENT;
  122. }
  123. err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
  124. se6x_ids, se6x_get_model);
  125. if (err >= 0)
  126. ++dev;
  127. return err;
  128. }
  129. static struct pci_driver se6x_driver = {
  130. .name = KBUILD_MODNAME,
  131. .id_table = se6x_ids,
  132. .probe = se6x_probe,
  133. .remove = oxygen_pci_remove,
  134. #ifdef CONFIG_PM_SLEEP
  135. .driver = {
  136. .pm = &oxygen_pci_pm,
  137. },
  138. #endif
  139. .shutdown = oxygen_pci_shutdown,
  140. };
  141. module_pci_driver(se6x_driver);