2 * Copyright 2014 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
25 #include <subdev/gpio.h>
31 nvkm_connector_hpd_work(struct work_struct *w)
33 struct nvkm_connector *conn = container_of(w, typeof(*conn), hpd.work);
34 struct nouveau_disp *disp = nouveau_disp(conn);
35 struct nouveau_gpio *gpio = nouveau_gpio(conn);
36 u32 send = NVKM_HPD_UNPLUG;
37 if (gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.event->index))
39 nouveau_event_trigger(disp->hpd, send, conn->index);
40 nouveau_event_get(conn->hpd.event);
44 nvkm_connector_hpd(void *data, u32 type, int index)
46 struct nvkm_connector *conn = data;
47 DBG("HPD: %d\n", type);
48 schedule_work(&conn->hpd.work);
49 return NVKM_EVENT_DROP;
53 _nvkm_connector_fini(struct nouveau_object *object, bool suspend)
55 struct nvkm_connector *conn = (void *)object;
57 nouveau_event_put(conn->hpd.event);
58 return nouveau_object_fini(&conn->base, suspend);
62 _nvkm_connector_init(struct nouveau_object *object)
64 struct nvkm_connector *conn = (void *)object;
65 int ret = nouveau_object_init(&conn->base);
68 nouveau_event_get(conn->hpd.event);
74 _nvkm_connector_dtor(struct nouveau_object *object)
76 struct nvkm_connector *conn = (void *)object;
77 nouveau_event_ref(NULL, &conn->hpd.event);
78 nouveau_object_destroy(&conn->base);
82 nvkm_connector_create_(struct nouveau_object *parent,
83 struct nouveau_object *engine,
84 struct nouveau_oclass *oclass,
85 struct nvbios_connE *info, int index,
86 int length, void **pobject)
88 static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 };
89 struct nouveau_gpio *gpio = nouveau_gpio(parent);
90 struct nouveau_disp *disp = (void *)engine;
91 struct nvkm_connector *conn;
92 struct nvkm_output *outp;
93 struct dcb_gpio_func func;
96 list_for_each_entry(outp, &disp->outp, head) {
97 if (outp->conn && outp->conn->index == index) {
98 atomic_inc(&nv_object(outp->conn)->refcount);
99 *pobject = outp->conn;
104 ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
112 DBG("type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x\n",
113 info->type, info->location, info->hpd, info->dp,
114 info->di, info->sr, info->lcdid);
116 if ((info->hpd = ffs(info->hpd))) {
117 if (--info->hpd >= ARRAY_SIZE(hpd)) {
118 ERR("hpd %02x unknown\n", info->hpd);
121 info->hpd = hpd[info->hpd];
123 ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func);
125 ERR("func %02x lookup failed, %d\n", info->hpd, ret);
129 ret = nouveau_event_new(gpio->events, NVKM_GPIO_TOGGLED,
130 func.line, nvkm_connector_hpd,
131 conn, &conn->hpd.event);
133 ERR("func %02x failed, %d\n", info->hpd, ret);
135 DBG("func %02x (HPD)\n", info->hpd);
140 INIT_WORK(&conn->hpd.work, nvkm_connector_hpd_work);
145 _nvkm_connector_ctor(struct nouveau_object *parent,
146 struct nouveau_object *engine,
147 struct nouveau_oclass *oclass, void *info, u32 index,
148 struct nouveau_object **pobject)
150 struct nvkm_connector *conn;
153 ret = nvkm_connector_create(parent, engine, oclass, info, index, &conn);
154 *pobject = nv_object(conn);
161 struct nouveau_oclass *
162 nvkm_connector_oclass = &(struct nvkm_connector_impl) {
165 .ofuncs = &(struct nouveau_ofuncs) {
166 .ctor = _nvkm_connector_ctor,
167 .dtor = _nvkm_connector_dtor,
168 .init = _nvkm_connector_init,
169 .fini = _nvkm_connector_fini,