Home | History | Annotate | Line # | Download | only in dispnv04
      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 
     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 
     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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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. */
    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 
    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 
    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 
    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 
    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
    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