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