2 * Copyright 2012 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.
27 gm200_sor_dp_drive(struct nvkm_ior
*sor
, int ln
, int pc
, int dc
, int pe
, int pu
)
29 struct nvkm_device
*device
= sor
->disp
->engine
.subdev
.device
;
30 const u32 loff
= nv50_sor_link(sor
);
31 const u32 shift
= sor
->func
->dp
.lanes
[ln
] * 8;
36 data
[0] = nvkm_rd32(device
, 0x61c118 + loff
) & ~(0x000000ff << shift
);
37 data
[1] = nvkm_rd32(device
, 0x61c120 + loff
) & ~(0x000000ff << shift
);
38 data
[2] = nvkm_rd32(device
, 0x61c130 + loff
);
39 if ((data
[2] & 0x00000f00) < (pu
<< 8) || ln
== 0)
40 data
[2] = (data
[2] & ~0x00000f00) | (pu
<< 8);
41 nvkm_wr32(device
, 0x61c118 + loff
, data
[0] | (dc
<< shift
));
42 nvkm_wr32(device
, 0x61c120 + loff
, data
[1] | (pe
<< shift
));
43 nvkm_wr32(device
, 0x61c130 + loff
, data
[2]);
44 data
[3] = nvkm_rd32(device
, 0x61c13c + loff
) & ~(0x000000ff << shift
);
45 nvkm_wr32(device
, 0x61c13c + loff
, data
[3] | (pc
<< shift
));
49 gm200_sor_route_set(struct nvkm_outp
*outp
, struct nvkm_ior
*ior
)
51 struct nvkm_device
*device
= outp
->disp
->engine
.subdev
.device
;
52 const u32 moff
= __ffs(outp
->info
.or) * 0x100;
53 const u32 sor
= ior
? ior
->id
+ 1 : 0;
54 u32 link
= ior
? (ior
->asy
.link
== 2) : 0;
56 if (outp
->info
.sorconf
.link
& 1) {
57 nvkm_mask(device
, 0x612308 + moff
, 0x0000001f, link
<< 4 | sor
);
61 if (outp
->info
.sorconf
.link
& 2)
62 nvkm_mask(device
, 0x612388 + moff
, 0x0000001f, link
<< 4 | sor
);
66 gm200_sor_route_get(struct nvkm_outp
*outp
, int *link
)
68 struct nvkm_device
*device
= outp
->disp
->engine
.subdev
.device
;
69 const int sublinks
= outp
->info
.sorconf
.link
;
70 int lnk
[2], sor
[2], m
, s
;
72 for (*link
= 0, m
= __ffs(outp
->info
.or) * 2, s
= 0; s
< 2; m
++, s
++) {
73 if (sublinks
& BIT(s
)) {
74 u32 data
= nvkm_rd32(device
, 0x612308 + (m
* 0x80));
75 lnk
[s
] = (data
& 0x00000010) >> 4;
76 sor
[s
] = (data
& 0x0000000f);
84 if (sor
[0] != sor
[1] || WARN_ON(lnk
[0] || !lnk
[1]))
88 return ((sublinks
& 1) ? sor
[0] : sor
[1]) - 1;
91 static const struct nvkm_ior_func
94 .get
= gm200_sor_route_get
,
95 .set
= gm200_sor_route_set
,
97 .state
= gf119_sor_state
,
98 .power
= nv50_sor_power
,
99 .clock
= gf119_sor_clock
,
101 .ctrl
= gk104_hdmi_ctrl
,
104 .lanes
= { 0, 1, 2, 3 },
105 .links
= gf119_sor_dp_links
,
106 .power
= g94_sor_dp_power
,
107 .pattern
= gm107_sor_dp_pattern
,
108 .drive
= gm200_sor_dp_drive
,
109 .vcpi
= gf119_sor_dp_vcpi
,
110 .audio
= gf119_sor_dp_audio
,
111 .audio_sym
= gf119_sor_dp_audio_sym
,
112 .watermark
= gf119_sor_dp_watermark
,
115 .hpd
= gf119_hda_hpd
,
116 .eld
= gf119_hda_eld
,
121 gm200_sor_new(struct nvkm_disp
*disp
, int id
)
123 return gf119_sor_new_(&gm200_sor
, disp
, id
);