2 * Copyright 2013 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.
29 #include <core/notify.h>
30 #include <core/option.h>
31 #include <subdev/bios.h>
32 #include <subdev/bios/dcb.h>
33 #include <subdev/bios/i2c.h>
35 static struct nvkm_i2c_pad
*
36 nvkm_i2c_pad_find(struct nvkm_i2c
*i2c
, int id
)
38 struct nvkm_i2c_pad
*pad
;
40 list_for_each_entry(pad
, &i2c
->pad
, head
) {
49 nvkm_i2c_bus_find(struct nvkm_i2c
*i2c
, int id
)
51 struct nvkm_bios
*bios
= i2c
->subdev
.device
->bios
;
52 struct nvkm_i2c_bus
*bus
;
54 if (id
== NVKM_I2C_BUS_PRI
|| id
== NVKM_I2C_BUS_SEC
) {
55 u8 ver
, hdr
, cnt
, len
;
56 u16 i2c
= dcb_i2c_table(bios
, &ver
, &hdr
, &cnt
, &len
);
57 if (i2c
&& ver
>= 0x30) {
58 u8 auxidx
= nvbios_rd08(bios
, i2c
+ 4);
59 if (id
== NVKM_I2C_BUS_PRI
)
60 id
= NVKM_I2C_BUS_CCB((auxidx
& 0x0f) >> 0);
62 id
= NVKM_I2C_BUS_CCB((auxidx
& 0xf0) >> 4);
64 id
= NVKM_I2C_BUS_CCB(2);
68 list_for_each_entry(bus
, &i2c
->bus
, head
) {
77 nvkm_i2c_aux_find(struct nvkm_i2c
*i2c
, int id
)
79 struct nvkm_i2c_aux
*aux
;
81 list_for_each_entry(aux
, &i2c
->aux
, head
) {
90 nvkm_i2c_intr_fini(struct nvkm_event
*event
, int type
, int id
)
92 struct nvkm_i2c
*i2c
= container_of(event
, typeof(*i2c
), event
);
93 struct nvkm_i2c_aux
*aux
= nvkm_i2c_aux_find(i2c
, id
);
95 i2c
->func
->aux_mask(i2c
, type
, aux
->intr
, 0);
99 nvkm_i2c_intr_init(struct nvkm_event
*event
, int type
, int id
)
101 struct nvkm_i2c
*i2c
= container_of(event
, typeof(*i2c
), event
);
102 struct nvkm_i2c_aux
*aux
= nvkm_i2c_aux_find(i2c
, id
);
104 i2c
->func
->aux_mask(i2c
, type
, aux
->intr
, aux
->intr
);
108 nvkm_i2c_intr_ctor(struct nvkm_object
*object
, void *data
, u32 size
,
109 struct nvkm_notify
*notify
)
111 struct nvkm_i2c_ntfy_req
*req
= data
;
112 if (!WARN_ON(size
!= sizeof(*req
))) {
113 notify
->size
= sizeof(struct nvkm_i2c_ntfy_rep
);
114 notify
->types
= req
->mask
;
115 notify
->index
= req
->port
;
121 static const struct nvkm_event_func
122 nvkm_i2c_intr_func
= {
123 .ctor
= nvkm_i2c_intr_ctor
,
124 .init
= nvkm_i2c_intr_init
,
125 .fini
= nvkm_i2c_intr_fini
,
129 nvkm_i2c_intr(struct nvkm_subdev
*subdev
)
131 struct nvkm_i2c
*i2c
= nvkm_i2c(subdev
);
132 struct nvkm_i2c_aux
*aux
;
135 if (!i2c
->func
->aux_stat
)
138 i2c
->func
->aux_stat(i2c
, &hi
, &lo
, &rq
, &tx
);
139 if (!hi
&& !lo
&& !rq
&& !tx
)
142 list_for_each_entry(aux
, &i2c
->aux
, head
) {
144 if (hi
& aux
->intr
) mask
|= NVKM_I2C_PLUG
;
145 if (lo
& aux
->intr
) mask
|= NVKM_I2C_UNPLUG
;
146 if (rq
& aux
->intr
) mask
|= NVKM_I2C_IRQ
;
147 if (tx
& aux
->intr
) mask
|= NVKM_I2C_DONE
;
149 struct nvkm_i2c_ntfy_rep rep
= {
152 nvkm_event_send(&i2c
->event
, rep
.mask
, aux
->id
,
159 nvkm_i2c_fini(struct nvkm_subdev
*subdev
, bool suspend
)
161 struct nvkm_i2c
*i2c
= nvkm_i2c(subdev
);
162 struct nvkm_i2c_pad
*pad
;
165 if ((mask
= (1 << i2c
->func
->aux
) - 1), i2c
->func
->aux_stat
) {
166 i2c
->func
->aux_mask(i2c
, NVKM_I2C_ANY
, mask
, 0);
167 i2c
->func
->aux_stat(i2c
, &mask
, &mask
, &mask
, &mask
);
170 list_for_each_entry(pad
, &i2c
->pad
, head
) {
171 nvkm_i2c_pad_fini(pad
);
178 nvkm_i2c_init(struct nvkm_subdev
*subdev
)
180 struct nvkm_i2c
*i2c
= nvkm_i2c(subdev
);
181 struct nvkm_i2c_bus
*bus
;
182 struct nvkm_i2c_pad
*pad
;
184 list_for_each_entry(pad
, &i2c
->pad
, head
) {
185 nvkm_i2c_pad_init(pad
);
188 list_for_each_entry(bus
, &i2c
->bus
, head
) {
189 nvkm_i2c_bus_init(bus
);
196 nvkm_i2c_dtor(struct nvkm_subdev
*subdev
)
198 struct nvkm_i2c
*i2c
= nvkm_i2c(subdev
);
200 nvkm_event_fini(&i2c
->event
);
202 while (!list_empty(&i2c
->aux
)) {
203 struct nvkm_i2c_aux
*aux
=
204 list_first_entry(&i2c
->aux
, typeof(*aux
), head
);
205 nvkm_i2c_aux_del(&aux
);
208 while (!list_empty(&i2c
->bus
)) {
209 struct nvkm_i2c_bus
*bus
=
210 list_first_entry(&i2c
->bus
, typeof(*bus
), head
);
211 nvkm_i2c_bus_del(&bus
);
214 while (!list_empty(&i2c
->pad
)) {
215 struct nvkm_i2c_pad
*pad
=
216 list_first_entry(&i2c
->pad
, typeof(*pad
), head
);
217 nvkm_i2c_pad_del(&pad
);
223 static const struct nvkm_subdev_func
225 .dtor
= nvkm_i2c_dtor
,
226 .init
= nvkm_i2c_init
,
227 .fini
= nvkm_i2c_fini
,
228 .intr
= nvkm_i2c_intr
,
231 static const struct nvkm_i2c_drv
{
234 int (*pad_new
)(struct nvkm_i2c_bus
*, int id
, u8 addr
,
235 struct nvkm_i2c_pad
**);
238 { 0x0d, 0x39, anx9805_pad_new
},
239 { 0x0e, 0x3b, anx9805_pad_new
},
244 nvkm_i2c_new_(const struct nvkm_i2c_func
*func
, struct nvkm_device
*device
,
245 int index
, struct nvkm_i2c
**pi2c
)
247 struct nvkm_bios
*bios
= device
->bios
;
248 struct nvkm_i2c
*i2c
;
249 struct dcb_i2c_entry ccbE
;
250 struct dcb_output dcbE
;
254 if (!(i2c
= *pi2c
= kzalloc(sizeof(*i2c
), GFP_KERNEL
)))
257 nvkm_subdev_ctor(&nvkm_i2c
, device
, index
, 0, &i2c
->subdev
);
259 INIT_LIST_HEAD(&i2c
->pad
);
260 INIT_LIST_HEAD(&i2c
->bus
);
261 INIT_LIST_HEAD(&i2c
->aux
);
264 while (!dcb_i2c_parse(bios
, ++i
, &ccbE
)) {
265 struct nvkm_i2c_pad
*pad
= NULL
;
266 struct nvkm_i2c_bus
*bus
= NULL
;
267 struct nvkm_i2c_aux
*aux
= NULL
;
269 nvkm_debug(&i2c
->subdev
, "ccb %02x: type %02x drive %02x "
270 "sense %02x share %02x auxch %02x\n", i
, ccbE
.type
,
271 ccbE
.drive
, ccbE
.sense
, ccbE
.share
, ccbE
.auxch
);
273 if (ccbE
.share
!= DCB_I2C_UNUSED
) {
274 const int id
= NVKM_I2C_PAD_HYBRID(ccbE
.share
);
275 if (!(pad
= nvkm_i2c_pad_find(i2c
, id
)))
276 ret
= func
->pad_s_new(i2c
, id
, &pad
);
280 ret
= func
->pad_x_new(i2c
, NVKM_I2C_PAD_CCB(i
), &pad
);
284 nvkm_error(&i2c
->subdev
, "ccb %02x pad, %d\n", i
, ret
);
285 nvkm_i2c_pad_del(&pad
);
289 if (pad
->func
->bus_new_0
&& ccbE
.type
== DCB_I2C_NV04_BIT
) {
290 ret
= pad
->func
->bus_new_0(pad
, NVKM_I2C_BUS_CCB(i
),
294 if (pad
->func
->bus_new_4
&&
295 ( ccbE
.type
== DCB_I2C_NV4E_BIT
||
296 ccbE
.type
== DCB_I2C_NVIO_BIT
||
297 (ccbE
.type
== DCB_I2C_PMGR
&&
298 ccbE
.drive
!= DCB_I2C_UNUSED
))) {
299 ret
= pad
->func
->bus_new_4(pad
, NVKM_I2C_BUS_CCB(i
),
304 nvkm_error(&i2c
->subdev
, "ccb %02x bus, %d\n", i
, ret
);
305 nvkm_i2c_bus_del(&bus
);
308 if (pad
->func
->aux_new_6
&&
309 ( ccbE
.type
== DCB_I2C_NVIO_AUX
||
310 (ccbE
.type
== DCB_I2C_PMGR
&&
311 ccbE
.auxch
!= DCB_I2C_UNUSED
))) {
312 ret
= pad
->func
->aux_new_6(pad
, NVKM_I2C_BUS_CCB(i
),
319 nvkm_error(&i2c
->subdev
, "ccb %02x aux, %d\n", i
, ret
);
320 nvkm_i2c_aux_del(&aux
);
323 if (ccbE
.type
!= DCB_I2C_UNUSED
&& !bus
&& !aux
) {
324 nvkm_warn(&i2c
->subdev
, "ccb %02x was ignored\n", i
);
330 while (dcb_outp_parse(bios
, ++i
, &ver
, &hdr
, &dcbE
)) {
331 const struct nvkm_i2c_drv
*drv
= nvkm_i2c_drv
;
332 struct nvkm_i2c_bus
*bus
;
333 struct nvkm_i2c_pad
*pad
;
335 /* internal outputs handled by native i2c busses (above) */
339 /* we need an i2c bus to talk to the external encoder */
340 bus
= nvkm_i2c_bus_find(i2c
, dcbE
.i2c_index
);
342 nvkm_debug(&i2c
->subdev
, "dcb %02x no bus\n", i
);
346 /* ... and a driver for it */
347 while (drv
->pad_new
) {
348 if (drv
->bios
== dcbE
.extdev
)
354 nvkm_debug(&i2c
->subdev
, "dcb %02x drv %02x unknown\n",
359 /* find/create an instance of the driver */
360 pad
= nvkm_i2c_pad_find(i2c
, NVKM_I2C_PAD_EXT(dcbE
.extdev
));
362 const int id
= NVKM_I2C_PAD_EXT(dcbE
.extdev
);
363 ret
= drv
->pad_new(bus
, id
, drv
->addr
, &pad
);
365 nvkm_error(&i2c
->subdev
, "dcb %02x pad, %d\n",
367 nvkm_i2c_pad_del(&pad
);
372 /* create any i2c bus / aux channel required by the output */
373 if (pad
->func
->aux_new_6
&& dcbE
.type
== DCB_OUTPUT_DP
) {
374 const int id
= NVKM_I2C_AUX_EXT(dcbE
.extdev
);
375 struct nvkm_i2c_aux
*aux
= NULL
;
376 ret
= pad
->func
->aux_new_6(pad
, id
, 0, &aux
);
378 nvkm_error(&i2c
->subdev
, "dcb %02x aux, %d\n",
380 nvkm_i2c_aux_del(&aux
);
383 if (pad
->func
->bus_new_4
) {
384 const int id
= NVKM_I2C_BUS_EXT(dcbE
.extdev
);
385 struct nvkm_i2c_bus
*bus
= NULL
;
386 ret
= pad
->func
->bus_new_4(pad
, id
, 0, &bus
);
388 nvkm_error(&i2c
->subdev
, "dcb %02x bus, %d\n",
390 nvkm_i2c_bus_del(&bus
);
395 return nvkm_event_init(&nvkm_i2c_intr_func
, 4, i
, &i2c
->event
);