drm/g94-/disp: bash and wait for something after changing lane power regs
[deliverable/linux.git] / drivers / gpu / drm / nouveau / core / engine / disp / sornv94.c
CommitLineData
f7960736
BS
1/*
2 * Copyright 2012 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
25#include <core/os.h>
26#include <core/class.h>
27
28#include <subdev/bios.h>
29#include <subdev/bios/dcb.h>
30#include <subdev/bios/dp.h>
31#include <subdev/bios/init.h>
1ecee1cd 32#include <subdev/timer.h>
f7960736
BS
33
34#include "nv50.h"
b8407c9e 35#include "outpdp.h"
f7960736
BS
36
37static inline u32
3b52a1f9 38nv94_sor_soff(struct nvkm_output_dp *outp)
f7960736 39{
3b52a1f9 40 return (ffs(outp->base.info.or) - 1) * 0x800;
f7960736
BS
41}
42
0a0afd28 43static inline u32
3b52a1f9 44nv94_sor_loff(struct nvkm_output_dp *outp)
8f2abc25 45{
3b52a1f9 46 return nv94_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
8f2abc25
BS
47}
48
0a0afd28
BS
49static inline u32
50nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
8f2abc25 51{
0a0afd28
BS
52 static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */
53 static const u8 nv94[] = { 16, 8, 0, 24 };
54 if (nv_device(priv)->chipset == 0xaf)
55 return nvaf[lane];
56 return nv94[lane];
8f2abc25
BS
57}
58
0a0afd28 59static int
3b52a1f9 60nv94_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
f7960736 61{
3b52a1f9 62 struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
0a0afd28
BS
63 const u32 loff = nv94_sor_loff(outp);
64 nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24);
f7960736
BS
65 return 0;
66}
67
1ecee1cd
BS
68int
69nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
70{
71 struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
13a61757 72 const u32 soff = nv94_sor_soff(outp);
1ecee1cd
BS
73 const u32 loff = nv94_sor_loff(outp);
74 u32 mask = 0, i;
75
76 for (i = 0; i < nr; i++)
77 mask |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3);
78
79 nv_mask(priv, 0x61c130 + loff, 0x0000000f, mask);
13a61757
BS
80 nv_mask(priv, 0x61c034 + soff, 0x80000000, 0x80000000);
81 nv_wait(priv, 0x61c034 + soff, 0x80000000, 0x00000000);
1ecee1cd
BS
82 return 0;
83}
84
0a0afd28 85static int
3b52a1f9 86nv94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
f7960736 87{
3b52a1f9 88 struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
0a0afd28
BS
89 const u32 soff = nv94_sor_soff(outp);
90 const u32 loff = nv94_sor_loff(outp);
f7960736
BS
91 u32 dpctrl = 0x00000000;
92 u32 clksor = 0x00000000;
f7960736 93
3b52a1f9
BS
94 dpctrl |= ((1 << nr) - 1) << 16;
95 if (ef)
f7960736 96 dpctrl |= 0x00004000;
3b52a1f9 97 if (bw > 0x06)
f7960736
BS
98 clksor |= 0x00040000;
99
f7960736
BS
100 nv_mask(priv, 0x614300 + soff, 0x000c0000, clksor);
101 nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl);
f7960736
BS
102 return 0;
103}
104
0a0afd28 105static int
3b52a1f9 106nv94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
f7960736 107{
3b52a1f9
BS
108 struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
109 struct nouveau_bios *bios = nouveau_bios(priv);
110 const u32 shift = nv94_sor_dp_lane_map(priv, ln);
0a0afd28 111 const u32 loff = nv94_sor_loff(outp);
d7b023d8 112 u32 addr, data[3];
f7960736 113 u8 ver, hdr, cnt, len;
0a0afd28 114 struct nvbios_dpout info;
f7960736
BS
115 struct nvbios_dpcfg ocfg;
116
3b52a1f9
BS
117 addr = nvbios_dpout_match(bios, outp->base.info.hasht,
118 outp->base.info.hashm,
0a0afd28 119 &ver, &hdr, &cnt, &len, &info);
f7960736
BS
120 if (!addr)
121 return -ENODEV;
122
3b52a1f9 123 addr = nvbios_dpcfg_match(bios, addr, 0, vs, pe,
0a0afd28 124 &ver, &hdr, &cnt, &len, &ocfg);
f7960736
BS
125 if (!addr)
126 return -EINVAL;
127
d7b023d8
BS
128 data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift);
129 data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift);
130 data[2] = nv_rd32(priv, 0x61c130 + loff) & ~(0x0000ff00);
131 nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.drv << shift));
132 nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pre << shift));
133 nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.unk << 8));
f7960736
BS
134 return 0;
135}
0a0afd28 136
b8407c9e
BS
137struct nvkm_output_dp_impl
138nv94_sor_dp_impl = {
139 .base.base.handle = DCB_OUTPUT_DP,
140 .base.base.ofuncs = &(struct nouveau_ofuncs) {
141 .ctor = _nvkm_output_dp_ctor,
142 .dtor = _nvkm_output_dp_dtor,
143 .init = _nvkm_output_dp_init,
144 .fini = _nvkm_output_dp_fini,
145 },
3b52a1f9 146 .pattern = nv94_sor_dp_pattern,
1ecee1cd 147 .lnk_pwr = nv94_sor_dp_lnk_pwr,
3b52a1f9
BS
148 .lnk_ctl = nv94_sor_dp_lnk_ctl,
149 .drv_ctl = nv94_sor_dp_drv_ctl,
b8407c9e 150};
This page took 0.119108 seconds and 5 git commands to generate.