Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 543 lines (443 sloc) 17.361 kb
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
1 /*
2 * Copyright 2003 NVIDIA, Corporation
3 * Copyright 2006 Dave Airlie
4 * Copyright 2007 Maarten Maathuis
5 * Copyright 2007-2009 Stuart Bennett
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "nouveau_drv.h"
1cf0fec @mlankhorst freebsd WIP
mlankhorst authored
28 #include "drm_crtc_helper.h"
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
29 #include "nouveau_encoder.h"
30 #include "nouveau_connector.h"
31 #include "nouveau_crtc.h"
32 #include "nouveau_hw.h"
33 #include "nvreg.h"
34
35 int nv04_dac_output_offset(struct drm_encoder *encoder)
36 {
37 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
38 int offset = 0;
39
40 if (dcb->or & (8 | OUTPUT_C))
41 offset += 0x68;
42 if (dcb->or & (8 | OUTPUT_B))
43 offset += 0x2000;
44
45 return offset;
46 }
47
48 /*
49 * arbitrary limit to number of sense oscillations tolerated in one sample
50 * period (observed to be at least 13 in "nvidia")
51 */
52 #define MAX_HBLANK_OSC 20
53
54 /*
55 * arbitrary limit to number of conflicting sample pairs to tolerate at a
56 * voltage step (observed to be at least 5 in "nvidia")
57 */
58 #define MAX_SAMPLE_PAIRS 10
59
60 static int sample_load_twice(struct drm_device *dev, bool sense[2])
61 {
62 int i;
63
64 for (i = 0; i < 2; i++) {
65 bool sense_a, sense_b, sense_b_prime;
66 int j = 0;
67
68 /*
69 * wait for bit 0 clear -- out of hblank -- (say reg value 0x4),
70 * then wait for transition 0x4->0x5->0x4: enter hblank, leave
71 * hblank again
72 * use a 10ms timeout (guards against crtc being inactive, in
73 * which case blank state would never change)
74 */
75 if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
76 0x00000001, 0x00000000))
77 return -EBUSY;
78 if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
79 0x00000001, 0x00000001))
80 return -EBUSY;
81 if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
82 0x00000001, 0x00000000))
83 return -EBUSY;
84
85 udelay(100);
86 /* when level triggers, sense is _LO_ */
87 sense_a = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10;
88
89 /* take another reading until it agrees with sense_a... */
90 do {
91 udelay(100);
92 sense_b = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10;
93 if (sense_a != sense_b) {
94 sense_b_prime =
95 nv_rd08(dev, NV_PRMCIO_INP0) & 0x10;
96 if (sense_b == sense_b_prime) {
97 /* ... unless two consecutive subsequent
98 * samples agree; sense_a is replaced */
99 sense_a = sense_b;
100 /* force mis-match so we loop */
101 sense_b = !sense_a;
102 }
103 }
104 } while ((sense_a != sense_b) && ++j < MAX_HBLANK_OSC);
105
106 if (j == MAX_HBLANK_OSC)
107 /* with so much oscillation, default to sense:LO */
108 sense[i] = false;
109 else
110 sense[i] = sense_a;
111 }
112
113 return 0;
114 }
115
116 static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
117 struct drm_connector *connector)
118 {
119 struct drm_device *dev = encoder->dev;
120 uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode;
121 uint8_t saved_palette0[3], saved_palette_mask;
122 uint32_t saved_rtest_ctrl, saved_rgen_ctrl;
123 int i;
124 uint8_t blue;
125 bool sense = true;
126
127 /*
128 * for this detection to work, there needs to be a mode set up on the
129 * CRTC. this is presumed to be the case
130 */
131
132 if (nv_two_heads(dev))
133 /* only implemented for head A for now */
134 NVSetOwner(dev, 0);
135
136 saved_cr_mode = NVReadVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX);
137 NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode | 0x80);
138
139 saved_seq1 = NVReadVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX);
140 NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1 & ~0x20);
141
142 saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL);
143 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL,
144 saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
145
146 msleep(10);
147
148 saved_pi = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX);
149 NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX,
150 saved_pi & ~(0x80 | MASK(NV_CIO_CRE_PIXEL_FORMAT)));
151 saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX);
152 NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0);
153
154 nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS, 0x0);
155 for (i = 0; i < 3; i++)
156 saved_palette0[i] = nv_rd08(dev, NV_PRMDIO_PALETTE_DATA);
157 saved_palette_mask = nv_rd08(dev, NV_PRMDIO_PIXEL_MASK);
158 nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, 0);
159
160 saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL);
161 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL,
162 (saved_rgen_ctrl & ~(NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
163 NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM)) |
164 NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON);
165
166 blue = 8; /* start of test range */
167
168 do {
169 bool sense_pair[2];
170
171 nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
172 nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0);
173 nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0);
174 /* testing blue won't find monochrome monitors. I don't care */
175 nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, blue);
176
177 i = 0;
178 /* take sample pairs until both samples in the pair agree */
179 do {
180 if (sample_load_twice(dev, sense_pair))
181 goto out;
182 } while ((sense_pair[0] != sense_pair[1]) &&
183 ++i < MAX_SAMPLE_PAIRS);
184
185 if (i == MAX_SAMPLE_PAIRS)
186 /* too much oscillation defaults to LO */
187 sense = false;
188 else
189 sense = sense_pair[0];
190
191 /*
192 * if sense goes LO before blue ramps to 0x18, monitor is not connected.
193 * ergo, if blue gets to 0x18, monitor must be connected
194 */
195 } while (++blue < 0x18 && sense);
196
197 out:
198 nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, saved_palette_mask);
199 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl);
200 nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
201 for (i = 0; i < 3; i++)
202 nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]);
203 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl);
204 NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi);
205 NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1);
206 NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1);
207 NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
208
209 if (blue == 0x18) {
210 NV_INFO(dev, "Load detected on head A\n");
211 return connector_status_connected;
212 }
213
214 return connector_status_disconnected;
215 }
216
217 uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
218 {
219 struct drm_device *dev = encoder->dev;
220 struct drm_nouveau_private *dev_priv = dev->dev_private;
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
221 struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
222 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
223 uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
224 uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
225 saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput;
226 int head;
227
228 #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
229 if (dcb->type == OUTPUT_TV) {
230 testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0);
231
232 if (dev_priv->vbios.tvdactestval)
233 testval = dev_priv->vbios.tvdactestval;
234 } else {
235 testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
236
237 if (dev_priv->vbios.dactestval)
238 testval = dev_priv->vbios.dactestval;
239 }
240
241 saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
242 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset,
243 saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
244
245 saved_powerctrl_2 = nvReadMC(dev, NV_PBUS_POWERCTRL_2);
246
247 nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
248 if (regoffset == 0x68) {
249 saved_powerctrl_4 = nvReadMC(dev, NV_PBUS_POWERCTRL_4);
250 nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
251 }
252
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
253 saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
254 saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
255
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
256 gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
257 gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
258
259 msleep(4);
260
261 saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
262 head = (saved_routput & 0x100) >> 8;
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
263
264 /* if there's a spare crtc, using it will minimise flicker */
265 if (!(NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX) & 0xC0))
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
266 head ^= 1;
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
267
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
268 /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
269 routput = (saved_routput & 0xfffffece) | head << 8;
270
271 if (dev_priv->card_type >= NV_40) {
272 if (dcb->type == OUTPUT_TV)
273 routput |= 0x1a << 16;
274 else
275 routput &= ~(0x1a << 16);
276 }
277
278 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, routput);
279 msleep(1);
280
281 temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
282 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, temp | 1);
283
284 NVWriteRAMDAC(dev, head, NV_PRAMDAC_TESTPOINT_DATA,
285 NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK | testval);
286 temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL);
287 NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL,
288 temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
289 msleep(5);
290
291 sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
420c14a @koriakin Merge upstream commit 5a4ff9f48f638d0cddeb6788743f32d8cdc89423
koriakin authored
292 /* do it again just in case it's a residual current */
293 sample &= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
294
295 temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL);
296 NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL,
297 temp & ~NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
298 NVWriteRAMDAC(dev, head, NV_PRAMDAC_TESTPOINT_DATA, 0);
299
300 /* bios does something more complex for restoring, but I think this is good enough */
301 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput);
302 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
303 if (regoffset == 0x68)
304 nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
305 nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
306
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
307 gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
308 gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
309
310 return sample;
311 }
312
313 static enum drm_connector_status
314 nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
315 {
316 struct drm_device *dev = encoder->dev;
317 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
318
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
319 if (nv04_dac_in_use(encoder))
320 return connector_status_disconnected;
321
322 if (nv17_dac_sample_load(encoder) &
323 NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
324 NV_INFO(dev, "Load detected on output %c\n",
325 '@' + ffs(dcb->or));
326 return connector_status_connected;
327 } else {
328 return connector_status_disconnected;
329 }
330 }
331
332 static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
333 struct drm_display_mode *mode,
334 struct drm_display_mode *adjusted_mode)
335 {
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
336 if (nv04_dac_in_use(encoder))
337 return false;
338
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
339 return true;
340 }
341
342 static void nv04_dac_prepare(struct drm_encoder *encoder)
343 {
344 struct drm_encoder_helper_funcs *helper = encoder->helper_private;
345 struct drm_device *dev = encoder->dev;
346 int head = nouveau_crtc(encoder->crtc)->index;
347
348 helper->dpms(encoder, DRM_MODE_DPMS_OFF);
349
350 nv04_dfp_disable(dev, head);
351 }
352
353 static void nv04_dac_mode_set(struct drm_encoder *encoder,
354 struct drm_display_mode *mode,
355 struct drm_display_mode *adjusted_mode)
356 {
357 struct drm_device *dev = encoder->dev;
358 struct drm_nouveau_private *dev_priv = dev->dev_private;
359 int head = nouveau_crtc(encoder->crtc)->index;
360
361 if (nv_gf4_disp_arch(dev)) {
362 struct drm_encoder *rebind;
363 uint32_t dac_offset = nv04_dac_output_offset(encoder);
364 uint32_t otherdac;
365
366 /* bit 16-19 are bits that are set on some G70 cards,
367 * but don't seem to have much effect */
368 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset,
369 head << 8 | NV_PRAMDAC_DACCLK_SEL_DACCLK);
370 /* force any other vga encoders to bind to the other crtc */
371 list_for_each_entry(rebind, &dev->mode_config.encoder_list, head) {
372 if (rebind == encoder
373 || nouveau_encoder(rebind)->dcb->type != OUTPUT_ANALOG)
374 continue;
375
376 dac_offset = nv04_dac_output_offset(rebind);
377 otherdac = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset);
378 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset,
379 (otherdac & ~0x0100) | (head ^ 1) << 8);
380 }
381 }
382
383 /* This could use refinement for flatpanels, but it should work this way */
384 if (dev_priv->chipset < 0x44)
385 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000);
386 else
387 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
388 }
389
390 static void nv04_dac_commit(struct drm_encoder *encoder)
391 {
392 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
393 struct drm_device *dev = encoder->dev;
394 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
395 struct drm_encoder_helper_funcs *helper = encoder->helper_private;
396
397 helper->dpms(encoder, DRM_MODE_DPMS_ON);
398
399 NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
400 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
401 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
402 }
403
404 void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
405 {
406 struct drm_device *dev = encoder->dev;
407 struct drm_nouveau_private *dev_priv = dev->dev_private;
408 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
409
410 if (nv_gf4_disp_arch(dev)) {
411 uint32_t *dac_users = &dev_priv->dac_users[ffs(dcb->or) - 1];
412 int dacclk_off = NV_PRAMDAC_DACCLK + nv04_dac_output_offset(encoder);
413 uint32_t dacclk = NVReadRAMDAC(dev, 0, dacclk_off);
414
415 if (enable) {
416 *dac_users |= 1 << dcb->index;
417 NVWriteRAMDAC(dev, 0, dacclk_off, dacclk | NV_PRAMDAC_DACCLK_SEL_DACCLK);
418
419 } else {
420 *dac_users &= ~(1 << dcb->index);
421 if (!*dac_users)
422 NVWriteRAMDAC(dev, 0, dacclk_off,
423 dacclk & ~NV_PRAMDAC_DACCLK_SEL_DACCLK);
424 }
425 }
426 }
427
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
428 /* Check if the DAC corresponding to 'encoder' is being used by
429 * someone else. */
430 bool nv04_dac_in_use(struct drm_encoder *encoder)
431 {
432 struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
433 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
434
435 return nv_gf4_disp_arch(encoder->dev) &&
436 (dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index));
437 }
438
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
439 static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
440 {
441 struct drm_device *dev = encoder->dev;
442 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
443
444 if (nv_encoder->last_dpms == mode)
445 return;
446 nv_encoder->last_dpms = mode;
447
448 NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n",
449 mode, nv_encoder->dcb->index);
450
451 nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
452 }
453
454 static void nv04_dac_save(struct drm_encoder *encoder)
455 {
456 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
457 struct drm_device *dev = encoder->dev;
458
459 if (nv_gf4_disp_arch(dev))
460 nv_encoder->restore.output = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK +
461 nv04_dac_output_offset(encoder));
462 }
463
464 static void nv04_dac_restore(struct drm_encoder *encoder)
465 {
466 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
467 struct drm_device *dev = encoder->dev;
468
469 if (nv_gf4_disp_arch(dev))
470 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + nv04_dac_output_offset(encoder),
471 nv_encoder->restore.output);
472
473 nv_encoder->last_dpms = NV_DPMS_CLEARED;
474 }
475
476 static void nv04_dac_destroy(struct drm_encoder *encoder)
477 {
478 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
479
480 NV_DEBUG_KMS(encoder->dev, "\n");
481
482 drm_encoder_cleanup(encoder);
483 kfree(nv_encoder);
484 }
485
486 static const struct drm_encoder_helper_funcs nv04_dac_helper_funcs = {
487 .dpms = nv04_dac_dpms,
488 .save = nv04_dac_save,
489 .restore = nv04_dac_restore,
490 .mode_fixup = nv04_dac_mode_fixup,
491 .prepare = nv04_dac_prepare,
492 .commit = nv04_dac_commit,
493 .mode_set = nv04_dac_mode_set,
494 .detect = nv04_dac_detect
495 };
496
497 static const struct drm_encoder_helper_funcs nv17_dac_helper_funcs = {
498 .dpms = nv04_dac_dpms,
499 .save = nv04_dac_save,
500 .restore = nv04_dac_restore,
501 .mode_fixup = nv04_dac_mode_fixup,
502 .prepare = nv04_dac_prepare,
503 .commit = nv04_dac_commit,
504 .mode_set = nv04_dac_mode_set,
505 .detect = nv17_dac_detect
506 };
507
508 static const struct drm_encoder_funcs nv04_dac_funcs = {
509 .destroy = nv04_dac_destroy,
510 };
511
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
512 int
513 nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
514 {
515 const struct drm_encoder_helper_funcs *helper;
516 struct nouveau_encoder *nv_encoder = NULL;
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
517 struct drm_device *dev = connector->dev;
518 struct drm_encoder *encoder;
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
519
520 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
521 if (!nv_encoder)
522 return -ENOMEM;
523
524 encoder = to_drm_encoder(nv_encoder);
525
526 nv_encoder->dcb = entry;
527 nv_encoder->or = ffs(entry->or) - 1;
528
529 if (nv_gf4_disp_arch(dev))
530 helper = &nv17_dac_helper_funcs;
531 else
532 helper = &nv04_dac_helper_funcs;
533
534 drm_encoder_init(dev, encoder, &nv04_dac_funcs, DRM_MODE_ENCODER_DAC);
535 drm_encoder_helper_add(encoder, helper);
536
537 encoder->possible_crtcs = entry->heads;
538 encoder->possible_clones = 0;
539
c2f32b8 @koriakin Bump to kernel 2.6.35.
koriakin authored
540 drm_mode_connector_attach_encoder(connector, encoder);
978685f @koriakin pscnv: Import linux module skeleton.
koriakin authored
541 return 0;
542 }
Something went wrong with that request. Please try again.