diff options
Diffstat (limited to 'linux-core/nv50_dac.c')
-rw-r--r-- | linux-core/nv50_dac.c | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/linux-core/nv50_dac.c b/linux-core/nv50_dac.c deleted file mode 100644 index 5dddb469..00000000 --- a/linux-core/nv50_dac.c +++ /dev/null | |||
@@ -1,265 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Maarten Maathuis. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining | ||
6 | * a copy of this software and associated documentation files (the | ||
7 | * "Software"), to deal in the Software without restriction, including | ||
8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
9 | * distribute, sublicense, and/or sell copies of the Software, and to | ||
10 | * permit persons to whom the Software is furnished to do so, subject to | ||
11 | * the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the | ||
14 | * next paragraph) shall be included in all copies or substantial | ||
15 | * portions of the Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
20 | * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | ||
21 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
22 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
23 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include "nv50_output.h" | ||
28 | |||
29 | static int nv50_dac_validate_mode(struct nv50_output *output, struct nouveau_hw_mode *mode) | ||
30 | { | ||
31 | NV50_DEBUG("\n"); | ||
32 | |||
33 | if (mode->clock > 400000) | ||
34 | return MODE_CLOCK_HIGH; | ||
35 | |||
36 | if (mode->clock < 25000) | ||
37 | return MODE_CLOCK_LOW; | ||
38 | |||
39 | return MODE_OK; | ||
40 | } | ||
41 | |||
42 | static int nv50_dac_execute_mode(struct nv50_output *output, bool disconnect) | ||
43 | { | ||
44 | struct drm_nouveau_private *dev_priv = output->dev->dev_private; | ||
45 | struct nv50_crtc *crtc = output->crtc; | ||
46 | struct nouveau_hw_mode *desired_mode = NULL; | ||
47 | |||
48 | uint32_t offset = nv50_output_or_offset(output) * 0x80; | ||
49 | |||
50 | uint32_t mode_ctl = NV50_DAC_MODE_CTRL_OFF; | ||
51 | uint32_t mode_ctl2 = 0; | ||
52 | |||
53 | NV50_DEBUG("or %d\n", nv50_output_or_offset(output)); | ||
54 | |||
55 | if (disconnect) { | ||
56 | NV50_DEBUG("Disconnecting DAC\n"); | ||
57 | OUT_MODE(NV50_DAC0_MODE_CTRL + offset, mode_ctl); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | desired_mode = (crtc->use_native_mode ? crtc->native_mode : | ||
62 | crtc->mode); | ||
63 | |||
64 | if (crtc->index == 1) | ||
65 | mode_ctl |= NV50_DAC_MODE_CTRL_CRTC1; | ||
66 | else | ||
67 | mode_ctl |= NV50_DAC_MODE_CTRL_CRTC0; | ||
68 | |||
69 | /* Lacking a working tv-out, this is not a 100% sure. */ | ||
70 | if (output->type == OUTPUT_DAC) { | ||
71 | mode_ctl |= 0x40; | ||
72 | } else if (output->type == OUTPUT_TV) { | ||
73 | mode_ctl |= 0x100; | ||
74 | } | ||
75 | |||
76 | if (desired_mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
77 | mode_ctl2 |= NV50_DAC_MODE_CTRL2_NHSYNC; | ||
78 | |||
79 | if (desired_mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
80 | mode_ctl2 |= NV50_DAC_MODE_CTRL2_NVSYNC; | ||
81 | |||
82 | OUT_MODE(NV50_DAC0_MODE_CTRL + offset, mode_ctl); | ||
83 | OUT_MODE(NV50_DAC0_MODE_CTRL2 + offset, mode_ctl2); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int nv50_dac_set_clock_mode(struct nv50_output *output) | ||
89 | { | ||
90 | struct drm_nouveau_private *dev_priv = output->dev->dev_private; | ||
91 | |||
92 | NV50_DEBUG("or %d\n", nv50_output_or_offset(output)); | ||
93 | |||
94 | NV_WRITE(NV50_PDISPLAY_DAC_CLK_CLK_CTRL2(nv50_output_or_offset(output)), 0); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static int nv50_dac_set_power_mode(struct nv50_output *output, int mode) | ||
100 | { | ||
101 | struct drm_nouveau_private *dev_priv = output->dev->dev_private; | ||
102 | uint32_t val; | ||
103 | int or = nv50_output_or_offset(output); | ||
104 | |||
105 | NV50_DEBUG("or %d\n", or); | ||
106 | |||
107 | /* wait for it to be done */ | ||
108 | while (NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)) & NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING); | ||
109 | |||
110 | val = NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)) & ~0x7F; | ||
111 | |||
112 | if (mode != DRM_MODE_DPMS_ON) | ||
113 | val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_BLANKED; | ||
114 | |||
115 | switch (mode) { | ||
116 | case DRM_MODE_DPMS_STANDBY: | ||
117 | val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_HSYNC_OFF; | ||
118 | break; | ||
119 | case DRM_MODE_DPMS_SUSPEND: | ||
120 | val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_VSYNC_OFF; | ||
121 | break; | ||
122 | case DRM_MODE_DPMS_OFF: | ||
123 | val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_OFF; | ||
124 | val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_HSYNC_OFF; | ||
125 | val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_VSYNC_OFF; | ||
126 | break; | ||
127 | default: | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | NV_WRITE(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or), val | NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int nv50_dac_detect(struct nv50_output *output) | ||
137 | { | ||
138 | struct drm_nouveau_private *dev_priv = output->dev->dev_private; | ||
139 | int or = nv50_output_or_offset(output); | ||
140 | bool present = 0; | ||
141 | uint32_t dpms_state, load_pattern, load_state; | ||
142 | |||
143 | NV_WRITE(NV50_PDISPLAY_DAC_REGS_CLK_CTRL1(or), 0x00000001); | ||
144 | dpms_state = NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)); | ||
145 | |||
146 | NV_WRITE(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or), 0x00150000 | NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING); | ||
147 | while (NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)) & NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING); | ||
148 | |||
149 | /* Use bios provided value if possible. */ | ||
150 | if (dev_priv->bios.dactestval) { | ||
151 | load_pattern = dev_priv->bios.dactestval; | ||
152 | NV50_DEBUG("Using bios provided load_pattern of %d\n", load_pattern); | ||
153 | } else { | ||
154 | load_pattern = 340; | ||
155 | NV50_DEBUG("Using default load_pattern of %d\n", load_pattern); | ||
156 | } | ||
157 | |||
158 | NV_WRITE(NV50_PDISPLAY_DAC_REGS_LOAD_CTRL(or), NV50_PDISPLAY_DAC_REGS_LOAD_CTRL_ACTIVE | load_pattern); | ||
159 | udelay(10000); /* give it some time to process */ | ||
160 | load_state = NV_READ(NV50_PDISPLAY_DAC_REGS_LOAD_CTRL(or)); | ||
161 | |||
162 | NV_WRITE(NV50_PDISPLAY_DAC_REGS_LOAD_CTRL(or), 0); | ||
163 | NV_WRITE(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or), dpms_state); | ||
164 | |||
165 | if ((load_state & NV50_PDISPLAY_DAC_REGS_LOAD_CTRL_PRESENT) == NV50_PDISPLAY_DAC_REGS_LOAD_CTRL_PRESENT) | ||
166 | present = 1; | ||
167 | |||
168 | if (present) | ||
169 | NV50_DEBUG("Load was detected on output with or %d\n", or); | ||
170 | else | ||
171 | NV50_DEBUG("Load was not detected on output with or %d\n", or); | ||
172 | |||
173 | return present; | ||
174 | } | ||
175 | |||
176 | static int nv50_dac_destroy(struct nv50_output *output) | ||
177 | { | ||
178 | struct drm_device *dev = output->dev; | ||
179 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
180 | struct nv50_display *display = nv50_get_display(dev); | ||
181 | |||
182 | NV50_DEBUG("\n"); | ||
183 | |||
184 | if (!display || !output) | ||
185 | return -EINVAL; | ||
186 | |||
187 | list_del(&output->item); | ||
188 | |||
189 | kfree(output->native_mode); | ||
190 | if (dev_priv->free_output) | ||
191 | dev_priv->free_output(output); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | int nv50_dac_create(struct drm_device *dev, int dcb_entry) | ||
197 | { | ||
198 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
199 | struct nv50_output *output = NULL; | ||
200 | struct nv50_display *display = NULL; | ||
201 | struct dcb_entry *entry = NULL; | ||
202 | int rval = 0; | ||
203 | |||
204 | NV50_DEBUG("\n"); | ||
205 | |||
206 | /* This allows the public layer to do it's thing. */ | ||
207 | if (dev_priv->alloc_output) | ||
208 | output = dev_priv->alloc_output(dev); | ||
209 | |||
210 | if (!output) | ||
211 | return -ENOMEM; | ||
212 | |||
213 | output->dev = dev; | ||
214 | |||
215 | display = nv50_get_display(dev); | ||
216 | if (!display) { | ||
217 | rval = -EINVAL; | ||
218 | goto out; | ||
219 | } | ||
220 | |||
221 | entry = &dev_priv->dcb_table.entry[dcb_entry]; | ||
222 | if (!entry) { | ||
223 | rval = -EINVAL; | ||
224 | goto out; | ||
225 | } | ||
226 | |||
227 | switch (entry->type) { | ||
228 | case DCB_OUTPUT_ANALOG: | ||
229 | output->type = OUTPUT_DAC; | ||
230 | DRM_INFO("Detected a DAC output\n"); | ||
231 | break; | ||
232 | default: | ||
233 | rval = -EINVAL; | ||
234 | goto out; | ||
235 | } | ||
236 | |||
237 | output->dcb_entry = dcb_entry; | ||
238 | output->bus = entry->bus; | ||
239 | |||
240 | list_add_tail(&output->item, &display->outputs); | ||
241 | |||
242 | output->native_mode = kzalloc(sizeof(struct nouveau_hw_mode), GFP_KERNEL); | ||
243 | if (!output->native_mode) { | ||
244 | rval = -ENOMEM; | ||
245 | goto out; | ||
246 | } | ||
247 | |||
248 | /* Set function pointers. */ | ||
249 | output->validate_mode = nv50_dac_validate_mode; | ||
250 | output->execute_mode = nv50_dac_execute_mode; | ||
251 | output->set_clock_mode = nv50_dac_set_clock_mode; | ||
252 | output->set_power_mode = nv50_dac_set_power_mode; | ||
253 | output->detect = nv50_dac_detect; | ||
254 | output->destroy = nv50_dac_destroy; | ||
255 | |||
256 | return 0; | ||
257 | |||
258 | out: | ||
259 | if (output->native_mode) | ||
260 | kfree(output->native_mode); | ||
261 | if (dev_priv->free_output) | ||
262 | dev_priv->free_output(output); | ||
263 | return rval; | ||
264 | } | ||
265 | |||