xref: /openbmc/linux/drivers/gpu/drm/radeon/radeon_encoders.c (revision 43c33ed87d0f1b900a6a3014db556ecc7f4a989b)
1771fe6b9SJerome Glisse /*
2771fe6b9SJerome Glisse  * Copyright 2007-8 Advanced Micro Devices, Inc.
3771fe6b9SJerome Glisse  * Copyright 2008 Red Hat Inc.
4771fe6b9SJerome Glisse  *
5771fe6b9SJerome Glisse  * Permission is hereby granted, free of charge, to any person obtaining a
6771fe6b9SJerome Glisse  * copy of this software and associated documentation files (the "Software"),
7771fe6b9SJerome Glisse  * to deal in the Software without restriction, including without limitation
8771fe6b9SJerome Glisse  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9771fe6b9SJerome Glisse  * and/or sell copies of the Software, and to permit persons to whom the
10771fe6b9SJerome Glisse  * Software is furnished to do so, subject to the following conditions:
11771fe6b9SJerome Glisse  *
12771fe6b9SJerome Glisse  * The above copyright notice and this permission notice shall be included in
13771fe6b9SJerome Glisse  * all copies or substantial portions of the Software.
14771fe6b9SJerome Glisse  *
15771fe6b9SJerome Glisse  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16771fe6b9SJerome Glisse  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17771fe6b9SJerome Glisse  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18771fe6b9SJerome Glisse  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19771fe6b9SJerome Glisse  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20771fe6b9SJerome Glisse  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21771fe6b9SJerome Glisse  * OTHER DEALINGS IN THE SOFTWARE.
22771fe6b9SJerome Glisse  *
23771fe6b9SJerome Glisse  * Authors: Dave Airlie
24771fe6b9SJerome Glisse  *          Alex Deucher
25771fe6b9SJerome Glisse  */
26771fe6b9SJerome Glisse #include "drmP.h"
27771fe6b9SJerome Glisse #include "drm_crtc_helper.h"
28771fe6b9SJerome Glisse #include "radeon_drm.h"
29771fe6b9SJerome Glisse #include "radeon.h"
30771fe6b9SJerome Glisse #include "atom.h"
31771fe6b9SJerome Glisse 
32771fe6b9SJerome Glisse extern int atom_debug;
33771fe6b9SJerome Glisse 
345a9bcaccSAlex Deucher /* evil but including atombios.h is much worse */
355a9bcaccSAlex Deucher bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
365a9bcaccSAlex Deucher 				struct drm_display_mode *mode);
375a9bcaccSAlex Deucher 
381f3b6a45SDave Airlie static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
391f3b6a45SDave Airlie {
401f3b6a45SDave Airlie 	struct drm_device *dev = encoder->dev;
411f3b6a45SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
421f3b6a45SDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
431f3b6a45SDave Airlie 	struct drm_encoder *clone_encoder;
441f3b6a45SDave Airlie 	uint32_t index_mask = 0;
451f3b6a45SDave Airlie 	int count;
461f3b6a45SDave Airlie 
471f3b6a45SDave Airlie 	/* DIG routing gets problematic */
481f3b6a45SDave Airlie 	if (rdev->family >= CHIP_R600)
491f3b6a45SDave Airlie 		return index_mask;
501f3b6a45SDave Airlie 	/* LVDS/TV are too wacky */
511f3b6a45SDave Airlie 	if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
521f3b6a45SDave Airlie 		return index_mask;
531f3b6a45SDave Airlie 	/* DVO requires 2x ppll clocks depending on tmds chip */
541f3b6a45SDave Airlie 	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
551f3b6a45SDave Airlie 		return index_mask;
561f3b6a45SDave Airlie 
571f3b6a45SDave Airlie 	count = -1;
581f3b6a45SDave Airlie 	list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
591f3b6a45SDave Airlie 		struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
601f3b6a45SDave Airlie 		count++;
611f3b6a45SDave Airlie 
621f3b6a45SDave Airlie 		if (clone_encoder == encoder)
631f3b6a45SDave Airlie 			continue;
641f3b6a45SDave Airlie 		if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT))
651f3b6a45SDave Airlie 			continue;
661f3b6a45SDave Airlie 		if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT)
671f3b6a45SDave Airlie 			continue;
681f3b6a45SDave Airlie 		else
691f3b6a45SDave Airlie 			index_mask |= (1 << count);
701f3b6a45SDave Airlie 	}
711f3b6a45SDave Airlie 	return index_mask;
721f3b6a45SDave Airlie }
731f3b6a45SDave Airlie 
741f3b6a45SDave Airlie void radeon_setup_encoder_clones(struct drm_device *dev)
751f3b6a45SDave Airlie {
761f3b6a45SDave Airlie 	struct drm_encoder *encoder;
771f3b6a45SDave Airlie 
781f3b6a45SDave Airlie 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
791f3b6a45SDave Airlie 		encoder->possible_clones = radeon_encoder_clones(encoder);
801f3b6a45SDave Airlie 	}
811f3b6a45SDave Airlie }
821f3b6a45SDave Airlie 
83771fe6b9SJerome Glisse uint32_t
84771fe6b9SJerome Glisse radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
85771fe6b9SJerome Glisse {
86771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
87771fe6b9SJerome Glisse 	uint32_t ret = 0;
88771fe6b9SJerome Glisse 
89771fe6b9SJerome Glisse 	switch (supported_device) {
90771fe6b9SJerome Glisse 	case ATOM_DEVICE_CRT1_SUPPORT:
91771fe6b9SJerome Glisse 	case ATOM_DEVICE_TV1_SUPPORT:
92771fe6b9SJerome Glisse 	case ATOM_DEVICE_TV2_SUPPORT:
93771fe6b9SJerome Glisse 	case ATOM_DEVICE_CRT2_SUPPORT:
94771fe6b9SJerome Glisse 	case ATOM_DEVICE_CV_SUPPORT:
95771fe6b9SJerome Glisse 		switch (dac) {
96771fe6b9SJerome Glisse 		case 1: /* dac a */
97771fe6b9SJerome Glisse 			if ((rdev->family == CHIP_RS300) ||
98771fe6b9SJerome Glisse 			    (rdev->family == CHIP_RS400) ||
99771fe6b9SJerome Glisse 			    (rdev->family == CHIP_RS480))
100771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
101771fe6b9SJerome Glisse 			else if (ASIC_IS_AVIVO(rdev))
102771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
103771fe6b9SJerome Glisse 			else
104771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DAC1;
105771fe6b9SJerome Glisse 			break;
106771fe6b9SJerome Glisse 		case 2: /* dac b */
107771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
108771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
109771fe6b9SJerome Glisse 			else {
110771fe6b9SJerome Glisse 				/*if (rdev->family == CHIP_R200)
111771fe6b9SJerome Glisse 				  ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
112771fe6b9SJerome Glisse 				  else*/
113771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
114771fe6b9SJerome Glisse 			}
115771fe6b9SJerome Glisse 			break;
116771fe6b9SJerome Glisse 		case 3: /* external dac */
117771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
118771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
119771fe6b9SJerome Glisse 			else
120771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
121771fe6b9SJerome Glisse 			break;
122771fe6b9SJerome Glisse 		}
123771fe6b9SJerome Glisse 		break;
124771fe6b9SJerome Glisse 	case ATOM_DEVICE_LCD1_SUPPORT:
125771fe6b9SJerome Glisse 		if (ASIC_IS_AVIVO(rdev))
126771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
127771fe6b9SJerome Glisse 		else
128771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_LVDS;
129771fe6b9SJerome Glisse 		break;
130771fe6b9SJerome Glisse 	case ATOM_DEVICE_DFP1_SUPPORT:
131771fe6b9SJerome Glisse 		if ((rdev->family == CHIP_RS300) ||
132771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS400) ||
133771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS480))
134771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
135771fe6b9SJerome Glisse 		else if (ASIC_IS_AVIVO(rdev))
136771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
137771fe6b9SJerome Glisse 		else
138771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1;
139771fe6b9SJerome Glisse 		break;
140771fe6b9SJerome Glisse 	case ATOM_DEVICE_LCD2_SUPPORT:
141771fe6b9SJerome Glisse 	case ATOM_DEVICE_DFP2_SUPPORT:
142771fe6b9SJerome Glisse 		if ((rdev->family == CHIP_RS600) ||
143771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS690) ||
144771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS740))
145771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_DDI;
146771fe6b9SJerome Glisse 		else if (ASIC_IS_AVIVO(rdev))
147771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
148771fe6b9SJerome Glisse 		else
149771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
150771fe6b9SJerome Glisse 		break;
151771fe6b9SJerome Glisse 	case ATOM_DEVICE_DFP3_SUPPORT:
152771fe6b9SJerome Glisse 		ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
153771fe6b9SJerome Glisse 		break;
154771fe6b9SJerome Glisse 	}
155771fe6b9SJerome Glisse 
156771fe6b9SJerome Glisse 	return ret;
157771fe6b9SJerome Glisse }
158771fe6b9SJerome Glisse 
159771fe6b9SJerome Glisse void
160771fe6b9SJerome Glisse radeon_link_encoder_connector(struct drm_device *dev)
161771fe6b9SJerome Glisse {
162771fe6b9SJerome Glisse 	struct drm_connector *connector;
163771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
164771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
165771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder;
166771fe6b9SJerome Glisse 
167771fe6b9SJerome Glisse 	/* walk the list and link encoders to connectors */
168771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
169771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
170771fe6b9SJerome Glisse 		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
171771fe6b9SJerome Glisse 			radeon_encoder = to_radeon_encoder(encoder);
172771fe6b9SJerome Glisse 			if (radeon_encoder->devices & radeon_connector->devices)
173771fe6b9SJerome Glisse 				drm_mode_connector_attach_encoder(connector, encoder);
174771fe6b9SJerome Glisse 		}
175771fe6b9SJerome Glisse 	}
176771fe6b9SJerome Glisse }
177771fe6b9SJerome Glisse 
1784ce001abSDave Airlie void radeon_encoder_set_active_device(struct drm_encoder *encoder)
1794ce001abSDave Airlie {
1804ce001abSDave Airlie 	struct drm_device *dev = encoder->dev;
1814ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1824ce001abSDave Airlie 	struct drm_connector *connector;
1834ce001abSDave Airlie 
1844ce001abSDave Airlie 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1854ce001abSDave Airlie 		if (connector->encoder == encoder) {
1864ce001abSDave Airlie 			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1874ce001abSDave Airlie 			radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
188f641e51eSDave Airlie 			DRM_DEBUG("setting active device to %08x from %08x %08x for encoder %d\n",
1894ce001abSDave Airlie 				  radeon_encoder->active_device, radeon_encoder->devices,
1904ce001abSDave Airlie 				  radeon_connector->devices, encoder->encoder_type);
1914ce001abSDave Airlie 		}
1924ce001abSDave Airlie 	}
1934ce001abSDave Airlie }
1944ce001abSDave Airlie 
195771fe6b9SJerome Glisse static struct drm_connector *
196771fe6b9SJerome Glisse radeon_get_connector_for_encoder(struct drm_encoder *encoder)
197771fe6b9SJerome Glisse {
198771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
199771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
200771fe6b9SJerome Glisse 	struct drm_connector *connector;
201771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
202771fe6b9SJerome Glisse 
203771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
204771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
205*43c33ed8SDave Airlie 		if (radeon_encoder->active_device & radeon_connector->devices)
206771fe6b9SJerome Glisse 			return connector;
207771fe6b9SJerome Glisse 	}
208771fe6b9SJerome Glisse 	return NULL;
209771fe6b9SJerome Glisse }
210771fe6b9SJerome Glisse 
211771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
212771fe6b9SJerome Glisse 				   struct drm_display_mode *mode,
213771fe6b9SJerome Glisse 				   struct drm_display_mode *adjusted_mode)
214771fe6b9SJerome Glisse {
215771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2165a9bcaccSAlex Deucher 	struct drm_device *dev = encoder->dev;
2175a9bcaccSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
218771fe6b9SJerome Glisse 
2198c2a6d73SAlex Deucher 	/* set the active encoder to connector routing */
2208c2a6d73SAlex Deucher 	radeon_encoder_set_active_device(encoder);
221771fe6b9SJerome Glisse 	drm_mode_set_crtcinfo(adjusted_mode, 0);
222771fe6b9SJerome Glisse 
223771fe6b9SJerome Glisse 	/* hw bug */
224771fe6b9SJerome Glisse 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
225771fe6b9SJerome Glisse 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
226771fe6b9SJerome Glisse 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
227771fe6b9SJerome Glisse 
22880297e87SAlex Deucher 	/* get the native mode for LVDS */
22980297e87SAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
23080297e87SAlex Deucher 		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
23180297e87SAlex Deucher 		int mode_id = adjusted_mode->base.id;
23280297e87SAlex Deucher 		*adjusted_mode = *native_mode;
23380297e87SAlex Deucher 		if (!ASIC_IS_AVIVO(rdev)) {
23480297e87SAlex Deucher 			adjusted_mode->hdisplay = mode->hdisplay;
23580297e87SAlex Deucher 			adjusted_mode->vdisplay = mode->vdisplay;
236310a82c8SAlex Deucher 			adjusted_mode->crtc_hdisplay = mode->hdisplay;
237310a82c8SAlex Deucher 			adjusted_mode->crtc_vdisplay = mode->vdisplay;
23880297e87SAlex Deucher 		}
23980297e87SAlex Deucher 		adjusted_mode->base.id = mode_id;
24080297e87SAlex Deucher 	}
24180297e87SAlex Deucher 
24280297e87SAlex Deucher 	/* get the native mode for TV */
243ceefedd8SAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
2445a9bcaccSAlex Deucher 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
2455a9bcaccSAlex Deucher 		if (tv_dac) {
2465a9bcaccSAlex Deucher 			if (tv_dac->tv_std == TV_STD_NTSC ||
2475a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_NTSC_J ||
2485a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_PAL_M)
2495a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
2505a9bcaccSAlex Deucher 			else
2515a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
2525a9bcaccSAlex Deucher 		}
2535a9bcaccSAlex Deucher 	}
2545a9bcaccSAlex Deucher 
2555801ead6SAlex Deucher 	if (ASIC_IS_DCE3(rdev) &&
2565801ead6SAlex Deucher 	    (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) {
2575801ead6SAlex Deucher 		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
2585801ead6SAlex Deucher 		radeon_dp_set_link_config(connector, mode);
2595801ead6SAlex Deucher 	}
2605801ead6SAlex Deucher 
261771fe6b9SJerome Glisse 	return true;
262771fe6b9SJerome Glisse }
263771fe6b9SJerome Glisse 
264771fe6b9SJerome Glisse static void
265771fe6b9SJerome Glisse atombios_dac_setup(struct drm_encoder *encoder, int action)
266771fe6b9SJerome Glisse {
267771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
268771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
269771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
270771fe6b9SJerome Glisse 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
271771fe6b9SJerome Glisse 	int index = 0, num = 0;
272445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
273771fe6b9SJerome Glisse 	enum radeon_tv_std tv_std = TV_STD_NTSC;
274771fe6b9SJerome Glisse 
275445282dbSDave Airlie 	if (dac_info->tv_std)
276445282dbSDave Airlie 		tv_std = dac_info->tv_std;
277445282dbSDave Airlie 
278771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
279771fe6b9SJerome Glisse 
280771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
281771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
282771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
283771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
284771fe6b9SJerome Glisse 		num = 1;
285771fe6b9SJerome Glisse 		break;
286771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
287771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
288771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
289771fe6b9SJerome Glisse 		num = 2;
290771fe6b9SJerome Glisse 		break;
291771fe6b9SJerome Glisse 	}
292771fe6b9SJerome Glisse 
293771fe6b9SJerome Glisse 	args.ucAction = action;
294771fe6b9SJerome Glisse 
2954ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
296771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_PS2;
2974ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
298771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_CV;
299771fe6b9SJerome Glisse 	else {
300771fe6b9SJerome Glisse 		switch (tv_std) {
301771fe6b9SJerome Glisse 		case TV_STD_PAL:
302771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
303771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
304771fe6b9SJerome Glisse 		case TV_STD_SECAM:
305771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
306771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_PAL;
307771fe6b9SJerome Glisse 			break;
308771fe6b9SJerome Glisse 		case TV_STD_NTSC:
309771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
310771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
311771fe6b9SJerome Glisse 		default:
312771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_NTSC;
313771fe6b9SJerome Glisse 			break;
314771fe6b9SJerome Glisse 		}
315771fe6b9SJerome Glisse 	}
316771fe6b9SJerome Glisse 	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
317771fe6b9SJerome Glisse 
318771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
319771fe6b9SJerome Glisse 
320771fe6b9SJerome Glisse }
321771fe6b9SJerome Glisse 
322771fe6b9SJerome Glisse static void
323771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action)
324771fe6b9SJerome Glisse {
325771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
326771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
327771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
328771fe6b9SJerome Glisse 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
329771fe6b9SJerome Glisse 	int index = 0;
330445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
331771fe6b9SJerome Glisse 	enum radeon_tv_std tv_std = TV_STD_NTSC;
332771fe6b9SJerome Glisse 
333445282dbSDave Airlie 	if (dac_info->tv_std)
334445282dbSDave Airlie 		tv_std = dac_info->tv_std;
335445282dbSDave Airlie 
336771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
337771fe6b9SJerome Glisse 
338771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
339771fe6b9SJerome Glisse 
340771fe6b9SJerome Glisse 	args.sTVEncoder.ucAction = action;
341771fe6b9SJerome Glisse 
3424ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
343771fe6b9SJerome Glisse 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
344771fe6b9SJerome Glisse 	else {
345771fe6b9SJerome Glisse 		switch (tv_std) {
346771fe6b9SJerome Glisse 		case TV_STD_NTSC:
347771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
348771fe6b9SJerome Glisse 			break;
349771fe6b9SJerome Glisse 		case TV_STD_PAL:
350771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
351771fe6b9SJerome Glisse 			break;
352771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
353771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
354771fe6b9SJerome Glisse 			break;
355771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
356771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
357771fe6b9SJerome Glisse 			break;
358771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
359771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
360771fe6b9SJerome Glisse 			break;
361771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
362771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
363771fe6b9SJerome Glisse 			break;
364771fe6b9SJerome Glisse 		case TV_STD_SECAM:
365771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
366771fe6b9SJerome Glisse 			break;
367771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
368771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
369771fe6b9SJerome Glisse 			break;
370771fe6b9SJerome Glisse 		default:
371771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
372771fe6b9SJerome Glisse 			break;
373771fe6b9SJerome Glisse 		}
374771fe6b9SJerome Glisse 	}
375771fe6b9SJerome Glisse 
376771fe6b9SJerome Glisse 	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
377771fe6b9SJerome Glisse 
378771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
379771fe6b9SJerome Glisse 
380771fe6b9SJerome Glisse }
381771fe6b9SJerome Glisse 
382771fe6b9SJerome Glisse void
383771fe6b9SJerome Glisse atombios_external_tmds_setup(struct drm_encoder *encoder, int action)
384771fe6b9SJerome Glisse {
385771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
386771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
387771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
388771fe6b9SJerome Glisse 	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args;
389771fe6b9SJerome Glisse 	int index = 0;
390771fe6b9SJerome Glisse 
391771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
392771fe6b9SJerome Glisse 
393771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
394771fe6b9SJerome Glisse 
395771fe6b9SJerome Glisse 	args.sXTmdsEncoder.ucEnable = action;
396771fe6b9SJerome Glisse 
397771fe6b9SJerome Glisse 	if (radeon_encoder->pixel_clock > 165000)
398771fe6b9SJerome Glisse 		args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
399771fe6b9SJerome Glisse 
400771fe6b9SJerome Glisse 	/*if (pScrn->rgbBits == 8)*/
401771fe6b9SJerome Glisse 	args.sXTmdsEncoder.ucMisc |= (1 << 1);
402771fe6b9SJerome Glisse 
403771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
404771fe6b9SJerome Glisse 
405771fe6b9SJerome Glisse }
406771fe6b9SJerome Glisse 
407771fe6b9SJerome Glisse static void
408771fe6b9SJerome Glisse atombios_ddia_setup(struct drm_encoder *encoder, int action)
409771fe6b9SJerome Glisse {
410771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
411771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
412771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
413771fe6b9SJerome Glisse 	DVO_ENCODER_CONTROL_PS_ALLOCATION args;
414771fe6b9SJerome Glisse 	int index = 0;
415771fe6b9SJerome Glisse 
416771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
417771fe6b9SJerome Glisse 
418771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
419771fe6b9SJerome Glisse 
420771fe6b9SJerome Glisse 	args.sDVOEncoder.ucAction = action;
421771fe6b9SJerome Glisse 	args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
422771fe6b9SJerome Glisse 
423771fe6b9SJerome Glisse 	if (radeon_encoder->pixel_clock > 165000)
424771fe6b9SJerome Glisse 		args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
425771fe6b9SJerome Glisse 
426771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
427771fe6b9SJerome Glisse 
428771fe6b9SJerome Glisse }
429771fe6b9SJerome Glisse 
430771fe6b9SJerome Glisse union lvds_encoder_control {
431771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
432771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
433771fe6b9SJerome Glisse };
434771fe6b9SJerome Glisse 
43532f48ffeSAlex Deucher void
436771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action)
437771fe6b9SJerome Glisse {
438771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
439771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
440771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
441771fe6b9SJerome Glisse 	union lvds_encoder_control args;
442771fe6b9SJerome Glisse 	int index = 0;
443dafc3bd5SChristian Koenig 	int hdmi_detected = 0;
444771fe6b9SJerome Glisse 	uint8_t frev, crev;
445771fe6b9SJerome Glisse 	struct radeon_encoder_atom_dig *dig;
446771fe6b9SJerome Glisse 	struct drm_connector *connector;
447771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
448771fe6b9SJerome Glisse 	struct radeon_connector_atom_dig *dig_connector;
449771fe6b9SJerome Glisse 
450771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
451771fe6b9SJerome Glisse 	if (!connector)
452771fe6b9SJerome Glisse 		return;
453771fe6b9SJerome Glisse 
454771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
455771fe6b9SJerome Glisse 
456771fe6b9SJerome Glisse 	if (!radeon_encoder->enc_priv)
457771fe6b9SJerome Glisse 		return;
458771fe6b9SJerome Glisse 
459771fe6b9SJerome Glisse 	dig = radeon_encoder->enc_priv;
460771fe6b9SJerome Glisse 
461771fe6b9SJerome Glisse 	if (!radeon_connector->con_priv)
462771fe6b9SJerome Glisse 		return;
463771fe6b9SJerome Glisse 
464dafc3bd5SChristian Koenig 	if (drm_detect_hdmi_monitor(radeon_connector->edid))
465dafc3bd5SChristian Koenig 		hdmi_detected = 1;
466dafc3bd5SChristian Koenig 
467771fe6b9SJerome Glisse 	dig_connector = radeon_connector->con_priv;
468771fe6b9SJerome Glisse 
469771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
470771fe6b9SJerome Glisse 
471771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
472771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
473771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
474771fe6b9SJerome Glisse 		break;
475771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
476771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
477771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
478771fe6b9SJerome Glisse 		break;
479771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
480771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
481771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
482771fe6b9SJerome Glisse 		else
483771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
484771fe6b9SJerome Glisse 		break;
485771fe6b9SJerome Glisse 	}
486771fe6b9SJerome Glisse 
487771fe6b9SJerome Glisse 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
488771fe6b9SJerome Glisse 
489771fe6b9SJerome Glisse 	switch (frev) {
490771fe6b9SJerome Glisse 	case 1:
491771fe6b9SJerome Glisse 	case 2:
492771fe6b9SJerome Glisse 		switch (crev) {
493771fe6b9SJerome Glisse 		case 1:
494771fe6b9SJerome Glisse 			args.v1.ucMisc = 0;
495771fe6b9SJerome Glisse 			args.v1.ucAction = action;
496dafc3bd5SChristian Koenig 			if (hdmi_detected)
497771fe6b9SJerome Glisse 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
498771fe6b9SJerome Glisse 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
499771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
500edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
501771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
502edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
503771fe6b9SJerome Glisse 					args.v1.ucMisc |= (1 << 1);
504771fe6b9SJerome Glisse 			} else {
505771fe6b9SJerome Glisse 				if (dig_connector->linkb)
506771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
507771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
508771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
509771fe6b9SJerome Glisse 				/*if (pScrn->rgbBits == 8) */
510771fe6b9SJerome Glisse 				args.v1.ucMisc |= (1 << 1);
511771fe6b9SJerome Glisse 			}
512771fe6b9SJerome Glisse 			break;
513771fe6b9SJerome Glisse 		case 2:
514771fe6b9SJerome Glisse 		case 3:
515771fe6b9SJerome Glisse 			args.v2.ucMisc = 0;
516771fe6b9SJerome Glisse 			args.v2.ucAction = action;
517771fe6b9SJerome Glisse 			if (crev == 3) {
518771fe6b9SJerome Glisse 				if (dig->coherent_mode)
519771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
520771fe6b9SJerome Glisse 			}
521dafc3bd5SChristian Koenig 			if (hdmi_detected)
522771fe6b9SJerome Glisse 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
523771fe6b9SJerome Glisse 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
524771fe6b9SJerome Glisse 			args.v2.ucTruncate = 0;
525771fe6b9SJerome Glisse 			args.v2.ucSpatial = 0;
526771fe6b9SJerome Glisse 			args.v2.ucTemporal = 0;
527771fe6b9SJerome Glisse 			args.v2.ucFRC = 0;
528771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
529edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
530771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
531edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) {
532771fe6b9SJerome Glisse 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
533edc664e3SAlex Deucher 					if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
534771fe6b9SJerome Glisse 						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
535771fe6b9SJerome Glisse 				}
536edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) {
537771fe6b9SJerome Glisse 					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
538edc664e3SAlex Deucher 					if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
539771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
540edc664e3SAlex Deucher 					if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
541771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
542771fe6b9SJerome Glisse 				}
543771fe6b9SJerome Glisse 			} else {
544771fe6b9SJerome Glisse 				if (dig_connector->linkb)
545771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
546771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
547771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
548771fe6b9SJerome Glisse 			}
549771fe6b9SJerome Glisse 			break;
550771fe6b9SJerome Glisse 		default:
551771fe6b9SJerome Glisse 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
552771fe6b9SJerome Glisse 			break;
553771fe6b9SJerome Glisse 		}
554771fe6b9SJerome Glisse 		break;
555771fe6b9SJerome Glisse 	default:
556771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
557771fe6b9SJerome Glisse 		break;
558771fe6b9SJerome Glisse 	}
559771fe6b9SJerome Glisse 
560771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
561dafc3bd5SChristian Koenig 	r600_hdmi_enable(encoder, hdmi_detected);
562771fe6b9SJerome Glisse }
563771fe6b9SJerome Glisse 
564771fe6b9SJerome Glisse int
565771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder)
566771fe6b9SJerome Glisse {
567771fe6b9SJerome Glisse 	struct drm_connector *connector;
568771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
569f92a8b67SAlex Deucher 	struct radeon_connector_atom_dig *radeon_dig_connector;
570771fe6b9SJerome Glisse 
571771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
572771fe6b9SJerome Glisse 	if (!connector)
573771fe6b9SJerome Glisse 		return 0;
574771fe6b9SJerome Glisse 
575771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
576771fe6b9SJerome Glisse 
577771fe6b9SJerome Glisse 	switch (connector->connector_type) {
578771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVII:
579705af9c7SAlex Deucher 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
5800294cf4fSAlex Deucher 		if (drm_detect_hdmi_monitor(radeon_connector->edid))
581771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_HDMI;
582771fe6b9SJerome Glisse 		else if (radeon_connector->use_digital)
583771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
584771fe6b9SJerome Glisse 		else
585771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_CRT;
586771fe6b9SJerome Glisse 		break;
587771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVID:
588771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_HDMIA:
589771fe6b9SJerome Glisse 	default:
5900294cf4fSAlex Deucher 		if (drm_detect_hdmi_monitor(radeon_connector->edid))
591771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_HDMI;
592771fe6b9SJerome Glisse 		else
593771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
594771fe6b9SJerome Glisse 		break;
595771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_LVDS:
596771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_LVDS;
597771fe6b9SJerome Glisse 		break;
598771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DisplayPort:
599196c58d2SAlex Deucher 	case DRM_MODE_CONNECTOR_eDP:
600f92a8b67SAlex Deucher 		radeon_dig_connector = radeon_connector->con_priv;
601196c58d2SAlex Deucher 		if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
602196c58d2SAlex Deucher 		    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
603771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DP;
604f92a8b67SAlex Deucher 		else if (drm_detect_hdmi_monitor(radeon_connector->edid))
605771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_HDMI;
606771fe6b9SJerome Glisse 		else
607771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
608771fe6b9SJerome Glisse 		break;
609a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_DVIA:
610a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_VGA:
611771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_CRT;
612771fe6b9SJerome Glisse 		break;
613a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_Composite:
614a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_SVIDEO:
615a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_9PinDIN:
616771fe6b9SJerome Glisse 		/* fix me */
617771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_TV;
618771fe6b9SJerome Glisse 		/*return ATOM_ENCODER_MODE_CV;*/
619771fe6b9SJerome Glisse 		break;
620771fe6b9SJerome Glisse 	}
621771fe6b9SJerome Glisse }
622771fe6b9SJerome Glisse 
6231a66c95aSAlex Deucher /*
6241a66c95aSAlex Deucher  * DIG Encoder/Transmitter Setup
6251a66c95aSAlex Deucher  *
6261a66c95aSAlex Deucher  * DCE 3.0/3.1
6271a66c95aSAlex Deucher  * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
6281a66c95aSAlex Deucher  * Supports up to 3 digital outputs
6291a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
6301a66c95aSAlex Deucher  * DIG1 can drive UNIPHY link A or link B
6311a66c95aSAlex Deucher  * DIG2 can drive UNIPHY link B or LVTMA
6321a66c95aSAlex Deucher  *
6331a66c95aSAlex Deucher  * DCE 3.2
6341a66c95aSAlex Deucher  * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
6351a66c95aSAlex Deucher  * Supports up to 5 digital outputs
6361a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
6371a66c95aSAlex Deucher  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
6381a66c95aSAlex Deucher  *
6391a66c95aSAlex Deucher  * Routing
6401a66c95aSAlex Deucher  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
6411a66c95aSAlex Deucher  * Examples:
6421a66c95aSAlex Deucher  * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
6431a66c95aSAlex Deucher  * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
6441a66c95aSAlex Deucher  * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
6451a66c95aSAlex Deucher  * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
6461a66c95aSAlex Deucher  */
647771fe6b9SJerome Glisse static void
648771fe6b9SJerome Glisse atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
649771fe6b9SJerome Glisse {
650771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
651771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
652771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
653771fe6b9SJerome Glisse 	DIG_ENCODER_CONTROL_PS_ALLOCATION args;
654771fe6b9SJerome Glisse 	int index = 0, num = 0;
655771fe6b9SJerome Glisse 	uint8_t frev, crev;
656771fe6b9SJerome Glisse 	struct radeon_encoder_atom_dig *dig;
657771fe6b9SJerome Glisse 	struct drm_connector *connector;
658771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
659771fe6b9SJerome Glisse 	struct radeon_connector_atom_dig *dig_connector;
660771fe6b9SJerome Glisse 
661771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
662771fe6b9SJerome Glisse 	if (!connector)
663771fe6b9SJerome Glisse 		return;
664771fe6b9SJerome Glisse 
665771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
666771fe6b9SJerome Glisse 
667771fe6b9SJerome Glisse 	if (!radeon_connector->con_priv)
668771fe6b9SJerome Glisse 		return;
669771fe6b9SJerome Glisse 
670771fe6b9SJerome Glisse 	dig_connector = radeon_connector->con_priv;
671771fe6b9SJerome Glisse 
672771fe6b9SJerome Glisse 	if (!radeon_encoder->enc_priv)
673771fe6b9SJerome Glisse 		return;
674771fe6b9SJerome Glisse 
675771fe6b9SJerome Glisse 	dig = radeon_encoder->enc_priv;
676771fe6b9SJerome Glisse 
677771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
678771fe6b9SJerome Glisse 
679771fe6b9SJerome Glisse 	if (ASIC_IS_DCE32(rdev)) {
680771fe6b9SJerome Glisse 		if (dig->dig_block)
681771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
682771fe6b9SJerome Glisse 		else
683771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
684771fe6b9SJerome Glisse 		num = dig->dig_block + 1;
685771fe6b9SJerome Glisse 	} else {
686771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
687771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
6881a66c95aSAlex Deucher 			/* XXX doesn't really matter which dig encoder we pick as long as it's
6891a66c95aSAlex Deucher 			 * not already in use
6901a66c95aSAlex Deucher 			 */
6911a66c95aSAlex Deucher 			if (dig_connector->linkb)
6921a66c95aSAlex Deucher 				index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
6931a66c95aSAlex Deucher 			else
694771fe6b9SJerome Glisse 				index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
695771fe6b9SJerome Glisse 			num = 1;
696771fe6b9SJerome Glisse 			break;
697771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
6981a66c95aSAlex Deucher 			/* Only dig2 encoder can drive LVTMA */
699771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
700771fe6b9SJerome Glisse 			num = 2;
701771fe6b9SJerome Glisse 			break;
702771fe6b9SJerome Glisse 		}
703771fe6b9SJerome Glisse 	}
704771fe6b9SJerome Glisse 
705771fe6b9SJerome Glisse 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
706771fe6b9SJerome Glisse 
707771fe6b9SJerome Glisse 	args.ucAction = action;
708771fe6b9SJerome Glisse 	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
709771fe6b9SJerome Glisse 
710771fe6b9SJerome Glisse 	if (ASIC_IS_DCE32(rdev)) {
711771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
712771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
713771fe6b9SJerome Glisse 			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
714771fe6b9SJerome Glisse 			break;
715771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
716771fe6b9SJerome Glisse 			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
717771fe6b9SJerome Glisse 			break;
718771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
719771fe6b9SJerome Glisse 			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
720771fe6b9SJerome Glisse 			break;
721771fe6b9SJerome Glisse 		}
722771fe6b9SJerome Glisse 	} else {
723771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
724771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
725771fe6b9SJerome Glisse 			args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
726771fe6b9SJerome Glisse 			break;
727771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
728771fe6b9SJerome Glisse 			args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2;
729771fe6b9SJerome Glisse 			break;
730771fe6b9SJerome Glisse 		}
731771fe6b9SJerome Glisse 	}
732771fe6b9SJerome Glisse 
733f92a8b67SAlex Deucher 	args.ucEncoderMode = atombios_get_encoder_mode(encoder);
734f92a8b67SAlex Deucher 
735f92a8b67SAlex Deucher 	if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
7365801ead6SAlex Deucher 		if (dig_connector->dp_clock == 270000)
737f92a8b67SAlex Deucher 			args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
7385801ead6SAlex Deucher 		args.ucLaneNum = dig_connector->dp_lane_count;
739f92a8b67SAlex Deucher 	} else if (radeon_encoder->pixel_clock > 165000)
740771fe6b9SJerome Glisse 		args.ucLaneNum = 8;
7411a66c95aSAlex Deucher 	else
7421a66c95aSAlex Deucher 		args.ucLaneNum = 4;
7431a66c95aSAlex Deucher 
744771fe6b9SJerome Glisse 	if (dig_connector->linkb)
745771fe6b9SJerome Glisse 		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
746771fe6b9SJerome Glisse 	else
747771fe6b9SJerome Glisse 		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
748771fe6b9SJerome Glisse 
749771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
750771fe6b9SJerome Glisse 
751771fe6b9SJerome Glisse }
752771fe6b9SJerome Glisse 
753771fe6b9SJerome Glisse union dig_transmitter_control {
754771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
755771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
756771fe6b9SJerome Glisse };
757771fe6b9SJerome Glisse 
7585801ead6SAlex Deucher void
7591a66c95aSAlex Deucher atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
760771fe6b9SJerome Glisse {
761771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
762771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
763771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
764771fe6b9SJerome Glisse 	union dig_transmitter_control args;
765771fe6b9SJerome Glisse 	int index = 0, num = 0;
766771fe6b9SJerome Glisse 	uint8_t frev, crev;
767771fe6b9SJerome Glisse 	struct radeon_encoder_atom_dig *dig;
768771fe6b9SJerome Glisse 	struct drm_connector *connector;
769771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
770771fe6b9SJerome Glisse 	struct radeon_connector_atom_dig *dig_connector;
771f92a8b67SAlex Deucher 	bool is_dp = false;
772771fe6b9SJerome Glisse 
773771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
774771fe6b9SJerome Glisse 	if (!connector)
775771fe6b9SJerome Glisse 		return;
776771fe6b9SJerome Glisse 
777771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
778771fe6b9SJerome Glisse 
779771fe6b9SJerome Glisse 	if (!radeon_encoder->enc_priv)
780771fe6b9SJerome Glisse 		return;
781771fe6b9SJerome Glisse 
782771fe6b9SJerome Glisse 	dig = radeon_encoder->enc_priv;
783771fe6b9SJerome Glisse 
784771fe6b9SJerome Glisse 	if (!radeon_connector->con_priv)
785771fe6b9SJerome Glisse 		return;
786771fe6b9SJerome Glisse 
787771fe6b9SJerome Glisse 	dig_connector = radeon_connector->con_priv;
788771fe6b9SJerome Glisse 
789f92a8b67SAlex Deucher 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
790f92a8b67SAlex Deucher 		is_dp = true;
791f92a8b67SAlex Deucher 
792771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
793771fe6b9SJerome Glisse 
794771fe6b9SJerome Glisse 	if (ASIC_IS_DCE32(rdev))
795771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
796771fe6b9SJerome Glisse 	else {
797771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
798771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
799771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
800771fe6b9SJerome Glisse 			break;
801771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
802771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
803771fe6b9SJerome Glisse 			break;
804771fe6b9SJerome Glisse 		}
805771fe6b9SJerome Glisse 	}
806771fe6b9SJerome Glisse 
807771fe6b9SJerome Glisse 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
808771fe6b9SJerome Glisse 
809771fe6b9SJerome Glisse 	args.v1.ucAction = action;
810f95a9f0bSAlex Deucher 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
811f95a9f0bSAlex Deucher 		args.v1.usInitInfo = radeon_connector->connector_object_id;
8121a66c95aSAlex Deucher 	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
8131a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSel = lane_num;
8141a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSet = lane_set;
815771fe6b9SJerome Glisse 	} else {
816f92a8b67SAlex Deucher 		if (is_dp)
817f92a8b67SAlex Deucher 			args.v1.usPixelClock =
8185801ead6SAlex Deucher 				cpu_to_le16(dig_connector->dp_clock / 10);
819f92a8b67SAlex Deucher 		else if (radeon_encoder->pixel_clock > 165000)
820f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
821f95a9f0bSAlex Deucher 		else
822f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
823771fe6b9SJerome Glisse 	}
824f95a9f0bSAlex Deucher 	if (ASIC_IS_DCE32(rdev)) {
825771fe6b9SJerome Glisse 		if (dig->dig_block)
826771fe6b9SJerome Glisse 			args.v2.acConfig.ucEncoderSel = 1;
8271a66c95aSAlex Deucher 		if (dig_connector->linkb)
8281a66c95aSAlex Deucher 			args.v2.acConfig.ucLinkSel = 1;
829771fe6b9SJerome Glisse 
830771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
831771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
832771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 0;
833771fe6b9SJerome Glisse 			num = 0;
834771fe6b9SJerome Glisse 			break;
835771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
836771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 1;
837771fe6b9SJerome Glisse 			num = 1;
838771fe6b9SJerome Glisse 			break;
839771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
840771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 2;
841771fe6b9SJerome Glisse 			num = 2;
842771fe6b9SJerome Glisse 			break;
843771fe6b9SJerome Glisse 		}
844771fe6b9SJerome Glisse 
845f92a8b67SAlex Deucher 		if (is_dp)
846f92a8b67SAlex Deucher 			args.v2.acConfig.fCoherentMode = 1;
847f92a8b67SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
848771fe6b9SJerome Glisse 			if (dig->coherent_mode)
849771fe6b9SJerome Glisse 				args.v2.acConfig.fCoherentMode = 1;
850771fe6b9SJerome Glisse 		}
851771fe6b9SJerome Glisse 	} else {
852771fe6b9SJerome Glisse 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
853771fe6b9SJerome Glisse 
854771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
855771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
8561a66c95aSAlex Deucher 			/* XXX doesn't really matter which dig encoder we pick as long as it's
8571a66c95aSAlex Deucher 			 * not already in use
8581a66c95aSAlex Deucher 			 */
8591a66c95aSAlex Deucher 			if (dig_connector->linkb)
8601a66c95aSAlex Deucher 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
8611a66c95aSAlex Deucher 			else
862771fe6b9SJerome Glisse 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
863771fe6b9SJerome Glisse 			if (rdev->flags & RADEON_IS_IGP) {
864771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000) {
865771fe6b9SJerome Glisse 					if (dig_connector->igp_lane_info & 0x3)
866771fe6b9SJerome Glisse 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
867771fe6b9SJerome Glisse 					else if (dig_connector->igp_lane_info & 0xc)
868771fe6b9SJerome Glisse 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
869771fe6b9SJerome Glisse 				} else {
870771fe6b9SJerome Glisse 					if (dig_connector->igp_lane_info & 0x1)
871771fe6b9SJerome Glisse 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
872771fe6b9SJerome Glisse 					else if (dig_connector->igp_lane_info & 0x2)
873771fe6b9SJerome Glisse 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
874771fe6b9SJerome Glisse 					else if (dig_connector->igp_lane_info & 0x4)
875771fe6b9SJerome Glisse 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
876771fe6b9SJerome Glisse 					else if (dig_connector->igp_lane_info & 0x8)
877771fe6b9SJerome Glisse 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
878771fe6b9SJerome Glisse 				}
879771fe6b9SJerome Glisse 			}
880771fe6b9SJerome Glisse 			break;
881771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
8821a66c95aSAlex Deucher 			/* Only dig2 encoder can drive LVTMA */
883771fe6b9SJerome Glisse 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
884771fe6b9SJerome Glisse 			break;
885771fe6b9SJerome Glisse 		}
886771fe6b9SJerome Glisse 
8871a66c95aSAlex Deucher 		if (radeon_encoder->pixel_clock > 165000)
8881a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
8891a66c95aSAlex Deucher 
8901a66c95aSAlex Deucher 		if (dig_connector->linkb)
8911a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
8921a66c95aSAlex Deucher 		else
8931a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
8941a66c95aSAlex Deucher 
895f92a8b67SAlex Deucher 		if (is_dp)
896f92a8b67SAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
897f92a8b67SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
898771fe6b9SJerome Glisse 			if (dig->coherent_mode)
899771fe6b9SJerome Glisse 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
900771fe6b9SJerome Glisse 		}
901771fe6b9SJerome Glisse 	}
902771fe6b9SJerome Glisse 
903771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
904771fe6b9SJerome Glisse }
905771fe6b9SJerome Glisse 
906771fe6b9SJerome Glisse static void
907771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
908771fe6b9SJerome Glisse {
909771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
910771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
911771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
912771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
913771fe6b9SJerome Glisse 	ENABLE_YUV_PS_ALLOCATION args;
914771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
915771fe6b9SJerome Glisse 	uint32_t temp, reg;
916771fe6b9SJerome Glisse 
917771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
918771fe6b9SJerome Glisse 
919771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
920771fe6b9SJerome Glisse 		reg = R600_BIOS_3_SCRATCH;
921771fe6b9SJerome Glisse 	else
922771fe6b9SJerome Glisse 		reg = RADEON_BIOS_3_SCRATCH;
923771fe6b9SJerome Glisse 
924771fe6b9SJerome Glisse 	/* XXX: fix up scratch reg handling */
925771fe6b9SJerome Glisse 	temp = RREG32(reg);
9264ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
927771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
928771fe6b9SJerome Glisse 			     (radeon_crtc->crtc_id << 18)));
9294ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
930771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
931771fe6b9SJerome Glisse 	else
932771fe6b9SJerome Glisse 		WREG32(reg, 0);
933771fe6b9SJerome Glisse 
934771fe6b9SJerome Glisse 	if (enable)
935771fe6b9SJerome Glisse 		args.ucEnable = ATOM_ENABLE;
936771fe6b9SJerome Glisse 	args.ucCRTC = radeon_crtc->crtc_id;
937771fe6b9SJerome Glisse 
938771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
939771fe6b9SJerome Glisse 
940771fe6b9SJerome Glisse 	WREG32(reg, temp);
941771fe6b9SJerome Glisse }
942771fe6b9SJerome Glisse 
943771fe6b9SJerome Glisse static void
944771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
945771fe6b9SJerome Glisse {
946771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
947771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
948771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
949771fe6b9SJerome Glisse 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
950771fe6b9SJerome Glisse 	int index = 0;
951771fe6b9SJerome Glisse 	bool is_dig = false;
952771fe6b9SJerome Glisse 
953771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
954771fe6b9SJerome Glisse 
955f641e51eSDave Airlie 	DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
9564ce001abSDave Airlie 		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
9574ce001abSDave Airlie 		  radeon_encoder->active_device);
958771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
959771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
960771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
961771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
962771fe6b9SJerome Glisse 		break;
963771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
964771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
965771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
966771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
967771fe6b9SJerome Glisse 		is_dig = true;
968771fe6b9SJerome Glisse 		break;
969771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
970771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
971771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
972771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
973771fe6b9SJerome Glisse 		break;
974771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
975771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
976771fe6b9SJerome Glisse 		break;
977771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
978771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
979771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
980771fe6b9SJerome Glisse 		else
981771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
982771fe6b9SJerome Glisse 		break;
983771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
984771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
9858c2a6d73SAlex Deucher 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
986771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
9878c2a6d73SAlex Deucher 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
988771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
989771fe6b9SJerome Glisse 		else
990771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
991771fe6b9SJerome Glisse 		break;
992771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
993771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
9948c2a6d73SAlex Deucher 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
995771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
9968c2a6d73SAlex Deucher 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
997771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
998771fe6b9SJerome Glisse 		else
999771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1000771fe6b9SJerome Glisse 		break;
1001771fe6b9SJerome Glisse 	}
1002771fe6b9SJerome Glisse 
1003771fe6b9SJerome Glisse 	if (is_dig) {
1004771fe6b9SJerome Glisse 		switch (mode) {
1005771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
100658682f10SDave Airlie 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
100758682f10SDave Airlie 			{
100858682f10SDave Airlie 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
100958682f10SDave Airlie 				dp_link_train(encoder, connector);
101058682f10SDave Airlie 			}
1011771fe6b9SJerome Glisse 			break;
1012771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1013771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1014771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
101558682f10SDave Airlie 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
1016771fe6b9SJerome Glisse 			break;
1017771fe6b9SJerome Glisse 		}
1018771fe6b9SJerome Glisse 	} else {
1019771fe6b9SJerome Glisse 		switch (mode) {
1020771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
1021771fe6b9SJerome Glisse 			args.ucAction = ATOM_ENABLE;
1022771fe6b9SJerome Glisse 			break;
1023771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1024771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1025771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
1026771fe6b9SJerome Glisse 			args.ucAction = ATOM_DISABLE;
1027771fe6b9SJerome Glisse 			break;
1028771fe6b9SJerome Glisse 		}
1029771fe6b9SJerome Glisse 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1030771fe6b9SJerome Glisse 	}
1031771fe6b9SJerome Glisse 	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1032771fe6b9SJerome Glisse }
1033771fe6b9SJerome Glisse 
1034771fe6b9SJerome Glisse union crtc_sourc_param {
1035771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
1036771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
1037771fe6b9SJerome Glisse };
1038771fe6b9SJerome Glisse 
1039771fe6b9SJerome Glisse static void
1040771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
1041771fe6b9SJerome Glisse {
1042771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1043771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1044771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1045771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1046771fe6b9SJerome Glisse 	union crtc_sourc_param args;
1047771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1048771fe6b9SJerome Glisse 	uint8_t frev, crev;
1049771fe6b9SJerome Glisse 
1050771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1051771fe6b9SJerome Glisse 
1052771fe6b9SJerome Glisse 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
1053771fe6b9SJerome Glisse 
1054771fe6b9SJerome Glisse 	switch (frev) {
1055771fe6b9SJerome Glisse 	case 1:
1056771fe6b9SJerome Glisse 		switch (crev) {
1057771fe6b9SJerome Glisse 		case 1:
1058771fe6b9SJerome Glisse 		default:
1059771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
1060771fe6b9SJerome Glisse 				args.v1.ucCRTC = radeon_crtc->crtc_id;
1061771fe6b9SJerome Glisse 			else {
1062771fe6b9SJerome Glisse 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
1063771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id;
1064771fe6b9SJerome Glisse 				} else {
1065771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
1066771fe6b9SJerome Glisse 				}
1067771fe6b9SJerome Glisse 			}
1068771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1069771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1070771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1071771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1072771fe6b9SJerome Glisse 				break;
1073771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1074771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1075771fe6b9SJerome Glisse 				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
1076771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1077771fe6b9SJerome Glisse 				else
1078771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1079771fe6b9SJerome Glisse 				break;
1080771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1081771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DDI:
1082771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1083771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1084771fe6b9SJerome Glisse 				break;
1085771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1086771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
10874ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1088771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
10894ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1090771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1091771fe6b9SJerome Glisse 				else
1092771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1093771fe6b9SJerome Glisse 				break;
1094771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1095771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
10964ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1097771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
10984ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1099771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1100771fe6b9SJerome Glisse 				else
1101771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1102771fe6b9SJerome Glisse 				break;
1103771fe6b9SJerome Glisse 			}
1104771fe6b9SJerome Glisse 			break;
1105771fe6b9SJerome Glisse 		case 2:
1106771fe6b9SJerome Glisse 			args.v2.ucCRTC = radeon_crtc->crtc_id;
1107771fe6b9SJerome Glisse 			args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1108771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1109771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1110771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1111771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1112771fe6b9SJerome Glisse 				if (ASIC_IS_DCE32(rdev)) {
1113771fe6b9SJerome Glisse 					if (radeon_crtc->crtc_id)
1114771fe6b9SJerome Glisse 						args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1115771fe6b9SJerome Glisse 					else
1116771fe6b9SJerome Glisse 						args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
11171a66c95aSAlex Deucher 				} else {
11181a66c95aSAlex Deucher 					struct drm_connector *connector;
11191a66c95aSAlex Deucher 					struct radeon_connector *radeon_connector;
11201a66c95aSAlex Deucher 					struct radeon_connector_atom_dig *dig_connector;
11211a66c95aSAlex Deucher 
11221a66c95aSAlex Deucher 					connector = radeon_get_connector_for_encoder(encoder);
11231a66c95aSAlex Deucher 					if (!connector)
11241a66c95aSAlex Deucher 						return;
11251a66c95aSAlex Deucher 					radeon_connector = to_radeon_connector(connector);
11261a66c95aSAlex Deucher 					if (!radeon_connector->con_priv)
11271a66c95aSAlex Deucher 						return;
11281a66c95aSAlex Deucher 					dig_connector = radeon_connector->con_priv;
11291a66c95aSAlex Deucher 
11301a66c95aSAlex Deucher 					/* XXX doesn't really matter which dig encoder we pick as long as it's
11311a66c95aSAlex Deucher 					 * not already in use
11321a66c95aSAlex Deucher 					 */
11331a66c95aSAlex Deucher 					if (dig_connector->linkb)
11341a66c95aSAlex Deucher 						args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
11351a66c95aSAlex Deucher 					else
1136771fe6b9SJerome Glisse 						args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
11371a66c95aSAlex Deucher 				}
1138771fe6b9SJerome Glisse 				break;
1139771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1140771fe6b9SJerome Glisse 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
1141771fe6b9SJerome Glisse 				break;
1142771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
11431a66c95aSAlex Deucher 				/* Only dig2 encoder can drive LVTMA */
1144771fe6b9SJerome Glisse 				args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1145771fe6b9SJerome Glisse 				break;
1146771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
11474ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1148771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
11494ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1150771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1151771fe6b9SJerome Glisse 				else
1152771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1153771fe6b9SJerome Glisse 				break;
1154771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
11554ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1156771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
11574ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1158771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1159771fe6b9SJerome Glisse 				else
1160771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1161771fe6b9SJerome Glisse 				break;
1162771fe6b9SJerome Glisse 			}
1163771fe6b9SJerome Glisse 			break;
1164771fe6b9SJerome Glisse 		}
1165771fe6b9SJerome Glisse 		break;
1166771fe6b9SJerome Glisse 	default:
1167771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1168771fe6b9SJerome Glisse 		break;
1169771fe6b9SJerome Glisse 	}
1170771fe6b9SJerome Glisse 
1171771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1172771fe6b9SJerome Glisse }
1173771fe6b9SJerome Glisse 
1174771fe6b9SJerome Glisse static void
1175771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder,
1176771fe6b9SJerome Glisse 			      struct drm_display_mode *mode)
1177771fe6b9SJerome Glisse {
1178771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1179771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1180771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1181771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1182771fe6b9SJerome Glisse 
1183771fe6b9SJerome Glisse 	/* Funky macbooks */
1184771fe6b9SJerome Glisse 	if ((dev->pdev->device == 0x71C5) &&
1185771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_vendor == 0x106b) &&
1186771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_device == 0x0080)) {
1187771fe6b9SJerome Glisse 		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1188771fe6b9SJerome Glisse 			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1189771fe6b9SJerome Glisse 
1190771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1191771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1192771fe6b9SJerome Glisse 
1193771fe6b9SJerome Glisse 			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1194771fe6b9SJerome Glisse 		}
1195771fe6b9SJerome Glisse 	}
1196771fe6b9SJerome Glisse 
1197771fe6b9SJerome Glisse 	/* set scaler clears this on some chips */
1198ceefedd8SAlex Deucher 	if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) {
1199771fe6b9SJerome Glisse 		if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
1200ceefedd8SAlex Deucher 			WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
1201ceefedd8SAlex Deucher 			       AVIVO_D1MODE_INTERLEAVE_EN);
1202ceefedd8SAlex Deucher 	}
1203771fe6b9SJerome Glisse }
1204771fe6b9SJerome Glisse 
1205771fe6b9SJerome Glisse static void
1206771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1207771fe6b9SJerome Glisse 			     struct drm_display_mode *mode,
1208771fe6b9SJerome Glisse 			     struct drm_display_mode *adjusted_mode)
1209771fe6b9SJerome Glisse {
1210771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1211771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1212771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1213771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1214771fe6b9SJerome Glisse 
12155801ead6SAlex Deucher 	if (radeon_encoder->active_device &
12165801ead6SAlex Deucher 	    (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
1217771fe6b9SJerome Glisse 		if (radeon_encoder->enc_priv) {
1218771fe6b9SJerome Glisse 			struct radeon_encoder_atom_dig *dig;
1219771fe6b9SJerome Glisse 
1220771fe6b9SJerome Glisse 			dig = radeon_encoder->enc_priv;
1221771fe6b9SJerome Glisse 			dig->dig_block = radeon_crtc->crtc_id;
1222771fe6b9SJerome Glisse 		}
12235801ead6SAlex Deucher 	}
1224771fe6b9SJerome Glisse 	radeon_encoder->pixel_clock = adjusted_mode->clock;
1225771fe6b9SJerome Glisse 
1226771fe6b9SJerome Glisse 	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1227771fe6b9SJerome Glisse 	atombios_set_encoder_crtc_source(encoder);
1228771fe6b9SJerome Glisse 
1229771fe6b9SJerome Glisse 	if (ASIC_IS_AVIVO(rdev)) {
12304ce001abSDave Airlie 		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
1231771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, true);
1232771fe6b9SJerome Glisse 		else
1233771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, false);
1234771fe6b9SJerome Glisse 	}
1235771fe6b9SJerome Glisse 
1236771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1237771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1238771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1239771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1240771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1241771fe6b9SJerome Glisse 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
1242771fe6b9SJerome Glisse 		break;
1243771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1244771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1245771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1246771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1247771fe6b9SJerome Glisse 		/* disable the encoder and transmitter */
12481a66c95aSAlex Deucher 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1249771fe6b9SJerome Glisse 		atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
1250771fe6b9SJerome Glisse 
1251771fe6b9SJerome Glisse 		/* setup and enable the encoder and transmitter */
1252771fe6b9SJerome Glisse 		atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
12531a66c95aSAlex Deucher 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
12541a66c95aSAlex Deucher 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
12551a66c95aSAlex Deucher 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1256771fe6b9SJerome Glisse 		break;
1257771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1258771fe6b9SJerome Glisse 		atombios_ddia_setup(encoder, ATOM_ENABLE);
1259771fe6b9SJerome Glisse 		break;
1260771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1261771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1262771fe6b9SJerome Glisse 		atombios_external_tmds_setup(encoder, ATOM_ENABLE);
1263771fe6b9SJerome Glisse 		break;
1264771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1265771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1266771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1267771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1268771fe6b9SJerome Glisse 		atombios_dac_setup(encoder, ATOM_ENABLE);
12694ce001abSDave Airlie 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
1270771fe6b9SJerome Glisse 			atombios_tv_setup(encoder, ATOM_ENABLE);
1271771fe6b9SJerome Glisse 		break;
1272771fe6b9SJerome Glisse 	}
1273771fe6b9SJerome Glisse 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
1274dafc3bd5SChristian Koenig 
1275dafc3bd5SChristian Koenig 	r600_hdmi_setmode(encoder, adjusted_mode);
1276771fe6b9SJerome Glisse }
1277771fe6b9SJerome Glisse 
1278771fe6b9SJerome Glisse static bool
12794ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1280771fe6b9SJerome Glisse {
1281771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1282771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1283771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
12844ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1285771fe6b9SJerome Glisse 
1286771fe6b9SJerome Glisse 	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
1287771fe6b9SJerome Glisse 				       ATOM_DEVICE_CV_SUPPORT |
1288771fe6b9SJerome Glisse 				       ATOM_DEVICE_CRT_SUPPORT)) {
1289771fe6b9SJerome Glisse 		DAC_LOAD_DETECTION_PS_ALLOCATION args;
1290771fe6b9SJerome Glisse 		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1291771fe6b9SJerome Glisse 		uint8_t frev, crev;
1292771fe6b9SJerome Glisse 
1293771fe6b9SJerome Glisse 		memset(&args, 0, sizeof(args));
1294771fe6b9SJerome Glisse 
1295771fe6b9SJerome Glisse 		atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
1296771fe6b9SJerome Glisse 
1297771fe6b9SJerome Glisse 		args.sDacload.ucMisc = 0;
1298771fe6b9SJerome Glisse 
1299771fe6b9SJerome Glisse 		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1300771fe6b9SJerome Glisse 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
1301771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_A;
1302771fe6b9SJerome Glisse 		else
1303771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_B;
1304771fe6b9SJerome Glisse 
13054ce001abSDave Airlie 		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
1306771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
13074ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
1308771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
13094ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
1310771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
1311771fe6b9SJerome Glisse 			if (crev >= 3)
1312771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
13134ce001abSDave Airlie 		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
1314771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
1315771fe6b9SJerome Glisse 			if (crev >= 3)
1316771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1317771fe6b9SJerome Glisse 		}
1318771fe6b9SJerome Glisse 
1319771fe6b9SJerome Glisse 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1320771fe6b9SJerome Glisse 
1321771fe6b9SJerome Glisse 		return true;
1322771fe6b9SJerome Glisse 	} else
1323771fe6b9SJerome Glisse 		return false;
1324771fe6b9SJerome Glisse }
1325771fe6b9SJerome Glisse 
1326771fe6b9SJerome Glisse static enum drm_connector_status
1327771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1328771fe6b9SJerome Glisse {
1329771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1330771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1331771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
13324ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1333771fe6b9SJerome Glisse 	uint32_t bios_0_scratch;
1334771fe6b9SJerome Glisse 
13354ce001abSDave Airlie 	if (!atombios_dac_load_detect(encoder, connector)) {
1336771fe6b9SJerome Glisse 		DRM_DEBUG("detect returned false \n");
1337771fe6b9SJerome Glisse 		return connector_status_unknown;
1338771fe6b9SJerome Glisse 	}
1339771fe6b9SJerome Glisse 
1340771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
1341771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
1342771fe6b9SJerome Glisse 	else
1343771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
1344771fe6b9SJerome Glisse 
13454ce001abSDave Airlie 	DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
13464ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
1347771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
1348771fe6b9SJerome Glisse 			return connector_status_connected;
13494ce001abSDave Airlie 	}
13504ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
1351771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
1352771fe6b9SJerome Glisse 			return connector_status_connected;
13534ce001abSDave Airlie 	}
13544ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
1355771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
1356771fe6b9SJerome Glisse 			return connector_status_connected;
13574ce001abSDave Airlie 	}
13584ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
1359771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
1360771fe6b9SJerome Glisse 			return connector_status_connected; /* CTV */
1361771fe6b9SJerome Glisse 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
1362771fe6b9SJerome Glisse 			return connector_status_connected; /* STV */
1363771fe6b9SJerome Glisse 	}
1364771fe6b9SJerome Glisse 	return connector_status_disconnected;
1365771fe6b9SJerome Glisse }
1366771fe6b9SJerome Glisse 
1367771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
1368771fe6b9SJerome Glisse {
1369771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, true);
1370771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
1371771fe6b9SJerome Glisse }
1372771fe6b9SJerome Glisse 
1373771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
1374771fe6b9SJerome Glisse {
1375771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
1376771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, false);
1377771fe6b9SJerome Glisse }
1378771fe6b9SJerome Glisse 
13794ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
13804ce001abSDave Airlie {
13814ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
13824ce001abSDave Airlie 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
13834ce001abSDave Airlie 	radeon_encoder->active_device = 0;
13844ce001abSDave Airlie }
13854ce001abSDave Airlie 
1386771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
1387771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
1388771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
1389771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
1390771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
1391771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
13924ce001abSDave Airlie 	.disable = radeon_atom_encoder_disable,
1393771fe6b9SJerome Glisse 	/* no detect for TMDS/LVDS yet */
1394771fe6b9SJerome Glisse };
1395771fe6b9SJerome Glisse 
1396771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
1397771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
1398771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
1399771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
1400771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
1401771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
1402771fe6b9SJerome Glisse 	.detect = radeon_atom_dac_detect,
1403771fe6b9SJerome Glisse };
1404771fe6b9SJerome Glisse 
1405771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder)
1406771fe6b9SJerome Glisse {
1407771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1408771fe6b9SJerome Glisse 	kfree(radeon_encoder->enc_priv);
1409771fe6b9SJerome Glisse 	drm_encoder_cleanup(encoder);
1410771fe6b9SJerome Glisse 	kfree(radeon_encoder);
1411771fe6b9SJerome Glisse }
1412771fe6b9SJerome Glisse 
1413771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
1414771fe6b9SJerome Glisse 	.destroy = radeon_enc_destroy,
1415771fe6b9SJerome Glisse };
1416771fe6b9SJerome Glisse 
14174ce001abSDave Airlie struct radeon_encoder_atom_dac *
14184ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
14194ce001abSDave Airlie {
14204ce001abSDave Airlie 	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
14214ce001abSDave Airlie 
14224ce001abSDave Airlie 	if (!dac)
14234ce001abSDave Airlie 		return NULL;
14244ce001abSDave Airlie 
14254ce001abSDave Airlie 	dac->tv_std = TV_STD_NTSC;
14264ce001abSDave Airlie 	return dac;
14274ce001abSDave Airlie }
14284ce001abSDave Airlie 
1429771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *
1430771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
1431771fe6b9SJerome Glisse {
1432771fe6b9SJerome Glisse 	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
1433771fe6b9SJerome Glisse 
1434771fe6b9SJerome Glisse 	if (!dig)
1435771fe6b9SJerome Glisse 		return NULL;
1436771fe6b9SJerome Glisse 
1437771fe6b9SJerome Glisse 	/* coherent mode by default */
1438771fe6b9SJerome Glisse 	dig->coherent_mode = true;
1439771fe6b9SJerome Glisse 
1440771fe6b9SJerome Glisse 	return dig;
1441771fe6b9SJerome Glisse }
1442771fe6b9SJerome Glisse 
1443771fe6b9SJerome Glisse void
1444771fe6b9SJerome Glisse radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
1445771fe6b9SJerome Glisse {
1446dfee5614SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
1447771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
1448771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder;
1449771fe6b9SJerome Glisse 
1450771fe6b9SJerome Glisse 	/* see if we already added it */
1451771fe6b9SJerome Glisse 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1452771fe6b9SJerome Glisse 		radeon_encoder = to_radeon_encoder(encoder);
1453771fe6b9SJerome Glisse 		if (radeon_encoder->encoder_id == encoder_id) {
1454771fe6b9SJerome Glisse 			radeon_encoder->devices |= supported_device;
1455771fe6b9SJerome Glisse 			return;
1456771fe6b9SJerome Glisse 		}
1457771fe6b9SJerome Glisse 
1458771fe6b9SJerome Glisse 	}
1459771fe6b9SJerome Glisse 
1460771fe6b9SJerome Glisse 	/* add a new one */
1461771fe6b9SJerome Glisse 	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
1462771fe6b9SJerome Glisse 	if (!radeon_encoder)
1463771fe6b9SJerome Glisse 		return;
1464771fe6b9SJerome Glisse 
1465771fe6b9SJerome Glisse 	encoder = &radeon_encoder->base;
1466dfee5614SDave Airlie 	if (rdev->flags & RADEON_SINGLE_CRTC)
1467dfee5614SDave Airlie 		encoder->possible_crtcs = 0x1;
1468dfee5614SDave Airlie 	else
1469771fe6b9SJerome Glisse 		encoder->possible_crtcs = 0x3;
1470771fe6b9SJerome Glisse 
1471771fe6b9SJerome Glisse 	radeon_encoder->enc_priv = NULL;
1472771fe6b9SJerome Glisse 
1473771fe6b9SJerome Glisse 	radeon_encoder->encoder_id = encoder_id;
1474771fe6b9SJerome Glisse 	radeon_encoder->devices = supported_device;
1475c93bb85bSJerome Glisse 	radeon_encoder->rmx_type = RMX_OFF;
1476771fe6b9SJerome Glisse 
1477771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1478771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1479771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1480771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1481771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1482771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1483771fe6b9SJerome Glisse 			radeon_encoder->rmx_type = RMX_FULL;
1484771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
1485771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
1486771fe6b9SJerome Glisse 		} else {
1487771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
1488771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
1489771fe6b9SJerome Glisse 		}
1490771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
1491771fe6b9SJerome Glisse 		break;
1492771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1493771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
1494771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
1495771fe6b9SJerome Glisse 		break;
1496771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1497771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1498771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1499771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
15004ce001abSDave Airlie 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
1501771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
1502771fe6b9SJerome Glisse 		break;
1503771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1504771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1505771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1506771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1507771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1508771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1509771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
151060d15f55SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
151160d15f55SAlex Deucher 			radeon_encoder->rmx_type = RMX_FULL;
151260d15f55SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
151360d15f55SAlex Deucher 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
151460d15f55SAlex Deucher 		} else {
1515771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
1516771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
151760d15f55SAlex Deucher 		}
1518771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
1519771fe6b9SJerome Glisse 		break;
1520771fe6b9SJerome Glisse 	}
1521dafc3bd5SChristian Koenig 
1522dafc3bd5SChristian Koenig 	r600_hdmi_init(encoder);
1523771fe6b9SJerome Glisse }
1524