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.
26 #include <nvif/event.h>
28 #include <subdev/gpio.h>
34 nvkm_connector_hpd(struct nvkm_notify
*notify
)
36 struct nvkm_connector
*conn
= container_of(notify
, typeof(*conn
), hpd
);
37 struct nouveau_disp
*disp
= nouveau_disp(conn
);
38 struct nouveau_gpio
*gpio
= nouveau_gpio(conn
);
39 const struct nvkm_gpio_ntfy_rep
*line
= notify
->data
;
40 struct nvif_notify_conn_rep_v0 rep
;
41 int index
= conn
->index
;
43 DBG("HPD: %d\n", line
->mask
);
45 if (!gpio
->get(gpio
, 0, DCB_GPIO_UNUSED
, conn
->hpd
.index
))
46 rep
.mask
= NVIF_NOTIFY_CONN_V0_UNPLUG
;
48 rep
.mask
= NVIF_NOTIFY_CONN_V0_PLUG
;
51 nvkm_event_send(&disp
->hpd
, rep
.mask
, index
, &rep
, sizeof(rep
));
52 return NVKM_NOTIFY_KEEP
;
56 _nvkm_connector_fini(struct nouveau_object
*object
, bool suspend
)
58 struct nvkm_connector
*conn
= (void *)object
;
59 nvkm_notify_put(&conn
->hpd
);
60 return nouveau_object_fini(&conn
->base
, suspend
);
64 _nvkm_connector_init(struct nouveau_object
*object
)
66 struct nvkm_connector
*conn
= (void *)object
;
67 int ret
= nouveau_object_init(&conn
->base
);
69 nvkm_notify_get(&conn
->hpd
);
74 _nvkm_connector_dtor(struct nouveau_object
*object
)
76 struct nvkm_connector
*conn
= (void *)object
;
77 nvkm_notify_fini(&conn
->hpd
);
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_disp
*disp
= nouveau_disp(parent
);
90 struct nouveau_gpio
*gpio
= nouveau_gpio(parent
);
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
= nvkm_notify_init(NULL
, &gpio
->event
, nvkm_connector_hpd
,
130 true, &(struct nvkm_gpio_ntfy_req
) {
131 .mask
= NVKM_GPIO_TOGGLED
,
134 sizeof(struct nvkm_gpio_ntfy_req
),
135 sizeof(struct nvkm_gpio_ntfy_rep
),
138 ERR("func %02x failed, %d\n", info
->hpd
, ret
);
140 DBG("func %02x (HPD)\n", info
->hpd
);
148 _nvkm_connector_ctor(struct nouveau_object
*parent
,
149 struct nouveau_object
*engine
,
150 struct nouveau_oclass
*oclass
, void *info
, u32 index
,
151 struct nouveau_object
**pobject
)
153 struct nvkm_connector
*conn
;
156 ret
= nvkm_connector_create(parent
, engine
, oclass
, info
, index
, &conn
);
157 *pobject
= nv_object(conn
);
164 struct nouveau_oclass
*
165 nvkm_connector_oclass
= &(struct nvkm_connector_impl
) {
168 .ofuncs
= &(struct nouveau_ofuncs
) {
169 .ctor
= _nvkm_connector_ctor
,
170 .dtor
= _nvkm_connector_dtor
,
171 .init
= _nvkm_connector_init
,
172 .fini
= _nvkm_connector_fini
,