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