xref: /openbmc/linux/drivers/gpu/drm/radeon/radeon_encoders.c (revision d7fa8bb385d71c0c0c563a063a0f574adc532585)
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 
2323e4b9982SAlex Deucher struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder)
2333e4b9982SAlex Deucher {
2343e4b9982SAlex Deucher 	struct drm_device *dev = encoder->dev;
2353e4b9982SAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2363e4b9982SAlex Deucher 	struct drm_encoder *other_encoder;
2373e4b9982SAlex Deucher 	struct radeon_encoder *other_radeon_encoder;
2383e4b9982SAlex Deucher 
2393e4b9982SAlex Deucher 	if (radeon_encoder->is_ext_encoder)
2403e4b9982SAlex Deucher 		return NULL;
2413e4b9982SAlex Deucher 
2423e4b9982SAlex Deucher 	list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
2433e4b9982SAlex Deucher 		if (other_encoder == encoder)
2443e4b9982SAlex Deucher 			continue;
2453e4b9982SAlex Deucher 		other_radeon_encoder = to_radeon_encoder(other_encoder);
2463e4b9982SAlex Deucher 		if (other_radeon_encoder->is_ext_encoder &&
2473e4b9982SAlex Deucher 		    (radeon_encoder->devices & other_radeon_encoder->devices))
2483e4b9982SAlex Deucher 			return other_encoder;
2493e4b9982SAlex Deucher 	}
2503e4b9982SAlex Deucher 	return NULL;
2513e4b9982SAlex Deucher }
2523e4b9982SAlex Deucher 
253*d7fa8bb3SAlex Deucher bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder)
254*d7fa8bb3SAlex Deucher {
255*d7fa8bb3SAlex Deucher 	struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder);
256*d7fa8bb3SAlex Deucher 
257*d7fa8bb3SAlex Deucher 	if (other_encoder) {
258*d7fa8bb3SAlex Deucher 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
259*d7fa8bb3SAlex Deucher 
260*d7fa8bb3SAlex Deucher 		switch (radeon_encoder->encoder_id) {
261*d7fa8bb3SAlex Deucher 		case ENCODER_OBJECT_ID_TRAVIS:
262*d7fa8bb3SAlex Deucher 		case ENCODER_OBJECT_ID_NUTMEG:
263*d7fa8bb3SAlex Deucher 			return true;
264*d7fa8bb3SAlex Deucher 		default:
265*d7fa8bb3SAlex Deucher 			return false;
266*d7fa8bb3SAlex Deucher 		}
267*d7fa8bb3SAlex Deucher 	}
268*d7fa8bb3SAlex Deucher 
269*d7fa8bb3SAlex Deucher 	return false;
270*d7fa8bb3SAlex Deucher }
271*d7fa8bb3SAlex Deucher 
2723515387bSAlex Deucher void radeon_panel_mode_fixup(struct drm_encoder *encoder,
2733515387bSAlex Deucher 			     struct drm_display_mode *adjusted_mode)
2743515387bSAlex Deucher {
2753515387bSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2763515387bSAlex Deucher 	struct drm_device *dev = encoder->dev;
2773515387bSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
2783515387bSAlex Deucher 	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
2793515387bSAlex Deucher 	unsigned hblank = native_mode->htotal - native_mode->hdisplay;
2803515387bSAlex Deucher 	unsigned vblank = native_mode->vtotal - native_mode->vdisplay;
2813515387bSAlex Deucher 	unsigned hover = native_mode->hsync_start - native_mode->hdisplay;
2823515387bSAlex Deucher 	unsigned vover = native_mode->vsync_start - native_mode->vdisplay;
2833515387bSAlex Deucher 	unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start;
2843515387bSAlex Deucher 	unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start;
2853515387bSAlex Deucher 
2863515387bSAlex Deucher 	adjusted_mode->clock = native_mode->clock;
2873515387bSAlex Deucher 	adjusted_mode->flags = native_mode->flags;
2883515387bSAlex Deucher 
2893515387bSAlex Deucher 	if (ASIC_IS_AVIVO(rdev)) {
2903515387bSAlex Deucher 		adjusted_mode->hdisplay = native_mode->hdisplay;
2913515387bSAlex Deucher 		adjusted_mode->vdisplay = native_mode->vdisplay;
2923515387bSAlex Deucher 	}
2933515387bSAlex Deucher 
2943515387bSAlex Deucher 	adjusted_mode->htotal = native_mode->hdisplay + hblank;
2953515387bSAlex Deucher 	adjusted_mode->hsync_start = native_mode->hdisplay + hover;
2963515387bSAlex Deucher 	adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width;
2973515387bSAlex Deucher 
2983515387bSAlex Deucher 	adjusted_mode->vtotal = native_mode->vdisplay + vblank;
2993515387bSAlex Deucher 	adjusted_mode->vsync_start = native_mode->vdisplay + vover;
3003515387bSAlex Deucher 	adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width;
3013515387bSAlex Deucher 
3023515387bSAlex Deucher 	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
3033515387bSAlex Deucher 
3043515387bSAlex Deucher 	if (ASIC_IS_AVIVO(rdev)) {
3053515387bSAlex Deucher 		adjusted_mode->crtc_hdisplay = native_mode->hdisplay;
3063515387bSAlex Deucher 		adjusted_mode->crtc_vdisplay = native_mode->vdisplay;
3073515387bSAlex Deucher 	}
3083515387bSAlex Deucher 
3093515387bSAlex Deucher 	adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank;
3103515387bSAlex Deucher 	adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover;
3113515387bSAlex Deucher 	adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width;
3123515387bSAlex Deucher 
3133515387bSAlex Deucher 	adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank;
3143515387bSAlex Deucher 	adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover;
3153515387bSAlex Deucher 	adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width;
3163515387bSAlex Deucher 
3173515387bSAlex Deucher }
3183515387bSAlex Deucher 
319771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
320771fe6b9SJerome Glisse 				   struct drm_display_mode *mode,
321771fe6b9SJerome Glisse 				   struct drm_display_mode *adjusted_mode)
322771fe6b9SJerome Glisse {
323771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3245a9bcaccSAlex Deucher 	struct drm_device *dev = encoder->dev;
3255a9bcaccSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
326771fe6b9SJerome Glisse 
3278c2a6d73SAlex Deucher 	/* set the active encoder to connector routing */
3288c2a6d73SAlex Deucher 	radeon_encoder_set_active_device(encoder);
329771fe6b9SJerome Glisse 	drm_mode_set_crtcinfo(adjusted_mode, 0);
330771fe6b9SJerome Glisse 
331771fe6b9SJerome Glisse 	/* hw bug */
332771fe6b9SJerome Glisse 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
333771fe6b9SJerome Glisse 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
334771fe6b9SJerome Glisse 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
335771fe6b9SJerome Glisse 
33680297e87SAlex Deucher 	/* get the native mode for LVDS */
3373515387bSAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
3383515387bSAlex Deucher 		radeon_panel_mode_fixup(encoder, adjusted_mode);
33980297e87SAlex Deucher 
34080297e87SAlex Deucher 	/* get the native mode for TV */
341ceefedd8SAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
3425a9bcaccSAlex Deucher 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
3435a9bcaccSAlex Deucher 		if (tv_dac) {
3445a9bcaccSAlex Deucher 			if (tv_dac->tv_std == TV_STD_NTSC ||
3455a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_NTSC_J ||
3465a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_PAL_M)
3475a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
3485a9bcaccSAlex Deucher 			else
3495a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
3505a9bcaccSAlex Deucher 		}
3515a9bcaccSAlex Deucher 	}
3525a9bcaccSAlex Deucher 
3535801ead6SAlex Deucher 	if (ASIC_IS_DCE3(rdev) &&
3549f998ad7SAlex Deucher 	    (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) {
3555801ead6SAlex Deucher 		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
3565801ead6SAlex Deucher 		radeon_dp_set_link_config(connector, mode);
3575801ead6SAlex Deucher 	}
3585801ead6SAlex Deucher 
359771fe6b9SJerome Glisse 	return true;
360771fe6b9SJerome Glisse }
361771fe6b9SJerome Glisse 
362771fe6b9SJerome Glisse static void
363771fe6b9SJerome Glisse atombios_dac_setup(struct drm_encoder *encoder, int action)
364771fe6b9SJerome Glisse {
365771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
366771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
367771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
368771fe6b9SJerome Glisse 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
369affd8589SAlex Deucher 	int index = 0;
370445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
371445282dbSDave Airlie 
372771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
373771fe6b9SJerome Glisse 
374771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
375771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
376771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
377771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
378771fe6b9SJerome Glisse 		break;
379771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
380771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
381771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
382771fe6b9SJerome Glisse 		break;
383771fe6b9SJerome Glisse 	}
384771fe6b9SJerome Glisse 
385771fe6b9SJerome Glisse 	args.ucAction = action;
386771fe6b9SJerome Glisse 
3874ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
388771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_PS2;
3894ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
390771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_CV;
391771fe6b9SJerome Glisse 	else {
392affd8589SAlex Deucher 		switch (dac_info->tv_std) {
393771fe6b9SJerome Glisse 		case TV_STD_PAL:
394771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
395771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
396771fe6b9SJerome Glisse 		case TV_STD_SECAM:
397771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
398771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_PAL;
399771fe6b9SJerome Glisse 			break;
400771fe6b9SJerome Glisse 		case TV_STD_NTSC:
401771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
402771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
403771fe6b9SJerome Glisse 		default:
404771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_NTSC;
405771fe6b9SJerome Glisse 			break;
406771fe6b9SJerome Glisse 		}
407771fe6b9SJerome Glisse 	}
408771fe6b9SJerome Glisse 	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
409771fe6b9SJerome Glisse 
410771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
411771fe6b9SJerome Glisse 
412771fe6b9SJerome Glisse }
413771fe6b9SJerome Glisse 
414771fe6b9SJerome Glisse static void
415771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action)
416771fe6b9SJerome Glisse {
417771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
418771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
419771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
420771fe6b9SJerome Glisse 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
421771fe6b9SJerome Glisse 	int index = 0;
422445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
423445282dbSDave Airlie 
424771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
425771fe6b9SJerome Glisse 
426771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
427771fe6b9SJerome Glisse 
428771fe6b9SJerome Glisse 	args.sTVEncoder.ucAction = action;
429771fe6b9SJerome Glisse 
4304ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
431771fe6b9SJerome Glisse 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
432771fe6b9SJerome Glisse 	else {
433affd8589SAlex Deucher 		switch (dac_info->tv_std) {
434771fe6b9SJerome Glisse 		case TV_STD_NTSC:
435771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
436771fe6b9SJerome Glisse 			break;
437771fe6b9SJerome Glisse 		case TV_STD_PAL:
438771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
439771fe6b9SJerome Glisse 			break;
440771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
441771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
442771fe6b9SJerome Glisse 			break;
443771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
444771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
445771fe6b9SJerome Glisse 			break;
446771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
447771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
448771fe6b9SJerome Glisse 			break;
449771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
450771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
451771fe6b9SJerome Glisse 			break;
452771fe6b9SJerome Glisse 		case TV_STD_SECAM:
453771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
454771fe6b9SJerome Glisse 			break;
455771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
456771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
457771fe6b9SJerome Glisse 			break;
458771fe6b9SJerome Glisse 		default:
459771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
460771fe6b9SJerome Glisse 			break;
461771fe6b9SJerome Glisse 		}
462771fe6b9SJerome Glisse 	}
463771fe6b9SJerome Glisse 
464771fe6b9SJerome Glisse 	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
465771fe6b9SJerome Glisse 
466771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
467771fe6b9SJerome Glisse 
468771fe6b9SJerome Glisse }
469771fe6b9SJerome Glisse 
47099999aaaSAlex Deucher union dvo_encoder_control {
47199999aaaSAlex Deucher 	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
47299999aaaSAlex Deucher 	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
47399999aaaSAlex Deucher 	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
47499999aaaSAlex Deucher };
47599999aaaSAlex Deucher 
476771fe6b9SJerome Glisse void
47799999aaaSAlex Deucher atombios_dvo_setup(struct drm_encoder *encoder, int action)
478771fe6b9SJerome Glisse {
479771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
480771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
481771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
48299999aaaSAlex Deucher 	union dvo_encoder_control args;
48399999aaaSAlex Deucher 	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
484771fe6b9SJerome Glisse 
485771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
486771fe6b9SJerome Glisse 
48799999aaaSAlex Deucher 	if (ASIC_IS_DCE3(rdev)) {
48899999aaaSAlex Deucher 		/* DCE3+ */
48999999aaaSAlex Deucher 		args.dvo_v3.ucAction = action;
49099999aaaSAlex Deucher 		args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
49199999aaaSAlex Deucher 		args.dvo_v3.ucDVOConfig = 0; /* XXX */
49299999aaaSAlex Deucher 	} else if (ASIC_IS_DCE2(rdev)) {
49399999aaaSAlex Deucher 		/* DCE2 (pre-DCE3 R6xx, RS600/690/740 */
49499999aaaSAlex Deucher 		args.dvo.sDVOEncoder.ucAction = action;
49599999aaaSAlex Deucher 		args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
49699999aaaSAlex Deucher 		/* DFP1, CRT1, TV1 depending on the type of port */
49799999aaaSAlex Deucher 		args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
498771fe6b9SJerome Glisse 
499771fe6b9SJerome Glisse 		if (radeon_encoder->pixel_clock > 165000)
50099999aaaSAlex Deucher 			args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
50199999aaaSAlex Deucher 	} else {
50299999aaaSAlex Deucher 		/* R4xx, R5xx */
50399999aaaSAlex Deucher 		args.ext_tmds.sXTmdsEncoder.ucEnable = action;
50499999aaaSAlex Deucher 
50599999aaaSAlex Deucher 		if (radeon_encoder->pixel_clock > 165000)
50699999aaaSAlex Deucher 			args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
507771fe6b9SJerome Glisse 
508771fe6b9SJerome Glisse 		/*if (pScrn->rgbBits == 8)*/
50999999aaaSAlex Deucher 		args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
510771fe6b9SJerome Glisse 	}
511771fe6b9SJerome Glisse 
512771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
513771fe6b9SJerome Glisse }
514771fe6b9SJerome Glisse 
515771fe6b9SJerome Glisse union lvds_encoder_control {
516771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
517771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
518771fe6b9SJerome Glisse };
519771fe6b9SJerome Glisse 
52032f48ffeSAlex Deucher void
521771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action)
522771fe6b9SJerome Glisse {
523771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
524771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
525771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
5269ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
527771fe6b9SJerome Glisse 	union lvds_encoder_control args;
528771fe6b9SJerome Glisse 	int index = 0;
529dafc3bd5SChristian Koenig 	int hdmi_detected = 0;
530771fe6b9SJerome Glisse 	uint8_t frev, crev;
531771fe6b9SJerome Glisse 
5324aab97e8SAlex Deucher 	if (!dig)
533771fe6b9SJerome Glisse 		return;
534771fe6b9SJerome Glisse 
5359ae47867SAlex Deucher 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
536dafc3bd5SChristian Koenig 		hdmi_detected = 1;
537dafc3bd5SChristian Koenig 
538771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
539771fe6b9SJerome Glisse 
540771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
541771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
542771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
543771fe6b9SJerome Glisse 		break;
544771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
545771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
546771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
547771fe6b9SJerome Glisse 		break;
548771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
549771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
550771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
551771fe6b9SJerome Glisse 		else
552771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
553771fe6b9SJerome Glisse 		break;
554771fe6b9SJerome Glisse 	}
555771fe6b9SJerome Glisse 
556a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
557a084e6eeSAlex Deucher 		return;
558771fe6b9SJerome Glisse 
559771fe6b9SJerome Glisse 	switch (frev) {
560771fe6b9SJerome Glisse 	case 1:
561771fe6b9SJerome Glisse 	case 2:
562771fe6b9SJerome Glisse 		switch (crev) {
563771fe6b9SJerome Glisse 		case 1:
564771fe6b9SJerome Glisse 			args.v1.ucMisc = 0;
565771fe6b9SJerome Glisse 			args.v1.ucAction = action;
566dafc3bd5SChristian Koenig 			if (hdmi_detected)
567771fe6b9SJerome Glisse 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
568771fe6b9SJerome Glisse 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
569771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
570ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
571771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
572ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
57399999aaaSAlex Deucher 					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
574771fe6b9SJerome Glisse 			} else {
5755137ee94SAlex Deucher 				if (dig->linkb)
576771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
577771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
578771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
579771fe6b9SJerome Glisse 				/*if (pScrn->rgbBits == 8) */
58099999aaaSAlex Deucher 				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
581771fe6b9SJerome Glisse 			}
582771fe6b9SJerome Glisse 			break;
583771fe6b9SJerome Glisse 		case 2:
584771fe6b9SJerome Glisse 		case 3:
585771fe6b9SJerome Glisse 			args.v2.ucMisc = 0;
586771fe6b9SJerome Glisse 			args.v2.ucAction = action;
587771fe6b9SJerome Glisse 			if (crev == 3) {
588771fe6b9SJerome Glisse 				if (dig->coherent_mode)
589771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
590771fe6b9SJerome Glisse 			}
591dafc3bd5SChristian Koenig 			if (hdmi_detected)
592771fe6b9SJerome Glisse 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
593771fe6b9SJerome Glisse 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
594771fe6b9SJerome Glisse 			args.v2.ucTruncate = 0;
595771fe6b9SJerome Glisse 			args.v2.ucSpatial = 0;
596771fe6b9SJerome Glisse 			args.v2.ucTemporal = 0;
597771fe6b9SJerome Glisse 			args.v2.ucFRC = 0;
598771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
599ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
600771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
601ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
602771fe6b9SJerome Glisse 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
603ba032a58SAlex Deucher 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
604771fe6b9SJerome Glisse 						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
605771fe6b9SJerome Glisse 				}
606ba032a58SAlex Deucher 				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
607771fe6b9SJerome Glisse 					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
608ba032a58SAlex Deucher 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
609771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
610ba032a58SAlex Deucher 					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
611771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
612771fe6b9SJerome Glisse 				}
613771fe6b9SJerome Glisse 			} else {
6145137ee94SAlex Deucher 				if (dig->linkb)
615771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
616771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
617771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
618771fe6b9SJerome Glisse 			}
619771fe6b9SJerome Glisse 			break;
620771fe6b9SJerome Glisse 		default:
621771fe6b9SJerome Glisse 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
622771fe6b9SJerome Glisse 			break;
623771fe6b9SJerome Glisse 		}
624771fe6b9SJerome Glisse 		break;
625771fe6b9SJerome Glisse 	default:
626771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
627771fe6b9SJerome Glisse 		break;
628771fe6b9SJerome Glisse 	}
629771fe6b9SJerome Glisse 
630771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
631771fe6b9SJerome Glisse }
632771fe6b9SJerome Glisse 
633771fe6b9SJerome Glisse int
634771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder)
635771fe6b9SJerome Glisse {
636c7a71fc7SAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
637d033af87SAlex Deucher 	struct drm_device *dev = encoder->dev;
638d033af87SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
639771fe6b9SJerome Glisse 	struct drm_connector *connector;
640771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
6419ae47867SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector;
642771fe6b9SJerome Glisse 
643*d7fa8bb3SAlex Deucher 	/* dp bridges are always DP */
644*d7fa8bb3SAlex Deucher 	if (radeon_encoder_is_dp_bridge(encoder))
645*d7fa8bb3SAlex Deucher 		return ATOM_ENCODER_MODE_DP;
646*d7fa8bb3SAlex Deucher 
647771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
648c7a71fc7SAlex Deucher 	if (!connector) {
649c7a71fc7SAlex Deucher 		switch (radeon_encoder->encoder_id) {
650c7a71fc7SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
651c7a71fc7SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
652c7a71fc7SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
653c7a71fc7SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
654c7a71fc7SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
655c7a71fc7SAlex Deucher 			return ATOM_ENCODER_MODE_DVI;
656c7a71fc7SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
657c7a71fc7SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
658c7a71fc7SAlex Deucher 		default:
659c7a71fc7SAlex Deucher 			return ATOM_ENCODER_MODE_CRT;
660c7a71fc7SAlex Deucher 		}
661c7a71fc7SAlex Deucher 	}
662771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
663771fe6b9SJerome Glisse 
664771fe6b9SJerome Glisse 	switch (connector->connector_type) {
665771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVII:
666705af9c7SAlex Deucher 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
6679453d621SAlex Deucher 		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
668d033af87SAlex Deucher 			/* fix me */
669d033af87SAlex Deucher 			if (ASIC_IS_DCE4(rdev))
670d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_DVI;
671d033af87SAlex Deucher 			else
672771fe6b9SJerome Glisse 				return ATOM_ENCODER_MODE_HDMI;
673d033af87SAlex Deucher 		} else if (radeon_connector->use_digital)
674771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
675771fe6b9SJerome Glisse 		else
676771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_CRT;
677771fe6b9SJerome Glisse 		break;
678771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVID:
679771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_HDMIA:
680771fe6b9SJerome Glisse 	default:
6819453d621SAlex Deucher 		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
682d033af87SAlex Deucher 			/* fix me */
683d033af87SAlex Deucher 			if (ASIC_IS_DCE4(rdev))
684d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_DVI;
685771fe6b9SJerome Glisse 			else
686d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_HDMI;
687d033af87SAlex Deucher 		} else
688771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
689771fe6b9SJerome Glisse 		break;
690771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_LVDS:
691771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_LVDS;
692771fe6b9SJerome Glisse 		break;
693771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DisplayPort:
6949ae47867SAlex Deucher 		dig_connector = radeon_connector->con_priv;
6959ae47867SAlex Deucher 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
6969ae47867SAlex Deucher 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
697771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DP;
6989453d621SAlex Deucher 		else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
699d033af87SAlex Deucher 			/* fix me */
700d033af87SAlex Deucher 			if (ASIC_IS_DCE4(rdev))
701d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_DVI;
702771fe6b9SJerome Glisse 			else
703d033af87SAlex Deucher 				return ATOM_ENCODER_MODE_HDMI;
704d033af87SAlex Deucher 		} else
705771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
706771fe6b9SJerome Glisse 		break;
7073a5f4a21SAlex Deucher 	case DRM_MODE_CONNECTOR_eDP:
7083a5f4a21SAlex Deucher 		return ATOM_ENCODER_MODE_DP;
709a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_DVIA:
710a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_VGA:
711771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_CRT;
712771fe6b9SJerome Glisse 		break;
713a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_Composite:
714a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_SVIDEO:
715a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_9PinDIN:
716771fe6b9SJerome Glisse 		/* fix me */
717771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_TV;
718771fe6b9SJerome Glisse 		/*return ATOM_ENCODER_MODE_CV;*/
719771fe6b9SJerome Glisse 		break;
720771fe6b9SJerome Glisse 	}
721771fe6b9SJerome Glisse }
722771fe6b9SJerome Glisse 
7231a66c95aSAlex Deucher /*
7241a66c95aSAlex Deucher  * DIG Encoder/Transmitter Setup
7251a66c95aSAlex Deucher  *
7261a66c95aSAlex Deucher  * DCE 3.0/3.1
7271a66c95aSAlex Deucher  * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
7281a66c95aSAlex Deucher  * Supports up to 3 digital outputs
7291a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
7301a66c95aSAlex Deucher  * DIG1 can drive UNIPHY link A or link B
7311a66c95aSAlex Deucher  * DIG2 can drive UNIPHY link B or LVTMA
7321a66c95aSAlex Deucher  *
7331a66c95aSAlex Deucher  * DCE 3.2
7341a66c95aSAlex Deucher  * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
7351a66c95aSAlex Deucher  * Supports up to 5 digital outputs
7361a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
7371a66c95aSAlex Deucher  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
7381a66c95aSAlex Deucher  *
739a001182aSAlex Deucher  * DCE 4.0/5.0
7404e8c65a1SAlex Deucher  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
741bcc1c2a1SAlex Deucher  * Supports up to 6 digital outputs
742bcc1c2a1SAlex Deucher  * - 6 DIG encoder blocks.
743bcc1c2a1SAlex Deucher  * - DIG to PHY mapping is hardcoded
744bcc1c2a1SAlex Deucher  * DIG1 drives UNIPHY0 link A, A+B
745bcc1c2a1SAlex Deucher  * DIG2 drives UNIPHY0 link B
746bcc1c2a1SAlex Deucher  * DIG3 drives UNIPHY1 link A, A+B
747bcc1c2a1SAlex Deucher  * DIG4 drives UNIPHY1 link B
748bcc1c2a1SAlex Deucher  * DIG5 drives UNIPHY2 link A, A+B
749bcc1c2a1SAlex Deucher  * DIG6 drives UNIPHY2 link B
750bcc1c2a1SAlex Deucher  *
7514e8c65a1SAlex Deucher  * DCE 4.1
7524e8c65a1SAlex Deucher  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
7534e8c65a1SAlex Deucher  * Supports up to 6 digital outputs
7544e8c65a1SAlex Deucher  * - 2 DIG encoder blocks.
7554e8c65a1SAlex Deucher  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
7564e8c65a1SAlex Deucher  *
7571a66c95aSAlex Deucher  * Routing
7581a66c95aSAlex Deucher  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
7591a66c95aSAlex Deucher  * Examples:
7601a66c95aSAlex Deucher  * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
7611a66c95aSAlex Deucher  * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
7621a66c95aSAlex Deucher  * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
7631a66c95aSAlex Deucher  * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
7641a66c95aSAlex Deucher  */
765bcc1c2a1SAlex Deucher 
766bcc1c2a1SAlex Deucher union dig_encoder_control {
767bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
768bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
769bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
770badbb57bSAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
771bcc1c2a1SAlex Deucher };
772bcc1c2a1SAlex Deucher 
773bcc1c2a1SAlex Deucher void
774771fe6b9SJerome Glisse atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
775771fe6b9SJerome Glisse {
776771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
777771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
778771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
7799ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
7804aab97e8SAlex Deucher 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
781bcc1c2a1SAlex Deucher 	union dig_encoder_control args;
782d9c9fe36SAlex Deucher 	int index = 0;
783771fe6b9SJerome Glisse 	uint8_t frev, crev;
7844aab97e8SAlex Deucher 	int dp_clock = 0;
7854aab97e8SAlex Deucher 	int dp_lane_count = 0;
786badbb57bSAlex Deucher 	int hpd_id = RADEON_HPD_NONE;
787df271becSAlex Deucher 	int bpc = 8;
788771fe6b9SJerome Glisse 
7894aab97e8SAlex Deucher 	if (connector) {
7904aab97e8SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
7914aab97e8SAlex Deucher 		struct radeon_connector_atom_dig *dig_connector =
7924aab97e8SAlex Deucher 			radeon_connector->con_priv;
7934aab97e8SAlex Deucher 
7944aab97e8SAlex Deucher 		dp_clock = dig_connector->dp_clock;
7954aab97e8SAlex Deucher 		dp_lane_count = dig_connector->dp_lane_count;
796badbb57bSAlex Deucher 		hpd_id = radeon_connector->hpd.hpd;
797df271becSAlex Deucher 		bpc = connector->display_info.bpc;
7984aab97e8SAlex Deucher 	}
7994aab97e8SAlex Deucher 
8004aab97e8SAlex Deucher 	/* no dig encoder assigned */
8014aab97e8SAlex Deucher 	if (dig->dig_encoder == -1)
802771fe6b9SJerome Glisse 		return;
803771fe6b9SJerome Glisse 
804771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
805771fe6b9SJerome Glisse 
806bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev))
807bcc1c2a1SAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
808bcc1c2a1SAlex Deucher 	else {
809f28cf339SDave Airlie 		if (dig->dig_encoder)
810771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
811771fe6b9SJerome Glisse 		else
812771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
813bcc1c2a1SAlex Deucher 	}
814771fe6b9SJerome Glisse 
815a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
816a084e6eeSAlex Deucher 		return;
817771fe6b9SJerome Glisse 
818bcc1c2a1SAlex Deucher 	args.v1.ucAction = action;
819bcc1c2a1SAlex Deucher 	args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
820bcc1c2a1SAlex Deucher 	args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
821771fe6b9SJerome Glisse 
822badbb57bSAlex Deucher 	if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
823badbb57bSAlex Deucher 	    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST))
8244aab97e8SAlex Deucher 		args.v1.ucLaneNum = dp_lane_count;
825badbb57bSAlex Deucher 	else if (radeon_encoder->pixel_clock > 165000)
826bcc1c2a1SAlex Deucher 		args.v1.ucLaneNum = 8;
827bcc1c2a1SAlex Deucher 	else
828bcc1c2a1SAlex Deucher 		args.v1.ucLaneNum = 4;
829bcc1c2a1SAlex Deucher 
830badbb57bSAlex Deucher 	if (ASIC_IS_DCE5(rdev)) {
831badbb57bSAlex Deucher 		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
832badbb57bSAlex Deucher 		    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) {
833badbb57bSAlex Deucher 			if (dp_clock == 270000)
834badbb57bSAlex Deucher 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
835badbb57bSAlex Deucher 			else if (dp_clock == 540000)
836badbb57bSAlex Deucher 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
837badbb57bSAlex Deucher 		}
838badbb57bSAlex Deucher 		args.v4.acConfig.ucDigSel = dig->dig_encoder;
839df271becSAlex Deucher 		switch (bpc) {
840df271becSAlex Deucher 		case 0:
841df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
842df271becSAlex Deucher 			break;
843df271becSAlex Deucher 		case 6:
844df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
845df271becSAlex Deucher 			break;
846df271becSAlex Deucher 		case 8:
847df271becSAlex Deucher 		default:
848badbb57bSAlex Deucher 			args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
849df271becSAlex Deucher 			break;
850df271becSAlex Deucher 		case 10:
851df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
852df271becSAlex Deucher 			break;
853df271becSAlex Deucher 		case 12:
854df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
855df271becSAlex Deucher 			break;
856df271becSAlex Deucher 		case 16:
857df271becSAlex Deucher 			args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
858df271becSAlex Deucher 			break;
859df271becSAlex Deucher 		}
860badbb57bSAlex Deucher 		if (hpd_id == RADEON_HPD_NONE)
861badbb57bSAlex Deucher 			args.v4.ucHPD_ID = 0;
862badbb57bSAlex Deucher 		else
863badbb57bSAlex Deucher 			args.v4.ucHPD_ID = hpd_id + 1;
864badbb57bSAlex Deucher 	} else if (ASIC_IS_DCE4(rdev)) {
865badbb57bSAlex Deucher 		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
866badbb57bSAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
867bcc1c2a1SAlex Deucher 		args.v3.acConfig.ucDigSel = dig->dig_encoder;
868df271becSAlex Deucher 		switch (bpc) {
869df271becSAlex Deucher 		case 0:
870df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
871df271becSAlex Deucher 			break;
872df271becSAlex Deucher 		case 6:
873df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
874df271becSAlex Deucher 			break;
875df271becSAlex Deucher 		case 8:
876df271becSAlex Deucher 		default:
877bcc1c2a1SAlex Deucher 			args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
878df271becSAlex Deucher 			break;
879df271becSAlex Deucher 		case 10:
880df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
881df271becSAlex Deucher 			break;
882df271becSAlex Deucher 		case 12:
883df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
884df271becSAlex Deucher 			break;
885df271becSAlex Deucher 		case 16:
886df271becSAlex Deucher 			args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
887df271becSAlex Deucher 			break;
888df271becSAlex Deucher 		}
889771fe6b9SJerome Glisse 	} else {
890badbb57bSAlex Deucher 		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
891badbb57bSAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
892771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
893771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
894bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
895771fe6b9SJerome Glisse 			break;
896bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
897771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
898bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
899bcc1c2a1SAlex Deucher 			break;
900bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
901bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
902771fe6b9SJerome Glisse 			break;
903771fe6b9SJerome Glisse 		}
9045137ee94SAlex Deucher 		if (dig->linkb)
905bcc1c2a1SAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
906771fe6b9SJerome Glisse 		else
907bcc1c2a1SAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
908bcc1c2a1SAlex Deucher 	}
909771fe6b9SJerome Glisse 
910771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
911771fe6b9SJerome Glisse 
912771fe6b9SJerome Glisse }
913771fe6b9SJerome Glisse 
914771fe6b9SJerome Glisse union dig_transmitter_control {
915771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
916771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
917bcc1c2a1SAlex Deucher 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
918a001182aSAlex Deucher 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
919771fe6b9SJerome Glisse };
920771fe6b9SJerome Glisse 
9215801ead6SAlex Deucher void
9221a66c95aSAlex Deucher atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
923771fe6b9SJerome Glisse {
924771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
925771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
926771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
9279ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
9284aab97e8SAlex Deucher 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
929771fe6b9SJerome Glisse 	union dig_transmitter_control args;
930d9c9fe36SAlex Deucher 	int index = 0;
931771fe6b9SJerome Glisse 	uint8_t frev, crev;
932f92a8b67SAlex Deucher 	bool is_dp = false;
933bcc1c2a1SAlex Deucher 	int pll_id = 0;
9344aab97e8SAlex Deucher 	int dp_clock = 0;
9354aab97e8SAlex Deucher 	int dp_lane_count = 0;
9364aab97e8SAlex Deucher 	int connector_object_id = 0;
9374aab97e8SAlex Deucher 	int igp_lane_info = 0;
938771fe6b9SJerome Glisse 
9394aab97e8SAlex Deucher 	if (connector) {
9404aab97e8SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
9414aab97e8SAlex Deucher 		struct radeon_connector_atom_dig *dig_connector =
9424aab97e8SAlex Deucher 			radeon_connector->con_priv;
9434aab97e8SAlex Deucher 
9444aab97e8SAlex Deucher 		dp_clock = dig_connector->dp_clock;
9454aab97e8SAlex Deucher 		dp_lane_count = dig_connector->dp_lane_count;
9464aab97e8SAlex Deucher 		connector_object_id =
9474aab97e8SAlex Deucher 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
9484aab97e8SAlex Deucher 		igp_lane_info = dig_connector->igp_lane_info;
9494aab97e8SAlex Deucher 	}
9504aab97e8SAlex Deucher 
9514aab97e8SAlex Deucher 	/* no dig encoder assigned */
9524aab97e8SAlex Deucher 	if (dig->dig_encoder == -1)
9539ae47867SAlex Deucher 		return;
9549ae47867SAlex Deucher 
955f92a8b67SAlex Deucher 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
956f92a8b67SAlex Deucher 		is_dp = true;
957f92a8b67SAlex Deucher 
958771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
959771fe6b9SJerome Glisse 
960771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
96199999aaaSAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
96299999aaaSAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
96399999aaaSAlex Deucher 		break;
964771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
9654aab97e8SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
9664aab97e8SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
9674aab97e8SAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
968771fe6b9SJerome Glisse 		break;
969771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
9704aab97e8SAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
971771fe6b9SJerome Glisse 		break;
972771fe6b9SJerome Glisse 	}
973771fe6b9SJerome Glisse 
974a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
975a084e6eeSAlex Deucher 		return;
976771fe6b9SJerome Glisse 
977771fe6b9SJerome Glisse 	args.v1.ucAction = action;
978f95a9f0bSAlex Deucher 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
9794589433cSCédric Cano 		args.v1.usInitInfo = cpu_to_le16(connector_object_id);
9801a66c95aSAlex Deucher 	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
9811a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSel = lane_num;
9821a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSet = lane_set;
983771fe6b9SJerome Glisse 	} else {
984f92a8b67SAlex Deucher 		if (is_dp)
985f92a8b67SAlex Deucher 			args.v1.usPixelClock =
9864aab97e8SAlex Deucher 				cpu_to_le16(dp_clock / 10);
987f92a8b67SAlex Deucher 		else if (radeon_encoder->pixel_clock > 165000)
988f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
989f95a9f0bSAlex Deucher 		else
990f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
991771fe6b9SJerome Glisse 	}
992bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev)) {
993bcc1c2a1SAlex Deucher 		if (is_dp)
9944aab97e8SAlex Deucher 			args.v3.ucLaneNum = dp_lane_count;
995bcc1c2a1SAlex Deucher 		else if (radeon_encoder->pixel_clock > 165000)
996bcc1c2a1SAlex Deucher 			args.v3.ucLaneNum = 8;
997bcc1c2a1SAlex Deucher 		else
998bcc1c2a1SAlex Deucher 			args.v3.ucLaneNum = 4;
999bcc1c2a1SAlex Deucher 
100096b3bef8SAlex Deucher 		if (dig->linkb)
1001bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucLinkSel = 1;
100296b3bef8SAlex Deucher 		if (dig->dig_encoder & 1)
1003bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucEncoderSel = 1;
1004bcc1c2a1SAlex Deucher 
1005bcc1c2a1SAlex Deucher 		/* Select the PLL for the PHY
1006bcc1c2a1SAlex Deucher 		 * DP PHY should be clocked from external src if there is
1007bcc1c2a1SAlex Deucher 		 * one.
1008bcc1c2a1SAlex Deucher 		 */
1009bcc1c2a1SAlex Deucher 		if (encoder->crtc) {
1010bcc1c2a1SAlex Deucher 			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1011bcc1c2a1SAlex Deucher 			pll_id = radeon_crtc->pll_id;
1012bcc1c2a1SAlex Deucher 		}
1013a001182aSAlex Deucher 
1014a001182aSAlex Deucher 		if (ASIC_IS_DCE5(rdev)) {
101586a94defSAlex Deucher 			/* On DCE5 DCPLL usually generates the DP ref clock */
101686a94defSAlex Deucher 			if (is_dp) {
101786a94defSAlex Deucher 				if (rdev->clock.dp_extclk)
101886a94defSAlex Deucher 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
1019a001182aSAlex Deucher 				else
102086a94defSAlex Deucher 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
102186a94defSAlex Deucher 			} else
1022a001182aSAlex Deucher 				args.v4.acConfig.ucRefClkSource = pll_id;
1023a001182aSAlex Deucher 		} else {
102486a94defSAlex Deucher 			/* On DCE4, if there is an external clock, it generates the DP ref clock */
1025bcc1c2a1SAlex Deucher 			if (is_dp && rdev->clock.dp_extclk)
1026bcc1c2a1SAlex Deucher 				args.v3.acConfig.ucRefClkSource = 2; /* external src */
1027bcc1c2a1SAlex Deucher 			else
1028bcc1c2a1SAlex Deucher 				args.v3.acConfig.ucRefClkSource = pll_id;
1029a001182aSAlex Deucher 		}
1030bcc1c2a1SAlex Deucher 
1031bcc1c2a1SAlex Deucher 		switch (radeon_encoder->encoder_id) {
1032bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1033bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 0;
1034bcc1c2a1SAlex Deucher 			break;
1035bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1036bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 1;
1037bcc1c2a1SAlex Deucher 			break;
1038bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1039bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 2;
1040bcc1c2a1SAlex Deucher 			break;
1041bcc1c2a1SAlex Deucher 		}
1042bcc1c2a1SAlex Deucher 
1043bcc1c2a1SAlex Deucher 		if (is_dp)
1044bcc1c2a1SAlex Deucher 			args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
1045bcc1c2a1SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1046bcc1c2a1SAlex Deucher 			if (dig->coherent_mode)
1047bcc1c2a1SAlex Deucher 				args.v3.acConfig.fCoherentMode = 1;
1048b317a9ceSAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
1049b317a9ceSAlex Deucher 				args.v3.acConfig.fDualLinkConnector = 1;
1050bcc1c2a1SAlex Deucher 		}
1051bcc1c2a1SAlex Deucher 	} else if (ASIC_IS_DCE32(rdev)) {
1052d9c9fe36SAlex Deucher 		args.v2.acConfig.ucEncoderSel = dig->dig_encoder;
10535137ee94SAlex Deucher 		if (dig->linkb)
10541a66c95aSAlex Deucher 			args.v2.acConfig.ucLinkSel = 1;
1055771fe6b9SJerome Glisse 
1056771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
1057771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1058771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 0;
1059771fe6b9SJerome Glisse 			break;
1060771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1061771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 1;
1062771fe6b9SJerome Glisse 			break;
1063771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1064771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 2;
1065771fe6b9SJerome Glisse 			break;
1066771fe6b9SJerome Glisse 		}
1067771fe6b9SJerome Glisse 
1068f92a8b67SAlex Deucher 		if (is_dp)
1069f92a8b67SAlex Deucher 			args.v2.acConfig.fCoherentMode = 1;
1070f92a8b67SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1071771fe6b9SJerome Glisse 			if (dig->coherent_mode)
1072771fe6b9SJerome Glisse 				args.v2.acConfig.fCoherentMode = 1;
1073b317a9ceSAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
1074b317a9ceSAlex Deucher 				args.v2.acConfig.fDualLinkConnector = 1;
1075771fe6b9SJerome Glisse 		}
1076771fe6b9SJerome Glisse 	} else {
1077771fe6b9SJerome Glisse 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1078771fe6b9SJerome Glisse 
1079f28cf339SDave Airlie 		if (dig->dig_encoder)
10801a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
10811a66c95aSAlex Deucher 		else
1082771fe6b9SJerome Glisse 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1083f28cf339SDave Airlie 
1084d9c9fe36SAlex Deucher 		if ((rdev->flags & RADEON_IS_IGP) &&
1085d9c9fe36SAlex Deucher 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1086d9c9fe36SAlex Deucher 			if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
10874aab97e8SAlex Deucher 				if (igp_lane_info & 0x1)
1088771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
10894aab97e8SAlex Deucher 				else if (igp_lane_info & 0x2)
1090771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
10914aab97e8SAlex Deucher 				else if (igp_lane_info & 0x4)
1092771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
10934aab97e8SAlex Deucher 				else if (igp_lane_info & 0x8)
1094771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1095d9c9fe36SAlex Deucher 			} else {
10964aab97e8SAlex Deucher 				if (igp_lane_info & 0x3)
1097d9c9fe36SAlex Deucher 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
10984aab97e8SAlex Deucher 				else if (igp_lane_info & 0xc)
1099d9c9fe36SAlex Deucher 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1100771fe6b9SJerome Glisse 			}
1101771fe6b9SJerome Glisse 		}
11021a66c95aSAlex Deucher 
11035137ee94SAlex Deucher 		if (dig->linkb)
11041a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
11051a66c95aSAlex Deucher 		else
11061a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
11071a66c95aSAlex Deucher 
1108f92a8b67SAlex Deucher 		if (is_dp)
1109f92a8b67SAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1110f92a8b67SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1111771fe6b9SJerome Glisse 			if (dig->coherent_mode)
1112771fe6b9SJerome Glisse 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1113d9c9fe36SAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
1114d9c9fe36SAlex Deucher 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1115771fe6b9SJerome Glisse 		}
1116771fe6b9SJerome Glisse 	}
1117771fe6b9SJerome Glisse 
1118771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1119771fe6b9SJerome Glisse }
1120771fe6b9SJerome Glisse 
11212dafb74dSAlex Deucher bool
11228b834852SAlex Deucher atombios_set_edp_panel_power(struct drm_connector *connector, int action)
11238b834852SAlex Deucher {
11248b834852SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
11258b834852SAlex Deucher 	struct drm_device *dev = radeon_connector->base.dev;
11268b834852SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
11278b834852SAlex Deucher 	union dig_transmitter_control args;
11288b834852SAlex Deucher 	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
11298b834852SAlex Deucher 	uint8_t frev, crev;
11308b834852SAlex Deucher 
11318b834852SAlex Deucher 	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
11322dafb74dSAlex Deucher 		goto done;
11338b834852SAlex Deucher 
11348b834852SAlex Deucher 	if (!ASIC_IS_DCE4(rdev))
11352dafb74dSAlex Deucher 		goto done;
11368b834852SAlex Deucher 
1137e468e001SStefan Weil 	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
11388b834852SAlex Deucher 	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
11392dafb74dSAlex Deucher 		goto done;
11408b834852SAlex Deucher 
11418b834852SAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
11422dafb74dSAlex Deucher 		goto done;
11438b834852SAlex Deucher 
11448b834852SAlex Deucher 	memset(&args, 0, sizeof(args));
11458b834852SAlex Deucher 
11468b834852SAlex Deucher 	args.v1.ucAction = action;
11478b834852SAlex Deucher 
11488b834852SAlex Deucher 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
11492dafb74dSAlex Deucher 
11502dafb74dSAlex Deucher 	/* wait for the panel to power up */
11512dafb74dSAlex Deucher 	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
11522dafb74dSAlex Deucher 		int i;
11532dafb74dSAlex Deucher 
11542dafb74dSAlex Deucher 		for (i = 0; i < 300; i++) {
11552dafb74dSAlex Deucher 			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
11562dafb74dSAlex Deucher 				return true;
11572dafb74dSAlex Deucher 			mdelay(1);
11582dafb74dSAlex Deucher 		}
11592dafb74dSAlex Deucher 		return false;
11602dafb74dSAlex Deucher 	}
11612dafb74dSAlex Deucher done:
11622dafb74dSAlex Deucher 	return true;
11638b834852SAlex Deucher }
11648b834852SAlex Deucher 
11653e4b9982SAlex Deucher union external_encoder_control {
11663e4b9982SAlex Deucher 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
1167bf982ebfSAlex Deucher 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
11683e4b9982SAlex Deucher };
11693e4b9982SAlex Deucher 
11703e4b9982SAlex Deucher static void
11713e4b9982SAlex Deucher atombios_external_encoder_setup(struct drm_encoder *encoder,
11723e4b9982SAlex Deucher 				struct drm_encoder *ext_encoder,
11733e4b9982SAlex Deucher 				int action)
11743e4b9982SAlex Deucher {
11753e4b9982SAlex Deucher 	struct drm_device *dev = encoder->dev;
11763e4b9982SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
11773e4b9982SAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1178bf982ebfSAlex Deucher 	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
11793e4b9982SAlex Deucher 	union external_encoder_control args;
11803e4b9982SAlex Deucher 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
11813e4b9982SAlex Deucher 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
11823e4b9982SAlex Deucher 	u8 frev, crev;
11833e4b9982SAlex Deucher 	int dp_clock = 0;
11843e4b9982SAlex Deucher 	int dp_lane_count = 0;
11853e4b9982SAlex Deucher 	int connector_object_id = 0;
1186bf982ebfSAlex Deucher 	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
1187df271becSAlex Deucher 	int bpc = 8;
11883e4b9982SAlex Deucher 
11893e4b9982SAlex Deucher 	if (connector) {
11903e4b9982SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
11913e4b9982SAlex Deucher 		struct radeon_connector_atom_dig *dig_connector =
11923e4b9982SAlex Deucher 			radeon_connector->con_priv;
11933e4b9982SAlex Deucher 
11943e4b9982SAlex Deucher 		dp_clock = dig_connector->dp_clock;
11953e4b9982SAlex Deucher 		dp_lane_count = dig_connector->dp_lane_count;
11963e4b9982SAlex Deucher 		connector_object_id =
11973e4b9982SAlex Deucher 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1198df271becSAlex Deucher 		bpc = connector->display_info.bpc;
11993e4b9982SAlex Deucher 	}
12003e4b9982SAlex Deucher 
12013e4b9982SAlex Deucher 	memset(&args, 0, sizeof(args));
12023e4b9982SAlex Deucher 
12033e4b9982SAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
12043e4b9982SAlex Deucher 		return;
12053e4b9982SAlex Deucher 
12063e4b9982SAlex Deucher 	switch (frev) {
12073e4b9982SAlex Deucher 	case 1:
12083e4b9982SAlex Deucher 		/* no params on frev 1 */
12093e4b9982SAlex Deucher 		break;
12103e4b9982SAlex Deucher 	case 2:
12113e4b9982SAlex Deucher 		switch (crev) {
12123e4b9982SAlex Deucher 		case 1:
12133e4b9982SAlex Deucher 		case 2:
12143e4b9982SAlex Deucher 			args.v1.sDigEncoder.ucAction = action;
12153e4b9982SAlex Deucher 			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
12163e4b9982SAlex Deucher 			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
12173e4b9982SAlex Deucher 
12183e4b9982SAlex Deucher 			if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
12193e4b9982SAlex Deucher 				if (dp_clock == 270000)
12203e4b9982SAlex Deucher 					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
12213e4b9982SAlex Deucher 				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
12223e4b9982SAlex Deucher 			} else if (radeon_encoder->pixel_clock > 165000)
12233e4b9982SAlex Deucher 				args.v1.sDigEncoder.ucLaneNum = 8;
12243e4b9982SAlex Deucher 			else
12253e4b9982SAlex Deucher 				args.v1.sDigEncoder.ucLaneNum = 4;
12263e4b9982SAlex Deucher 			break;
1227bf982ebfSAlex Deucher 		case 3:
1228bf982ebfSAlex Deucher 			args.v3.sExtEncoder.ucAction = action;
1229bf982ebfSAlex Deucher 			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
12304589433cSCédric Cano 				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
1231bf982ebfSAlex Deucher 			else
1232bf982ebfSAlex Deucher 				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1233bf982ebfSAlex Deucher 			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1234bf982ebfSAlex Deucher 
1235bf982ebfSAlex Deucher 			if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
1236bf982ebfSAlex Deucher 				if (dp_clock == 270000)
1237bf982ebfSAlex Deucher 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1238bf982ebfSAlex Deucher 				else if (dp_clock == 540000)
1239bf982ebfSAlex Deucher 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1240bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
1241bf982ebfSAlex Deucher 			} else if (radeon_encoder->pixel_clock > 165000)
1242bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucLaneNum = 8;
1243bf982ebfSAlex Deucher 			else
1244bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucLaneNum = 4;
1245bf982ebfSAlex Deucher 			switch (ext_enum) {
1246bf982ebfSAlex Deucher 			case GRAPH_OBJECT_ENUM_ID1:
1247bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1248bf982ebfSAlex Deucher 				break;
1249bf982ebfSAlex Deucher 			case GRAPH_OBJECT_ENUM_ID2:
1250bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1251bf982ebfSAlex Deucher 				break;
1252bf982ebfSAlex Deucher 			case GRAPH_OBJECT_ENUM_ID3:
1253bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1254bf982ebfSAlex Deucher 				break;
1255bf982ebfSAlex Deucher 			}
1256df271becSAlex Deucher 			switch (bpc) {
1257df271becSAlex Deucher 			case 0:
1258df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
1259df271becSAlex Deucher 				break;
1260df271becSAlex Deucher 			case 6:
1261df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
1262df271becSAlex Deucher 				break;
1263df271becSAlex Deucher 			case 8:
1264df271becSAlex Deucher 			default:
1265bf982ebfSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
1266bf982ebfSAlex Deucher 				break;
1267df271becSAlex Deucher 			case 10:
1268df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
1269df271becSAlex Deucher 				break;
1270df271becSAlex Deucher 			case 12:
1271df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
1272df271becSAlex Deucher 				break;
1273df271becSAlex Deucher 			case 16:
1274df271becSAlex Deucher 				args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
1275df271becSAlex Deucher 				break;
1276df271becSAlex Deucher 			}
1277df271becSAlex Deucher 			break;
12783e4b9982SAlex Deucher 		default:
12793e4b9982SAlex Deucher 			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
12803e4b9982SAlex Deucher 			return;
12813e4b9982SAlex Deucher 		}
12823e4b9982SAlex Deucher 		break;
12833e4b9982SAlex Deucher 	default:
12843e4b9982SAlex Deucher 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
12853e4b9982SAlex Deucher 		return;
12863e4b9982SAlex Deucher 	}
12873e4b9982SAlex Deucher 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
12883e4b9982SAlex Deucher }
12893e4b9982SAlex Deucher 
1290771fe6b9SJerome Glisse static void
1291771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
1292771fe6b9SJerome Glisse {
1293771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1294771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1295771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1296771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1297771fe6b9SJerome Glisse 	ENABLE_YUV_PS_ALLOCATION args;
1298771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
1299771fe6b9SJerome Glisse 	uint32_t temp, reg;
1300771fe6b9SJerome Glisse 
1301771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1302771fe6b9SJerome Glisse 
1303771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
1304771fe6b9SJerome Glisse 		reg = R600_BIOS_3_SCRATCH;
1305771fe6b9SJerome Glisse 	else
1306771fe6b9SJerome Glisse 		reg = RADEON_BIOS_3_SCRATCH;
1307771fe6b9SJerome Glisse 
1308771fe6b9SJerome Glisse 	/* XXX: fix up scratch reg handling */
1309771fe6b9SJerome Glisse 	temp = RREG32(reg);
13104ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1311771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
1312771fe6b9SJerome Glisse 			     (radeon_crtc->crtc_id << 18)));
13134ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1314771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
1315771fe6b9SJerome Glisse 	else
1316771fe6b9SJerome Glisse 		WREG32(reg, 0);
1317771fe6b9SJerome Glisse 
1318771fe6b9SJerome Glisse 	if (enable)
1319771fe6b9SJerome Glisse 		args.ucEnable = ATOM_ENABLE;
1320771fe6b9SJerome Glisse 	args.ucCRTC = radeon_crtc->crtc_id;
1321771fe6b9SJerome Glisse 
1322771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1323771fe6b9SJerome Glisse 
1324771fe6b9SJerome Glisse 	WREG32(reg, temp);
1325771fe6b9SJerome Glisse }
1326771fe6b9SJerome Glisse 
1327771fe6b9SJerome Glisse static void
1328771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1329771fe6b9SJerome Glisse {
1330771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1331771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1332771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
13333e4b9982SAlex Deucher 	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
1334771fe6b9SJerome Glisse 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1335771fe6b9SJerome Glisse 	int index = 0;
1336771fe6b9SJerome Glisse 	bool is_dig = false;
133769c74525SAlex Deucher 	bool is_dce5_dac = false;
1338d07f4e83SAlex Deucher 	bool is_dce5_dvo = false;
1339771fe6b9SJerome Glisse 
1340771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1341771fe6b9SJerome Glisse 
1342d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
13434ce001abSDave Airlie 		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
13444ce001abSDave Airlie 		  radeon_encoder->active_device);
1345771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1346771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1347771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1348771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1349771fe6b9SJerome Glisse 		break;
1350771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1351771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1352771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1353771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1354771fe6b9SJerome Glisse 		is_dig = true;
1355771fe6b9SJerome Glisse 		break;
1356771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1357771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
135899999aaaSAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
135999999aaaSAlex Deucher 		break;
1360771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1361d07f4e83SAlex Deucher 		if (ASIC_IS_DCE5(rdev))
1362d07f4e83SAlex Deucher 			is_dce5_dvo = true;
1363d07f4e83SAlex Deucher 		else if (ASIC_IS_DCE3(rdev))
136499999aaaSAlex Deucher 			is_dig = true;
136599999aaaSAlex Deucher 		else
1366771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1367771fe6b9SJerome Glisse 		break;
1368771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1369771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1370771fe6b9SJerome Glisse 		break;
1371771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1372771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1373771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1374771fe6b9SJerome Glisse 		else
1375771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1376771fe6b9SJerome Glisse 		break;
1377771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1378771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
137969c74525SAlex Deucher 		if (ASIC_IS_DCE5(rdev))
138069c74525SAlex Deucher 			is_dce5_dac = true;
138169c74525SAlex Deucher 		else {
13828c2a6d73SAlex Deucher 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1383771fe6b9SJerome Glisse 				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
13848c2a6d73SAlex Deucher 			else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1385771fe6b9SJerome Glisse 				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1386771fe6b9SJerome Glisse 			else
1387771fe6b9SJerome Glisse 				index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
138869c74525SAlex Deucher 		}
1389771fe6b9SJerome Glisse 		break;
1390771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1391771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
13928c2a6d73SAlex Deucher 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1393771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
13948c2a6d73SAlex Deucher 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1395771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1396771fe6b9SJerome Glisse 		else
1397771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1398771fe6b9SJerome Glisse 		break;
1399771fe6b9SJerome Glisse 	}
1400771fe6b9SJerome Glisse 
1401771fe6b9SJerome Glisse 	if (is_dig) {
1402771fe6b9SJerome Glisse 		switch (mode) {
1403771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
1404a5f798ceSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
1405fb668c2fSAlex Deucher 			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
140658682f10SDave Airlie 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1407fb668c2fSAlex Deucher 
14088b834852SAlex Deucher 				if (connector &&
14098b834852SAlex Deucher 				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
14108b834852SAlex Deucher 					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
14118b834852SAlex Deucher 					struct radeon_connector_atom_dig *radeon_dig_connector =
14128b834852SAlex Deucher 						radeon_connector->con_priv;
14138b834852SAlex Deucher 					atombios_set_edp_panel_power(connector,
14148b834852SAlex Deucher 								     ATOM_TRANSMITTER_ACTION_POWER_ON);
14158b834852SAlex Deucher 					radeon_dig_connector->edp_on = true;
14168b834852SAlex Deucher 				}
141758682f10SDave Airlie 				dp_link_train(encoder, connector);
1418fb668c2fSAlex Deucher 				if (ASIC_IS_DCE4(rdev))
1419fb668c2fSAlex Deucher 					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
142058682f10SDave Airlie 			}
1421ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1422ba251bdeSAlex Deucher 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
1423771fe6b9SJerome Glisse 			break;
1424771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1425771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1426771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
142758682f10SDave Airlie 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
1428fb668c2fSAlex Deucher 			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
14298b834852SAlex Deucher 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
14308b834852SAlex Deucher 
1431fb668c2fSAlex Deucher 				if (ASIC_IS_DCE4(rdev))
1432fb668c2fSAlex Deucher 					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
14338b834852SAlex Deucher 				if (connector &&
14348b834852SAlex Deucher 				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
14358b834852SAlex Deucher 					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
14368b834852SAlex Deucher 					struct radeon_connector_atom_dig *radeon_dig_connector =
14378b834852SAlex Deucher 						radeon_connector->con_priv;
14388b834852SAlex Deucher 					atombios_set_edp_panel_power(connector,
14398b834852SAlex Deucher 								     ATOM_TRANSMITTER_ACTION_POWER_OFF);
14408b834852SAlex Deucher 					radeon_dig_connector->edp_on = false;
14418b834852SAlex Deucher 				}
1442fb668c2fSAlex Deucher 			}
1443ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1444ba251bdeSAlex Deucher 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1445771fe6b9SJerome Glisse 			break;
1446771fe6b9SJerome Glisse 		}
144769c74525SAlex Deucher 	} else if (is_dce5_dac) {
144869c74525SAlex Deucher 		switch (mode) {
144969c74525SAlex Deucher 		case DRM_MODE_DPMS_ON:
145069c74525SAlex Deucher 			atombios_dac_setup(encoder, ATOM_ENABLE);
145169c74525SAlex Deucher 			break;
145269c74525SAlex Deucher 		case DRM_MODE_DPMS_STANDBY:
145369c74525SAlex Deucher 		case DRM_MODE_DPMS_SUSPEND:
145469c74525SAlex Deucher 		case DRM_MODE_DPMS_OFF:
145569c74525SAlex Deucher 			atombios_dac_setup(encoder, ATOM_DISABLE);
145669c74525SAlex Deucher 			break;
145769c74525SAlex Deucher 		}
1458d07f4e83SAlex Deucher 	} else if (is_dce5_dvo) {
1459d07f4e83SAlex Deucher 		switch (mode) {
1460d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_ON:
1461d07f4e83SAlex Deucher 			atombios_dvo_setup(encoder, ATOM_ENABLE);
1462d07f4e83SAlex Deucher 			break;
1463d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_STANDBY:
1464d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_SUSPEND:
1465d07f4e83SAlex Deucher 		case DRM_MODE_DPMS_OFF:
1466d07f4e83SAlex Deucher 			atombios_dvo_setup(encoder, ATOM_DISABLE);
1467d07f4e83SAlex Deucher 			break;
1468d07f4e83SAlex Deucher 		}
1469771fe6b9SJerome Glisse 	} else {
1470771fe6b9SJerome Glisse 		switch (mode) {
1471771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
1472771fe6b9SJerome Glisse 			args.ucAction = ATOM_ENABLE;
1473ba251bdeSAlex Deucher 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1474ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1475ba251bdeSAlex Deucher 				args.ucAction = ATOM_LCD_BLON;
1476ba251bdeSAlex Deucher 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1477ba251bdeSAlex Deucher 			}
1478771fe6b9SJerome Glisse 			break;
1479771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1480771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1481771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
1482771fe6b9SJerome Glisse 			args.ucAction = ATOM_DISABLE;
1483ba251bdeSAlex Deucher 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1484ba251bdeSAlex Deucher 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1485ba251bdeSAlex Deucher 				args.ucAction = ATOM_LCD_BLOFF;
1486ba251bdeSAlex Deucher 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1487ba251bdeSAlex Deucher 			}
1488771fe6b9SJerome Glisse 			break;
1489771fe6b9SJerome Glisse 		}
1490771fe6b9SJerome Glisse 	}
14913e4b9982SAlex Deucher 
14923e4b9982SAlex Deucher 	if (ext_encoder) {
14933e4b9982SAlex Deucher 		int action;
14943e4b9982SAlex Deucher 
14953e4b9982SAlex Deucher 		switch (mode) {
14963e4b9982SAlex Deucher 		case DRM_MODE_DPMS_ON:
14973e4b9982SAlex Deucher 		default:
1498633b9164SAlex Deucher 			if (ASIC_IS_DCE41(rdev))
1499bf982ebfSAlex Deucher 				action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT;
1500bf982ebfSAlex Deucher 			else
15013e4b9982SAlex Deucher 				action = ATOM_ENABLE;
15023e4b9982SAlex Deucher 			break;
15033e4b9982SAlex Deucher 		case DRM_MODE_DPMS_STANDBY:
15043e4b9982SAlex Deucher 		case DRM_MODE_DPMS_SUSPEND:
15053e4b9982SAlex Deucher 		case DRM_MODE_DPMS_OFF:
1506633b9164SAlex Deucher 			if (ASIC_IS_DCE41(rdev))
1507bf982ebfSAlex Deucher 				action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT;
1508bf982ebfSAlex Deucher 			else
15093e4b9982SAlex Deucher 				action = ATOM_DISABLE;
15103e4b9982SAlex Deucher 			break;
15113e4b9982SAlex Deucher 		}
15123e4b9982SAlex Deucher 		atombios_external_encoder_setup(encoder, ext_encoder, action);
15133e4b9982SAlex Deucher 	}
15143e4b9982SAlex Deucher 
1515771fe6b9SJerome Glisse 	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1516c913e23aSRafał Miłecki 
1517771fe6b9SJerome Glisse }
1518771fe6b9SJerome Glisse 
15199ae47867SAlex Deucher union crtc_source_param {
1520771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
1521771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
1522771fe6b9SJerome Glisse };
1523771fe6b9SJerome Glisse 
1524771fe6b9SJerome Glisse static void
1525771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
1526771fe6b9SJerome Glisse {
1527771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1528771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1529771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1530771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
15319ae47867SAlex Deucher 	union crtc_source_param args;
1532771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1533771fe6b9SJerome Glisse 	uint8_t frev, crev;
1534f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
1535771fe6b9SJerome Glisse 
1536771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1537771fe6b9SJerome Glisse 
1538a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1539a084e6eeSAlex Deucher 		return;
1540771fe6b9SJerome Glisse 
1541771fe6b9SJerome Glisse 	switch (frev) {
1542771fe6b9SJerome Glisse 	case 1:
1543771fe6b9SJerome Glisse 		switch (crev) {
1544771fe6b9SJerome Glisse 		case 1:
1545771fe6b9SJerome Glisse 		default:
1546771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
1547771fe6b9SJerome Glisse 				args.v1.ucCRTC = radeon_crtc->crtc_id;
1548771fe6b9SJerome Glisse 			else {
1549771fe6b9SJerome Glisse 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
1550771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id;
1551771fe6b9SJerome Glisse 				} else {
1552771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
1553771fe6b9SJerome Glisse 				}
1554771fe6b9SJerome Glisse 			}
1555771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1556771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1557771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1558771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1559771fe6b9SJerome Glisse 				break;
1560771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1561771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1562771fe6b9SJerome Glisse 				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
1563771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1564771fe6b9SJerome Glisse 				else
1565771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1566771fe6b9SJerome Glisse 				break;
1567771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1568771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DDI:
1569771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1570771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1571771fe6b9SJerome Glisse 				break;
1572771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1573771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
15744ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1575771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
15764ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1577771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1578771fe6b9SJerome Glisse 				else
1579771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1580771fe6b9SJerome Glisse 				break;
1581771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1582771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
15834ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1584771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
15854ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1586771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1587771fe6b9SJerome Glisse 				else
1588771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1589771fe6b9SJerome Glisse 				break;
1590771fe6b9SJerome Glisse 			}
1591771fe6b9SJerome Glisse 			break;
1592771fe6b9SJerome Glisse 		case 2:
1593771fe6b9SJerome Glisse 			args.v2.ucCRTC = radeon_crtc->crtc_id;
1594771fe6b9SJerome Glisse 			args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1595771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1596771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1597771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1598771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1599f28cf339SDave Airlie 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1600f28cf339SDave Airlie 				dig = radeon_encoder->enc_priv;
1601bcc1c2a1SAlex Deucher 				switch (dig->dig_encoder) {
1602bcc1c2a1SAlex Deucher 				case 0:
1603771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1604771fe6b9SJerome Glisse 					break;
1605bcc1c2a1SAlex Deucher 				case 1:
1606bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1607bcc1c2a1SAlex Deucher 					break;
1608bcc1c2a1SAlex Deucher 				case 2:
1609bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
1610bcc1c2a1SAlex Deucher 					break;
1611bcc1c2a1SAlex Deucher 				case 3:
1612bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
1613bcc1c2a1SAlex Deucher 					break;
1614bcc1c2a1SAlex Deucher 				case 4:
1615bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
1616bcc1c2a1SAlex Deucher 					break;
1617bcc1c2a1SAlex Deucher 				case 5:
1618bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
1619bcc1c2a1SAlex Deucher 					break;
1620bcc1c2a1SAlex Deucher 				}
1621bcc1c2a1SAlex Deucher 				break;
1622771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1623771fe6b9SJerome Glisse 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
1624771fe6b9SJerome Glisse 				break;
1625771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
16264ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1627771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
16284ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1629771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1630771fe6b9SJerome Glisse 				else
1631771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1632771fe6b9SJerome Glisse 				break;
1633771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
16344ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1635771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
16364ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1637771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1638771fe6b9SJerome Glisse 				else
1639771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1640771fe6b9SJerome Glisse 				break;
1641771fe6b9SJerome Glisse 			}
1642771fe6b9SJerome Glisse 			break;
1643771fe6b9SJerome Glisse 		}
1644771fe6b9SJerome Glisse 		break;
1645771fe6b9SJerome Glisse 	default:
1646771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
164799999aaaSAlex Deucher 		return;
1648771fe6b9SJerome Glisse 	}
1649771fe6b9SJerome Glisse 
1650771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1651267364acSAlex Deucher 
1652267364acSAlex Deucher 	/* update scratch regs with new routing */
1653267364acSAlex Deucher 	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1654771fe6b9SJerome Glisse }
1655771fe6b9SJerome Glisse 
1656771fe6b9SJerome Glisse static void
1657771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder,
1658771fe6b9SJerome Glisse 			      struct drm_display_mode *mode)
1659771fe6b9SJerome Glisse {
1660771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1661771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1662771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1663771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1664771fe6b9SJerome Glisse 
1665771fe6b9SJerome Glisse 	/* Funky macbooks */
1666771fe6b9SJerome Glisse 	if ((dev->pdev->device == 0x71C5) &&
1667771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_vendor == 0x106b) &&
1668771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_device == 0x0080)) {
1669771fe6b9SJerome Glisse 		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1670771fe6b9SJerome Glisse 			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1671771fe6b9SJerome Glisse 
1672771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1673771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1674771fe6b9SJerome Glisse 
1675771fe6b9SJerome Glisse 			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1676771fe6b9SJerome Glisse 		}
1677771fe6b9SJerome Glisse 	}
1678771fe6b9SJerome Glisse 
1679771fe6b9SJerome Glisse 	/* set scaler clears this on some chips */
1680c9417bddSAlex Deucher 	if (ASIC_IS_AVIVO(rdev) &&
1681c9417bddSAlex Deucher 	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
1682c9417bddSAlex Deucher 		if (ASIC_IS_DCE4(rdev)) {
1683c9417bddSAlex Deucher 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1684c9417bddSAlex Deucher 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
1685c9417bddSAlex Deucher 				       EVERGREEN_INTERLEAVE_EN);
1686c9417bddSAlex Deucher 			else
1687c9417bddSAlex Deucher 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1688c9417bddSAlex Deucher 		} else {
1689c9417bddSAlex Deucher 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1690ceefedd8SAlex Deucher 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
1691ceefedd8SAlex Deucher 				       AVIVO_D1MODE_INTERLEAVE_EN);
1692c9417bddSAlex Deucher 			else
1693c9417bddSAlex Deucher 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1694c9417bddSAlex Deucher 		}
1695ceefedd8SAlex Deucher 	}
1696771fe6b9SJerome Glisse }
1697771fe6b9SJerome Glisse 
1698f28cf339SDave Airlie static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
1699f28cf339SDave Airlie {
1700f28cf339SDave Airlie 	struct drm_device *dev = encoder->dev;
1701f28cf339SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
1702f28cf339SDave Airlie 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1703f28cf339SDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1704f28cf339SDave Airlie 	struct drm_encoder *test_encoder;
1705f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
1706f28cf339SDave Airlie 	uint32_t dig_enc_in_use = 0;
1707bcc1c2a1SAlex Deucher 
1708badbb57bSAlex Deucher 	/* DCE4/5 */
1709bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev)) {
17105137ee94SAlex Deucher 		dig = radeon_encoder->enc_priv;
171196b3bef8SAlex Deucher 		if (ASIC_IS_DCE41(rdev))
171296b3bef8SAlex Deucher 			return radeon_crtc->crtc_id;
171396b3bef8SAlex Deucher 		else {
1714bcc1c2a1SAlex Deucher 			switch (radeon_encoder->encoder_id) {
1715bcc1c2a1SAlex Deucher 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
17165137ee94SAlex Deucher 				if (dig->linkb)
1717bcc1c2a1SAlex Deucher 					return 1;
1718bcc1c2a1SAlex Deucher 				else
1719bcc1c2a1SAlex Deucher 					return 0;
1720bcc1c2a1SAlex Deucher 				break;
1721bcc1c2a1SAlex Deucher 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
17225137ee94SAlex Deucher 				if (dig->linkb)
1723bcc1c2a1SAlex Deucher 					return 3;
1724bcc1c2a1SAlex Deucher 				else
1725bcc1c2a1SAlex Deucher 					return 2;
1726bcc1c2a1SAlex Deucher 				break;
1727bcc1c2a1SAlex Deucher 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
17285137ee94SAlex Deucher 				if (dig->linkb)
1729bcc1c2a1SAlex Deucher 					return 5;
1730bcc1c2a1SAlex Deucher 				else
1731bcc1c2a1SAlex Deucher 					return 4;
1732bcc1c2a1SAlex Deucher 				break;
1733bcc1c2a1SAlex Deucher 			}
1734bcc1c2a1SAlex Deucher 		}
1735b61c99deSAlex Deucher 	}
1736bcc1c2a1SAlex Deucher 
1737f28cf339SDave Airlie 	/* on DCE32 and encoder can driver any block so just crtc id */
1738f28cf339SDave Airlie 	if (ASIC_IS_DCE32(rdev)) {
1739f28cf339SDave Airlie 		return radeon_crtc->crtc_id;
1740f28cf339SDave Airlie 	}
1741f28cf339SDave Airlie 
1742f28cf339SDave Airlie 	/* on DCE3 - LVTMA can only be driven by DIGB */
1743f28cf339SDave Airlie 	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
1744f28cf339SDave Airlie 		struct radeon_encoder *radeon_test_encoder;
1745f28cf339SDave Airlie 
1746f28cf339SDave Airlie 		if (encoder == test_encoder)
1747f28cf339SDave Airlie 			continue;
1748f28cf339SDave Airlie 
1749f28cf339SDave Airlie 		if (!radeon_encoder_is_digital(test_encoder))
1750f28cf339SDave Airlie 			continue;
1751f28cf339SDave Airlie 
1752f28cf339SDave Airlie 		radeon_test_encoder = to_radeon_encoder(test_encoder);
1753f28cf339SDave Airlie 		dig = radeon_test_encoder->enc_priv;
1754f28cf339SDave Airlie 
1755f28cf339SDave Airlie 		if (dig->dig_encoder >= 0)
1756f28cf339SDave Airlie 			dig_enc_in_use |= (1 << dig->dig_encoder);
1757f28cf339SDave Airlie 	}
1758f28cf339SDave Airlie 
1759f28cf339SDave Airlie 	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
1760f28cf339SDave Airlie 		if (dig_enc_in_use & 0x2)
1761f28cf339SDave Airlie 			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
1762f28cf339SDave Airlie 		return 1;
1763f28cf339SDave Airlie 	}
1764f28cf339SDave Airlie 	if (!(dig_enc_in_use & 1))
1765f28cf339SDave Airlie 		return 0;
1766f28cf339SDave Airlie 	return 1;
1767f28cf339SDave Airlie }
1768f28cf339SDave Airlie 
1769771fe6b9SJerome Glisse static void
1770771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1771771fe6b9SJerome Glisse 			     struct drm_display_mode *mode,
1772771fe6b9SJerome Glisse 			     struct drm_display_mode *adjusted_mode)
1773771fe6b9SJerome Glisse {
1774771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1775771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1776771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
17773e4b9982SAlex Deucher 	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
1778771fe6b9SJerome Glisse 
1779771fe6b9SJerome Glisse 	radeon_encoder->pixel_clock = adjusted_mode->clock;
1780771fe6b9SJerome Glisse 
1781c6f8505eSAlex Deucher 	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
17824ce001abSDave Airlie 		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
1783771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, true);
1784771fe6b9SJerome Glisse 		else
1785771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, false);
1786771fe6b9SJerome Glisse 	}
1787771fe6b9SJerome Glisse 
1788771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1789771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1790771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1791771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1792771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1793771fe6b9SJerome Glisse 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
1794771fe6b9SJerome Glisse 		break;
1795771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1796771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1797771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1798771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1799bcc1c2a1SAlex Deucher 		if (ASIC_IS_DCE4(rdev)) {
1800bcc1c2a1SAlex Deucher 			/* disable the transmitter */
1801bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1802bcc1c2a1SAlex Deucher 			/* setup and enable the encoder */
1803bcc1c2a1SAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP);
1804bcc1c2a1SAlex Deucher 
1805bcc1c2a1SAlex Deucher 			/* init and enable the transmitter */
1806bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
1807bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1808bcc1c2a1SAlex Deucher 		} else {
1809771fe6b9SJerome Glisse 			/* disable the encoder and transmitter */
18101a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1811771fe6b9SJerome Glisse 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
1812771fe6b9SJerome Glisse 
1813771fe6b9SJerome Glisse 			/* setup and enable the encoder and transmitter */
1814771fe6b9SJerome Glisse 			atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
18151a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
18161a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
18171a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1818bcc1c2a1SAlex Deucher 		}
1819771fe6b9SJerome Glisse 		break;
1820771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1821771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1822771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
182399999aaaSAlex Deucher 		atombios_dvo_setup(encoder, ATOM_ENABLE);
1824771fe6b9SJerome Glisse 		break;
1825771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1826771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1827771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1828771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1829771fe6b9SJerome Glisse 		atombios_dac_setup(encoder, ATOM_ENABLE);
1830d3a67a43SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
18314ce001abSDave Airlie 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
1832771fe6b9SJerome Glisse 				atombios_tv_setup(encoder, ATOM_ENABLE);
1833d3a67a43SAlex Deucher 			else
1834d3a67a43SAlex Deucher 				atombios_tv_setup(encoder, ATOM_DISABLE);
1835d3a67a43SAlex Deucher 		}
1836771fe6b9SJerome Glisse 		break;
1837771fe6b9SJerome Glisse 	}
18383e4b9982SAlex Deucher 
18393e4b9982SAlex Deucher 	if (ext_encoder) {
1840633b9164SAlex Deucher 		if (ASIC_IS_DCE41(rdev)) {
1841bf982ebfSAlex Deucher 			atombios_external_encoder_setup(encoder, ext_encoder,
1842bf982ebfSAlex Deucher 							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
1843bf982ebfSAlex Deucher 			atombios_external_encoder_setup(encoder, ext_encoder,
1844bf982ebfSAlex Deucher 							EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
1845bf982ebfSAlex Deucher 		} else
18463e4b9982SAlex Deucher 			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
18473e4b9982SAlex Deucher 	}
18483e4b9982SAlex Deucher 
1849771fe6b9SJerome Glisse 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
1850dafc3bd5SChristian Koenig 
18512cd6218cSRafał Miłecki 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
18522cd6218cSRafał Miłecki 		r600_hdmi_enable(encoder);
1853dafc3bd5SChristian Koenig 		r600_hdmi_setmode(encoder, adjusted_mode);
1854771fe6b9SJerome Glisse 	}
18552cd6218cSRafał Miłecki }
1856771fe6b9SJerome Glisse 
1857771fe6b9SJerome Glisse static bool
18584ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1859771fe6b9SJerome Glisse {
1860771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1861771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1862771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
18634ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1864771fe6b9SJerome Glisse 
1865771fe6b9SJerome Glisse 	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
1866771fe6b9SJerome Glisse 				       ATOM_DEVICE_CV_SUPPORT |
1867771fe6b9SJerome Glisse 				       ATOM_DEVICE_CRT_SUPPORT)) {
1868771fe6b9SJerome Glisse 		DAC_LOAD_DETECTION_PS_ALLOCATION args;
1869771fe6b9SJerome Glisse 		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1870771fe6b9SJerome Glisse 		uint8_t frev, crev;
1871771fe6b9SJerome Glisse 
1872771fe6b9SJerome Glisse 		memset(&args, 0, sizeof(args));
1873771fe6b9SJerome Glisse 
1874a084e6eeSAlex Deucher 		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1875a084e6eeSAlex Deucher 			return false;
1876771fe6b9SJerome Glisse 
1877771fe6b9SJerome Glisse 		args.sDacload.ucMisc = 0;
1878771fe6b9SJerome Glisse 
1879771fe6b9SJerome Glisse 		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1880771fe6b9SJerome Glisse 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
1881771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_A;
1882771fe6b9SJerome Glisse 		else
1883771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_B;
1884771fe6b9SJerome Glisse 
18854ce001abSDave Airlie 		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
1886771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
18874ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
1888771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
18894ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
1890771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
1891771fe6b9SJerome Glisse 			if (crev >= 3)
1892771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
18934ce001abSDave Airlie 		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
1894771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
1895771fe6b9SJerome Glisse 			if (crev >= 3)
1896771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1897771fe6b9SJerome Glisse 		}
1898771fe6b9SJerome Glisse 
1899771fe6b9SJerome Glisse 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1900771fe6b9SJerome Glisse 
1901771fe6b9SJerome Glisse 		return true;
1902771fe6b9SJerome Glisse 	} else
1903771fe6b9SJerome Glisse 		return false;
1904771fe6b9SJerome Glisse }
1905771fe6b9SJerome Glisse 
1906771fe6b9SJerome Glisse static enum drm_connector_status
1907771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1908771fe6b9SJerome Glisse {
1909771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1910771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1911771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
19124ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1913771fe6b9SJerome Glisse 	uint32_t bios_0_scratch;
1914771fe6b9SJerome Glisse 
19154ce001abSDave Airlie 	if (!atombios_dac_load_detect(encoder, connector)) {
1916d9fdaafbSDave Airlie 		DRM_DEBUG_KMS("detect returned false \n");
1917771fe6b9SJerome Glisse 		return connector_status_unknown;
1918771fe6b9SJerome Glisse 	}
1919771fe6b9SJerome Glisse 
1920771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
1921771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
1922771fe6b9SJerome Glisse 	else
1923771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
1924771fe6b9SJerome Glisse 
1925d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
19264ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
1927771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
1928771fe6b9SJerome Glisse 			return connector_status_connected;
19294ce001abSDave Airlie 	}
19304ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
1931771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
1932771fe6b9SJerome Glisse 			return connector_status_connected;
19334ce001abSDave Airlie 	}
19344ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
1935771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
1936771fe6b9SJerome Glisse 			return connector_status_connected;
19374ce001abSDave Airlie 	}
19384ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
1939771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
1940771fe6b9SJerome Glisse 			return connector_status_connected; /* CTV */
1941771fe6b9SJerome Glisse 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
1942771fe6b9SJerome Glisse 			return connector_status_connected; /* STV */
1943771fe6b9SJerome Glisse 	}
1944771fe6b9SJerome Glisse 	return connector_status_disconnected;
1945771fe6b9SJerome Glisse }
1946771fe6b9SJerome Glisse 
1947771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
1948771fe6b9SJerome Glisse {
1949267364acSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1950fb939dfcSAlex Deucher 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1951267364acSAlex Deucher 
1952267364acSAlex Deucher 	if (radeon_encoder->active_device &
1953267364acSAlex Deucher 	    (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
1954267364acSAlex Deucher 		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1955267364acSAlex Deucher 		if (dig)
1956267364acSAlex Deucher 			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
1957267364acSAlex Deucher 	}
1958267364acSAlex Deucher 
1959771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, true);
1960771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
1961267364acSAlex Deucher 
1962fb939dfcSAlex Deucher 	if (connector) {
1963fb939dfcSAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
19644e633939SAlex Deucher 
19654e633939SAlex Deucher 		/* select the clock/data port if it uses a router */
1966fb939dfcSAlex Deucher 		if (radeon_connector->router.cd_valid)
1967fb939dfcSAlex Deucher 			radeon_router_select_cd_port(radeon_connector);
19684e633939SAlex Deucher 
19694e633939SAlex Deucher 		/* turn eDP panel on for mode set */
19704e633939SAlex Deucher 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
19714e633939SAlex Deucher 			atombios_set_edp_panel_power(connector,
19724e633939SAlex Deucher 						     ATOM_TRANSMITTER_ACTION_POWER_ON);
1973fb939dfcSAlex Deucher 	}
1974fb939dfcSAlex Deucher 
1975267364acSAlex Deucher 	/* this is needed for the pll/ss setup to work correctly in some cases */
1976267364acSAlex Deucher 	atombios_set_encoder_crtc_source(encoder);
1977771fe6b9SJerome Glisse }
1978771fe6b9SJerome Glisse 
1979771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
1980771fe6b9SJerome Glisse {
1981771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
1982771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, false);
1983771fe6b9SJerome Glisse }
1984771fe6b9SJerome Glisse 
19854ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
19864ce001abSDave Airlie {
1987aa961391SAlex Deucher 	struct drm_device *dev = encoder->dev;
1988aa961391SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
19894ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1990f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
1991a0ae5864SAlex Deucher 
1992a0ae5864SAlex Deucher 	/* check for pre-DCE3 cards with shared encoders;
1993a0ae5864SAlex Deucher 	 * can't really use the links individually, so don't disable
1994a0ae5864SAlex Deucher 	 * the encoder if it's in use by another connector
1995a0ae5864SAlex Deucher 	 */
1996a0ae5864SAlex Deucher 	if (!ASIC_IS_DCE3(rdev)) {
1997a0ae5864SAlex Deucher 		struct drm_encoder *other_encoder;
1998a0ae5864SAlex Deucher 		struct radeon_encoder *other_radeon_encoder;
1999a0ae5864SAlex Deucher 
2000a0ae5864SAlex Deucher 		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
2001a0ae5864SAlex Deucher 			other_radeon_encoder = to_radeon_encoder(other_encoder);
2002a0ae5864SAlex Deucher 			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
2003a0ae5864SAlex Deucher 			    drm_helper_encoder_in_use(other_encoder))
2004a0ae5864SAlex Deucher 				goto disable_done;
2005a0ae5864SAlex Deucher 		}
2006a0ae5864SAlex Deucher 	}
2007a0ae5864SAlex Deucher 
20084ce001abSDave Airlie 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2009f28cf339SDave Airlie 
2010aa961391SAlex Deucher 	switch (radeon_encoder->encoder_id) {
2011aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2012aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2013aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2014aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2015aa961391SAlex Deucher 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
2016aa961391SAlex Deucher 		break;
2017aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2018aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2019aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2020aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2021aa961391SAlex Deucher 		if (ASIC_IS_DCE4(rdev))
2022aa961391SAlex Deucher 			/* disable the transmitter */
2023aa961391SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
2024aa961391SAlex Deucher 		else {
2025aa961391SAlex Deucher 			/* disable the encoder and transmitter */
2026aa961391SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
2027aa961391SAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
2028aa961391SAlex Deucher 		}
2029aa961391SAlex Deucher 		break;
2030aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2031aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2032aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
203399999aaaSAlex Deucher 		atombios_dvo_setup(encoder, ATOM_DISABLE);
2034aa961391SAlex Deucher 		break;
2035aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2036aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2037aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2038aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2039aa961391SAlex Deucher 		atombios_dac_setup(encoder, ATOM_DISABLE);
20408bf3aae6SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2041aa961391SAlex Deucher 			atombios_tv_setup(encoder, ATOM_DISABLE);
2042aa961391SAlex Deucher 		break;
2043aa961391SAlex Deucher 	}
2044aa961391SAlex Deucher 
2045a0ae5864SAlex Deucher disable_done:
2046f28cf339SDave Airlie 	if (radeon_encoder_is_digital(encoder)) {
20472cd6218cSRafał Miłecki 		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
20482cd6218cSRafał Miłecki 			r600_hdmi_disable(encoder);
2049f28cf339SDave Airlie 		dig = radeon_encoder->enc_priv;
2050f28cf339SDave Airlie 		dig->dig_encoder = -1;
2051f28cf339SDave Airlie 	}
20524ce001abSDave Airlie 	radeon_encoder->active_device = 0;
20534ce001abSDave Airlie }
20544ce001abSDave Airlie 
20553e4b9982SAlex Deucher /* these are handled by the primary encoders */
20563e4b9982SAlex Deucher static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
20573e4b9982SAlex Deucher {
20583e4b9982SAlex Deucher 
20593e4b9982SAlex Deucher }
20603e4b9982SAlex Deucher 
20613e4b9982SAlex Deucher static void radeon_atom_ext_commit(struct drm_encoder *encoder)
20623e4b9982SAlex Deucher {
20633e4b9982SAlex Deucher 
20643e4b9982SAlex Deucher }
20653e4b9982SAlex Deucher 
20663e4b9982SAlex Deucher static void
20673e4b9982SAlex Deucher radeon_atom_ext_mode_set(struct drm_encoder *encoder,
20683e4b9982SAlex Deucher 			 struct drm_display_mode *mode,
20693e4b9982SAlex Deucher 			 struct drm_display_mode *adjusted_mode)
20703e4b9982SAlex Deucher {
20713e4b9982SAlex Deucher 
20723e4b9982SAlex Deucher }
20733e4b9982SAlex Deucher 
20743e4b9982SAlex Deucher static void radeon_atom_ext_disable(struct drm_encoder *encoder)
20753e4b9982SAlex Deucher {
20763e4b9982SAlex Deucher 
20773e4b9982SAlex Deucher }
20783e4b9982SAlex Deucher 
20793e4b9982SAlex Deucher static void
20803e4b9982SAlex Deucher radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
20813e4b9982SAlex Deucher {
20823e4b9982SAlex Deucher 
20833e4b9982SAlex Deucher }
20843e4b9982SAlex Deucher 
20853e4b9982SAlex Deucher static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
20863e4b9982SAlex Deucher 				       struct drm_display_mode *mode,
20873e4b9982SAlex Deucher 				       struct drm_display_mode *adjusted_mode)
20883e4b9982SAlex Deucher {
20893e4b9982SAlex Deucher 	return true;
20903e4b9982SAlex Deucher }
20913e4b9982SAlex Deucher 
20923e4b9982SAlex Deucher static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
20933e4b9982SAlex Deucher 	.dpms = radeon_atom_ext_dpms,
20943e4b9982SAlex Deucher 	.mode_fixup = radeon_atom_ext_mode_fixup,
20953e4b9982SAlex Deucher 	.prepare = radeon_atom_ext_prepare,
20963e4b9982SAlex Deucher 	.mode_set = radeon_atom_ext_mode_set,
20973e4b9982SAlex Deucher 	.commit = radeon_atom_ext_commit,
20983e4b9982SAlex Deucher 	.disable = radeon_atom_ext_disable,
20993e4b9982SAlex Deucher 	/* no detect for TMDS/LVDS yet */
21003e4b9982SAlex Deucher };
21013e4b9982SAlex Deucher 
2102771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
2103771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
2104771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
2105771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
2106771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
2107771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
21084ce001abSDave Airlie 	.disable = radeon_atom_encoder_disable,
2109771fe6b9SJerome Glisse 	/* no detect for TMDS/LVDS yet */
2110771fe6b9SJerome Glisse };
2111771fe6b9SJerome Glisse 
2112771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
2113771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
2114771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
2115771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
2116771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
2117771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
2118771fe6b9SJerome Glisse 	.detect = radeon_atom_dac_detect,
2119771fe6b9SJerome Glisse };
2120771fe6b9SJerome Glisse 
2121771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder)
2122771fe6b9SJerome Glisse {
2123771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2124771fe6b9SJerome Glisse 	kfree(radeon_encoder->enc_priv);
2125771fe6b9SJerome Glisse 	drm_encoder_cleanup(encoder);
2126771fe6b9SJerome Glisse 	kfree(radeon_encoder);
2127771fe6b9SJerome Glisse }
2128771fe6b9SJerome Glisse 
2129771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
2130771fe6b9SJerome Glisse 	.destroy = radeon_enc_destroy,
2131771fe6b9SJerome Glisse };
2132771fe6b9SJerome Glisse 
21334ce001abSDave Airlie struct radeon_encoder_atom_dac *
21344ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
21354ce001abSDave Airlie {
2136affd8589SAlex Deucher 	struct drm_device *dev = radeon_encoder->base.dev;
2137affd8589SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
21384ce001abSDave Airlie 	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
21394ce001abSDave Airlie 
21404ce001abSDave Airlie 	if (!dac)
21414ce001abSDave Airlie 		return NULL;
21424ce001abSDave Airlie 
2143affd8589SAlex Deucher 	dac->tv_std = radeon_atombios_get_tv_info(rdev);
21444ce001abSDave Airlie 	return dac;
21454ce001abSDave Airlie }
21464ce001abSDave Airlie 
2147771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *
2148771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
2149771fe6b9SJerome Glisse {
21505137ee94SAlex Deucher 	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
2151771fe6b9SJerome Glisse 	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
2152771fe6b9SJerome Glisse 
2153771fe6b9SJerome Glisse 	if (!dig)
2154771fe6b9SJerome Glisse 		return NULL;
2155771fe6b9SJerome Glisse 
2156771fe6b9SJerome Glisse 	/* coherent mode by default */
2157771fe6b9SJerome Glisse 	dig->coherent_mode = true;
2158f28cf339SDave Airlie 	dig->dig_encoder = -1;
2159771fe6b9SJerome Glisse 
21605137ee94SAlex Deucher 	if (encoder_enum == 2)
21615137ee94SAlex Deucher 		dig->linkb = true;
21625137ee94SAlex Deucher 	else
21635137ee94SAlex Deucher 		dig->linkb = false;
21645137ee94SAlex Deucher 
2165771fe6b9SJerome Glisse 	return dig;
2166771fe6b9SJerome Glisse }
2167771fe6b9SJerome Glisse 
2168771fe6b9SJerome Glisse void
216936868bdaSAlex Deucher radeon_add_atom_encoder(struct drm_device *dev,
217036868bdaSAlex Deucher 			uint32_t encoder_enum,
217136868bdaSAlex Deucher 			uint32_t supported_device,
217236868bdaSAlex Deucher 			u16 caps)
2173771fe6b9SJerome Glisse {
2174dfee5614SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
2175771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
2176771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder;
2177771fe6b9SJerome Glisse 
2178771fe6b9SJerome Glisse 	/* see if we already added it */
2179771fe6b9SJerome Glisse 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2180771fe6b9SJerome Glisse 		radeon_encoder = to_radeon_encoder(encoder);
21815137ee94SAlex Deucher 		if (radeon_encoder->encoder_enum == encoder_enum) {
2182771fe6b9SJerome Glisse 			radeon_encoder->devices |= supported_device;
2183771fe6b9SJerome Glisse 			return;
2184771fe6b9SJerome Glisse 		}
2185771fe6b9SJerome Glisse 
2186771fe6b9SJerome Glisse 	}
2187771fe6b9SJerome Glisse 
2188771fe6b9SJerome Glisse 	/* add a new one */
2189771fe6b9SJerome Glisse 	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
2190771fe6b9SJerome Glisse 	if (!radeon_encoder)
2191771fe6b9SJerome Glisse 		return;
2192771fe6b9SJerome Glisse 
2193771fe6b9SJerome Glisse 	encoder = &radeon_encoder->base;
2194bcc1c2a1SAlex Deucher 	switch (rdev->num_crtc) {
2195bcc1c2a1SAlex Deucher 	case 1:
2196dfee5614SDave Airlie 		encoder->possible_crtcs = 0x1;
2197bcc1c2a1SAlex Deucher 		break;
2198bcc1c2a1SAlex Deucher 	case 2:
2199bcc1c2a1SAlex Deucher 	default:
2200771fe6b9SJerome Glisse 		encoder->possible_crtcs = 0x3;
2201bcc1c2a1SAlex Deucher 		break;
2202bcc1c2a1SAlex Deucher 	case 6:
2203bcc1c2a1SAlex Deucher 		encoder->possible_crtcs = 0x3f;
2204bcc1c2a1SAlex Deucher 		break;
2205bcc1c2a1SAlex Deucher 	}
2206771fe6b9SJerome Glisse 
2207771fe6b9SJerome Glisse 	radeon_encoder->enc_priv = NULL;
2208771fe6b9SJerome Glisse 
22095137ee94SAlex Deucher 	radeon_encoder->encoder_enum = encoder_enum;
22105137ee94SAlex Deucher 	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
2211771fe6b9SJerome Glisse 	radeon_encoder->devices = supported_device;
2212c93bb85bSJerome Glisse 	radeon_encoder->rmx_type = RMX_OFF;
22135b1714d3SAlex Deucher 	radeon_encoder->underscan_type = UNDERSCAN_OFF;
22143e4b9982SAlex Deucher 	radeon_encoder->is_ext_encoder = false;
221536868bdaSAlex Deucher 	radeon_encoder->caps = caps;
2216771fe6b9SJerome Glisse 
2217771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
2218771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2219771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2220771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2221771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2222771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2223771fe6b9SJerome Glisse 			radeon_encoder->rmx_type = RMX_FULL;
2224771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
2225771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2226771fe6b9SJerome Glisse 		} else {
2227771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
2228771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2229771fe6b9SJerome Glisse 		}
2230771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2231771fe6b9SJerome Glisse 		break;
2232771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2233771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
2234affd8589SAlex Deucher 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2235771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2236771fe6b9SJerome Glisse 		break;
2237771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2238771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2239771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2240771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
22414ce001abSDave Airlie 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2242771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2243771fe6b9SJerome Glisse 		break;
2244771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2245771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2246771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2247771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2248771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2249771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2250771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
225160d15f55SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
225260d15f55SAlex Deucher 			radeon_encoder->rmx_type = RMX_FULL;
225360d15f55SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
225460d15f55SAlex Deucher 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
22553e4b9982SAlex Deucher 		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
22563e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
22573e4b9982SAlex Deucher 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
225860d15f55SAlex Deucher 		} else {
2259771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
2260771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
226160d15f55SAlex Deucher 		}
2262771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2263771fe6b9SJerome Glisse 		break;
22643e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_SI170B:
22653e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_CH7303:
22663e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
22673e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
22683e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_TITFP513:
22693e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_VT1623:
22703e4b9982SAlex Deucher 	case ENCODER_OBJECT_ID_HDMI_SI1930:
2271bf982ebfSAlex Deucher 	case ENCODER_OBJECT_ID_TRAVIS:
2272bf982ebfSAlex Deucher 	case ENCODER_OBJECT_ID_NUTMEG:
22733e4b9982SAlex Deucher 		/* these are handled by the primary encoders */
22743e4b9982SAlex Deucher 		radeon_encoder->is_ext_encoder = true;
22753e4b9982SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
22763e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
22773e4b9982SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
22783e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
22793e4b9982SAlex Deucher 		else
22803e4b9982SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
22813e4b9982SAlex Deucher 		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
22823e4b9982SAlex Deucher 		break;
2283771fe6b9SJerome Glisse 	}
2284771fe6b9SJerome Glisse }
2285