Commit | Line | Data |
---|---|---|
35b21d39 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 | */ | |
878da15a BS |
24 | #include "nv50.h" |
25 | #include "outp.h" | |
35b21d39 | 26 | |
bf0eb898 | 27 | #include <core/client.h> |
35b21d39 BS |
28 | #include <subdev/timer.h> |
29 | ||
7568b106 | 30 | #include <nvif/cl5070.h> |
878da15a | 31 | #include <nvif/unpack.h> |
35b21d39 BS |
32 | |
33 | int | |
bf0eb898 | 34 | nv50_dac_power(NV50_DISP_MTHD_V1) |
35b21d39 | 35 | { |
2fde1f1c | 36 | struct nvkm_device *device = disp->base.engine.subdev.device; |
bf0eb898 BS |
37 | const u32 doff = outp->or * 0x800; |
38 | union { | |
39 | struct nv50_disp_dac_pwr_v0 v0; | |
40 | } *args = data; | |
41 | u32 stat; | |
42 | int ret; | |
43 | ||
53003941 | 44 | nvif_ioctl(object, "disp dac pwr size %d\n", size); |
bf0eb898 | 45 | if (nvif_unpack(args->v0, 0, 0, false)) { |
53003941 BS |
46 | nvif_ioctl(object, "disp dac pwr vers %d state %d data %d " |
47 | "vsync %d hsync %d\n", | |
48 | args->v0.version, args->v0.state, args->v0.data, | |
49 | args->v0.vsync, args->v0.hsync); | |
bf0eb898 BS |
50 | stat = 0x00000040 * !args->v0.state; |
51 | stat |= 0x00000010 * !args->v0.data; | |
52 | stat |= 0x00000004 * !args->v0.vsync; | |
53 | stat |= 0x00000001 * !args->v0.hsync; | |
54 | } else | |
55 | return ret; | |
56 | ||
3a020b4d BS |
57 | nvkm_msec(device, 2000, |
58 | if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) | |
59 | break; | |
60 | ); | |
2fde1f1c | 61 | nvkm_mask(device, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat); |
3a020b4d BS |
62 | nvkm_msec(device, 2000, |
63 | if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) | |
64 | break; | |
65 | ); | |
35b21d39 BS |
66 | return 0; |
67 | } | |
68 | ||
69 | int | |
c4abd317 | 70 | nv50_dac_sense(NV50_DISP_MTHD_V1) |
35b21d39 | 71 | { |
84407824 BS |
72 | struct nvkm_subdev *subdev = &disp->base.engine.subdev; |
73 | struct nvkm_device *device = subdev->device; | |
c4abd317 BS |
74 | union { |
75 | struct nv50_disp_dac_load_v0 v0; | |
76 | } *args = data; | |
77 | const u32 doff = outp->or * 0x800; | |
78 | u32 loadval; | |
79 | int ret; | |
80 | ||
53003941 | 81 | nvif_ioctl(object, "disp dac load size %d\n", size); |
c4abd317 | 82 | if (nvif_unpack(args->v0, 0, 0, false)) { |
53003941 BS |
83 | nvif_ioctl(object, "disp dac load vers %d data %08x\n", |
84 | args->v0.version, args->v0.data); | |
c4abd317 BS |
85 | if (args->v0.data & 0xfff00000) |
86 | return -EINVAL; | |
87 | loadval = args->v0.data; | |
88 | } else | |
89 | return ret; | |
5087f51d | 90 | |
2fde1f1c | 91 | nvkm_mask(device, 0x61a004 + doff, 0x807f0000, 0x80150000); |
3a020b4d BS |
92 | nvkm_msec(device, 2000, |
93 | if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) | |
94 | break; | |
95 | ); | |
5087f51d | 96 | |
2fde1f1c | 97 | nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); |
b06f6a9d AB |
98 | mdelay(9); |
99 | udelay(500); | |
2fde1f1c | 100 | loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); |
5087f51d | 101 | |
2fde1f1c | 102 | nvkm_mask(device, 0x61a004 + doff, 0x807f0000, 0x80550000); |
3a020b4d BS |
103 | nvkm_msec(device, 2000, |
104 | if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) | |
105 | break; | |
106 | ); | |
5087f51d | 107 | |
84407824 | 108 | nvkm_debug(subdev, "DAC%d sense: %08x\n", outp->or, loadval); |
5087f51d EV |
109 | if (!(loadval & 0x80000000)) |
110 | return -ETIMEDOUT; | |
111 | ||
c4abd317 BS |
112 | args->v0.load = (loadval & 0x38000000) >> 27; |
113 | return 0; | |
35b21d39 | 114 | } |
f2c906fc BS |
115 | |
116 | static const struct nvkm_output_func | |
117 | nv50_dac_output_func = { | |
118 | }; | |
119 | ||
120 | int | |
121 | nv50_dac_output_new(struct nvkm_disp *disp, int index, | |
122 | struct dcb_output *dcbE, struct nvkm_output **poutp) | |
123 | { | |
124 | return nvkm_output_new_(&nv50_dac_output_func, disp, | |
125 | index, dcbE, poutp); | |
126 | } |