xref: /openbmc/linux/drivers/gpu/drm/radeon/radeon_encoders.c (revision 1d33e1fc8dcce667a70387b666a8b6f60153d90f)
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
845137ee94SAlex Deucher radeon_get_encoder_enum(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))
1005137ee94SAlex Deucher 				ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
101771fe6b9SJerome Glisse 			else if (ASIC_IS_AVIVO(rdev))
1025137ee94SAlex Deucher 				ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
103771fe6b9SJerome Glisse 			else
1045137ee94SAlex Deucher 				ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
105771fe6b9SJerome Glisse 			break;
106771fe6b9SJerome Glisse 		case 2: /* dac b */
107771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
1085137ee94SAlex Deucher 				ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
109771fe6b9SJerome Glisse 			else {
110771fe6b9SJerome Glisse 				/*if (rdev->family == CHIP_R200)
1115137ee94SAlex Deucher 				  ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
112771fe6b9SJerome Glisse 				  else*/
1135137ee94SAlex Deucher 				ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
114771fe6b9SJerome Glisse 			}
115771fe6b9SJerome Glisse 			break;
116771fe6b9SJerome Glisse 		case 3: /* external dac */
117771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
1185137ee94SAlex Deucher 				ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
119771fe6b9SJerome Glisse 			else
1205137ee94SAlex Deucher 				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
121771fe6b9SJerome Glisse 			break;
122771fe6b9SJerome Glisse 		}
123771fe6b9SJerome Glisse 		break;
124771fe6b9SJerome Glisse 	case ATOM_DEVICE_LCD1_SUPPORT:
125771fe6b9SJerome Glisse 		if (ASIC_IS_AVIVO(rdev))
1265137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
127771fe6b9SJerome Glisse 		else
1285137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
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))
1345137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
135771fe6b9SJerome Glisse 		else if (ASIC_IS_AVIVO(rdev))
1365137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
137771fe6b9SJerome Glisse 		else
1385137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
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))
1455137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
146771fe6b9SJerome Glisse 		else if (ASIC_IS_AVIVO(rdev))
1475137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
148771fe6b9SJerome Glisse 		else
1495137ee94SAlex Deucher 			ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
150771fe6b9SJerome Glisse 		break;
151771fe6b9SJerome Glisse 	case ATOM_DEVICE_DFP3_SUPPORT:
1525137ee94SAlex Deucher 		ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
153771fe6b9SJerome Glisse 		break;
154771fe6b9SJerome Glisse 	}
155771fe6b9SJerome Glisse 
156771fe6b9SJerome Glisse 	return ret;
157771fe6b9SJerome Glisse }
158771fe6b9SJerome Glisse 
159f28cf339SDave Airlie static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
160f28cf339SDave Airlie {
161f28cf339SDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
162f28cf339SDave Airlie 	switch (radeon_encoder->encoder_id) {
163f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
164f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
165f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
166f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
167f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
168f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
169f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
170f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
171f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
172f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
173f28cf339SDave Airlie 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
174f28cf339SDave Airlie 		return true;
175f28cf339SDave Airlie 	default:
176f28cf339SDave Airlie 		return false;
177f28cf339SDave Airlie 	}
178f28cf339SDave Airlie }
17999999aaaSAlex Deucher 
180771fe6b9SJerome Glisse void
181771fe6b9SJerome Glisse radeon_link_encoder_connector(struct drm_device *dev)
182771fe6b9SJerome Glisse {
183771fe6b9SJerome Glisse 	struct drm_connector *connector;
184771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
185771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
186771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder;
187771fe6b9SJerome Glisse 
188771fe6b9SJerome Glisse 	/* walk the list and link encoders to connectors */
189771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
190771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
191771fe6b9SJerome Glisse 		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
192771fe6b9SJerome Glisse 			radeon_encoder = to_radeon_encoder(encoder);
193771fe6b9SJerome Glisse 			if (radeon_encoder->devices & radeon_connector->devices)
194771fe6b9SJerome Glisse 				drm_mode_connector_attach_encoder(connector, encoder);
195771fe6b9SJerome Glisse 		}
196771fe6b9SJerome Glisse 	}
197771fe6b9SJerome Glisse }
198771fe6b9SJerome Glisse 
1994ce001abSDave Airlie void radeon_encoder_set_active_device(struct drm_encoder *encoder)
2004ce001abSDave Airlie {
2014ce001abSDave Airlie 	struct drm_device *dev = encoder->dev;
2024ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2034ce001abSDave Airlie 	struct drm_connector *connector;
2044ce001abSDave Airlie 
2054ce001abSDave Airlie 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2064ce001abSDave Airlie 		if (connector->encoder == encoder) {
2074ce001abSDave Airlie 			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2084ce001abSDave Airlie 			radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
209d9fdaafbSDave Airlie 			DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n",
2104ce001abSDave Airlie 				  radeon_encoder->active_device, radeon_encoder->devices,
2114ce001abSDave Airlie 				  radeon_connector->devices, encoder->encoder_type);
2124ce001abSDave Airlie 		}
2134ce001abSDave Airlie 	}
2144ce001abSDave Airlie }
2154ce001abSDave Airlie 
2165b1714d3SAlex Deucher struct drm_connector *
217771fe6b9SJerome Glisse radeon_get_connector_for_encoder(struct drm_encoder *encoder)
218771fe6b9SJerome Glisse {
219771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
220771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
221771fe6b9SJerome Glisse 	struct drm_connector *connector;
222771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
223771fe6b9SJerome Glisse 
224771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
225771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
22643c33ed8SDave Airlie 		if (radeon_encoder->active_device & radeon_connector->devices)
227771fe6b9SJerome Glisse 			return connector;
228771fe6b9SJerome Glisse 	}
229771fe6b9SJerome Glisse 	return NULL;
230771fe6b9SJerome Glisse }
231771fe6b9SJerome Glisse 
232ac89af1eSAlex Deucher static struct drm_connector *
233ac89af1eSAlex Deucher radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
234ac89af1eSAlex Deucher {
235ac89af1eSAlex Deucher 	struct drm_device *dev = encoder->dev;
236ac89af1eSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
237ac89af1eSAlex Deucher 	struct drm_connector *connector;
238ac89af1eSAlex Deucher 	struct radeon_connector *radeon_connector;
239ac89af1eSAlex Deucher 
240ac89af1eSAlex Deucher 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
241ac89af1eSAlex Deucher 		radeon_connector = to_radeon_connector(connector);
242ac89af1eSAlex Deucher 		if (radeon_encoder->devices & radeon_connector->devices)
243ac89af1eSAlex Deucher 			return connector;
244ac89af1eSAlex Deucher 	}
245ac89af1eSAlex Deucher 	return NULL;
246ac89af1eSAlex Deucher }
247ac89af1eSAlex Deucher 
2483e4b9982SAlex Deucher struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder)
2493e4b9982SAlex Deucher {
2503e4b9982SAlex Deucher 	struct drm_device *dev = encoder->dev;
2513e4b9982SAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2523e4b9982SAlex Deucher 	struct drm_encoder *other_encoder;
2533e4b9982SAlex Deucher 	struct radeon_encoder *other_radeon_encoder;
2543e4b9982SAlex Deucher 
2553e4b9982SAlex Deucher 	if (radeon_encoder->is_ext_encoder)
2563e4b9982SAlex Deucher 		return NULL;
2573e4b9982SAlex Deucher 
2583e4b9982SAlex Deucher 	list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
2593e4b9982SAlex Deucher 		if (other_encoder == encoder)
2603e4b9982SAlex Deucher 			continue;
2613e4b9982SAlex Deucher 		other_radeon_encoder = to_radeon_encoder(other_encoder);
2623e4b9982SAlex Deucher 		if (other_radeon_encoder->is_ext_encoder &&
2633e4b9982SAlex Deucher 		    (radeon_encoder->devices & other_radeon_encoder->devices))
2643e4b9982SAlex Deucher 			return other_encoder;
2653e4b9982SAlex Deucher 	}
2663e4b9982SAlex Deucher 	return NULL;
2673e4b9982SAlex Deucher }
2683e4b9982SAlex Deucher 
269*1d33e1fcSAlex Deucher u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder)
270d7fa8bb3SAlex Deucher {
271d7fa8bb3SAlex Deucher 	struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder);
272d7fa8bb3SAlex Deucher 
273d7fa8bb3SAlex Deucher 	if (other_encoder) {
274d7fa8bb3SAlex Deucher 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
275d7fa8bb3SAlex Deucher 
276d7fa8bb3SAlex Deucher 		switch (radeon_encoder->encoder_id) {
277d7fa8bb3SAlex Deucher 		case ENCODER_OBJECT_ID_TRAVIS:
278d7fa8bb3SAlex Deucher 		case ENCODER_OBJECT_ID_NUTMEG:
279d7fa8bb3SAlex Deucher 			return true;
280d7fa8bb3SAlex Deucher 		default:
281d7fa8bb3SAlex Deucher 			return false;
282d7fa8bb3SAlex Deucher 		}
283d7fa8bb3SAlex Deucher 	}
284d7fa8bb3SAlex Deucher 
285d7fa8bb3SAlex Deucher 	return false;
286d7fa8bb3SAlex Deucher }
287d7fa8bb3SAlex Deucher 
2883515387bSAlex Deucher void radeon_panel_mode_fixup(struct drm_encoder *encoder,
2893515387bSAlex Deucher 			     struct drm_display_mode *adjusted_mode)
2903515387bSAlex Deucher {
2913515387bSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2923515387bSAlex Deucher 	struct drm_device *dev = encoder->dev;
2933515387bSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
2943515387bSAlex Deucher 	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
2953515387bSAlex Deucher 	unsigned hblank = native_mode->htotal - native_mode->hdisplay;
2963515387bSAlex Deucher 	unsigned vblank = native_mode->vtotal - native_mode->vdisplay;
2973515387bSAlex Deucher 	unsigned hover = native_mode->hsync_start - native_mode->hdisplay;
2983515387bSAlex Deucher 	unsigned vover = native_mode->vsync_start - native_mode->vdisplay;
2993515387bSAlex Deucher 	unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start;
3003515387bSAlex Deucher 	unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start;
3013515387bSAlex Deucher 
3023515387bSAlex Deucher 	adjusted_mode->clock = native_mode->clock;
3033515387bSAlex Deucher 	adjusted_mode->flags = native_mode->flags;
3043515387bSAlex Deucher 
3053515387bSAlex Deucher 	if (ASIC_IS_AVIVO(rdev)) {
3063515387bSAlex Deucher 		adjusted_mode->hdisplay = native_mode->hdisplay;
3073515387bSAlex Deucher 		adjusted_mode->vdisplay = native_mode->vdisplay;
3083515387bSAlex Deucher 	}
3093515387bSAlex Deucher 
3103515387bSAlex Deucher 	adjusted_mode->htotal = native_mode->hdisplay + hblank;
3113515387bSAlex Deucher 	adjusted_mode->hsync_start = native_mode->hdisplay + hover;
3123515387bSAlex Deucher 	adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width;
3133515387bSAlex Deucher 
3143515387bSAlex Deucher 	adjusted_mode->vtotal = native_mode->vdisplay + vblank;
3153515387bSAlex Deucher 	adjusted_mode->vsync_start = native_mode->vdisplay + vover;
3163515387bSAlex Deucher 	adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width;
3173515387bSAlex Deucher 
3183515387bSAlex Deucher 	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
3193515387bSAlex Deucher 
3203515387bSAlex Deucher 	if (ASIC_IS_AVIVO(rdev)) {
3213515387bSAlex Deucher 		adjusted_mode->crtc_hdisplay = native_mode->hdisplay;
3223515387bSAlex Deucher 		adjusted_mode->crtc_vdisplay = native_mode->vdisplay;
3233515387bSAlex Deucher 	}
3243515387bSAlex Deucher 
3253515387bSAlex Deucher 	adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank;
3263515387bSAlex Deucher 	adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover;
3273515387bSAlex Deucher 	adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width;
3283515387bSAlex Deucher 
3293515387bSAlex Deucher 	adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank;
3303515387bSAlex Deucher 	adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover;
3313515387bSAlex Deucher 	adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width;
3323515387bSAlex Deucher 
3333515387bSAlex Deucher }
3343515387bSAlex Deucher 
335771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
336771fe6b9SJerome Glisse 				   struct drm_display_mode *mode,
337771fe6b9SJerome Glisse 				   struct drm_display_mode *adjusted_mode)
338771fe6b9SJerome Glisse {
339771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3405a9bcaccSAlex Deucher 	struct drm_device *dev = encoder->dev;
3415a9bcaccSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
342771fe6b9SJerome Glisse 
3438c2a6d73SAlex Deucher 	/* set the active encoder to connector routing */
3448c2a6d73SAlex Deucher 	radeon_encoder_set_active_device(encoder);
345771fe6b9SJerome Glisse 	drm_mode_set_crtcinfo(adjusted_mode, 0);
346771fe6b9SJerome Glisse 
347771fe6b9SJerome Glisse 	/* hw bug */
348771fe6b9SJerome Glisse 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
349771fe6b9SJerome Glisse 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
350771fe6b9SJerome Glisse 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
351771fe6b9SJerome Glisse 
35280297e87SAlex Deucher 	/* get the native mode for LVDS */
3533515387bSAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
3543515387bSAlex Deucher 		radeon_panel_mode_fixup(encoder, adjusted_mode);
35580297e87SAlex Deucher 
35680297e87SAlex Deucher 	/* get the native mode for TV */
357ceefedd8SAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
3585a9bcaccSAlex Deucher 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
3595a9bcaccSAlex Deucher 		if (tv_dac) {
3605a9bcaccSAlex Deucher 			if (tv_dac->tv_std == TV_STD_NTSC ||
3615a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_NTSC_J ||
3625a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_PAL_M)
3635a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
3645a9bcaccSAlex Deucher 			else
3655a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
3665a9bcaccSAlex Deucher 		}
3675a9bcaccSAlex Deucher 	}
3685a9bcaccSAlex Deucher 
3695801ead6SAlex Deucher 	if (ASIC_IS_DCE3(rdev) &&
37011b0a5b8SAlex Deucher 	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
371*1d33e1fcSAlex Deucher 	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
3725801ead6SAlex Deucher 		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
3735801ead6SAlex Deucher 		radeon_dp_set_link_config(connector, mode);
3745801ead6SAlex Deucher 	}
3755801ead6SAlex Deucher 
376771fe6b9SJerome Glisse 	return true;
377771fe6b9SJerome Glisse }
378771fe6b9SJerome Glisse 
379771fe6b9SJerome Glisse static void
380771fe6b9SJerome Glisse atombios_dac_setup(struct drm_encoder *encoder, int action)
381771fe6b9SJerome Glisse {
382771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
383771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
384771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
385771fe6b9SJerome Glisse 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
386affd8589SAlex Deucher 	int index = 0;
387445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
388445282dbSDave Airlie 
389771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
390771fe6b9SJerome Glisse 
391771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
392771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
393771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
394771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
395771fe6b9SJerome Glisse 		break;
396771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
397771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
398771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
399771fe6b9SJerome Glisse 		break;
400771fe6b9SJerome Glisse 	}
401771fe6b9SJerome Glisse 
402771fe6b9SJerome Glisse 	args.ucAction = action;
403771fe6b9SJerome Glisse 
4044ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
405771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_PS2;
4064ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
407771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_CV;
408771fe6b9SJerome Glisse 	else {
409affd8589SAlex Deucher 		switch (dac_info->tv_std) {
410771fe6b9SJerome Glisse 		case TV_STD_PAL:
411771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
412771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
413771fe6b9SJerome Glisse 		case TV_STD_SECAM:
414771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
415771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_PAL;
416771fe6b9SJerome Glisse 			break;
417771fe6b9SJerome Glisse 		case TV_STD_NTSC:
418771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
419771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
420771fe6b9SJerome Glisse 		default:
421771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_NTSC;
422771fe6b9SJerome Glisse 			break;
423771fe6b9SJerome Glisse 		}
424771fe6b9SJerome Glisse 	}
425771fe6b9SJerome Glisse 	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
426771fe6b9SJerome Glisse 
427771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
428771fe6b9SJerome Glisse 
429771fe6b9SJerome Glisse }
430771fe6b9SJerome Glisse 
431771fe6b9SJerome Glisse static void
432771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action)
433771fe6b9SJerome Glisse {
434771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
435771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
436771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
437771fe6b9SJerome Glisse 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
438771fe6b9SJerome Glisse 	int index = 0;
439445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
440445282dbSDave Airlie 
441771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
442771fe6b9SJerome Glisse 
443771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
444771fe6b9SJerome Glisse 
445771fe6b9SJerome Glisse 	args.sTVEncoder.ucAction = action;
446771fe6b9SJerome Glisse 
4474ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
448771fe6b9SJerome Glisse 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
449771fe6b9SJerome Glisse 	else {
450affd8589SAlex Deucher 		switch (dac_info->tv_std) {
451771fe6b9SJerome Glisse 		case TV_STD_NTSC:
452771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
453771fe6b9SJerome Glisse 			break;
454771fe6b9SJerome Glisse 		case TV_STD_PAL:
455771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
456771fe6b9SJerome Glisse 			break;
457771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
458771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
459771fe6b9SJerome Glisse 			break;
460771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
461771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
462771fe6b9SJerome Glisse 			break;
463771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
464771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
465771fe6b9SJerome Glisse 			break;
466771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
467771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
468771fe6b9SJerome Glisse 			break;
469771fe6b9SJerome Glisse 		case TV_STD_SECAM:
470771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
471771fe6b9SJerome Glisse 			break;
472771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
473771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
474771fe6b9SJerome Glisse 			break;
475771fe6b9SJerome Glisse 		default:
476771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
477771fe6b9SJerome Glisse 			break;
478771fe6b9SJerome Glisse 		}
479771fe6b9SJerome Glisse 	}
480771fe6b9SJerome Glisse 
481771fe6b9SJerome Glisse 	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
482771fe6b9SJerome Glisse 
483771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
484771fe6b9SJerome Glisse 
485771fe6b9SJerome Glisse }
486771fe6b9SJerome Glisse 
48799999aaaSAlex Deucher union dvo_encoder_control {
48899999aaaSAlex Deucher 	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
48999999aaaSAlex Deucher 	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
49099999aaaSAlex Deucher 	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
49199999aaaSAlex Deucher };
49299999aaaSAlex Deucher 
493771fe6b9SJerome Glisse void
49499999aaaSAlex Deucher atombios_dvo_setup(struct drm_encoder *encoder, int action)
495771fe6b9SJerome Glisse {
496771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
497771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
498771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
49999999aaaSAlex Deucher 	union dvo_encoder_control args;
50099999aaaSAlex Deucher 	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
501771fe6b9SJerome Glisse 
502771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
503771fe6b9SJerome Glisse 
50499999aaaSAlex Deucher 	if (ASIC_IS_DCE3(rdev)) {
50599999aaaSAlex Deucher 		/* DCE3+ */
50699999aaaSAlex Deucher 		args.dvo_v3.ucAction = action;
50799999aaaSAlex Deucher 		args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
50899999aaaSAlex Deucher 		args.dvo_v3.ucDVOConfig = 0; /* XXX */
50999999aaaSAlex Deucher 	} else if (ASIC_IS_DCE2(rdev)) {
51099999aaaSAlex Deucher 		/* DCE2 (pre-DCE3 R6xx, RS600/690/740 */
51199999aaaSAlex Deucher 		args.dvo.sDVOEncoder.ucAction = action;
51299999aaaSAlex Deucher 		args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
51399999aaaSAlex Deucher 		/* DFP1, CRT1, TV1 depending on the type of port */
51499999aaaSAlex Deucher 		args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
515771fe6b9SJerome Glisse 
516771fe6b9SJerome Glisse 		if (radeon_encoder->pixel_clock > 165000)
51799999aaaSAlex Deucher 			args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
51899999aaaSAlex Deucher 	} else {
51999999aaaSAlex Deucher 		/* R4xx, R5xx */
52099999aaaSAlex Deucher 		args.ext_tmds.sXTmdsEncoder.ucEnable = action;
52199999aaaSAlex Deucher 
52299999aaaSAlex Deucher 		if (radeon_encoder->pixel_clock > 165000)
52399999aaaSAlex Deucher 			args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
524771fe6b9SJerome Glisse 
525771fe6b9SJerome Glisse 		/*if (pScrn->rgbBits == 8)*/
52699999aaaSAlex Deucher 		args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
527771fe6b9SJerome Glisse 	}
528771fe6b9SJerome Glisse 
529771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
530771fe6b9SJerome Glisse }
531771fe6b9SJerome Glisse 
532771fe6b9SJerome Glisse union lvds_encoder_control {
533771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
534771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
535771fe6b9SJerome Glisse };
536771fe6b9SJerome Glisse 
53732f48ffeSAlex Deucher void
538771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action)
539771fe6b9SJerome Glisse {
540771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
541771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
542771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
5439ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
544771fe6b9SJerome Glisse 	union lvds_encoder_control args;
545771fe6b9SJerome Glisse 	int index = 0;
546dafc3bd5SChristian Koenig 	int hdmi_detected = 0;
547771fe6b9SJerome Glisse 	uint8_t frev, crev;
548771fe6b9SJerome Glisse 
5494aab97e8SAlex Deucher 	if (!dig)
550771fe6b9SJerome Glisse 		return;
551771fe6b9SJerome Glisse 
5529ae47867SAlex Deucher 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
553dafc3bd5SChristian Koenig 		hdmi_detected = 1;
554dafc3bd5SChristian Koenig 
555771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
556771fe6b9SJerome Glisse 
557771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
558771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
559771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
560771fe6b9SJerome Glisse 		break;
561771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
562771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
563771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
564771fe6b9SJerome Glisse 		break;
565771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
566771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
567771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
568771fe6b9SJerome Glisse 		else
569771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
570771fe6b9SJerome Glisse 		break;
571771fe6b9SJerome Glisse 	}
572771fe6b9SJerome Glisse 
573a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
574a084e6eeSAlex Deucher 		return;
575771fe6b9SJerome Glisse 
576771fe6b9SJerome Glisse 	switch (frev) {
577771fe6b9SJerome Glisse 	case 1:
578771fe6b9SJerome Glisse 	case 2:
579771fe6b9SJerome Glisse 		switch (crev) {
580771fe6b9SJerome Glisse 		case 1:
581771fe6b9SJerome Glisse 			args.v1.ucMisc = 0;
582771fe6b9SJerome Glisse 			args.v1.ucAction = action;
583dafc3bd5SChristian Koenig 			if (hdmi_detected)
584771fe6b9SJerome Glisse 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
585771fe6b9SJerome Glisse 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
586771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
587ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
588771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
589ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
59099999aaaSAlex Deucher 					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
591771fe6b9SJerome Glisse 			} else {
5925137ee94SAlex Deucher 				if (dig->linkb)
593771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
594771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
595771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
596771fe6b9SJerome Glisse 				/*if (pScrn->rgbBits == 8) */
59799999aaaSAlex Deucher 				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
598771fe6b9SJerome Glisse 			}
599771fe6b9SJerome Glisse 			break;
600771fe6b9SJerome Glisse 		case 2:
601771fe6b9SJerome Glisse 		case 3:
602771fe6b9SJerome Glisse 			args.v2.ucMisc = 0;
603771fe6b9SJerome Glisse 			args.v2.ucAction = action;
604771fe6b9SJerome Glisse 			if (crev == 3) {
605771fe6b9SJerome Glisse 				if (dig->coherent_mode)
606771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
607771fe6b9SJerome Glisse 			}
608dafc3bd5SChristian Koenig 			if (hdmi_detected)
609771fe6b9SJerome Glisse 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
610771fe6b9SJerome Glisse 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
611771fe6b9SJerome Glisse 			args.v2.ucTruncate = 0;
612771fe6b9SJerome Glisse 			args.v2.ucSpatial = 0;
613771fe6b9SJerome Glisse 			args.v2.ucTemporal = 0;
614771fe6b9SJerome Glisse 			args.v2.ucFRC = 0;
615771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
616ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
617771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
618ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
619771fe6b9SJerome Glisse 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
620ba032a58SAlex Deucher 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
621771fe6b9SJerome Glisse 						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
622771fe6b9SJerome Glisse 				}
623ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
624771fe6b9SJerome Glisse 					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
625ba032a58SAlex Deucher 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
626771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
627ba032a58SAlex Deucher 					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
628771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
629771fe6b9SJerome Glisse 				}
630771fe6b9SJerome Glisse 			} else {
6315137ee94SAlex Deucher 				if (dig->linkb)
632771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
633771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
634771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
635771fe6b9SJerome Glisse 			}
636771fe6b9SJerome Glisse 			break;
637771fe6b9SJerome Glisse 		default:
638771fe6b9SJerome Glisse 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
639771fe6b9SJerome Glisse 			break;
640771fe6b9SJerome Glisse 		}
641771fe6b9SJerome Glisse 		break;
642771fe6b9SJerome Glisse 	default:
643771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
644771fe6b9SJerome Glisse 		break;
645771fe6b9SJerome Glisse 	}
646771fe6b9SJerome Glisse 
647771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
648771fe6b9SJerome Glisse }
649771fe6b9SJerome Glisse 
650771fe6b9SJerome Glisse int
651771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder)
652771fe6b9SJerome Glisse {
653c7a71fc7SAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
654d033af87SAlex Deucher 	struct drm_device *dev = encoder->dev;
655d033af87SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
656771fe6b9SJerome Glisse 	struct drm_connector *connector;
657771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
6589ae47867SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector;
659771fe6b9SJerome Glisse 
660d7fa8bb3SAlex Deucher 	/* dp bridges are always DP */
661*1d33e1fcSAlex Deucher 	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
662d7fa8bb3SAlex Deucher 		return ATOM_ENCODER_MODE_DP;
663d7fa8bb3SAlex Deucher 
664fbb87773SAlex Deucher 	/* DVO is always DVO */
665fbb87773SAlex Deucher 	if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
666fbb87773SAlex Deucher 		return ATOM_ENCODER_MODE_DVO;
667fbb87773SAlex Deucher 
668771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
669fbb87773SAlex Deucher 	/* if we don't have an active device yet, just use one of
670fbb87773SAlex Deucher 	 * the connectors tied to the encoder.
671fbb87773SAlex Deucher 	 */
672fbb87773SAlex Deucher 	if (!connector)
673fbb87773SAlex Deucher 		connector = radeon_get_connector_for_encoder_init(encoder);
674771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
675771fe6b9SJerome Glisse 
676771fe6b9SJerome Glisse 	switch (connector->connector_type) {
677771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVII:
678705af9c7SAlex Deucher 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
6799453d621SAlex Deucher 		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
680d033af87SAlex Deucher 			/* fix me */
681d033af87SAlex Deucher 			if (ASIC_IS_DCE4(rdev))
682d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_DVI;
683d033af87SAlex Deucher 			else
684771fe6b9SJerome Glisse 				return ATOM_ENCODER_MODE_HDMI;
685d033af87SAlex Deucher 		} else if (radeon_connector->use_digital)
686771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
687771fe6b9SJerome Glisse 		else
688771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_CRT;
689771fe6b9SJerome Glisse 		break;
690771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVID:
691771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_HDMIA:
692771fe6b9SJerome Glisse 	default:
6939453d621SAlex Deucher 		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
694d033af87SAlex Deucher 			/* fix me */
695d033af87SAlex Deucher 			if (ASIC_IS_DCE4(rdev))
696d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_DVI;
697771fe6b9SJerome Glisse 			else
698d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_HDMI;
699d033af87SAlex Deucher 		} else
700771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
701771fe6b9SJerome Glisse 		break;
702771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_LVDS:
703771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_LVDS;
704771fe6b9SJerome Glisse 		break;
705771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DisplayPort:
7069ae47867SAlex Deucher 		dig_connector = radeon_connector->con_priv;
7079ae47867SAlex Deucher 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
7089ae47867SAlex Deucher 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
709771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DP;
7109453d621SAlex Deucher 		else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
711d033af87SAlex Deucher 			/* fix me */
712d033af87SAlex Deucher 			if (ASIC_IS_DCE4(rdev))
713d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_DVI;
714771fe6b9SJerome Glisse 			else
715d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_HDMI;
716d033af87SAlex Deucher 		} else
717771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
718771fe6b9SJerome Glisse 		break;
7193a5f4a21SAlex Deucher 	case DRM_MODE_CONNECTOR_eDP:
7203a5f4a21SAlex Deucher 		return ATOM_ENCODER_MODE_DP;
721a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_DVIA:
722a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_VGA:
723771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_CRT;
724771fe6b9SJerome Glisse 		break;
725a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_Composite:
726a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_SVIDEO:
727a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_9PinDIN:
728771fe6b9SJerome Glisse 		/* fix me */
729771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_TV;
730771fe6b9SJerome Glisse 		/*return ATOM_ENCODER_MODE_CV;*/
731771fe6b9SJerome Glisse 		break;
732771fe6b9SJerome Glisse 	}
733771fe6b9SJerome Glisse }
734771fe6b9SJerome Glisse 
7351a66c95aSAlex Deucher /*
7361a66c95aSAlex Deucher  * DIG Encoder/Transmitter Setup
7371a66c95aSAlex Deucher  *
7381a66c95aSAlex Deucher  * DCE 3.0/3.1
7391a66c95aSAlex Deucher  * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
7401a66c95aSAlex Deucher  * Supports up to 3 digital outputs
7411a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
7421a66c95aSAlex Deucher  * DIG1 can drive UNIPHY link A or link B
7431a66c95aSAlex Deucher  * DIG2 can drive UNIPHY link B or LVTMA
7441a66c95aSAlex Deucher  *
7451a66c95aSAlex Deucher  * DCE 3.2
7461a66c95aSAlex Deucher  * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
7471a66c95aSAlex Deucher  * Supports up to 5 digital outputs
7481a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
7491a66c95aSAlex Deucher  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
7501a66c95aSAlex Deucher  *
751a001182aSAlex Deucher  * DCE 4.0/5.0
7524e8c65a1SAlex Deucher  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
753bcc1c2a1SAlex Deucher  * Supports up to 6 digital outputs
754bcc1c2a1SAlex Deucher  * - 6 DIG encoder blocks.
755bcc1c2a1SAlex Deucher  * - DIG to PHY mapping is hardcoded
756bcc1c2a1SAlex Deucher  * DIG1 drives UNIPHY0 link A, A+B
757bcc1c2a1SAlex Deucher  * DIG2 drives UNIPHY0 link B
758bcc1c2a1SAlex Deucher  * DIG3 drives UNIPHY1 link A, A+B
759bcc1c2a1SAlex Deucher  * DIG4 drives UNIPHY1 link B
760bcc1c2a1SAlex Deucher  * DIG5 drives UNIPHY2 link A, A+B
761bcc1c2a1SAlex Deucher  * DIG6 drives UNIPHY2 link B
762bcc1c2a1SAlex Deucher  *
7634e8c65a1SAlex Deucher  * DCE 4.1
7644e8c65a1SAlex Deucher  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
7654e8c65a1SAlex Deucher  * Supports up to 6 digital outputs
7664e8c65a1SAlex Deucher  * - 2 DIG encoder blocks.
7674e8c65a1SAlex Deucher  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
7684e8c65a1SAlex Deucher  *
7691a66c95aSAlex Deucher  * Routing
7701a66c95aSAlex Deucher  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
7711a66c95aSAlex Deucher  * Examples:
7721a66c95aSAlex Deucher  * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
7731a66c95aSAlex Deucher  * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
7741a66c95aSAlex Deucher  * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
7751a66c95aSAlex Deucher  * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
7761a66c95aSAlex Deucher  */
777bcc1c2a1SAlex Deucher 
778bcc1c2a1SAlex Deucher union dig_encoder_control {
779bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
780bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
781bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
782badbb57bSAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
783bcc1c2a1SAlex Deucher };
784bcc1c2a1SAlex Deucher 
785bcc1c2a1SAlex Deucher void
786558e27dbSAlex Deucher atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
787771fe6b9SJerome Glisse {
788771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
789771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
790771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
7919ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
7924aab97e8SAlex Deucher 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
793bcc1c2a1SAlex Deucher 	union dig_encoder_control args;
794d9c9fe36SAlex Deucher 	int index = 0;
795771fe6b9SJerome Glisse 	uint8_t frev, crev;
7964aab97e8SAlex Deucher 	int dp_clock = 0;
7974aab97e8SAlex Deucher 	int dp_lane_count = 0;
798badbb57bSAlex Deucher 	int hpd_id = RADEON_HPD_NONE;
799df271becSAlex Deucher 	int bpc = 8;
800771fe6b9SJerome Glisse 
8014aab97e8SAlex Deucher 	if (connector) {
8024aab97e8SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
8034aab97e8SAlex Deucher 		struct radeon_connector_atom_dig *dig_connector =
8044aab97e8SAlex Deucher 			radeon_connector->con_priv;
8054aab97e8SAlex Deucher 
8064aab97e8SAlex Deucher 		dp_clock = dig_connector->dp_clock;
8074aab97e8SAlex Deucher 		dp_lane_count = dig_connector->dp_lane_count;
808badbb57bSAlex Deucher 		hpd_id = radeon_connector->hpd.hpd;
809df271becSAlex Deucher 		bpc = connector->display_info.bpc;
8104aab97e8SAlex Deucher 	}
8114aab97e8SAlex Deucher 
8124aab97e8SAlex Deucher 	/* no dig encoder assigned */
8134aab97e8SAlex Deucher 	if (dig->dig_encoder == -1)
814771fe6b9SJerome Glisse 		return;
815771fe6b9SJerome Glisse 
816771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
817771fe6b9SJerome Glisse 
818bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev))
819bcc1c2a1SAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
820bcc1c2a1SAlex Deucher 	else {
821f28cf339SDave Airlie 		if (dig->dig_encoder)
822771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
823771fe6b9SJerome Glisse 		else
824771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
825bcc1c2a1SAlex Deucher 	}
826771fe6b9SJerome Glisse 
827a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
828a084e6eeSAlex Deucher 		return;
829771fe6b9SJerome Glisse 
830bcc1c2a1SAlex Deucher 	args.v1.ucAction = action;
831bcc1c2a1SAlex Deucher 	args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
832558e27dbSAlex Deucher 	if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
833558e27dbSAlex Deucher 		args.v3.ucPanelMode = panel_mode;
834558e27dbSAlex Deucher 	else
835bcc1c2a1SAlex Deucher 		args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
836771fe6b9SJerome Glisse 
837badbb57bSAlex Deucher 	if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
838badbb57bSAlex Deucher 	    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST))
8394aab97e8SAlex Deucher 		args.v1.ucLaneNum = dp_lane_count;
840badbb57bSAlex Deucher 	else if (radeon_encoder->pixel_clock > 165000)
841bcc1c2a1SAlex Deucher 		args.v1.ucLaneNum = 8;
842bcc1c2a1SAlex Deucher 	else
843bcc1c2a1SAlex Deucher 		args.v1.ucLaneNum = 4;
844bcc1c2a1SAlex Deucher 
845badbb57bSAlex Deucher 	if (ASIC_IS_DCE5(rdev)) {
846badbb57bSAlex Deucher 		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
847badbb57bSAlex Deucher 		    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) {
848badbb57bSAlex Deucher 			if (dp_clock == 270000)
849badbb57bSAlex Deucher 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
850badbb57bSAlex Deucher 			else if (dp_clock == 540000)
851badbb57bSAlex Deucher 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
852badbb57bSAlex Deucher 		}
853badbb57bSAlex Deucher 		args.v4.acConfig.ucDigSel = dig->dig_encoder;
854df271becSAlex Deucher 		switch (bpc) {
855df271becSAlex Deucher 		case 0:
856df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
857df271becSAlex Deucher 			break;
858df271becSAlex Deucher 		case 6:
859df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
860df271becSAlex Deucher 			break;
861df271becSAlex Deucher 		case 8:
862df271becSAlex Deucher 		default:
863badbb57bSAlex Deucher 			args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
864df271becSAlex Deucher 			break;
865df271becSAlex Deucher 		case 10:
866df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
867df271becSAlex Deucher 			break;
868df271becSAlex Deucher 		case 12:
869df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
870df271becSAlex Deucher 			break;
871df271becSAlex Deucher 		case 16:
872df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
873df271becSAlex Deucher 			break;
874df271becSAlex Deucher 		}
875badbb57bSAlex Deucher 		if (hpd_id == RADEON_HPD_NONE)
876badbb57bSAlex Deucher 			args.v4.ucHPD_ID = 0;
877badbb57bSAlex Deucher 		else
878badbb57bSAlex Deucher 			args.v4.ucHPD_ID = hpd_id + 1;
879badbb57bSAlex Deucher 	} else if (ASIC_IS_DCE4(rdev)) {
880badbb57bSAlex Deucher 		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
881badbb57bSAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
882bcc1c2a1SAlex Deucher 		args.v3.acConfig.ucDigSel = dig->dig_encoder;
883df271becSAlex Deucher 		switch (bpc) {
884df271becSAlex Deucher 		case 0:
885df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
886df271becSAlex Deucher 			break;
887df271becSAlex Deucher 		case 6:
888df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
889df271becSAlex Deucher 			break;
890df271becSAlex Deucher 		case 8:
891df271becSAlex Deucher 		default:
892bcc1c2a1SAlex Deucher 			args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
893df271becSAlex Deucher 			break;
894df271becSAlex Deucher 		case 10:
895df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
896df271becSAlex Deucher 			break;
897df271becSAlex Deucher 		case 12:
898df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
899df271becSAlex Deucher 			break;
900df271becSAlex Deucher 		case 16:
901df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
902df271becSAlex Deucher 			break;
903df271becSAlex Deucher 		}
904771fe6b9SJerome Glisse 	} else {
905badbb57bSAlex Deucher 		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
906badbb57bSAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
907771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
908771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
909bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
910771fe6b9SJerome Glisse 			break;
911bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
912771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
913bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
914bcc1c2a1SAlex Deucher 			break;
915bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
916bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
917771fe6b9SJerome Glisse 			break;
918771fe6b9SJerome Glisse 		}
9195137ee94SAlex Deucher 		if (dig->linkb)
920bcc1c2a1SAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
921771fe6b9SJerome Glisse 		else
922bcc1c2a1SAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
923bcc1c2a1SAlex Deucher 	}
924771fe6b9SJerome Glisse 
925771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
926771fe6b9SJerome Glisse 
927771fe6b9SJerome Glisse }
928771fe6b9SJerome Glisse 
929771fe6b9SJerome Glisse union dig_transmitter_control {
930771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
931771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
932bcc1c2a1SAlex Deucher 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
933a001182aSAlex Deucher 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
934771fe6b9SJerome Glisse };
935771fe6b9SJerome Glisse 
9365801ead6SAlex Deucher void
9371a66c95aSAlex Deucher atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
938771fe6b9SJerome Glisse {
939771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
940771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
941771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
9429ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
943ac89af1eSAlex Deucher 	struct drm_connector *connector;
944771fe6b9SJerome Glisse 	union dig_transmitter_control args;
945d9c9fe36SAlex Deucher 	int index = 0;
946771fe6b9SJerome Glisse 	uint8_t frev, crev;
947f92a8b67SAlex Deucher 	bool is_dp = false;
948bcc1c2a1SAlex Deucher 	int pll_id = 0;
9494aab97e8SAlex Deucher 	int dp_clock = 0;
9504aab97e8SAlex Deucher 	int dp_lane_count = 0;
9514aab97e8SAlex Deucher 	int connector_object_id = 0;
9524aab97e8SAlex Deucher 	int igp_lane_info = 0;
953f3aeceacSAlex Deucher 	int dig_encoder = dig->dig_encoder;
954771fe6b9SJerome Glisse 
955f3aeceacSAlex Deucher 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
956ac89af1eSAlex Deucher 		connector = radeon_get_connector_for_encoder_init(encoder);
957f3aeceacSAlex Deucher 		/* just needed to avoid bailing in the encoder check.  the encoder
958f3aeceacSAlex Deucher 		 * isn't used for init
959f3aeceacSAlex Deucher 		 */
960f3aeceacSAlex Deucher 		dig_encoder = 0;
961f3aeceacSAlex Deucher 	} else
962ac89af1eSAlex Deucher 		connector = radeon_get_connector_for_encoder(encoder);
963ac89af1eSAlex Deucher 
9644aab97e8SAlex Deucher 	if (connector) {
9654aab97e8SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
9664aab97e8SAlex Deucher 		struct radeon_connector_atom_dig *dig_connector =
9674aab97e8SAlex Deucher 			radeon_connector->con_priv;
9684aab97e8SAlex Deucher 
9694aab97e8SAlex Deucher 		dp_clock = dig_connector->dp_clock;
9704aab97e8SAlex Deucher 		dp_lane_count = dig_connector->dp_lane_count;
9714aab97e8SAlex Deucher 		connector_object_id =
9724aab97e8SAlex Deucher 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
9734aab97e8SAlex Deucher 		igp_lane_info = dig_connector->igp_lane_info;
9744aab97e8SAlex Deucher 	}
9754aab97e8SAlex Deucher 
9764aab97e8SAlex Deucher 	/* no dig encoder assigned */
977f3aeceacSAlex Deucher 	if (dig_encoder == -1)
9789ae47867SAlex Deucher 		return;
9799ae47867SAlex Deucher 
980f92a8b67SAlex Deucher 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
981f92a8b67SAlex Deucher 		is_dp = true;
982f92a8b67SAlex Deucher 
983771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
984771fe6b9SJerome Glisse 
985771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
98699999aaaSAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
98799999aaaSAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
98899999aaaSAlex Deucher 		break;
989771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
9904aab97e8SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
9914aab97e8SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
9924aab97e8SAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
993771fe6b9SJerome Glisse 		break;
994771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
9954aab97e8SAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
996771fe6b9SJerome Glisse 		break;
997771fe6b9SJerome Glisse 	}
998771fe6b9SJerome Glisse 
999a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1000a084e6eeSAlex Deucher 		return;
1001771fe6b9SJerome Glisse 
1002771fe6b9SJerome Glisse 	args.v1.ucAction = action;
1003f95a9f0bSAlex Deucher 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
10044589433cSCédric Cano 		args.v1.usInitInfo = cpu_to_le16(connector_object_id);
10051a66c95aSAlex Deucher 	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
10061a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSel = lane_num;
10071a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSet = lane_set;
1008771fe6b9SJerome Glisse 	} else {
1009f92a8b67SAlex Deucher 		if (is_dp)
1010f92a8b67SAlex Deucher 			args.v1.usPixelClock =
10114aab97e8SAlex Deucher 				cpu_to_le16(dp_clock / 10);
1012f92a8b67SAlex Deucher 		else if (radeon_encoder->pixel_clock > 165000)
1013f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1014f95a9f0bSAlex Deucher 		else
1015f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1016771fe6b9SJerome Glisse 	}
1017bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev)) {
1018bcc1c2a1SAlex Deucher 		if (is_dp)
10194aab97e8SAlex Deucher 			args.v3.ucLaneNum = dp_lane_count;
1020bcc1c2a1SAlex Deucher 		else if (radeon_encoder->pixel_clock > 165000)
1021bcc1c2a1SAlex Deucher 			args.v3.ucLaneNum = 8;
1022bcc1c2a1SAlex Deucher 		else
1023bcc1c2a1SAlex Deucher 			args.v3.ucLaneNum = 4;
1024bcc1c2a1SAlex Deucher 
102596b3bef8SAlex Deucher 		if (dig->linkb)
1026bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucLinkSel = 1;
1027f3aeceacSAlex Deucher 		if (dig_encoder & 1)
1028bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucEncoderSel = 1;
1029bcc1c2a1SAlex Deucher 
1030bcc1c2a1SAlex Deucher 		/* Select the PLL for the PHY
1031bcc1c2a1SAlex Deucher 		 * DP PHY should be clocked from external src if there is
1032bcc1c2a1SAlex Deucher 		 * one.
1033bcc1c2a1SAlex Deucher 		 */
1034bcc1c2a1SAlex Deucher 		if (encoder->crtc) {
1035bcc1c2a1SAlex Deucher 			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1036bcc1c2a1SAlex Deucher 			pll_id = radeon_crtc->pll_id;
1037bcc1c2a1SAlex Deucher 		}
1038a001182aSAlex Deucher 
1039a001182aSAlex Deucher 		if (ASIC_IS_DCE5(rdev)) {
104086a94defSAlex Deucher 			/* On DCE5 DCPLL usually generates the DP ref clock */
104186a94defSAlex Deucher 			if (is_dp) {
104286a94defSAlex Deucher 				if (rdev->clock.dp_extclk)
104386a94defSAlex Deucher 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
1044a001182aSAlex Deucher 				else
104586a94defSAlex Deucher 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
104686a94defSAlex Deucher 			} else
1047a001182aSAlex Deucher 				args.v4.acConfig.ucRefClkSource = pll_id;
1048a001182aSAlex Deucher 		} else {
104986a94defSAlex Deucher 			/* On DCE4, if there is an external clock, it generates the DP ref clock */
1050bcc1c2a1SAlex Deucher 			if (is_dp && rdev->clock.dp_extclk)
1051bcc1c2a1SAlex Deucher 				args.v3.acConfig.ucRefClkSource = 2; /* external src */
1052bcc1c2a1SAlex Deucher 			else
1053bcc1c2a1SAlex Deucher 				args.v3.acConfig.ucRefClkSource = pll_id;
1054a001182aSAlex Deucher 		}
1055bcc1c2a1SAlex Deucher 
1056bcc1c2a1SAlex Deucher 		switch (radeon_encoder->encoder_id) {
1057bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1058bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 0;
1059bcc1c2a1SAlex Deucher 			break;
1060bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1061bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 1;
1062bcc1c2a1SAlex Deucher 			break;
1063bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1064bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 2;
1065bcc1c2a1SAlex Deucher 			break;
1066bcc1c2a1SAlex Deucher 		}
1067bcc1c2a1SAlex Deucher 
1068bcc1c2a1SAlex Deucher 		if (is_dp)
1069bcc1c2a1SAlex Deucher 			args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
1070bcc1c2a1SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1071bcc1c2a1SAlex Deucher 			if (dig->coherent_mode)
1072bcc1c2a1SAlex Deucher 				args.v3.acConfig.fCoherentMode = 1;
1073b317a9ceSAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
1074b317a9ceSAlex Deucher 				args.v3.acConfig.fDualLinkConnector = 1;
1075bcc1c2a1SAlex Deucher 		}
1076bcc1c2a1SAlex Deucher 	} else if (ASIC_IS_DCE32(rdev)) {
1077f3aeceacSAlex Deucher 		args.v2.acConfig.ucEncoderSel = dig_encoder;
10785137ee94SAlex Deucher 		if (dig->linkb)
10791a66c95aSAlex Deucher 			args.v2.acConfig.ucLinkSel = 1;
1080771fe6b9SJerome Glisse 
1081771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
1082771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1083771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 0;
1084771fe6b9SJerome Glisse 			break;
1085771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1086771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 1;
1087771fe6b9SJerome Glisse 			break;
1088771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1089771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 2;
1090771fe6b9SJerome Glisse 			break;
1091771fe6b9SJerome Glisse 		}
1092771fe6b9SJerome Glisse 
109374d074eeSAlex Deucher 		if (is_dp) {
1094f92a8b67SAlex Deucher 			args.v2.acConfig.fCoherentMode = 1;
109574d074eeSAlex Deucher 			args.v2.acConfig.fDPConnector = 1;
109674d074eeSAlex Deucher 		} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1097771fe6b9SJerome Glisse 			if (dig->coherent_mode)
1098771fe6b9SJerome Glisse 				args.v2.acConfig.fCoherentMode = 1;
1099b317a9ceSAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
1100b317a9ceSAlex Deucher 				args.v2.acConfig.fDualLinkConnector = 1;
1101771fe6b9SJerome Glisse 		}
1102771fe6b9SJerome Glisse 	} else {
1103771fe6b9SJerome Glisse 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1104771fe6b9SJerome Glisse 
1105f3aeceacSAlex Deucher 		if (dig_encoder)
11061a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
11071a66c95aSAlex Deucher 		else
1108771fe6b9SJerome Glisse 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1109f28cf339SDave Airlie 
1110d9c9fe36SAlex Deucher 		if ((rdev->flags & RADEON_IS_IGP) &&
1111d9c9fe36SAlex Deucher 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1112d9c9fe36SAlex Deucher 			if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
11134aab97e8SAlex Deucher 				if (igp_lane_info & 0x1)
1114771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
11154aab97e8SAlex Deucher 				else if (igp_lane_info & 0x2)
1116771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
11174aab97e8SAlex Deucher 				else if (igp_lane_info & 0x4)
1118771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
11194aab97e8SAlex Deucher 				else if (igp_lane_info & 0x8)
1120771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1121d9c9fe36SAlex Deucher 			} else {
11224aab97e8SAlex Deucher 				if (igp_lane_info & 0x3)
1123d9c9fe36SAlex Deucher 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
11244aab97e8SAlex Deucher 				else if (igp_lane_info & 0xc)
1125d9c9fe36SAlex Deucher 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1126771fe6b9SJerome Glisse 			}
1127771fe6b9SJerome Glisse 		}
11281a66c95aSAlex Deucher 
11295137ee94SAlex Deucher 		if (dig->linkb)
11301a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
11311a66c95aSAlex Deucher 		else
11321a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
11331a66c95aSAlex Deucher 
1134f92a8b67SAlex Deucher 		if (is_dp)
1135f92a8b67SAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1136f92a8b67SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1137771fe6b9SJerome Glisse 			if (dig->coherent_mode)
1138771fe6b9SJerome Glisse 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1139d9c9fe36SAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
1140d9c9fe36SAlex Deucher 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1141771fe6b9SJerome Glisse 		}
1142771fe6b9SJerome Glisse 	}
1143771fe6b9SJerome Glisse 
1144771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1145771fe6b9SJerome Glisse }
1146771fe6b9SJerome Glisse 
11472dafb74dSAlex Deucher bool
11488b834852SAlex Deucher atombios_set_edp_panel_power(struct drm_connector *connector, int action)
11498b834852SAlex Deucher {
11508b834852SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
11518b834852SAlex Deucher 	struct drm_device *dev = radeon_connector->base.dev;
11528b834852SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
11538b834852SAlex Deucher 	union dig_transmitter_control args;
11548b834852SAlex Deucher 	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
11558b834852SAlex Deucher 	uint8_t frev, crev;
11568b834852SAlex Deucher 
11578b834852SAlex Deucher 	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
11582dafb74dSAlex Deucher 		goto done;
11598b834852SAlex Deucher 
11608b834852SAlex Deucher 	if (!ASIC_IS_DCE4(rdev))
11612dafb74dSAlex Deucher 		goto done;
11628b834852SAlex Deucher 
1163e468e001SStefan Weil 	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
11648b834852SAlex Deucher 	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
11652dafb74dSAlex Deucher 		goto done;
11668b834852SAlex Deucher 
11678b834852SAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
11682dafb74dSAlex Deucher 		goto done;
11698b834852SAlex Deucher 
11708b834852SAlex Deucher 	memset(&args, 0, sizeof(args));
11718b834852SAlex Deucher 
11728b834852SAlex Deucher 	args.v1.ucAction = action;
11738b834852SAlex Deucher 
11748b834852SAlex Deucher 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
11752dafb74dSAlex Deucher 
11762dafb74dSAlex Deucher 	/* wait for the panel to power up */
11772dafb74dSAlex Deucher 	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
11782dafb74dSAlex Deucher 		int i;
11792dafb74dSAlex Deucher 
11802dafb74dSAlex Deucher 		for (i = 0; i < 300; i++) {
11812dafb74dSAlex Deucher 			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
11822dafb74dSAlex Deucher 				return true;
11832dafb74dSAlex Deucher 			mdelay(1);
11842dafb74dSAlex Deucher 		}
11852dafb74dSAlex Deucher 		return false;
11862dafb74dSAlex Deucher 	}
11872dafb74dSAlex Deucher done:
11882dafb74dSAlex Deucher 	return true;
11898b834852SAlex Deucher }
11908b834852SAlex Deucher 
11913e4b9982SAlex Deucher union external_encoder_control {
11923e4b9982SAlex Deucher 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
1193bf982ebfSAlex Deucher 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
11943e4b9982SAlex Deucher };
11953e4b9982SAlex Deucher 
11963e4b9982SAlex Deucher static void
11973e4b9982SAlex Deucher atombios_external_encoder_setup(struct drm_encoder *encoder,
11983e4b9982SAlex Deucher 				struct drm_encoder *ext_encoder,
11993e4b9982SAlex Deucher 				int action)
12003e4b9982SAlex Deucher {
12013e4b9982SAlex Deucher 	struct drm_device *dev = encoder->dev;
12023e4b9982SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
12033e4b9982SAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1204bf982ebfSAlex Deucher 	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
12053e4b9982SAlex Deucher 	union external_encoder_control args;
1206ac89af1eSAlex Deucher 	struct drm_connector *connector;
12073e4b9982SAlex Deucher 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
12083e4b9982SAlex Deucher 	u8 frev, crev;
12093e4b9982SAlex Deucher 	int dp_clock = 0;
12103e4b9982SAlex Deucher 	int dp_lane_count = 0;
12113e4b9982SAlex Deucher 	int connector_object_id = 0;
1212bf982ebfSAlex Deucher 	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
1213df271becSAlex Deucher 	int bpc = 8;
12143e4b9982SAlex Deucher 
1215ac89af1eSAlex Deucher 	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1216ac89af1eSAlex Deucher 		connector = radeon_get_connector_for_encoder_init(encoder);
1217ac89af1eSAlex Deucher 	else
1218ac89af1eSAlex Deucher 		connector = radeon_get_connector_for_encoder(encoder);
1219ac89af1eSAlex Deucher 
12203e4b9982SAlex Deucher 	if (connector) {
12213e4b9982SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
12223e4b9982SAlex Deucher 		struct radeon_connector_atom_dig *dig_connector =
12233e4b9982SAlex Deucher 			radeon_connector->con_priv;
12243e4b9982SAlex Deucher 
12253e4b9982SAlex Deucher 		dp_clock = dig_connector->dp_clock;
12263e4b9982SAlex Deucher 		dp_lane_count = dig_connector->dp_lane_count;
12273e4b9982SAlex Deucher 		connector_object_id =
12283e4b9982SAlex Deucher 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1229df271becSAlex Deucher 		bpc = connector->display_info.bpc;
12303e4b9982SAlex Deucher 	}
12313e4b9982SAlex Deucher 
12323e4b9982SAlex Deucher 	memset(&args, 0, sizeof(args));
12333e4b9982SAlex Deucher 
12343e4b9982SAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
12353e4b9982SAlex Deucher 		return;
12363e4b9982SAlex Deucher 
12373e4b9982SAlex Deucher 	switch (frev) {
12383e4b9982SAlex Deucher 	case 1:
12393e4b9982SAlex Deucher 		/* no params on frev 1 */
12403e4b9982SAlex Deucher 		break;
12413e4b9982SAlex Deucher 	case 2:
12423e4b9982SAlex Deucher 		switch (crev) {
12433e4b9982SAlex Deucher 		case 1:
12443e4b9982SAlex Deucher 		case 2:
12453e4b9982SAlex Deucher 			args.v1.sDigEncoder.ucAction = action;
12463e4b9982SAlex Deucher 			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
12473e4b9982SAlex Deucher 			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
12483e4b9982SAlex Deucher 
12493e4b9982SAlex Deucher 			if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
12503e4b9982SAlex Deucher 				if (dp_clock == 270000)
12513e4b9982SAlex Deucher 					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
12523e4b9982SAlex Deucher 				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
12533e4b9982SAlex Deucher 			} else if (radeon_encoder->pixel_clock > 165000)
12543e4b9982SAlex Deucher 				args.v1.sDigEncoder.ucLaneNum = 8;
12553e4b9982SAlex Deucher 			else
12563e4b9982SAlex Deucher 				args.v1.sDigEncoder.ucLaneNum = 4;
12573e4b9982SAlex Deucher 			break;
1258bf982ebfSAlex Deucher 		case 3:
1259bf982ebfSAlex Deucher 			args.v3.sExtEncoder.ucAction = action;
1260bf982ebfSAlex Deucher 			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
12614589433cSCédric Cano 				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
1262bf982ebfSAlex Deucher 			else
1263bf982ebfSAlex Deucher 				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1264bf982ebfSAlex Deucher 			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1265bf982ebfSAlex Deucher 
1266bf982ebfSAlex Deucher 			if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
1267bf982ebfSAlex Deucher 				if (dp_clock == 270000)
1268bf982ebfSAlex Deucher 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1269bf982ebfSAlex Deucher 				else if (dp_clock == 540000)
1270bf982ebfSAlex Deucher 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1271bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
1272bf982ebfSAlex Deucher 			} else if (radeon_encoder->pixel_clock > 165000)
1273bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucLaneNum = 8;
1274bf982ebfSAlex Deucher 			else
1275bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucLaneNum = 4;
1276bf982ebfSAlex Deucher 			switch (ext_enum) {
1277bf982ebfSAlex Deucher 			case GRAPH_OBJECT_ENUM_ID1:
1278bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1279bf982ebfSAlex Deucher 				break;
1280bf982ebfSAlex Deucher 			case GRAPH_OBJECT_ENUM_ID2:
1281bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1282bf982ebfSAlex Deucher 				break;
1283bf982ebfSAlex Deucher 			case GRAPH_OBJECT_ENUM_ID3:
1284bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1285bf982ebfSAlex Deucher 				break;
1286bf982ebfSAlex Deucher 			}
1287df271becSAlex Deucher 			switch (bpc) {
1288df271becSAlex Deucher 			case 0:
1289df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
1290df271becSAlex Deucher 				break;
1291df271becSAlex Deucher 			case 6:
1292df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
1293df271becSAlex Deucher 				break;
1294df271becSAlex Deucher 			case 8:
1295df271becSAlex Deucher 			default:
1296bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
1297bf982ebfSAlex Deucher 				break;
1298df271becSAlex Deucher 			case 10:
1299df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
1300df271becSAlex Deucher 				break;
1301df271becSAlex Deucher 			case 12:
1302df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
1303df271becSAlex Deucher 				break;
1304df271becSAlex Deucher 			case 16:
1305df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
1306df271becSAlex Deucher 				break;
1307df271becSAlex Deucher 			}
1308df271becSAlex Deucher 			break;
13093e4b9982SAlex Deucher 		default:
13103e4b9982SAlex Deucher 			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
13113e4b9982SAlex Deucher 			return;
13123e4b9982SAlex Deucher 		}
13133e4b9982SAlex Deucher 		break;
13143e4b9982SAlex Deucher 	default:
13153e4b9982SAlex Deucher 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
13163e4b9982SAlex Deucher 		return;
13173e4b9982SAlex Deucher 	}
13183e4b9982SAlex Deucher 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
13193e4b9982SAlex Deucher }
13203e4b9982SAlex Deucher 
1321771fe6b9SJerome Glisse static void
1322771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
1323771fe6b9SJerome Glisse {
1324771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1325771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1326771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1327771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1328771fe6b9SJerome Glisse 	ENABLE_YUV_PS_ALLOCATION args;
1329771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
1330771fe6b9SJerome Glisse 	uint32_t temp, reg;
1331771fe6b9SJerome Glisse 
1332771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1333771fe6b9SJerome Glisse 
1334771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
1335771fe6b9SJerome Glisse 		reg = R600_BIOS_3_SCRATCH;
1336771fe6b9SJerome Glisse 	else
1337771fe6b9SJerome Glisse 		reg = RADEON_BIOS_3_SCRATCH;
1338771fe6b9SJerome Glisse 
1339771fe6b9SJerome Glisse 	/* XXX: fix up scratch reg handling */
1340771fe6b9SJerome Glisse 	temp = RREG32(reg);
13414ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1342771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
1343771fe6b9SJerome Glisse 			     (radeon_crtc->crtc_id << 18)));
13444ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1345771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
1346771fe6b9SJerome Glisse 	else
1347771fe6b9SJerome Glisse 		WREG32(reg, 0);
1348771fe6b9SJerome Glisse 
1349771fe6b9SJerome Glisse 	if (enable)
1350771fe6b9SJerome Glisse 		args.ucEnable = ATOM_ENABLE;
1351771fe6b9SJerome Glisse 	args.ucCRTC = radeon_crtc->crtc_id;
1352771fe6b9SJerome Glisse 
1353771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1354771fe6b9SJerome Glisse 
1355771fe6b9SJerome Glisse 	WREG32(reg, temp);
1356771fe6b9SJerome Glisse }
1357771fe6b9SJerome Glisse 
1358771fe6b9SJerome Glisse static void
1359771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1360771fe6b9SJerome Glisse {
1361771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1362771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1363771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
13643e4b9982SAlex Deucher 	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
1365771fe6b9SJerome Glisse 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1366771fe6b9SJerome Glisse 	int index = 0;
1367771fe6b9SJerome Glisse 	bool is_dig = false;
136869c74525SAlex Deucher 	bool is_dce5_dac = false;
1369d07f4e83SAlex Deucher 	bool is_dce5_dvo = false;
1370771fe6b9SJerome Glisse 
1371771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1372771fe6b9SJerome Glisse 
1373d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
13744ce001abSDave Airlie 		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
13754ce001abSDave Airlie 		  radeon_encoder->active_device);
1376771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1377771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1378771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1379771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1380771fe6b9SJerome Glisse 		break;
1381771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1382771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1383771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1384771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1385771fe6b9SJerome Glisse 		is_dig = true;
1386771fe6b9SJerome Glisse 		break;
1387771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1388771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
138999999aaaSAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
139099999aaaSAlex Deucher 		break;
1391771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1392d07f4e83SAlex Deucher 		if (ASIC_IS_DCE5(rdev))
1393d07f4e83SAlex Deucher 			is_dce5_dvo = true;
1394d07f4e83SAlex Deucher 		else if (ASIC_IS_DCE3(rdev))
139599999aaaSAlex Deucher 			is_dig = true;
139699999aaaSAlex Deucher 		else
1397771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1398771fe6b9SJerome Glisse 		break;
1399771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1400771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1401771fe6b9SJerome Glisse 		break;
1402771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1403771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1404771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1405771fe6b9SJerome Glisse 		else
1406771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1407771fe6b9SJerome Glisse 		break;
1408771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1409771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
141069c74525SAlex Deucher 		if (ASIC_IS_DCE5(rdev))
141169c74525SAlex Deucher 			is_dce5_dac = true;
141269c74525SAlex Deucher 		else {
14138c2a6d73SAlex Deucher 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1414771fe6b9SJerome Glisse 				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
14158c2a6d73SAlex Deucher 			else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1416771fe6b9SJerome Glisse 				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1417771fe6b9SJerome Glisse 			else
1418771fe6b9SJerome Glisse 				index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
141969c74525SAlex Deucher 		}
1420771fe6b9SJerome Glisse 		break;
1421771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1422771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
14238c2a6d73SAlex Deucher 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1424771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
14258c2a6d73SAlex Deucher 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1426771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1427771fe6b9SJerome Glisse 		else
1428771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1429771fe6b9SJerome Glisse 		break;
1430771fe6b9SJerome Glisse 	}
1431771fe6b9SJerome Glisse 
1432771fe6b9SJerome Glisse 	if (is_dig) {
1433771fe6b9SJerome Glisse 		switch (mode) {
1434771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
14358323fa6bSAlex Deucher 			/* some early dce3.2 boards have a bug in their transmitter control table */
14368323fa6bSAlex Deucher 			if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
14378323fa6bSAlex Deucher 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
14388323fa6bSAlex Deucher 			else
1439a5f798ceSAlex Deucher 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
1440fb668c2fSAlex Deucher 			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
144158682f10SDave Airlie 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1442fb668c2fSAlex Deucher 
14438b834852SAlex Deucher 				if (connector &&
14448b834852SAlex Deucher 				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
14458b834852SAlex Deucher 					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
14468b834852SAlex Deucher 					struct radeon_connector_atom_dig *radeon_dig_connector =
14478b834852SAlex Deucher 						radeon_connector->con_priv;
14488b834852SAlex Deucher 					atombios_set_edp_panel_power(connector,
14498b834852SAlex Deucher 								     ATOM_TRANSMITTER_ACTION_POWER_ON);
14508b834852SAlex Deucher 					radeon_dig_connector->edp_on = true;
14518b834852SAlex Deucher 				}
1452224d94b1SAlex Deucher 				if (ASIC_IS_DCE4(rdev))
1453224d94b1SAlex Deucher 					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
1454224d94b1SAlex Deucher 				radeon_dp_link_train(encoder, connector);
1455fb668c2fSAlex Deucher 				if (ASIC_IS_DCE4(rdev))
1456558e27dbSAlex Deucher 					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
145758682f10SDave Airlie 			}
1458ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1459ba251bdeSAlex Deucher 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
1460771fe6b9SJerome Glisse 			break;
1461771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1462771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1463771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
146458682f10SDave Airlie 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
1465fb668c2fSAlex Deucher 			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
14668b834852SAlex Deucher 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
14678b834852SAlex Deucher 
1468fb668c2fSAlex Deucher 				if (ASIC_IS_DCE4(rdev))
1469558e27dbSAlex Deucher 					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
14708b834852SAlex Deucher 				if (connector &&
14718b834852SAlex Deucher 				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
14728b834852SAlex Deucher 					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
14738b834852SAlex Deucher 					struct radeon_connector_atom_dig *radeon_dig_connector =
14748b834852SAlex Deucher 						radeon_connector->con_priv;
14758b834852SAlex Deucher 					atombios_set_edp_panel_power(connector,
14768b834852SAlex Deucher 								     ATOM_TRANSMITTER_ACTION_POWER_OFF);
14778b834852SAlex Deucher 					radeon_dig_connector->edp_on = false;
14788b834852SAlex Deucher 				}
1479fb668c2fSAlex Deucher 			}
1480ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1481ba251bdeSAlex Deucher 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1482771fe6b9SJerome Glisse 			break;
1483771fe6b9SJerome Glisse 		}
148469c74525SAlex Deucher 	} else if (is_dce5_dac) {
148569c74525SAlex Deucher 		switch (mode) {
148669c74525SAlex Deucher 		case DRM_MODE_DPMS_ON:
148769c74525SAlex Deucher 			atombios_dac_setup(encoder, ATOM_ENABLE);
148869c74525SAlex Deucher 			break;
148969c74525SAlex Deucher 		case DRM_MODE_DPMS_STANDBY:
149069c74525SAlex Deucher 		case DRM_MODE_DPMS_SUSPEND:
149169c74525SAlex Deucher 		case DRM_MODE_DPMS_OFF:
149269c74525SAlex Deucher 			atombios_dac_setup(encoder, ATOM_DISABLE);
149369c74525SAlex Deucher 			break;
149469c74525SAlex Deucher 		}
1495d07f4e83SAlex Deucher 	} else if (is_dce5_dvo) {
1496d07f4e83SAlex Deucher 		switch (mode) {
1497d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_ON:
1498d07f4e83SAlex Deucher 			atombios_dvo_setup(encoder, ATOM_ENABLE);
1499d07f4e83SAlex Deucher 			break;
1500d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_STANDBY:
1501d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_SUSPEND:
1502d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_OFF:
1503d07f4e83SAlex Deucher 			atombios_dvo_setup(encoder, ATOM_DISABLE);
1504d07f4e83SAlex Deucher 			break;
1505d07f4e83SAlex Deucher 		}
1506771fe6b9SJerome Glisse 	} else {
1507771fe6b9SJerome Glisse 		switch (mode) {
1508771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
1509771fe6b9SJerome Glisse 			args.ucAction = ATOM_ENABLE;
1510fdfc6159SAlex Deucher 			/* workaround for DVOOutputControl on some RS690 systems */
1511fdfc6159SAlex Deucher 			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
1512fdfc6159SAlex Deucher 				u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
1513fdfc6159SAlex Deucher 				WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
1514fdfc6159SAlex Deucher 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1515fdfc6159SAlex Deucher 				WREG32(RADEON_BIOS_3_SCRATCH, reg);
1516fdfc6159SAlex Deucher 			} else
1517ba251bdeSAlex Deucher 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1518ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1519ba251bdeSAlex Deucher 				args.ucAction = ATOM_LCD_BLON;
1520ba251bdeSAlex Deucher 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1521ba251bdeSAlex Deucher 			}
1522771fe6b9SJerome Glisse 			break;
1523771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1524771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1525771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
1526771fe6b9SJerome Glisse 			args.ucAction = ATOM_DISABLE;
1527ba251bdeSAlex Deucher 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1528ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1529ba251bdeSAlex Deucher 				args.ucAction = ATOM_LCD_BLOFF;
1530ba251bdeSAlex Deucher 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1531ba251bdeSAlex Deucher 			}
1532771fe6b9SJerome Glisse 			break;
1533771fe6b9SJerome Glisse 		}
1534771fe6b9SJerome Glisse 	}
15353e4b9982SAlex Deucher 
15363e4b9982SAlex Deucher 	if (ext_encoder) {
15373e4b9982SAlex Deucher 		switch (mode) {
15383e4b9982SAlex Deucher 		case DRM_MODE_DPMS_ON:
15393e4b9982SAlex Deucher 		default:
1540d6c66952SAlex Deucher 			if (ASIC_IS_DCE41(rdev)) {
1541d6c66952SAlex Deucher 				atombios_external_encoder_setup(encoder, ext_encoder,
1542d6c66952SAlex Deucher 								EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
1543d6c66952SAlex Deucher 				atombios_external_encoder_setup(encoder, ext_encoder,
1544d6c66952SAlex Deucher 								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
1545d6c66952SAlex Deucher 			} else
1546d6c66952SAlex Deucher 				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
15473e4b9982SAlex Deucher 			break;
15483e4b9982SAlex Deucher 		case DRM_MODE_DPMS_STANDBY:
15493e4b9982SAlex Deucher 		case DRM_MODE_DPMS_SUSPEND:
15503e4b9982SAlex Deucher 		case DRM_MODE_DPMS_OFF:
1551d6c66952SAlex Deucher 			if (ASIC_IS_DCE41(rdev)) {
1552d6c66952SAlex Deucher 				atombios_external_encoder_setup(encoder, ext_encoder,
1553d6c66952SAlex Deucher 								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
1554d6c66952SAlex Deucher 				atombios_external_encoder_setup(encoder, ext_encoder,
1555d6c66952SAlex Deucher 								EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
1556d6c66952SAlex Deucher 			} else
1557d6c66952SAlex Deucher 				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
15583e4b9982SAlex Deucher 			break;
15593e4b9982SAlex Deucher 		}
15603e4b9982SAlex Deucher 	}
15613e4b9982SAlex Deucher 
1562771fe6b9SJerome Glisse 	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1563c913e23aSRafał Miłecki 
1564771fe6b9SJerome Glisse }
1565771fe6b9SJerome Glisse 
15669ae47867SAlex Deucher union crtc_source_param {
1567771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
1568771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
1569771fe6b9SJerome Glisse };
1570771fe6b9SJerome Glisse 
1571771fe6b9SJerome Glisse static void
1572771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
1573771fe6b9SJerome Glisse {
1574771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1575771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1576771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1577771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
15789ae47867SAlex Deucher 	union crtc_source_param args;
1579771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1580771fe6b9SJerome Glisse 	uint8_t frev, crev;
1581f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
1582771fe6b9SJerome Glisse 
1583771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1584771fe6b9SJerome Glisse 
1585a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1586a084e6eeSAlex Deucher 		return;
1587771fe6b9SJerome Glisse 
1588771fe6b9SJerome Glisse 	switch (frev) {
1589771fe6b9SJerome Glisse 	case 1:
1590771fe6b9SJerome Glisse 		switch (crev) {
1591771fe6b9SJerome Glisse 		case 1:
1592771fe6b9SJerome Glisse 		default:
1593771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
1594771fe6b9SJerome Glisse 				args.v1.ucCRTC = radeon_crtc->crtc_id;
1595771fe6b9SJerome Glisse 			else {
1596771fe6b9SJerome Glisse 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
1597771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id;
1598771fe6b9SJerome Glisse 				} else {
1599771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
1600771fe6b9SJerome Glisse 				}
1601771fe6b9SJerome Glisse 			}
1602771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1603771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1604771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1605771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1606771fe6b9SJerome Glisse 				break;
1607771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1608771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1609771fe6b9SJerome Glisse 				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
1610771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1611771fe6b9SJerome Glisse 				else
1612771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1613771fe6b9SJerome Glisse 				break;
1614771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1615771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DDI:
1616771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1617771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1618771fe6b9SJerome Glisse 				break;
1619771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1620771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
16214ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1622771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
16234ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1624771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1625771fe6b9SJerome Glisse 				else
1626771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1627771fe6b9SJerome Glisse 				break;
1628771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1629771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
16304ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1631771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
16324ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1633771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1634771fe6b9SJerome Glisse 				else
1635771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1636771fe6b9SJerome Glisse 				break;
1637771fe6b9SJerome Glisse 			}
1638771fe6b9SJerome Glisse 			break;
1639771fe6b9SJerome Glisse 		case 2:
1640771fe6b9SJerome Glisse 			args.v2.ucCRTC = radeon_crtc->crtc_id;
1641*1d33e1fcSAlex Deucher 			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
1642a4863ca9SAlex Deucher 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1643a4863ca9SAlex Deucher 
1644a4863ca9SAlex Deucher 				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
1645a4863ca9SAlex Deucher 					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
1646a4863ca9SAlex Deucher 				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
1647a4863ca9SAlex Deucher 					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
1648a4863ca9SAlex Deucher 				else
1649a4863ca9SAlex Deucher 					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1650a4863ca9SAlex Deucher 			} else
1651771fe6b9SJerome Glisse 				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1652771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1653771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1654771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1655771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1656f28cf339SDave Airlie 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1657f28cf339SDave Airlie 				dig = radeon_encoder->enc_priv;
1658bcc1c2a1SAlex Deucher 				switch (dig->dig_encoder) {
1659bcc1c2a1SAlex Deucher 				case 0:
1660771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1661771fe6b9SJerome Glisse 					break;
1662bcc1c2a1SAlex Deucher 				case 1:
1663bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1664bcc1c2a1SAlex Deucher 					break;
1665bcc1c2a1SAlex Deucher 				case 2:
1666bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
1667bcc1c2a1SAlex Deucher 					break;
1668bcc1c2a1SAlex Deucher 				case 3:
1669bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
1670bcc1c2a1SAlex Deucher 					break;
1671bcc1c2a1SAlex Deucher 				case 4:
1672bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
1673bcc1c2a1SAlex Deucher 					break;
1674bcc1c2a1SAlex Deucher 				case 5:
1675bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
1676bcc1c2a1SAlex Deucher 					break;
1677bcc1c2a1SAlex Deucher 				}
1678bcc1c2a1SAlex Deucher 				break;
1679771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1680771fe6b9SJerome Glisse 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
1681771fe6b9SJerome Glisse 				break;
1682771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
16834ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1684771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
16854ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1686771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1687771fe6b9SJerome Glisse 				else
1688771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1689771fe6b9SJerome Glisse 				break;
1690771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
16914ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1692771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
16934ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1694771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1695771fe6b9SJerome Glisse 				else
1696771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1697771fe6b9SJerome Glisse 				break;
1698771fe6b9SJerome Glisse 			}
1699771fe6b9SJerome Glisse 			break;
1700771fe6b9SJerome Glisse 		}
1701771fe6b9SJerome Glisse 		break;
1702771fe6b9SJerome Glisse 	default:
1703771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
170499999aaaSAlex Deucher 		return;
1705771fe6b9SJerome Glisse 	}
1706771fe6b9SJerome Glisse 
1707771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1708267364acSAlex Deucher 
1709267364acSAlex Deucher 	/* update scratch regs with new routing */
1710267364acSAlex Deucher 	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1711771fe6b9SJerome Glisse }
1712771fe6b9SJerome Glisse 
1713771fe6b9SJerome Glisse static void
1714771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder,
1715771fe6b9SJerome Glisse 			      struct drm_display_mode *mode)
1716771fe6b9SJerome Glisse {
1717771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1718771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1719771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1720771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1721771fe6b9SJerome Glisse 
1722771fe6b9SJerome Glisse 	/* Funky macbooks */
1723771fe6b9SJerome Glisse 	if ((dev->pdev->device == 0x71C5) &&
1724771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_vendor == 0x106b) &&
1725771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_device == 0x0080)) {
1726771fe6b9SJerome Glisse 		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1727771fe6b9SJerome Glisse 			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1728771fe6b9SJerome Glisse 
1729771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1730771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1731771fe6b9SJerome Glisse 
1732771fe6b9SJerome Glisse 			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1733771fe6b9SJerome Glisse 		}
1734771fe6b9SJerome Glisse 	}
1735771fe6b9SJerome Glisse 
1736771fe6b9SJerome Glisse 	/* set scaler clears this on some chips */
1737c9417bddSAlex Deucher 	if (ASIC_IS_AVIVO(rdev) &&
1738c9417bddSAlex Deucher 	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
1739c9417bddSAlex Deucher 		if (ASIC_IS_DCE4(rdev)) {
1740c9417bddSAlex Deucher 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1741c9417bddSAlex Deucher 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
1742c9417bddSAlex Deucher 				       EVERGREEN_INTERLEAVE_EN);
1743c9417bddSAlex Deucher 			else
1744c9417bddSAlex Deucher 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1745c9417bddSAlex Deucher 		} else {
1746c9417bddSAlex Deucher 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1747ceefedd8SAlex Deucher 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
1748ceefedd8SAlex Deucher 				       AVIVO_D1MODE_INTERLEAVE_EN);
1749c9417bddSAlex Deucher 			else
1750c9417bddSAlex Deucher 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1751c9417bddSAlex Deucher 		}
1752ceefedd8SAlex Deucher 	}
1753771fe6b9SJerome Glisse }
1754771fe6b9SJerome Glisse 
1755f28cf339SDave Airlie static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
1756f28cf339SDave Airlie {
1757f28cf339SDave Airlie 	struct drm_device *dev = encoder->dev;
1758f28cf339SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
1759f28cf339SDave Airlie 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1760f28cf339SDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1761f28cf339SDave Airlie 	struct drm_encoder *test_encoder;
1762f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
1763f28cf339SDave Airlie 	uint32_t dig_enc_in_use = 0;
1764bcc1c2a1SAlex Deucher 
1765badbb57bSAlex Deucher 	/* DCE4/5 */
1766bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev)) {
17675137ee94SAlex Deucher 		dig = radeon_encoder->enc_priv;
1768cb7cf419SAlex Deucher 		if (ASIC_IS_DCE41(rdev)) {
17693a6dea31SAlex Deucher 			/* ontario follows DCE4 */
17703a6dea31SAlex Deucher 			if (rdev->family == CHIP_PALM) {
1771cb7cf419SAlex Deucher 				if (dig->linkb)
1772cb7cf419SAlex Deucher 					return 1;
1773cb7cf419SAlex Deucher 				else
1774cb7cf419SAlex Deucher 					return 0;
17753a6dea31SAlex Deucher 			} else
17763a6dea31SAlex Deucher 				/* llano follows DCE3.2 */
17773a6dea31SAlex Deucher 				return radeon_crtc->crtc_id;
1778cb7cf419SAlex Deucher 		} else {
1779bcc1c2a1SAlex Deucher 			switch (radeon_encoder->encoder_id) {
1780bcc1c2a1SAlex Deucher 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
17815137ee94SAlex Deucher 				if (dig->linkb)
1782bcc1c2a1SAlex Deucher 					return 1;
1783bcc1c2a1SAlex Deucher 				else
1784bcc1c2a1SAlex Deucher 					return 0;
1785bcc1c2a1SAlex Deucher 				break;
1786bcc1c2a1SAlex Deucher 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
17875137ee94SAlex Deucher 				if (dig->linkb)
1788bcc1c2a1SAlex Deucher 					return 3;
1789bcc1c2a1SAlex Deucher 				else
1790bcc1c2a1SAlex Deucher 					return 2;
1791bcc1c2a1SAlex Deucher 				break;
1792bcc1c2a1SAlex Deucher 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
17935137ee94SAlex Deucher 				if (dig->linkb)
1794bcc1c2a1SAlex Deucher 					return 5;
1795bcc1c2a1SAlex Deucher 				else
1796bcc1c2a1SAlex Deucher 					return 4;
1797bcc1c2a1SAlex Deucher 				break;
1798bcc1c2a1SAlex Deucher 			}
1799bcc1c2a1SAlex Deucher 		}
1800b61c99deSAlex Deucher 	}
1801bcc1c2a1SAlex Deucher 
1802f28cf339SDave Airlie 	/* on DCE32 and encoder can driver any block so just crtc id */
1803f28cf339SDave Airlie 	if (ASIC_IS_DCE32(rdev)) {
1804f28cf339SDave Airlie 		return radeon_crtc->crtc_id;
1805f28cf339SDave Airlie 	}
1806f28cf339SDave Airlie 
1807f28cf339SDave Airlie 	/* on DCE3 - LVTMA can only be driven by DIGB */
1808f28cf339SDave Airlie 	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
1809f28cf339SDave Airlie 		struct radeon_encoder *radeon_test_encoder;
1810f28cf339SDave Airlie 
1811f28cf339SDave Airlie 		if (encoder == test_encoder)
1812f28cf339SDave Airlie 			continue;
1813f28cf339SDave Airlie 
1814f28cf339SDave Airlie 		if (!radeon_encoder_is_digital(test_encoder))
1815f28cf339SDave Airlie 			continue;
1816f28cf339SDave Airlie 
1817f28cf339SDave Airlie 		radeon_test_encoder = to_radeon_encoder(test_encoder);
1818f28cf339SDave Airlie 		dig = radeon_test_encoder->enc_priv;
1819f28cf339SDave Airlie 
1820f28cf339SDave Airlie 		if (dig->dig_encoder >= 0)
1821f28cf339SDave Airlie 			dig_enc_in_use |= (1 << dig->dig_encoder);
1822f28cf339SDave Airlie 	}
1823f28cf339SDave Airlie 
1824f28cf339SDave Airlie 	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
1825f28cf339SDave Airlie 		if (dig_enc_in_use & 0x2)
1826f28cf339SDave Airlie 			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
1827f28cf339SDave Airlie 		return 1;
1828f28cf339SDave Airlie 	}
1829f28cf339SDave Airlie 	if (!(dig_enc_in_use & 1))
1830f28cf339SDave Airlie 		return 0;
1831f28cf339SDave Airlie 	return 1;
1832f28cf339SDave Airlie }
1833f28cf339SDave Airlie 
1834ac89af1eSAlex Deucher /* This only needs to be called once at startup */
1835ac89af1eSAlex Deucher void
1836ac89af1eSAlex Deucher radeon_atom_encoder_init(struct radeon_device *rdev)
1837ac89af1eSAlex Deucher {
1838ac89af1eSAlex Deucher 	struct drm_device *dev = rdev->ddev;
1839ac89af1eSAlex Deucher 	struct drm_encoder *encoder;
1840ac89af1eSAlex Deucher 
1841ac89af1eSAlex Deucher 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1842ac89af1eSAlex Deucher 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1843ac89af1eSAlex Deucher 		struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
1844ac89af1eSAlex Deucher 
1845ac89af1eSAlex Deucher 		switch (radeon_encoder->encoder_id) {
1846ac89af1eSAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1847ac89af1eSAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1848ac89af1eSAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1849ac89af1eSAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1850ac89af1eSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
1851ac89af1eSAlex Deucher 			break;
1852ac89af1eSAlex Deucher 		default:
1853ac89af1eSAlex Deucher 			break;
1854ac89af1eSAlex Deucher 		}
1855ac89af1eSAlex Deucher 
1856ac89af1eSAlex Deucher 		if (ext_encoder && ASIC_IS_DCE41(rdev))
1857ac89af1eSAlex Deucher 			atombios_external_encoder_setup(encoder, ext_encoder,
1858ac89af1eSAlex Deucher 							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
1859ac89af1eSAlex Deucher 	}
1860ac89af1eSAlex Deucher }
1861ac89af1eSAlex Deucher 
1862771fe6b9SJerome Glisse static void
1863771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1864771fe6b9SJerome Glisse 			     struct drm_display_mode *mode,
1865771fe6b9SJerome Glisse 			     struct drm_display_mode *adjusted_mode)
1866771fe6b9SJerome Glisse {
1867771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1868771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1869771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
18703e4b9982SAlex Deucher 	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
1871771fe6b9SJerome Glisse 
1872771fe6b9SJerome Glisse 	radeon_encoder->pixel_clock = adjusted_mode->clock;
1873771fe6b9SJerome Glisse 
1874c6f8505eSAlex Deucher 	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
18754ce001abSDave Airlie 		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
1876771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, true);
1877771fe6b9SJerome Glisse 		else
1878771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, false);
1879771fe6b9SJerome Glisse 	}
1880771fe6b9SJerome Glisse 
1881771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1882771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1883771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1884771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1885771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1886771fe6b9SJerome Glisse 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
1887771fe6b9SJerome Glisse 		break;
1888771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1889771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1890771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1891771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1892bcc1c2a1SAlex Deucher 		if (ASIC_IS_DCE4(rdev)) {
1893bcc1c2a1SAlex Deucher 			/* disable the transmitter */
1894bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1895bcc1c2a1SAlex Deucher 			/* setup and enable the encoder */
1896558e27dbSAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1897bcc1c2a1SAlex Deucher 
1898ac89af1eSAlex Deucher 			/* enable the transmitter */
1899bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1900bcc1c2a1SAlex Deucher 		} else {
1901771fe6b9SJerome Glisse 			/* disable the encoder and transmitter */
19021a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1903558e27dbSAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
1904771fe6b9SJerome Glisse 
1905771fe6b9SJerome Glisse 			/* setup and enable the encoder and transmitter */
1906558e27dbSAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
19071a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
19081a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1909bcc1c2a1SAlex Deucher 		}
1910771fe6b9SJerome Glisse 		break;
1911771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1912771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1913771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
191499999aaaSAlex Deucher 		atombios_dvo_setup(encoder, ATOM_ENABLE);
1915771fe6b9SJerome Glisse 		break;
1916771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1917771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1918771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1919771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1920771fe6b9SJerome Glisse 		atombios_dac_setup(encoder, ATOM_ENABLE);
1921d3a67a43SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
19224ce001abSDave Airlie 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
1923771fe6b9SJerome Glisse 				atombios_tv_setup(encoder, ATOM_ENABLE);
1924d3a67a43SAlex Deucher 			else
1925d3a67a43SAlex Deucher 				atombios_tv_setup(encoder, ATOM_DISABLE);
1926d3a67a43SAlex Deucher 		}
1927771fe6b9SJerome Glisse 		break;
1928771fe6b9SJerome Glisse 	}
19293e4b9982SAlex Deucher 
19303e4b9982SAlex Deucher 	if (ext_encoder) {
1931ac89af1eSAlex Deucher 		if (ASIC_IS_DCE41(rdev))
1932bf982ebfSAlex Deucher 			atombios_external_encoder_setup(encoder, ext_encoder,
1933bf982ebfSAlex Deucher 							EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
1934ac89af1eSAlex Deucher 		else
19353e4b9982SAlex Deucher 			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
19363e4b9982SAlex Deucher 	}
19373e4b9982SAlex Deucher 
1938771fe6b9SJerome Glisse 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
1939dafc3bd5SChristian Koenig 
19402cd6218cSRafał Miłecki 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
19412cd6218cSRafał Miłecki 		r600_hdmi_enable(encoder);
1942dafc3bd5SChristian Koenig 		r600_hdmi_setmode(encoder, adjusted_mode);
1943771fe6b9SJerome Glisse 	}
19442cd6218cSRafał Miłecki }
1945771fe6b9SJerome Glisse 
1946771fe6b9SJerome Glisse static bool
19474ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1948771fe6b9SJerome Glisse {
1949771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1950771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1951771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
19524ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1953771fe6b9SJerome Glisse 
1954771fe6b9SJerome Glisse 	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
1955771fe6b9SJerome Glisse 				       ATOM_DEVICE_CV_SUPPORT |
1956771fe6b9SJerome Glisse 				       ATOM_DEVICE_CRT_SUPPORT)) {
1957771fe6b9SJerome Glisse 		DAC_LOAD_DETECTION_PS_ALLOCATION args;
1958771fe6b9SJerome Glisse 		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1959771fe6b9SJerome Glisse 		uint8_t frev, crev;
1960771fe6b9SJerome Glisse 
1961771fe6b9SJerome Glisse 		memset(&args, 0, sizeof(args));
1962771fe6b9SJerome Glisse 
1963a084e6eeSAlex Deucher 		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1964a084e6eeSAlex Deucher 			return false;
1965771fe6b9SJerome Glisse 
1966771fe6b9SJerome Glisse 		args.sDacload.ucMisc = 0;
1967771fe6b9SJerome Glisse 
1968771fe6b9SJerome Glisse 		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1969771fe6b9SJerome Glisse 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
1970771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_A;
1971771fe6b9SJerome Glisse 		else
1972771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_B;
1973771fe6b9SJerome Glisse 
19744ce001abSDave Airlie 		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
1975771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
19764ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
1977771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
19784ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
1979771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
1980771fe6b9SJerome Glisse 			if (crev >= 3)
1981771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
19824ce001abSDave Airlie 		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
1983771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
1984771fe6b9SJerome Glisse 			if (crev >= 3)
1985771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1986771fe6b9SJerome Glisse 		}
1987771fe6b9SJerome Glisse 
1988771fe6b9SJerome Glisse 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1989771fe6b9SJerome Glisse 
1990771fe6b9SJerome Glisse 		return true;
1991771fe6b9SJerome Glisse 	} else
1992771fe6b9SJerome Glisse 		return false;
1993771fe6b9SJerome Glisse }
1994771fe6b9SJerome Glisse 
1995771fe6b9SJerome Glisse static enum drm_connector_status
1996771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1997771fe6b9SJerome Glisse {
1998771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1999771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
2000771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
20014ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2002771fe6b9SJerome Glisse 	uint32_t bios_0_scratch;
2003771fe6b9SJerome Glisse 
20044ce001abSDave Airlie 	if (!atombios_dac_load_detect(encoder, connector)) {
2005d9fdaafbSDave Airlie 		DRM_DEBUG_KMS("detect returned false \n");
2006771fe6b9SJerome Glisse 		return connector_status_unknown;
2007771fe6b9SJerome Glisse 	}
2008771fe6b9SJerome Glisse 
2009771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
2010771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2011771fe6b9SJerome Glisse 	else
2012771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
2013771fe6b9SJerome Glisse 
2014d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
20154ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2016771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2017771fe6b9SJerome Glisse 			return connector_status_connected;
20184ce001abSDave Airlie 	}
20194ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2020771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2021771fe6b9SJerome Glisse 			return connector_status_connected;
20224ce001abSDave Airlie 	}
20234ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2024771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2025771fe6b9SJerome Glisse 			return connector_status_connected;
20264ce001abSDave Airlie 	}
20274ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2028771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2029771fe6b9SJerome Glisse 			return connector_status_connected; /* CTV */
2030771fe6b9SJerome Glisse 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2031771fe6b9SJerome Glisse 			return connector_status_connected; /* STV */
2032771fe6b9SJerome Glisse 	}
2033771fe6b9SJerome Glisse 	return connector_status_disconnected;
2034771fe6b9SJerome Glisse }
2035771fe6b9SJerome Glisse 
2036d629a3ceSAlex Deucher static enum drm_connector_status
2037d629a3ceSAlex Deucher radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2038d629a3ceSAlex Deucher {
2039d629a3ceSAlex Deucher 	struct drm_device *dev = encoder->dev;
2040d629a3ceSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
2041d629a3ceSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2042d629a3ceSAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2043d629a3ceSAlex Deucher 	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
2044d629a3ceSAlex Deucher 	u32 bios_0_scratch;
2045d629a3ceSAlex Deucher 
2046d629a3ceSAlex Deucher 	if (!ASIC_IS_DCE4(rdev))
2047d629a3ceSAlex Deucher 		return connector_status_unknown;
2048d629a3ceSAlex Deucher 
2049d629a3ceSAlex Deucher 	if (!ext_encoder)
2050d629a3ceSAlex Deucher 		return connector_status_unknown;
2051d629a3ceSAlex Deucher 
2052d629a3ceSAlex Deucher 	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
2053d629a3ceSAlex Deucher 		return connector_status_unknown;
2054d629a3ceSAlex Deucher 
2055d629a3ceSAlex Deucher 	/* load detect on the dp bridge */
2056d629a3ceSAlex Deucher 	atombios_external_encoder_setup(encoder, ext_encoder,
2057d629a3ceSAlex Deucher 					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
2058d629a3ceSAlex Deucher 
2059d629a3ceSAlex Deucher 	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2060d629a3ceSAlex Deucher 
2061d629a3ceSAlex Deucher 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
2062d629a3ceSAlex Deucher 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2063d629a3ceSAlex Deucher 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2064d629a3ceSAlex Deucher 			return connector_status_connected;
2065d629a3ceSAlex Deucher 	}
2066d629a3ceSAlex Deucher 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2067d629a3ceSAlex Deucher 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2068d629a3ceSAlex Deucher 			return connector_status_connected;
2069d629a3ceSAlex Deucher 	}
2070d629a3ceSAlex Deucher 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2071d629a3ceSAlex Deucher 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2072d629a3ceSAlex Deucher 			return connector_status_connected;
2073d629a3ceSAlex Deucher 	}
2074d629a3ceSAlex Deucher 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2075d629a3ceSAlex Deucher 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2076d629a3ceSAlex Deucher 			return connector_status_connected; /* CTV */
2077d629a3ceSAlex Deucher 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2078d629a3ceSAlex Deucher 			return connector_status_connected; /* STV */
2079d629a3ceSAlex Deucher 	}
2080d629a3ceSAlex Deucher 	return connector_status_disconnected;
2081d629a3ceSAlex Deucher }
2082d629a3ceSAlex Deucher 
2083591a10e1SAlex Deucher void
2084591a10e1SAlex Deucher radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
2085591a10e1SAlex Deucher {
2086591a10e1SAlex Deucher 	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
2087591a10e1SAlex Deucher 
2088591a10e1SAlex Deucher 	if (ext_encoder)
2089591a10e1SAlex Deucher 		/* ddc_setup on the dp bridge */
2090591a10e1SAlex Deucher 		atombios_external_encoder_setup(encoder, ext_encoder,
2091591a10e1SAlex Deucher 						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
2092591a10e1SAlex Deucher 
2093591a10e1SAlex Deucher }
2094591a10e1SAlex Deucher 
2095771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
2096771fe6b9SJerome Glisse {
2097267364acSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2098fb939dfcSAlex Deucher 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
2099267364acSAlex Deucher 
2100eac4dff6SAlex Deucher 	if ((radeon_encoder->active_device &
2101eac4dff6SAlex Deucher 	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
2102*1d33e1fcSAlex Deucher 	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
2103*1d33e1fcSAlex Deucher 	     ENCODER_OBJECT_ID_NONE)) {
2104267364acSAlex Deucher 		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
2105267364acSAlex Deucher 		if (dig)
2106267364acSAlex Deucher 			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
2107267364acSAlex Deucher 	}
2108267364acSAlex Deucher 
2109771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, true);
2110771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2111267364acSAlex Deucher 
2112fb939dfcSAlex Deucher 	if (connector) {
2113fb939dfcSAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
21144e633939SAlex Deucher 
21154e633939SAlex Deucher 		/* select the clock/data port if it uses a router */
2116fb939dfcSAlex Deucher 		if (radeon_connector->router.cd_valid)
2117fb939dfcSAlex Deucher 			radeon_router_select_cd_port(radeon_connector);
21184e633939SAlex Deucher 
21194e633939SAlex Deucher 		/* turn eDP panel on for mode set */
21204e633939SAlex Deucher 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
21214e633939SAlex Deucher 			atombios_set_edp_panel_power(connector,
21224e633939SAlex Deucher 						     ATOM_TRANSMITTER_ACTION_POWER_ON);
2123fb939dfcSAlex Deucher 	}
2124fb939dfcSAlex Deucher 
2125267364acSAlex Deucher 	/* this is needed for the pll/ss setup to work correctly in some cases */
2126267364acSAlex Deucher 	atombios_set_encoder_crtc_source(encoder);
2127771fe6b9SJerome Glisse }
2128771fe6b9SJerome Glisse 
2129771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
2130771fe6b9SJerome Glisse {
2131771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
2132771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, false);
2133771fe6b9SJerome Glisse }
2134771fe6b9SJerome Glisse 
21354ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
21364ce001abSDave Airlie {
2137aa961391SAlex Deucher 	struct drm_device *dev = encoder->dev;
2138aa961391SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
21394ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2140f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
2141a0ae5864SAlex Deucher 
2142a0ae5864SAlex Deucher 	/* check for pre-DCE3 cards with shared encoders;
2143a0ae5864SAlex Deucher 	 * can't really use the links individually, so don't disable
2144a0ae5864SAlex Deucher 	 * the encoder if it's in use by another connector
2145a0ae5864SAlex Deucher 	 */
2146a0ae5864SAlex Deucher 	if (!ASIC_IS_DCE3(rdev)) {
2147a0ae5864SAlex Deucher 		struct drm_encoder *other_encoder;
2148a0ae5864SAlex Deucher 		struct radeon_encoder *other_radeon_encoder;
2149a0ae5864SAlex Deucher 
2150a0ae5864SAlex Deucher 		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
2151a0ae5864SAlex Deucher 			other_radeon_encoder = to_radeon_encoder(other_encoder);
2152a0ae5864SAlex Deucher 			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
2153a0ae5864SAlex Deucher 			    drm_helper_encoder_in_use(other_encoder))
2154a0ae5864SAlex Deucher 				goto disable_done;
2155a0ae5864SAlex Deucher 		}
2156a0ae5864SAlex Deucher 	}
2157a0ae5864SAlex Deucher 
21584ce001abSDave Airlie 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2159f28cf339SDave Airlie 
2160aa961391SAlex Deucher 	switch (radeon_encoder->encoder_id) {
2161aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2162aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2163aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2164aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2165aa961391SAlex Deucher 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
2166aa961391SAlex Deucher 		break;
2167aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2168aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2169aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2170aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2171aa961391SAlex Deucher 		if (ASIC_IS_DCE4(rdev))
2172aa961391SAlex Deucher 			/* disable the transmitter */
2173aa961391SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
2174aa961391SAlex Deucher 		else {
2175aa961391SAlex Deucher 			/* disable the encoder and transmitter */
2176aa961391SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
2177558e27dbSAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
2178aa961391SAlex Deucher 		}
2179aa961391SAlex Deucher 		break;
2180aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2181aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2182aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
218399999aaaSAlex Deucher 		atombios_dvo_setup(encoder, ATOM_DISABLE);
2184aa961391SAlex Deucher 		break;
2185aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2186aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2187aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2188aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2189aa961391SAlex Deucher 		atombios_dac_setup(encoder, ATOM_DISABLE);
21908bf3aae6SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2191aa961391SAlex Deucher 			atombios_tv_setup(encoder, ATOM_DISABLE);
2192aa961391SAlex Deucher 		break;
2193aa961391SAlex Deucher 	}
2194aa961391SAlex Deucher 
2195a0ae5864SAlex Deucher disable_done:
2196f28cf339SDave Airlie 	if (radeon_encoder_is_digital(encoder)) {
21972cd6218cSRafał Miłecki 		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
21982cd6218cSRafał Miłecki 			r600_hdmi_disable(encoder);
2199f28cf339SDave Airlie 		dig = radeon_encoder->enc_priv;
2200f28cf339SDave Airlie 		dig->dig_encoder = -1;
2201f28cf339SDave Airlie 	}
22024ce001abSDave Airlie 	radeon_encoder->active_device = 0;
22034ce001abSDave Airlie }
22044ce001abSDave Airlie 
22053e4b9982SAlex Deucher /* these are handled by the primary encoders */
22063e4b9982SAlex Deucher static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
22073e4b9982SAlex Deucher {
22083e4b9982SAlex Deucher 
22093e4b9982SAlex Deucher }
22103e4b9982SAlex Deucher 
22113e4b9982SAlex Deucher static void radeon_atom_ext_commit(struct drm_encoder *encoder)
22123e4b9982SAlex Deucher {
22133e4b9982SAlex Deucher 
22143e4b9982SAlex Deucher }
22153e4b9982SAlex Deucher 
22163e4b9982SAlex Deucher static void
22173e4b9982SAlex Deucher radeon_atom_ext_mode_set(struct drm_encoder *encoder,
22183e4b9982SAlex Deucher 			 struct drm_display_mode *mode,
22193e4b9982SAlex Deucher 			 struct drm_display_mode *adjusted_mode)
22203e4b9982SAlex Deucher {
22213e4b9982SAlex Deucher 
22223e4b9982SAlex Deucher }
22233e4b9982SAlex Deucher 
22243e4b9982SAlex Deucher static void radeon_atom_ext_disable(struct drm_encoder *encoder)
22253e4b9982SAlex Deucher {
22263e4b9982SAlex Deucher 
22273e4b9982SAlex Deucher }
22283e4b9982SAlex Deucher 
22293e4b9982SAlex Deucher static void
22303e4b9982SAlex Deucher radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
22313e4b9982SAlex Deucher {
22323e4b9982SAlex Deucher 
22333e4b9982SAlex Deucher }
22343e4b9982SAlex Deucher 
22353e4b9982SAlex Deucher static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
22363e4b9982SAlex Deucher 				       struct drm_display_mode *mode,
22373e4b9982SAlex Deucher 				       struct drm_display_mode *adjusted_mode)
22383e4b9982SAlex Deucher {
22393e4b9982SAlex Deucher 	return true;
22403e4b9982SAlex Deucher }
22413e4b9982SAlex Deucher 
22423e4b9982SAlex Deucher static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
22433e4b9982SAlex Deucher 	.dpms = radeon_atom_ext_dpms,
22443e4b9982SAlex Deucher 	.mode_fixup = radeon_atom_ext_mode_fixup,
22453e4b9982SAlex Deucher 	.prepare = radeon_atom_ext_prepare,
22463e4b9982SAlex Deucher 	.mode_set = radeon_atom_ext_mode_set,
22473e4b9982SAlex Deucher 	.commit = radeon_atom_ext_commit,
22483e4b9982SAlex Deucher 	.disable = radeon_atom_ext_disable,
22493e4b9982SAlex Deucher 	/* no detect for TMDS/LVDS yet */
22503e4b9982SAlex Deucher };
22513e4b9982SAlex Deucher 
2252771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
2253771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
2254771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
2255771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
2256771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
2257771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
22584ce001abSDave Airlie 	.disable = radeon_atom_encoder_disable,
2259d629a3ceSAlex Deucher 	.detect = radeon_atom_dig_detect,
2260771fe6b9SJerome Glisse };
2261771fe6b9SJerome Glisse 
2262771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
2263771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
2264771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
2265771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
2266771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
2267771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
2268771fe6b9SJerome Glisse 	.detect = radeon_atom_dac_detect,
2269771fe6b9SJerome Glisse };
2270771fe6b9SJerome Glisse 
2271771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder)
2272771fe6b9SJerome Glisse {
2273771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2274771fe6b9SJerome Glisse 	kfree(radeon_encoder->enc_priv);
2275771fe6b9SJerome Glisse 	drm_encoder_cleanup(encoder);
2276771fe6b9SJerome Glisse 	kfree(radeon_encoder);
2277771fe6b9SJerome Glisse }
2278771fe6b9SJerome Glisse 
2279771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
2280771fe6b9SJerome Glisse 	.destroy = radeon_enc_destroy,
2281771fe6b9SJerome Glisse };
2282771fe6b9SJerome Glisse 
22834ce001abSDave Airlie struct radeon_encoder_atom_dac *
22844ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
22854ce001abSDave Airlie {
2286affd8589SAlex Deucher 	struct drm_device *dev = radeon_encoder->base.dev;
2287affd8589SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
22884ce001abSDave Airlie 	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
22894ce001abSDave Airlie 
22904ce001abSDave Airlie 	if (!dac)
22914ce001abSDave Airlie 		return NULL;
22924ce001abSDave Airlie 
2293affd8589SAlex Deucher 	dac->tv_std = radeon_atombios_get_tv_info(rdev);
22944ce001abSDave Airlie 	return dac;
22954ce001abSDave Airlie }
22964ce001abSDave Airlie 
2297771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *
2298771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
2299771fe6b9SJerome Glisse {
23005137ee94SAlex Deucher 	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
2301771fe6b9SJerome Glisse 	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
2302771fe6b9SJerome Glisse 
2303771fe6b9SJerome Glisse 	if (!dig)
2304771fe6b9SJerome Glisse 		return NULL;
2305771fe6b9SJerome Glisse 
2306771fe6b9SJerome Glisse 	/* coherent mode by default */
2307771fe6b9SJerome Glisse 	dig->coherent_mode = true;
2308f28cf339SDave Airlie 	dig->dig_encoder = -1;
2309771fe6b9SJerome Glisse 
23105137ee94SAlex Deucher 	if (encoder_enum == 2)
23115137ee94SAlex Deucher 		dig->linkb = true;
23125137ee94SAlex Deucher 	else
23135137ee94SAlex Deucher 		dig->linkb = false;
23145137ee94SAlex Deucher 
2315771fe6b9SJerome Glisse 	return dig;
2316771fe6b9SJerome Glisse }
2317771fe6b9SJerome Glisse 
2318771fe6b9SJerome Glisse void
231936868bdaSAlex Deucher radeon_add_atom_encoder(struct drm_device *dev,
232036868bdaSAlex Deucher 			uint32_t encoder_enum,
232136868bdaSAlex Deucher 			uint32_t supported_device,
232236868bdaSAlex Deucher 			u16 caps)
2323771fe6b9SJerome Glisse {
2324dfee5614SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
2325771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
2326771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder;
2327771fe6b9SJerome Glisse 
2328771fe6b9SJerome Glisse 	/* see if we already added it */
2329771fe6b9SJerome Glisse 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2330771fe6b9SJerome Glisse 		radeon_encoder = to_radeon_encoder(encoder);
23315137ee94SAlex Deucher 		if (radeon_encoder->encoder_enum == encoder_enum) {
2332771fe6b9SJerome Glisse 			radeon_encoder->devices |= supported_device;
2333771fe6b9SJerome Glisse 			return;
2334771fe6b9SJerome Glisse 		}
2335771fe6b9SJerome Glisse 
2336771fe6b9SJerome Glisse 	}
2337771fe6b9SJerome Glisse 
2338771fe6b9SJerome Glisse 	/* add a new one */
2339771fe6b9SJerome Glisse 	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
2340771fe6b9SJerome Glisse 	if (!radeon_encoder)
2341771fe6b9SJerome Glisse 		return;
2342771fe6b9SJerome Glisse 
2343771fe6b9SJerome Glisse 	encoder = &radeon_encoder->base;
2344bcc1c2a1SAlex Deucher 	switch (rdev->num_crtc) {
2345bcc1c2a1SAlex Deucher 	case 1:
2346dfee5614SDave Airlie 		encoder->possible_crtcs = 0x1;
2347bcc1c2a1SAlex Deucher 		break;
2348bcc1c2a1SAlex Deucher 	case 2:
2349bcc1c2a1SAlex Deucher 	default:
2350771fe6b9SJerome Glisse 		encoder->possible_crtcs = 0x3;
2351bcc1c2a1SAlex Deucher 		break;
235233ae1827SAlex Deucher 	case 4:
235333ae1827SAlex Deucher 		encoder->possible_crtcs = 0xf;
235433ae1827SAlex Deucher 		break;
2355bcc1c2a1SAlex Deucher 	case 6:
2356bcc1c2a1SAlex Deucher 		encoder->possible_crtcs = 0x3f;
2357bcc1c2a1SAlex Deucher 		break;
2358bcc1c2a1SAlex Deucher 	}
2359771fe6b9SJerome Glisse 
2360771fe6b9SJerome Glisse 	radeon_encoder->enc_priv = NULL;
2361771fe6b9SJerome Glisse 
23625137ee94SAlex Deucher 	radeon_encoder->encoder_enum = encoder_enum;
23635137ee94SAlex Deucher 	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
2364771fe6b9SJerome Glisse 	radeon_encoder->devices = supported_device;
2365c93bb85bSJerome Glisse 	radeon_encoder->rmx_type = RMX_OFF;
23665b1714d3SAlex Deucher 	radeon_encoder->underscan_type = UNDERSCAN_OFF;
23673e4b9982SAlex Deucher 	radeon_encoder->is_ext_encoder = false;
236836868bdaSAlex Deucher 	radeon_encoder->caps = caps;
2369771fe6b9SJerome Glisse 
2370771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
2371771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2372771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2373771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2374771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2375771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2376771fe6b9SJerome Glisse 			radeon_encoder->rmx_type = RMX_FULL;
2377771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
2378771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2379771fe6b9SJerome Glisse 		} else {
2380771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
2381771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2382771fe6b9SJerome Glisse 		}
2383771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2384771fe6b9SJerome Glisse 		break;
2385771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2386771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
2387affd8589SAlex Deucher 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2388771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2389771fe6b9SJerome Glisse 		break;
2390771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2391771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2392771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2393771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
23944ce001abSDave Airlie 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2395771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2396771fe6b9SJerome Glisse 		break;
2397771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2398771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2399771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2400771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2401771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2402771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2403771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
240460d15f55SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
240560d15f55SAlex Deucher 			radeon_encoder->rmx_type = RMX_FULL;
240660d15f55SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
240760d15f55SAlex Deucher 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
24083e4b9982SAlex Deucher 		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
24093e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
24103e4b9982SAlex Deucher 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
241160d15f55SAlex Deucher 		} else {
2412771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
2413771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
241460d15f55SAlex Deucher 		}
2415771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2416771fe6b9SJerome Glisse 		break;
24173e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_SI170B:
24183e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_CH7303:
24193e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
24203e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
24213e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_TITFP513:
24223e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_VT1623:
24233e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_HDMI_SI1930:
2424bf982ebfSAlex Deucher 	case ENCODER_OBJECT_ID_TRAVIS:
2425bf982ebfSAlex Deucher 	case ENCODER_OBJECT_ID_NUTMEG:
24263e4b9982SAlex Deucher 		/* these are handled by the primary encoders */
24273e4b9982SAlex Deucher 		radeon_encoder->is_ext_encoder = true;
24283e4b9982SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
24293e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
24303e4b9982SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
24313e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
24323e4b9982SAlex Deucher 		else
24333e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
24343e4b9982SAlex Deucher 		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
24353e4b9982SAlex Deucher 		break;
2436771fe6b9SJerome Glisse 	}
2437771fe6b9SJerome Glisse }
2438