conn.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Copyright 2014 Red Hat Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * Authors: Ben Skeggs
  23. */
  24. #include "conn.h"
  25. #include "outp.h"
  26. #include "priv.h"
  27. #include <subdev/gpio.h>
  28. #include <nvif/event.h>
  29. static int
  30. nvkm_connector_hpd(struct nvkm_notify *notify)
  31. {
  32. struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd);
  33. struct nvkm_disp *disp = conn->disp;
  34. struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio;
  35. const struct nvkm_gpio_ntfy_rep *line = notify->data;
  36. struct nvif_notify_conn_rep_v0 rep;
  37. int index = conn->index;
  38. CONN_DBG(conn, "HPD: %d", line->mask);
  39. if (!nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index))
  40. rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG;
  41. else
  42. rep.mask = NVIF_NOTIFY_CONN_V0_PLUG;
  43. rep.version = 0;
  44. nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
  45. return NVKM_NOTIFY_KEEP;
  46. }
  47. void
  48. nvkm_connector_fini(struct nvkm_connector *conn)
  49. {
  50. nvkm_notify_put(&conn->hpd);
  51. }
  52. void
  53. nvkm_connector_init(struct nvkm_connector *conn)
  54. {
  55. nvkm_notify_get(&conn->hpd);
  56. }
  57. void
  58. nvkm_connector_del(struct nvkm_connector **pconn)
  59. {
  60. struct nvkm_connector *conn = *pconn;
  61. if (conn) {
  62. nvkm_notify_fini(&conn->hpd);
  63. kfree(*pconn);
  64. *pconn = NULL;
  65. }
  66. }
  67. static void
  68. nvkm_connector_ctor(struct nvkm_disp *disp, int index,
  69. struct nvbios_connE *info, struct nvkm_connector *conn)
  70. {
  71. static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 };
  72. struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio;
  73. struct dcb_gpio_func func;
  74. int ret;
  75. conn->disp = disp;
  76. conn->index = index;
  77. conn->info = *info;
  78. CONN_DBG(conn, "type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x",
  79. info->type, info->location, info->hpd, info->dp,
  80. info->di, info->sr, info->lcdid);
  81. if ((info->hpd = ffs(info->hpd))) {
  82. if (--info->hpd >= ARRAY_SIZE(hpd)) {
  83. CONN_ERR(conn, "hpd %02x unknown", info->hpd);
  84. return;
  85. }
  86. info->hpd = hpd[info->hpd];
  87. ret = nvkm_gpio_find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func);
  88. if (ret) {
  89. CONN_ERR(conn, "func %02x lookup failed, %d",
  90. info->hpd, ret);
  91. return;
  92. }
  93. ret = nvkm_notify_init(NULL, &gpio->event, nvkm_connector_hpd,
  94. true, &(struct nvkm_gpio_ntfy_req) {
  95. .mask = NVKM_GPIO_TOGGLED,
  96. .line = func.line,
  97. },
  98. sizeof(struct nvkm_gpio_ntfy_req),
  99. sizeof(struct nvkm_gpio_ntfy_rep),
  100. &conn->hpd);
  101. if (ret) {
  102. CONN_ERR(conn, "func %02x failed, %d", info->hpd, ret);
  103. } else {
  104. CONN_DBG(conn, "func %02x (HPD)", info->hpd);
  105. }
  106. }
  107. }
  108. int
  109. nvkm_connector_new(struct nvkm_disp *disp, int index,
  110. struct nvbios_connE *info, struct nvkm_connector **pconn)
  111. {
  112. if (!(*pconn = kzalloc(sizeof(**pconn), GFP_KERNEL)))
  113. return -ENOMEM;
  114. nvkm_connector_ctor(disp, index, info, *pconn);
  115. return 0;
  116. }