keywest.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * common keywest i2c layer
  4. *
  5. * Copyright (c) by Takashi Iwai <tiwai@suse.de>
  6. */
  7. #include <linux/init.h>
  8. #include <linux/i2c.h>
  9. #include <linux/delay.h>
  10. #include <linux/module.h>
  11. #include <sound/core.h>
  12. #include "pmac.h"
  13. /*
  14. * we have to keep a static variable here since i2c attach_adapter
  15. * callback cannot pass a private data.
  16. */
  17. static struct pmac_keywest *keywest_ctx;
  18. static bool keywest_probed;
  19. static int keywest_probe(struct i2c_client *client,
  20. const struct i2c_device_id *id)
  21. {
  22. keywest_probed = true;
  23. /* If instantiated via i2c-powermac, we still need to set the client */
  24. if (!keywest_ctx->client)
  25. keywest_ctx->client = client;
  26. i2c_set_clientdata(client, keywest_ctx);
  27. return 0;
  28. }
  29. /*
  30. * This is kind of a hack, best would be to turn powermac to fixed i2c
  31. * bus numbers and declare the sound device as part of platform
  32. * initialization
  33. */
  34. static int keywest_attach_adapter(struct i2c_adapter *adapter)
  35. {
  36. struct i2c_board_info info;
  37. struct i2c_client *client;
  38. if (! keywest_ctx)
  39. return -EINVAL;
  40. if (strncmp(adapter->name, "mac-io", 6))
  41. return -EINVAL; /* ignored */
  42. memset(&info, 0, sizeof(struct i2c_board_info));
  43. strlcpy(info.type, "keywest", I2C_NAME_SIZE);
  44. info.addr = keywest_ctx->addr;
  45. client = i2c_new_client_device(adapter, &info);
  46. if (IS_ERR(client))
  47. return PTR_ERR(client);
  48. keywest_ctx->client = client;
  49. /*
  50. * We know the driver is already loaded, so the device should be
  51. * already bound. If not it means binding failed, and then there
  52. * is no point in keeping the device instantiated.
  53. */
  54. if (!keywest_ctx->client->dev.driver) {
  55. i2c_unregister_device(keywest_ctx->client);
  56. keywest_ctx->client = NULL;
  57. return -ENODEV;
  58. }
  59. /*
  60. * Let i2c-core delete that device on driver removal.
  61. * This is safe because i2c-core holds the core_lock mutex for us.
  62. */
  63. list_add_tail(&keywest_ctx->client->detected,
  64. &to_i2c_driver(keywest_ctx->client->dev.driver)->clients);
  65. return 0;
  66. }
  67. static int keywest_remove(struct i2c_client *client)
  68. {
  69. if (! keywest_ctx)
  70. return 0;
  71. if (client == keywest_ctx->client)
  72. keywest_ctx->client = NULL;
  73. return 0;
  74. }
  75. static const struct i2c_device_id keywest_i2c_id[] = {
  76. { "MAC,tas3004", 0 }, /* instantiated by i2c-powermac */
  77. { "keywest", 0 }, /* instantiated by us if needed */
  78. { }
  79. };
  80. MODULE_DEVICE_TABLE(i2c, keywest_i2c_id);
  81. static struct i2c_driver keywest_driver = {
  82. .driver = {
  83. .name = "PMac Keywest Audio",
  84. },
  85. .probe = keywest_probe,
  86. .remove = keywest_remove,
  87. .id_table = keywest_i2c_id,
  88. };
  89. /* exported */
  90. void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
  91. {
  92. if (keywest_ctx && keywest_ctx == i2c) {
  93. i2c_del_driver(&keywest_driver);
  94. keywest_ctx = NULL;
  95. }
  96. }
  97. int snd_pmac_tumbler_post_init(void)
  98. {
  99. int err;
  100. if (!keywest_ctx || !keywest_ctx->client)
  101. return -ENXIO;
  102. if ((err = keywest_ctx->init_client(keywest_ctx)) < 0) {
  103. snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err);
  104. return err;
  105. }
  106. return 0;
  107. }
  108. /* exported */
  109. int snd_pmac_keywest_init(struct pmac_keywest *i2c)
  110. {
  111. struct i2c_adapter *adap;
  112. int err, i = 0;
  113. if (keywest_ctx)
  114. return -EBUSY;
  115. adap = i2c_get_adapter(0);
  116. if (!adap)
  117. return -EPROBE_DEFER;
  118. keywest_ctx = i2c;
  119. if ((err = i2c_add_driver(&keywest_driver))) {
  120. snd_printk(KERN_ERR "cannot register keywest i2c driver\n");
  121. i2c_put_adapter(adap);
  122. return err;
  123. }
  124. /* There was already a device from i2c-powermac. Great, let's return */
  125. if (keywest_probed)
  126. return 0;
  127. /* We assume Macs have consecutive I2C bus numbers starting at 0 */
  128. while (adap) {
  129. /* Scan for devices to be bound to */
  130. err = keywest_attach_adapter(adap);
  131. if (!err)
  132. return 0;
  133. i2c_put_adapter(adap);
  134. adap = i2c_get_adapter(++i);
  135. }
  136. return -ENODEV;
  137. }