core.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * soundbus
  3. *
  4. * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
  5. *
  6. * GPL v2, can be found in COPYING.
  7. */
  8. #include <linux/module.h>
  9. #include "soundbus.h"
  10. MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
  11. MODULE_LICENSE("GPL");
  12. MODULE_DESCRIPTION("Apple Soundbus");
  13. struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev)
  14. {
  15. struct device *tmp;
  16. if (!dev)
  17. return NULL;
  18. tmp = get_device(&dev->ofdev.dev);
  19. if (tmp)
  20. return to_soundbus_device(tmp);
  21. else
  22. return NULL;
  23. }
  24. EXPORT_SYMBOL_GPL(soundbus_dev_get);
  25. void soundbus_dev_put(struct soundbus_dev *dev)
  26. {
  27. if (dev)
  28. put_device(&dev->ofdev.dev);
  29. }
  30. EXPORT_SYMBOL_GPL(soundbus_dev_put);
  31. static int soundbus_probe(struct device *dev)
  32. {
  33. int error = -ENODEV;
  34. struct soundbus_driver *drv;
  35. struct soundbus_dev *soundbus_dev;
  36. drv = to_soundbus_driver(dev->driver);
  37. soundbus_dev = to_soundbus_device(dev);
  38. if (!drv->probe)
  39. return error;
  40. soundbus_dev_get(soundbus_dev);
  41. error = drv->probe(soundbus_dev);
  42. if (error)
  43. soundbus_dev_put(soundbus_dev);
  44. return error;
  45. }
  46. static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env)
  47. {
  48. struct soundbus_dev * soundbus_dev;
  49. struct platform_device * of;
  50. const char *compat;
  51. int retval = 0;
  52. int cplen, seen = 0;
  53. if (!dev)
  54. return -ENODEV;
  55. soundbus_dev = to_soundbus_device(dev);
  56. if (!soundbus_dev)
  57. return -ENODEV;
  58. of = &soundbus_dev->ofdev;
  59. /* stuff we want to pass to /sbin/hotplug */
  60. retval = add_uevent_var(env, "OF_NAME=%s", of->dev.of_node->name);
  61. if (retval)
  62. return retval;
  63. retval = add_uevent_var(env, "OF_TYPE=%s", of->dev.of_node->type);
  64. if (retval)
  65. return retval;
  66. /* Since the compatible field can contain pretty much anything
  67. * it's not really legal to split it out with commas. We split it
  68. * up using a number of environment variables instead. */
  69. compat = of_get_property(of->dev.of_node, "compatible", &cplen);
  70. while (compat && cplen > 0) {
  71. int tmp = env->buflen;
  72. retval = add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
  73. if (retval)
  74. return retval;
  75. compat += env->buflen - tmp;
  76. cplen -= env->buflen - tmp;
  77. seen += 1;
  78. }
  79. retval = add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
  80. if (retval)
  81. return retval;
  82. retval = add_uevent_var(env, "MODALIAS=%s", soundbus_dev->modalias);
  83. return retval;
  84. }
  85. static int soundbus_device_remove(struct device *dev)
  86. {
  87. struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
  88. struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
  89. if (dev->driver && drv->remove)
  90. drv->remove(soundbus_dev);
  91. soundbus_dev_put(soundbus_dev);
  92. return 0;
  93. }
  94. static void soundbus_device_shutdown(struct device *dev)
  95. {
  96. struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
  97. struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
  98. if (dev->driver && drv->shutdown)
  99. drv->shutdown(soundbus_dev);
  100. }
  101. #ifdef CONFIG_PM
  102. static int soundbus_device_suspend(struct device *dev, pm_message_t state)
  103. {
  104. struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
  105. struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
  106. if (dev->driver && drv->suspend)
  107. return drv->suspend(soundbus_dev, state);
  108. return 0;
  109. }
  110. static int soundbus_device_resume(struct device * dev)
  111. {
  112. struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
  113. struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
  114. if (dev->driver && drv->resume)
  115. return drv->resume(soundbus_dev);
  116. return 0;
  117. }
  118. #endif /* CONFIG_PM */
  119. static struct bus_type soundbus_bus_type = {
  120. .name = "aoa-soundbus",
  121. .probe = soundbus_probe,
  122. .uevent = soundbus_uevent,
  123. .remove = soundbus_device_remove,
  124. .shutdown = soundbus_device_shutdown,
  125. #ifdef CONFIG_PM
  126. .suspend = soundbus_device_suspend,
  127. .resume = soundbus_device_resume,
  128. #endif
  129. .dev_attrs = soundbus_dev_attrs,
  130. };
  131. int soundbus_add_one(struct soundbus_dev *dev)
  132. {
  133. static int devcount;
  134. /* sanity checks */
  135. if (!dev->attach_codec ||
  136. !dev->ofdev.dev.of_node ||
  137. dev->pcmname ||
  138. dev->pcmid != -1) {
  139. printk(KERN_ERR "soundbus: adding device failed sanity check!\n");
  140. return -EINVAL;
  141. }
  142. dev_set_name(&dev->ofdev.dev, "soundbus:%x", ++devcount);
  143. dev->ofdev.dev.bus = &soundbus_bus_type;
  144. return of_device_register(&dev->ofdev);
  145. }
  146. EXPORT_SYMBOL_GPL(soundbus_add_one);
  147. void soundbus_remove_one(struct soundbus_dev *dev)
  148. {
  149. of_device_unregister(&dev->ofdev);
  150. }
  151. EXPORT_SYMBOL_GPL(soundbus_remove_one);
  152. int soundbus_register_driver(struct soundbus_driver *drv)
  153. {
  154. /* initialize common driver fields */
  155. drv->driver.name = drv->name;
  156. drv->driver.bus = &soundbus_bus_type;
  157. /* register with core */
  158. return driver_register(&drv->driver);
  159. }
  160. EXPORT_SYMBOL_GPL(soundbus_register_driver);
  161. void soundbus_unregister_driver(struct soundbus_driver *drv)
  162. {
  163. driver_unregister(&drv->driver);
  164. }
  165. EXPORT_SYMBOL_GPL(soundbus_unregister_driver);
  166. static int __init soundbus_init(void)
  167. {
  168. return bus_register(&soundbus_bus_type);
  169. }
  170. static void __exit soundbus_exit(void)
  171. {
  172. bus_unregister(&soundbus_bus_type);
  173. }
  174. subsys_initcall(soundbus_init);
  175. module_exit(soundbus_exit);