/sound/soc/codecs/sound_control_gpl.c

https://bitbucket.org/gideonx/bms-jb-3.4.y · C · 333 lines · 248 code · 69 blank · 16 comment · 6 complexity · e73ab0ac0e240f9ace5f19e1b50b276b MD5 · raw file

  1. /*
  2. * Author: Paul Reioux aka Faux123 <reioux@gmail.com>
  3. *
  4. * WCD93xx sound control module
  5. * Copyright 2013 Paul Reioux
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #include <linux/module.h>
  18. #include <linux/kobject.h>
  19. #include <linux/sysfs.h>
  20. #include <linux/kallsyms.h>
  21. #include <sound/control.h>
  22. #include <sound/soc.h>
  23. extern struct snd_kcontrol_new *gpl_faux_snd_controls_ptr;
  24. #define SOUND_CONTROL_MAJOR_VERSION 2
  25. #define SOUND_CONTROL_MINOR_VERSION 1
  26. #define CAMCORDER_MIC_L_OFFSET 17
  27. #define CAMCORDER_MIC_R_OFFSET 18
  28. #define HANDSET_MIC_OFFSET 21
  29. #define SPEAKER_OFFSET 12
  30. #define HEADPHONE_L_OFFSET 8
  31. #define HEADPHONE_R_OFFSET 9
  32. #define HEADPHONE_PA_L_OFFSET 6
  33. #define HEADPHONE_PA_R_OFFSET 7
  34. static ssize_t cam_mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  35. {
  36. struct soc_mixer_control *l_mixer_ptr;
  37. l_mixer_ptr =
  38. (struct soc_mixer_control *)
  39. gpl_faux_snd_controls_ptr[CAMCORDER_MIC_L_OFFSET].private_value;
  40. return sprintf(buf, "%d", l_mixer_ptr->max);
  41. }
  42. static ssize_t cam_mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  43. {
  44. int l_max;
  45. int l_delta;
  46. struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr;
  47. l_mixer_ptr =
  48. (struct soc_mixer_control *)
  49. gpl_faux_snd_controls_ptr[CAMCORDER_MIC_L_OFFSET].private_value;
  50. r_mixer_ptr =
  51. (struct soc_mixer_control *)
  52. gpl_faux_snd_controls_ptr[CAMCORDER_MIC_R_OFFSET].private_value;
  53. sscanf(buf, "%d", &l_max);
  54. l_delta = l_max - l_mixer_ptr->platform_max;
  55. l_mixer_ptr->platform_max = l_max;
  56. l_mixer_ptr->max = l_max;
  57. l_mixer_ptr->min += l_delta;
  58. r_mixer_ptr->platform_max = l_max;
  59. r_mixer_ptr->max = l_max;
  60. r_mixer_ptr->min += l_delta;
  61. return (count);
  62. }
  63. static ssize_t mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  64. {
  65. struct soc_mixer_control *l_mixer_ptr;
  66. l_mixer_ptr =
  67. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET].
  68. private_value;
  69. return sprintf(buf, "%d", l_mixer_ptr->max);
  70. }
  71. static ssize_t mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  72. {
  73. int l_max;
  74. int l_delta;
  75. struct soc_mixer_control *l_mixer_ptr;
  76. l_mixer_ptr =
  77. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET].
  78. private_value;
  79. sscanf(buf, "%d", &l_max);
  80. l_delta = l_max - l_mixer_ptr->platform_max;
  81. l_mixer_ptr->platform_max = l_max;
  82. l_mixer_ptr->max = l_max;
  83. l_mixer_ptr->min += l_delta;
  84. return (count);
  85. }
  86. static ssize_t speaker_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  87. {
  88. struct soc_mixer_control *l_mixer_ptr;
  89. l_mixer_ptr =
  90. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET].
  91. private_value;
  92. return sprintf(buf, "%d", l_mixer_ptr->max);
  93. }
  94. static ssize_t speaker_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  95. {
  96. int l_max;
  97. int l_delta;
  98. struct soc_mixer_control *l_mixer_ptr;
  99. l_mixer_ptr =
  100. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET].
  101. private_value;
  102. sscanf(buf, "%d", &l_max);
  103. l_delta = l_max - l_mixer_ptr->platform_max;
  104. l_mixer_ptr->platform_max = l_max;
  105. l_mixer_ptr->max = l_max;
  106. l_mixer_ptr->min += l_delta;
  107. return (count);
  108. }
  109. static ssize_t headphone_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  110. {
  111. struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr;
  112. l_mixer_ptr =
  113. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET].
  114. private_value;
  115. r_mixer_ptr =
  116. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET].
  117. private_value;
  118. return sprintf(buf, "%d %d",
  119. l_mixer_ptr->max,
  120. r_mixer_ptr->max);
  121. }
  122. static ssize_t headphone_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  123. {
  124. int l_max, r_max;
  125. int l_delta, r_delta;
  126. struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr;
  127. l_mixer_ptr =
  128. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET].
  129. private_value;
  130. r_mixer_ptr =
  131. (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET].
  132. private_value;
  133. sscanf(buf, "%d %d", &l_max, &r_max);
  134. l_delta = l_max - l_mixer_ptr->platform_max;
  135. l_mixer_ptr->platform_max = l_max;
  136. l_mixer_ptr->max = l_max;
  137. l_mixer_ptr->min += l_delta;
  138. r_delta = r_max - r_mixer_ptr->platform_max;
  139. r_mixer_ptr->platform_max = r_max;
  140. r_mixer_ptr->max = r_max;
  141. r_mixer_ptr->min += r_delta;
  142. return count;
  143. }
  144. static ssize_t headphone_pa_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  145. {
  146. struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr;
  147. l_mixer_ptr =
  148. (struct soc_mixer_control *)
  149. gpl_faux_snd_controls_ptr[HEADPHONE_PA_L_OFFSET].
  150. private_value;
  151. r_mixer_ptr =
  152. (struct soc_mixer_control *)
  153. gpl_faux_snd_controls_ptr[HEADPHONE_PA_R_OFFSET].
  154. private_value;
  155. return sprintf(buf, "%d %d",
  156. l_mixer_ptr->max,
  157. r_mixer_ptr->max);
  158. }
  159. static ssize_t headphone_pa_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  160. {
  161. int l_max, r_max;
  162. int l_delta, r_delta;
  163. struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr;
  164. l_mixer_ptr =
  165. (struct soc_mixer_control *)
  166. gpl_faux_snd_controls_ptr[HEADPHONE_PA_L_OFFSET].
  167. private_value;
  168. r_mixer_ptr =
  169. (struct soc_mixer_control *)
  170. gpl_faux_snd_controls_ptr[HEADPHONE_PA_R_OFFSET].
  171. private_value;
  172. sscanf(buf, "%d %d", &l_max, &r_max);
  173. l_delta = l_max - l_mixer_ptr->platform_max;
  174. l_mixer_ptr->platform_max = l_max;
  175. l_mixer_ptr->max = l_max;
  176. l_mixer_ptr->min += l_delta;
  177. r_delta = r_max - r_mixer_ptr->platform_max;
  178. r_mixer_ptr->platform_max = r_max;
  179. r_mixer_ptr->max = r_max;
  180. r_mixer_ptr->min += r_delta;
  181. return count;
  182. }
  183. static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  184. {
  185. return sprintf(buf, "version: %u.%u\n",
  186. SOUND_CONTROL_MAJOR_VERSION,
  187. SOUND_CONTROL_MINOR_VERSION);
  188. }
  189. static struct kobj_attribute cam_mic_gain_attribute =
  190. __ATTR(gpl_cam_mic_gain,
  191. 0666,
  192. cam_mic_gain_show,
  193. cam_mic_gain_store);
  194. static struct kobj_attribute mic_gain_attribute =
  195. __ATTR(gpl_mic_gain,
  196. 0666,
  197. mic_gain_show,
  198. mic_gain_store);
  199. static struct kobj_attribute speaker_gain_attribute =
  200. __ATTR(gpl_speaker_gain,
  201. 0666,
  202. speaker_gain_show,
  203. speaker_gain_store);
  204. static struct kobj_attribute headphone_gain_attribute =
  205. __ATTR(gpl_headphone_gain,
  206. 0666,
  207. headphone_gain_show,
  208. headphone_gain_store);
  209. static struct kobj_attribute headphone_pa_gain_attribute =
  210. __ATTR(gpl_headphone_pa_gain,
  211. 0666,
  212. headphone_pa_gain_show,
  213. headphone_pa_gain_store);
  214. static struct kobj_attribute sound_control_version_attribute =
  215. __ATTR(gpl_sound_control_version,
  216. 0444,
  217. sound_control_version_show, NULL);
  218. static struct attribute *sound_control_attrs[] =
  219. {
  220. &cam_mic_gain_attribute.attr,
  221. &mic_gain_attribute.attr,
  222. &speaker_gain_attribute.attr,
  223. &headphone_gain_attribute.attr,
  224. &headphone_pa_gain_attribute.attr,
  225. &sound_control_version_attribute.attr,
  226. NULL,
  227. };
  228. static struct attribute_group sound_control_attr_group =
  229. {
  230. .attrs = sound_control_attrs,
  231. };
  232. static struct kobject *sound_control_kobj;
  233. static int sound_control_init(void)
  234. {
  235. int sysfs_result;
  236. if (gpl_faux_snd_controls_ptr == NULL) {
  237. pr_err("%s sound_controls_ptr is NULL!\n", __FUNCTION__);
  238. return -1;
  239. }
  240. sound_control_kobj =
  241. kobject_create_and_add("sound_control", kernel_kobj);
  242. if (!sound_control_kobj) {
  243. pr_err("%s sound_control_kobj create failed!\n",
  244. __FUNCTION__);
  245. return -ENOMEM;
  246. }
  247. sysfs_result = sysfs_create_group(sound_control_kobj,
  248. &sound_control_attr_group);
  249. if (sysfs_result) {
  250. pr_info("%s sysfs create failed!\n", __FUNCTION__);
  251. kobject_put(sound_control_kobj);
  252. }
  253. return sysfs_result;
  254. }
  255. static void sound_control_exit(void)
  256. {
  257. if (sound_control_kobj != NULL)
  258. kobject_put(sound_control_kobj);
  259. }
  260. module_init(sound_control_init);
  261. module_exit(sound_control_exit);
  262. MODULE_LICENSE("GPL");
  263. MODULE_AUTHOR("Paul Reioux <reioux@gmail.com>");
  264. MODULE_DESCRIPTION("Sound Control Module GPL Edition");