xref: /openbmc/linux/drivers/gpu/drm/radeon/radeon_encoders.c (revision d9fdaafbe912a34ef06ed569c6606fe2811f325b)
1771fe6b9SJerome Glisse /*
2771fe6b9SJerome Glisse  * Copyright 2007-8 Advanced Micro Devices, Inc.
3771fe6b9SJerome Glisse  * Copyright 2008 Red Hat Inc.
4771fe6b9SJerome Glisse  *
5771fe6b9SJerome Glisse  * Permission is hereby granted, free of charge, to any person obtaining a
6771fe6b9SJerome Glisse  * copy of this software and associated documentation files (the "Software"),
7771fe6b9SJerome Glisse  * to deal in the Software without restriction, including without limitation
8771fe6b9SJerome Glisse  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9771fe6b9SJerome Glisse  * and/or sell copies of the Software, and to permit persons to whom the
10771fe6b9SJerome Glisse  * Software is furnished to do so, subject to the following conditions:
11771fe6b9SJerome Glisse  *
12771fe6b9SJerome Glisse  * The above copyright notice and this permission notice shall be included in
13771fe6b9SJerome Glisse  * all copies or substantial portions of the Software.
14771fe6b9SJerome Glisse  *
15771fe6b9SJerome Glisse  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16771fe6b9SJerome Glisse  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17771fe6b9SJerome Glisse  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18771fe6b9SJerome Glisse  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19771fe6b9SJerome Glisse  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20771fe6b9SJerome Glisse  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21771fe6b9SJerome Glisse  * OTHER DEALINGS IN THE SOFTWARE.
22771fe6b9SJerome Glisse  *
23771fe6b9SJerome Glisse  * Authors: Dave Airlie
24771fe6b9SJerome Glisse  *          Alex Deucher
25771fe6b9SJerome Glisse  */
26771fe6b9SJerome Glisse #include "drmP.h"
27771fe6b9SJerome Glisse #include "drm_crtc_helper.h"
28771fe6b9SJerome Glisse #include "radeon_drm.h"
29771fe6b9SJerome Glisse #include "radeon.h"
30771fe6b9SJerome Glisse #include "atom.h"
31771fe6b9SJerome Glisse 
32771fe6b9SJerome Glisse extern int atom_debug;
33771fe6b9SJerome Glisse 
345a9bcaccSAlex Deucher /* evil but including atombios.h is much worse */
355a9bcaccSAlex Deucher bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
365a9bcaccSAlex Deucher 				struct drm_display_mode *mode);
375a9bcaccSAlex Deucher 
381f3b6a45SDave Airlie static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
391f3b6a45SDave Airlie {
401f3b6a45SDave Airlie 	struct drm_device *dev = encoder->dev;
411f3b6a45SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
421f3b6a45SDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
431f3b6a45SDave Airlie 	struct drm_encoder *clone_encoder;
441f3b6a45SDave Airlie 	uint32_t index_mask = 0;
451f3b6a45SDave Airlie 	int count;
461f3b6a45SDave Airlie 
471f3b6a45SDave Airlie 	/* DIG routing gets problematic */
481f3b6a45SDave Airlie 	if (rdev->family >= CHIP_R600)
491f3b6a45SDave Airlie 		return index_mask;
501f3b6a45SDave Airlie 	/* LVDS/TV are too wacky */
511f3b6a45SDave Airlie 	if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
521f3b6a45SDave Airlie 		return index_mask;
531f3b6a45SDave Airlie 	/* DVO requires 2x ppll clocks depending on tmds chip */
541f3b6a45SDave Airlie 	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
551f3b6a45SDave Airlie 		return index_mask;
561f3b6a45SDave Airlie 
571f3b6a45SDave Airlie 	count = -1;
581f3b6a45SDave Airlie 	list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
591f3b6a45SDave Airlie 		struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
601f3b6a45SDave Airlie 		count++;
611f3b6a45SDave Airlie 
621f3b6a45SDave Airlie 		if (clone_encoder == encoder)
631f3b6a45SDave Airlie 			continue;
641f3b6a45SDave Airlie 		if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT))
651f3b6a45SDave Airlie 			continue;
661f3b6a45SDave Airlie 		if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT)
671f3b6a45SDave Airlie 			continue;
681f3b6a45SDave Airlie 		else
691f3b6a45SDave Airlie 			index_mask |= (1 << count);
701f3b6a45SDave Airlie 	}
711f3b6a45SDave Airlie 	return index_mask;
721f3b6a45SDave Airlie }
731f3b6a45SDave Airlie 
741f3b6a45SDave Airlie void radeon_setup_encoder_clones(struct drm_device *dev)
751f3b6a45SDave Airlie {
761f3b6a45SDave Airlie 	struct drm_encoder *encoder;
771f3b6a45SDave Airlie 
781f3b6a45SDave Airlie 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
791f3b6a45SDave Airlie 		encoder->possible_clones = radeon_encoder_clones(encoder);
801f3b6a45SDave Airlie 	}
811f3b6a45SDave Airlie }
821f3b6a45SDave Airlie 
83771fe6b9SJerome Glisse uint32_t
84771fe6b9SJerome Glisse radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
85771fe6b9SJerome Glisse {
86771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
87771fe6b9SJerome Glisse 	uint32_t ret = 0;
88771fe6b9SJerome Glisse 
89771fe6b9SJerome Glisse 	switch (supported_device) {
90771fe6b9SJerome Glisse 	case ATOM_DEVICE_CRT1_SUPPORT:
91771fe6b9SJerome Glisse 	case ATOM_DEVICE_TV1_SUPPORT:
92771fe6b9SJerome Glisse 	case ATOM_DEVICE_TV2_SUPPORT:
93771fe6b9SJerome Glisse 	case ATOM_DEVICE_CRT2_SUPPORT:
94771fe6b9SJerome Glisse 	case ATOM_DEVICE_CV_SUPPORT:
95771fe6b9SJerome Glisse 		switch (dac) {
96771fe6b9SJerome Glisse 		case 1: /* dac a */
97771fe6b9SJerome Glisse 			if ((rdev->family == CHIP_RS300) ||
98771fe6b9SJerome Glisse 			    (rdev->family == CHIP_RS400) ||
99771fe6b9SJerome Glisse 			    (rdev->family == CHIP_RS480))
100771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
101771fe6b9SJerome Glisse 			else if (ASIC_IS_AVIVO(rdev))
102771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
103771fe6b9SJerome Glisse 			else
104771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DAC1;
105771fe6b9SJerome Glisse 			break;
106771fe6b9SJerome Glisse 		case 2: /* dac b */
107771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
108771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
109771fe6b9SJerome Glisse 			else {
110771fe6b9SJerome Glisse 				/*if (rdev->family == CHIP_R200)
111771fe6b9SJerome Glisse 				  ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
112771fe6b9SJerome Glisse 				  else*/
113771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
114771fe6b9SJerome Glisse 			}
115771fe6b9SJerome Glisse 			break;
116771fe6b9SJerome Glisse 		case 3: /* external dac */
117771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
118771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
119771fe6b9SJerome Glisse 			else
120771fe6b9SJerome Glisse 				ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
121771fe6b9SJerome Glisse 			break;
122771fe6b9SJerome Glisse 		}
123771fe6b9SJerome Glisse 		break;
124771fe6b9SJerome Glisse 	case ATOM_DEVICE_LCD1_SUPPORT:
125771fe6b9SJerome Glisse 		if (ASIC_IS_AVIVO(rdev))
126771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
127771fe6b9SJerome Glisse 		else
128771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_LVDS;
129771fe6b9SJerome Glisse 		break;
130771fe6b9SJerome Glisse 	case ATOM_DEVICE_DFP1_SUPPORT:
131771fe6b9SJerome Glisse 		if ((rdev->family == CHIP_RS300) ||
132771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS400) ||
133771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS480))
134771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
135771fe6b9SJerome Glisse 		else if (ASIC_IS_AVIVO(rdev))
136771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
137771fe6b9SJerome Glisse 		else
138771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1;
139771fe6b9SJerome Glisse 		break;
140771fe6b9SJerome Glisse 	case ATOM_DEVICE_LCD2_SUPPORT:
141771fe6b9SJerome Glisse 	case ATOM_DEVICE_DFP2_SUPPORT:
142771fe6b9SJerome Glisse 		if ((rdev->family == CHIP_RS600) ||
143771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS690) ||
144771fe6b9SJerome Glisse 		    (rdev->family == CHIP_RS740))
145771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_DDI;
146771fe6b9SJerome Glisse 		else if (ASIC_IS_AVIVO(rdev))
147771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
148771fe6b9SJerome Glisse 		else
149771fe6b9SJerome Glisse 			ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
150771fe6b9SJerome Glisse 		break;
151771fe6b9SJerome Glisse 	case ATOM_DEVICE_DFP3_SUPPORT:
152771fe6b9SJerome Glisse 		ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
153771fe6b9SJerome Glisse 		break;
154771fe6b9SJerome Glisse 	}
155771fe6b9SJerome Glisse 
156771fe6b9SJerome Glisse 	return ret;
157771fe6b9SJerome Glisse }
158771fe6b9SJerome Glisse 
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 }
179771fe6b9SJerome Glisse void
180771fe6b9SJerome Glisse radeon_link_encoder_connector(struct drm_device *dev)
181771fe6b9SJerome Glisse {
182771fe6b9SJerome Glisse 	struct drm_connector *connector;
183771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
184771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
185771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder;
186771fe6b9SJerome Glisse 
187771fe6b9SJerome Glisse 	/* walk the list and link encoders to connectors */
188771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
189771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
190771fe6b9SJerome Glisse 		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
191771fe6b9SJerome Glisse 			radeon_encoder = to_radeon_encoder(encoder);
192771fe6b9SJerome Glisse 			if (radeon_encoder->devices & radeon_connector->devices)
193771fe6b9SJerome Glisse 				drm_mode_connector_attach_encoder(connector, encoder);
194771fe6b9SJerome Glisse 		}
195771fe6b9SJerome Glisse 	}
196771fe6b9SJerome Glisse }
197771fe6b9SJerome Glisse 
1984ce001abSDave Airlie void radeon_encoder_set_active_device(struct drm_encoder *encoder)
1994ce001abSDave Airlie {
2004ce001abSDave Airlie 	struct drm_device *dev = encoder->dev;
2014ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2024ce001abSDave Airlie 	struct drm_connector *connector;
2034ce001abSDave Airlie 
2044ce001abSDave Airlie 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2054ce001abSDave Airlie 		if (connector->encoder == encoder) {
2064ce001abSDave Airlie 			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2074ce001abSDave Airlie 			radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
208*d9fdaafbSDave Airlie 			DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n",
2094ce001abSDave Airlie 				  radeon_encoder->active_device, radeon_encoder->devices,
2104ce001abSDave Airlie 				  radeon_connector->devices, encoder->encoder_type);
2114ce001abSDave Airlie 		}
2124ce001abSDave Airlie 	}
2134ce001abSDave Airlie }
2144ce001abSDave Airlie 
215771fe6b9SJerome Glisse static struct drm_connector *
216771fe6b9SJerome Glisse radeon_get_connector_for_encoder(struct drm_encoder *encoder)
217771fe6b9SJerome Glisse {
218771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
219771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
220771fe6b9SJerome Glisse 	struct drm_connector *connector;
221771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
222771fe6b9SJerome Glisse 
223771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
224771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
22543c33ed8SDave Airlie 		if (radeon_encoder->active_device & radeon_connector->devices)
226771fe6b9SJerome Glisse 			return connector;
227771fe6b9SJerome Glisse 	}
228771fe6b9SJerome Glisse 	return NULL;
229771fe6b9SJerome Glisse }
230771fe6b9SJerome Glisse 
2319ae47867SAlex Deucher static struct radeon_connector_atom_dig *
2329ae47867SAlex Deucher radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder)
2339ae47867SAlex Deucher {
2349ae47867SAlex Deucher 	struct drm_device *dev = encoder->dev;
2359ae47867SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
2369ae47867SAlex Deucher 	struct drm_connector *connector;
2379ae47867SAlex Deucher 	struct radeon_connector *radeon_connector;
2389ae47867SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector;
2399ae47867SAlex Deucher 
2409ae47867SAlex Deucher 	if (!rdev->is_atom_bios)
2419ae47867SAlex Deucher 		return NULL;
2429ae47867SAlex Deucher 
2439ae47867SAlex Deucher 	connector = radeon_get_connector_for_encoder(encoder);
2449ae47867SAlex Deucher 	if (!connector)
2459ae47867SAlex Deucher 		return NULL;
2469ae47867SAlex Deucher 
2479ae47867SAlex Deucher 	radeon_connector = to_radeon_connector(connector);
2489ae47867SAlex Deucher 
2499ae47867SAlex Deucher 	if (!radeon_connector->con_priv)
2509ae47867SAlex Deucher 		return NULL;
2519ae47867SAlex Deucher 
2529ae47867SAlex Deucher 	dig_connector = radeon_connector->con_priv;
2539ae47867SAlex Deucher 
2549ae47867SAlex Deucher 	return dig_connector;
2559ae47867SAlex Deucher }
2569ae47867SAlex Deucher 
2573515387bSAlex Deucher void radeon_panel_mode_fixup(struct drm_encoder *encoder,
2583515387bSAlex Deucher 			     struct drm_display_mode *adjusted_mode)
2593515387bSAlex Deucher {
2603515387bSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2613515387bSAlex Deucher 	struct drm_device *dev = encoder->dev;
2623515387bSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
2633515387bSAlex Deucher 	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
2643515387bSAlex Deucher 	unsigned hblank = native_mode->htotal - native_mode->hdisplay;
2653515387bSAlex Deucher 	unsigned vblank = native_mode->vtotal - native_mode->vdisplay;
2663515387bSAlex Deucher 	unsigned hover = native_mode->hsync_start - native_mode->hdisplay;
2673515387bSAlex Deucher 	unsigned vover = native_mode->vsync_start - native_mode->vdisplay;
2683515387bSAlex Deucher 	unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start;
2693515387bSAlex Deucher 	unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start;
2703515387bSAlex Deucher 
2713515387bSAlex Deucher 	adjusted_mode->clock = native_mode->clock;
2723515387bSAlex Deucher 	adjusted_mode->flags = native_mode->flags;
2733515387bSAlex Deucher 
2743515387bSAlex Deucher 	if (ASIC_IS_AVIVO(rdev)) {
2753515387bSAlex Deucher 		adjusted_mode->hdisplay = native_mode->hdisplay;
2763515387bSAlex Deucher 		adjusted_mode->vdisplay = native_mode->vdisplay;
2773515387bSAlex Deucher 	}
2783515387bSAlex Deucher 
2793515387bSAlex Deucher 	adjusted_mode->htotal = native_mode->hdisplay + hblank;
2803515387bSAlex Deucher 	adjusted_mode->hsync_start = native_mode->hdisplay + hover;
2813515387bSAlex Deucher 	adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width;
2823515387bSAlex Deucher 
2833515387bSAlex Deucher 	adjusted_mode->vtotal = native_mode->vdisplay + vblank;
2843515387bSAlex Deucher 	adjusted_mode->vsync_start = native_mode->vdisplay + vover;
2853515387bSAlex Deucher 	adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width;
2863515387bSAlex Deucher 
2873515387bSAlex Deucher 	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
2883515387bSAlex Deucher 
2893515387bSAlex Deucher 	if (ASIC_IS_AVIVO(rdev)) {
2903515387bSAlex Deucher 		adjusted_mode->crtc_hdisplay = native_mode->hdisplay;
2913515387bSAlex Deucher 		adjusted_mode->crtc_vdisplay = native_mode->vdisplay;
2923515387bSAlex Deucher 	}
2933515387bSAlex Deucher 
2943515387bSAlex Deucher 	adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank;
2953515387bSAlex Deucher 	adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover;
2963515387bSAlex Deucher 	adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width;
2973515387bSAlex Deucher 
2983515387bSAlex Deucher 	adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank;
2993515387bSAlex Deucher 	adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover;
3003515387bSAlex Deucher 	adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width;
3013515387bSAlex Deucher 
3023515387bSAlex Deucher }
3033515387bSAlex Deucher 
304771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
305771fe6b9SJerome Glisse 				   struct drm_display_mode *mode,
306771fe6b9SJerome Glisse 				   struct drm_display_mode *adjusted_mode)
307771fe6b9SJerome Glisse {
308771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3095a9bcaccSAlex Deucher 	struct drm_device *dev = encoder->dev;
3105a9bcaccSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
311771fe6b9SJerome Glisse 
3128c2a6d73SAlex Deucher 	/* set the active encoder to connector routing */
3138c2a6d73SAlex Deucher 	radeon_encoder_set_active_device(encoder);
314771fe6b9SJerome Glisse 	drm_mode_set_crtcinfo(adjusted_mode, 0);
315771fe6b9SJerome Glisse 
316771fe6b9SJerome Glisse 	/* hw bug */
317771fe6b9SJerome Glisse 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
318771fe6b9SJerome Glisse 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
319771fe6b9SJerome Glisse 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
320771fe6b9SJerome Glisse 
32180297e87SAlex Deucher 	/* get the native mode for LVDS */
3223515387bSAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
3233515387bSAlex Deucher 		radeon_panel_mode_fixup(encoder, adjusted_mode);
32480297e87SAlex Deucher 
32580297e87SAlex Deucher 	/* get the native mode for TV */
326ceefedd8SAlex Deucher 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
3275a9bcaccSAlex Deucher 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
3285a9bcaccSAlex Deucher 		if (tv_dac) {
3295a9bcaccSAlex Deucher 			if (tv_dac->tv_std == TV_STD_NTSC ||
3305a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_NTSC_J ||
3315a9bcaccSAlex Deucher 			    tv_dac->tv_std == TV_STD_PAL_M)
3325a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
3335a9bcaccSAlex Deucher 			else
3345a9bcaccSAlex Deucher 				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
3355a9bcaccSAlex Deucher 		}
3365a9bcaccSAlex Deucher 	}
3375a9bcaccSAlex Deucher 
3385801ead6SAlex Deucher 	if (ASIC_IS_DCE3(rdev) &&
3399f998ad7SAlex Deucher 	    (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) {
3405801ead6SAlex Deucher 		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
3415801ead6SAlex Deucher 		radeon_dp_set_link_config(connector, mode);
3425801ead6SAlex Deucher 	}
3435801ead6SAlex Deucher 
344771fe6b9SJerome Glisse 	return true;
345771fe6b9SJerome Glisse }
346771fe6b9SJerome Glisse 
347771fe6b9SJerome Glisse static void
348771fe6b9SJerome Glisse atombios_dac_setup(struct drm_encoder *encoder, int action)
349771fe6b9SJerome Glisse {
350771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
351771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
352771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
353771fe6b9SJerome Glisse 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
354affd8589SAlex Deucher 	int index = 0;
355445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
356445282dbSDave Airlie 
357771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
358771fe6b9SJerome Glisse 
359771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
360771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
361771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
362771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
363771fe6b9SJerome Glisse 		break;
364771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
365771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
366771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
367771fe6b9SJerome Glisse 		break;
368771fe6b9SJerome Glisse 	}
369771fe6b9SJerome Glisse 
370771fe6b9SJerome Glisse 	args.ucAction = action;
371771fe6b9SJerome Glisse 
3724ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
373771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_PS2;
3744ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
375771fe6b9SJerome Glisse 		args.ucDacStandard = ATOM_DAC1_CV;
376771fe6b9SJerome Glisse 	else {
377affd8589SAlex Deucher 		switch (dac_info->tv_std) {
378771fe6b9SJerome Glisse 		case TV_STD_PAL:
379771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
380771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
381771fe6b9SJerome Glisse 		case TV_STD_SECAM:
382771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
383771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_PAL;
384771fe6b9SJerome Glisse 			break;
385771fe6b9SJerome Glisse 		case TV_STD_NTSC:
386771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
387771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
388771fe6b9SJerome Glisse 		default:
389771fe6b9SJerome Glisse 			args.ucDacStandard = ATOM_DAC1_NTSC;
390771fe6b9SJerome Glisse 			break;
391771fe6b9SJerome Glisse 		}
392771fe6b9SJerome Glisse 	}
393771fe6b9SJerome Glisse 	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
394771fe6b9SJerome Glisse 
395771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
396771fe6b9SJerome Glisse 
397771fe6b9SJerome Glisse }
398771fe6b9SJerome Glisse 
399771fe6b9SJerome Glisse static void
400771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action)
401771fe6b9SJerome Glisse {
402771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
403771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
404771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
405771fe6b9SJerome Glisse 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
406771fe6b9SJerome Glisse 	int index = 0;
407445282dbSDave Airlie 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
408445282dbSDave Airlie 
409771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
410771fe6b9SJerome Glisse 
411771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
412771fe6b9SJerome Glisse 
413771fe6b9SJerome Glisse 	args.sTVEncoder.ucAction = action;
414771fe6b9SJerome Glisse 
4154ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
416771fe6b9SJerome Glisse 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
417771fe6b9SJerome Glisse 	else {
418affd8589SAlex Deucher 		switch (dac_info->tv_std) {
419771fe6b9SJerome Glisse 		case TV_STD_NTSC:
420771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
421771fe6b9SJerome Glisse 			break;
422771fe6b9SJerome Glisse 		case TV_STD_PAL:
423771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
424771fe6b9SJerome Glisse 			break;
425771fe6b9SJerome Glisse 		case TV_STD_PAL_M:
426771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
427771fe6b9SJerome Glisse 			break;
428771fe6b9SJerome Glisse 		case TV_STD_PAL_60:
429771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
430771fe6b9SJerome Glisse 			break;
431771fe6b9SJerome Glisse 		case TV_STD_NTSC_J:
432771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
433771fe6b9SJerome Glisse 			break;
434771fe6b9SJerome Glisse 		case TV_STD_SCART_PAL:
435771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
436771fe6b9SJerome Glisse 			break;
437771fe6b9SJerome Glisse 		case TV_STD_SECAM:
438771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
439771fe6b9SJerome Glisse 			break;
440771fe6b9SJerome Glisse 		case TV_STD_PAL_CN:
441771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
442771fe6b9SJerome Glisse 			break;
443771fe6b9SJerome Glisse 		default:
444771fe6b9SJerome Glisse 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
445771fe6b9SJerome Glisse 			break;
446771fe6b9SJerome Glisse 		}
447771fe6b9SJerome Glisse 	}
448771fe6b9SJerome Glisse 
449771fe6b9SJerome Glisse 	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
450771fe6b9SJerome Glisse 
451771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
452771fe6b9SJerome Glisse 
453771fe6b9SJerome Glisse }
454771fe6b9SJerome Glisse 
455771fe6b9SJerome Glisse void
456771fe6b9SJerome Glisse atombios_external_tmds_setup(struct drm_encoder *encoder, int action)
457771fe6b9SJerome Glisse {
458771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
459771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
460771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
461771fe6b9SJerome Glisse 	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args;
462771fe6b9SJerome Glisse 	int index = 0;
463771fe6b9SJerome Glisse 
464771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
465771fe6b9SJerome Glisse 
466771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
467771fe6b9SJerome Glisse 
468771fe6b9SJerome Glisse 	args.sXTmdsEncoder.ucEnable = action;
469771fe6b9SJerome Glisse 
470771fe6b9SJerome Glisse 	if (radeon_encoder->pixel_clock > 165000)
471771fe6b9SJerome Glisse 		args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
472771fe6b9SJerome Glisse 
473771fe6b9SJerome Glisse 	/*if (pScrn->rgbBits == 8)*/
474771fe6b9SJerome Glisse 	args.sXTmdsEncoder.ucMisc |= (1 << 1);
475771fe6b9SJerome Glisse 
476771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
477771fe6b9SJerome Glisse 
478771fe6b9SJerome Glisse }
479771fe6b9SJerome Glisse 
480771fe6b9SJerome Glisse static void
481771fe6b9SJerome Glisse atombios_ddia_setup(struct drm_encoder *encoder, int action)
482771fe6b9SJerome Glisse {
483771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
484771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
485771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
486771fe6b9SJerome Glisse 	DVO_ENCODER_CONTROL_PS_ALLOCATION args;
487771fe6b9SJerome Glisse 	int index = 0;
488771fe6b9SJerome Glisse 
489771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
490771fe6b9SJerome Glisse 
491771fe6b9SJerome Glisse 	index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
492771fe6b9SJerome Glisse 
493771fe6b9SJerome Glisse 	args.sDVOEncoder.ucAction = action;
494771fe6b9SJerome Glisse 	args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
495771fe6b9SJerome Glisse 
496771fe6b9SJerome Glisse 	if (radeon_encoder->pixel_clock > 165000)
497771fe6b9SJerome Glisse 		args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
498771fe6b9SJerome Glisse 
499771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
500771fe6b9SJerome Glisse 
501771fe6b9SJerome Glisse }
502771fe6b9SJerome Glisse 
503771fe6b9SJerome Glisse union lvds_encoder_control {
504771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
505771fe6b9SJerome Glisse 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
506771fe6b9SJerome Glisse };
507771fe6b9SJerome Glisse 
50832f48ffeSAlex Deucher void
509771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action)
510771fe6b9SJerome Glisse {
511771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
512771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
513771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
5149ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
5159ae47867SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector =
5169ae47867SAlex Deucher 		radeon_get_atom_connector_priv_from_encoder(encoder);
517771fe6b9SJerome Glisse 	union lvds_encoder_control args;
518771fe6b9SJerome Glisse 	int index = 0;
519dafc3bd5SChristian Koenig 	int hdmi_detected = 0;
520771fe6b9SJerome Glisse 	uint8_t frev, crev;
521771fe6b9SJerome Glisse 
5229ae47867SAlex Deucher 	if (!dig || !dig_connector)
523771fe6b9SJerome Glisse 		return;
524771fe6b9SJerome Glisse 
5259ae47867SAlex Deucher 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
526dafc3bd5SChristian Koenig 		hdmi_detected = 1;
527dafc3bd5SChristian Koenig 
528771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
529771fe6b9SJerome Glisse 
530771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
531771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
532771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
533771fe6b9SJerome Glisse 		break;
534771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
535771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
536771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
537771fe6b9SJerome Glisse 		break;
538771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
539771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
540771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
541771fe6b9SJerome Glisse 		else
542771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
543771fe6b9SJerome Glisse 		break;
544771fe6b9SJerome Glisse 	}
545771fe6b9SJerome Glisse 
546a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
547a084e6eeSAlex Deucher 		return;
548771fe6b9SJerome Glisse 
549771fe6b9SJerome Glisse 	switch (frev) {
550771fe6b9SJerome Glisse 	case 1:
551771fe6b9SJerome Glisse 	case 2:
552771fe6b9SJerome Glisse 		switch (crev) {
553771fe6b9SJerome Glisse 		case 1:
554771fe6b9SJerome Glisse 			args.v1.ucMisc = 0;
555771fe6b9SJerome Glisse 			args.v1.ucAction = action;
556dafc3bd5SChristian Koenig 			if (hdmi_detected)
557771fe6b9SJerome Glisse 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
558771fe6b9SJerome Glisse 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
559771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
560edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
561771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
562edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
563771fe6b9SJerome Glisse 					args.v1.ucMisc |= (1 << 1);
564771fe6b9SJerome Glisse 			} else {
565771fe6b9SJerome Glisse 				if (dig_connector->linkb)
566771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
567771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
568771fe6b9SJerome Glisse 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
569771fe6b9SJerome Glisse 				/*if (pScrn->rgbBits == 8) */
570771fe6b9SJerome Glisse 				args.v1.ucMisc |= (1 << 1);
571771fe6b9SJerome Glisse 			}
572771fe6b9SJerome Glisse 			break;
573771fe6b9SJerome Glisse 		case 2:
574771fe6b9SJerome Glisse 		case 3:
575771fe6b9SJerome Glisse 			args.v2.ucMisc = 0;
576771fe6b9SJerome Glisse 			args.v2.ucAction = action;
577771fe6b9SJerome Glisse 			if (crev == 3) {
578771fe6b9SJerome Glisse 				if (dig->coherent_mode)
579771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
580771fe6b9SJerome Glisse 			}
581dafc3bd5SChristian Koenig 			if (hdmi_detected)
582771fe6b9SJerome Glisse 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
583771fe6b9SJerome Glisse 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
584771fe6b9SJerome Glisse 			args.v2.ucTruncate = 0;
585771fe6b9SJerome Glisse 			args.v2.ucSpatial = 0;
586771fe6b9SJerome Glisse 			args.v2.ucTemporal = 0;
587771fe6b9SJerome Glisse 			args.v2.ucFRC = 0;
588771fe6b9SJerome Glisse 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
589edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
590771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
591edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) {
592771fe6b9SJerome Glisse 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
593edc664e3SAlex Deucher 					if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
594771fe6b9SJerome Glisse 						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
595771fe6b9SJerome Glisse 				}
596edc664e3SAlex Deucher 				if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) {
597771fe6b9SJerome Glisse 					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
598edc664e3SAlex Deucher 					if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
599771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
600edc664e3SAlex Deucher 					if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
601771fe6b9SJerome Glisse 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
602771fe6b9SJerome Glisse 				}
603771fe6b9SJerome Glisse 			} else {
604771fe6b9SJerome Glisse 				if (dig_connector->linkb)
605771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
606771fe6b9SJerome Glisse 				if (radeon_encoder->pixel_clock > 165000)
607771fe6b9SJerome Glisse 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
608771fe6b9SJerome Glisse 			}
609771fe6b9SJerome Glisse 			break;
610771fe6b9SJerome Glisse 		default:
611771fe6b9SJerome Glisse 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
612771fe6b9SJerome Glisse 			break;
613771fe6b9SJerome Glisse 		}
614771fe6b9SJerome Glisse 		break;
615771fe6b9SJerome Glisse 	default:
616771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
617771fe6b9SJerome Glisse 		break;
618771fe6b9SJerome Glisse 	}
619771fe6b9SJerome Glisse 
620771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
621771fe6b9SJerome Glisse }
622771fe6b9SJerome Glisse 
623771fe6b9SJerome Glisse int
624771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder)
625771fe6b9SJerome Glisse {
626771fe6b9SJerome Glisse 	struct drm_connector *connector;
627771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
6289ae47867SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector;
629771fe6b9SJerome Glisse 
630771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
631771fe6b9SJerome Glisse 	if (!connector)
632771fe6b9SJerome Glisse 		return 0;
633771fe6b9SJerome Glisse 
634771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
635771fe6b9SJerome Glisse 
636771fe6b9SJerome Glisse 	switch (connector->connector_type) {
637771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVII:
638705af9c7SAlex Deucher 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
6390294cf4fSAlex Deucher 		if (drm_detect_hdmi_monitor(radeon_connector->edid))
640771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_HDMI;
641771fe6b9SJerome Glisse 		else if (radeon_connector->use_digital)
642771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
643771fe6b9SJerome Glisse 		else
644771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_CRT;
645771fe6b9SJerome Glisse 		break;
646771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVID:
647771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_HDMIA:
648771fe6b9SJerome Glisse 	default:
6490294cf4fSAlex Deucher 		if (drm_detect_hdmi_monitor(radeon_connector->edid))
650771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_HDMI;
651771fe6b9SJerome Glisse 		else
652771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
653771fe6b9SJerome Glisse 		break;
654771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_LVDS:
655771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_LVDS;
656771fe6b9SJerome Glisse 		break;
657771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DisplayPort:
658196c58d2SAlex Deucher 	case DRM_MODE_CONNECTOR_eDP:
6599ae47867SAlex Deucher 		dig_connector = radeon_connector->con_priv;
6609ae47867SAlex Deucher 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
6619ae47867SAlex Deucher 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
662771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DP;
663f92a8b67SAlex Deucher 		else if (drm_detect_hdmi_monitor(radeon_connector->edid))
664771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_HDMI;
665771fe6b9SJerome Glisse 		else
666771fe6b9SJerome Glisse 			return ATOM_ENCODER_MODE_DVI;
667771fe6b9SJerome Glisse 		break;
668a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_DVIA:
669a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_VGA:
670771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_CRT;
671771fe6b9SJerome Glisse 		break;
672a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_Composite:
673a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_SVIDEO:
674a5899fccSAlex Deucher 	case DRM_MODE_CONNECTOR_9PinDIN:
675771fe6b9SJerome Glisse 		/* fix me */
676771fe6b9SJerome Glisse 		return ATOM_ENCODER_MODE_TV;
677771fe6b9SJerome Glisse 		/*return ATOM_ENCODER_MODE_CV;*/
678771fe6b9SJerome Glisse 		break;
679771fe6b9SJerome Glisse 	}
680771fe6b9SJerome Glisse }
681771fe6b9SJerome Glisse 
6821a66c95aSAlex Deucher /*
6831a66c95aSAlex Deucher  * DIG Encoder/Transmitter Setup
6841a66c95aSAlex Deucher  *
6851a66c95aSAlex Deucher  * DCE 3.0/3.1
6861a66c95aSAlex Deucher  * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
6871a66c95aSAlex Deucher  * Supports up to 3 digital outputs
6881a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
6891a66c95aSAlex Deucher  * DIG1 can drive UNIPHY link A or link B
6901a66c95aSAlex Deucher  * DIG2 can drive UNIPHY link B or LVTMA
6911a66c95aSAlex Deucher  *
6921a66c95aSAlex Deucher  * DCE 3.2
6931a66c95aSAlex Deucher  * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
6941a66c95aSAlex Deucher  * Supports up to 5 digital outputs
6951a66c95aSAlex Deucher  * - 2 DIG encoder blocks.
6961a66c95aSAlex Deucher  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
6971a66c95aSAlex Deucher  *
698bcc1c2a1SAlex Deucher  * DCE 4.0
699bcc1c2a1SAlex Deucher  * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B).
700bcc1c2a1SAlex Deucher  * Supports up to 6 digital outputs
701bcc1c2a1SAlex Deucher  * - 6 DIG encoder blocks.
702bcc1c2a1SAlex Deucher  * - DIG to PHY mapping is hardcoded
703bcc1c2a1SAlex Deucher  * DIG1 drives UNIPHY0 link A, A+B
704bcc1c2a1SAlex Deucher  * DIG2 drives UNIPHY0 link B
705bcc1c2a1SAlex Deucher  * DIG3 drives UNIPHY1 link A, A+B
706bcc1c2a1SAlex Deucher  * DIG4 drives UNIPHY1 link B
707bcc1c2a1SAlex Deucher  * DIG5 drives UNIPHY2 link A, A+B
708bcc1c2a1SAlex Deucher  * DIG6 drives UNIPHY2 link B
709bcc1c2a1SAlex Deucher  *
7101a66c95aSAlex Deucher  * Routing
7111a66c95aSAlex Deucher  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
7121a66c95aSAlex Deucher  * Examples:
7131a66c95aSAlex Deucher  * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
7141a66c95aSAlex Deucher  * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
7151a66c95aSAlex Deucher  * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
7161a66c95aSAlex Deucher  * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
7171a66c95aSAlex Deucher  */
718bcc1c2a1SAlex Deucher 
719bcc1c2a1SAlex Deucher union dig_encoder_control {
720bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
721bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
722bcc1c2a1SAlex Deucher 	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
723bcc1c2a1SAlex Deucher };
724bcc1c2a1SAlex Deucher 
725bcc1c2a1SAlex Deucher void
726771fe6b9SJerome Glisse atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
727771fe6b9SJerome Glisse {
728771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
729771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
730771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
7319ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
7329ae47867SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector =
7339ae47867SAlex Deucher 		radeon_get_atom_connector_priv_from_encoder(encoder);
734bcc1c2a1SAlex Deucher 	union dig_encoder_control args;
735d9c9fe36SAlex Deucher 	int index = 0;
736771fe6b9SJerome Glisse 	uint8_t frev, crev;
737771fe6b9SJerome Glisse 
7389ae47867SAlex Deucher 	if (!dig || !dig_connector)
739771fe6b9SJerome Glisse 		return;
740771fe6b9SJerome Glisse 
741771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
742771fe6b9SJerome Glisse 
743bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev))
744bcc1c2a1SAlex Deucher 		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
745bcc1c2a1SAlex Deucher 	else {
746f28cf339SDave Airlie 		if (dig->dig_encoder)
747771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
748771fe6b9SJerome Glisse 		else
749771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
750bcc1c2a1SAlex Deucher 	}
751771fe6b9SJerome Glisse 
752a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
753a084e6eeSAlex Deucher 		return;
754771fe6b9SJerome Glisse 
755bcc1c2a1SAlex Deucher 	args.v1.ucAction = action;
756bcc1c2a1SAlex Deucher 	args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
757bcc1c2a1SAlex Deucher 	args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
758771fe6b9SJerome Glisse 
759bcc1c2a1SAlex Deucher 	if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
760bcc1c2a1SAlex Deucher 		if (dig_connector->dp_clock == 270000)
761bcc1c2a1SAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
762bcc1c2a1SAlex Deucher 		args.v1.ucLaneNum = dig_connector->dp_lane_count;
763bcc1c2a1SAlex Deucher 	} else if (radeon_encoder->pixel_clock > 165000)
764bcc1c2a1SAlex Deucher 		args.v1.ucLaneNum = 8;
765bcc1c2a1SAlex Deucher 	else
766bcc1c2a1SAlex Deucher 		args.v1.ucLaneNum = 4;
767bcc1c2a1SAlex Deucher 
768bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev)) {
769bcc1c2a1SAlex Deucher 		args.v3.acConfig.ucDigSel = dig->dig_encoder;
770bcc1c2a1SAlex Deucher 		args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
771771fe6b9SJerome Glisse 	} else {
772771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
773771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
774bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
775771fe6b9SJerome Glisse 			break;
776bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
777771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
778bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
779bcc1c2a1SAlex Deucher 			break;
780bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
781bcc1c2a1SAlex Deucher 			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
782771fe6b9SJerome Glisse 			break;
783771fe6b9SJerome Glisse 		}
784771fe6b9SJerome Glisse 		if (dig_connector->linkb)
785bcc1c2a1SAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
786771fe6b9SJerome Glisse 		else
787bcc1c2a1SAlex Deucher 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
788bcc1c2a1SAlex Deucher 	}
789771fe6b9SJerome Glisse 
790771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
791771fe6b9SJerome Glisse 
792771fe6b9SJerome Glisse }
793771fe6b9SJerome Glisse 
794771fe6b9SJerome Glisse union dig_transmitter_control {
795771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
796771fe6b9SJerome Glisse 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
797bcc1c2a1SAlex Deucher 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
798771fe6b9SJerome Glisse };
799771fe6b9SJerome Glisse 
8005801ead6SAlex Deucher void
8011a66c95aSAlex Deucher atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
802771fe6b9SJerome Glisse {
803771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
804771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
805771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
8069ae47867SAlex Deucher 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
8079ae47867SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector =
8089ae47867SAlex Deucher 		radeon_get_atom_connector_priv_from_encoder(encoder);
8099ae47867SAlex Deucher 	struct drm_connector *connector;
8109ae47867SAlex Deucher 	struct radeon_connector *radeon_connector;
811771fe6b9SJerome Glisse 	union dig_transmitter_control args;
812d9c9fe36SAlex Deucher 	int index = 0;
813771fe6b9SJerome Glisse 	uint8_t frev, crev;
814f92a8b67SAlex Deucher 	bool is_dp = false;
815bcc1c2a1SAlex Deucher 	int pll_id = 0;
816771fe6b9SJerome Glisse 
8179ae47867SAlex Deucher 	if (!dig || !dig_connector)
8189ae47867SAlex Deucher 		return;
8199ae47867SAlex Deucher 
820771fe6b9SJerome Glisse 	connector = radeon_get_connector_for_encoder(encoder);
821771fe6b9SJerome Glisse 	radeon_connector = to_radeon_connector(connector);
822771fe6b9SJerome Glisse 
823f92a8b67SAlex Deucher 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
824f92a8b67SAlex Deucher 		is_dp = true;
825f92a8b67SAlex Deucher 
826771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
827771fe6b9SJerome Glisse 
828bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE32(rdev) || ASIC_IS_DCE4(rdev))
829771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
830771fe6b9SJerome Glisse 	else {
831771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
832771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
833771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
834771fe6b9SJerome Glisse 			break;
835771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
836771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
837771fe6b9SJerome Glisse 			break;
838771fe6b9SJerome Glisse 		}
839771fe6b9SJerome Glisse 	}
840771fe6b9SJerome Glisse 
841a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
842a084e6eeSAlex Deucher 		return;
843771fe6b9SJerome Glisse 
844771fe6b9SJerome Glisse 	args.v1.ucAction = action;
845f95a9f0bSAlex Deucher 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
846f95a9f0bSAlex Deucher 		args.v1.usInitInfo = radeon_connector->connector_object_id;
8471a66c95aSAlex Deucher 	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
8481a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSel = lane_num;
8491a66c95aSAlex Deucher 		args.v1.asMode.ucLaneSet = lane_set;
850771fe6b9SJerome Glisse 	} else {
851f92a8b67SAlex Deucher 		if (is_dp)
852f92a8b67SAlex Deucher 			args.v1.usPixelClock =
8535801ead6SAlex Deucher 				cpu_to_le16(dig_connector->dp_clock / 10);
854f92a8b67SAlex Deucher 		else if (radeon_encoder->pixel_clock > 165000)
855f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
856f95a9f0bSAlex Deucher 		else
857f95a9f0bSAlex Deucher 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
858771fe6b9SJerome Glisse 	}
859bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev)) {
860bcc1c2a1SAlex Deucher 		if (is_dp)
861bcc1c2a1SAlex Deucher 			args.v3.ucLaneNum = dig_connector->dp_lane_count;
862bcc1c2a1SAlex Deucher 		else if (radeon_encoder->pixel_clock > 165000)
863bcc1c2a1SAlex Deucher 			args.v3.ucLaneNum = 8;
864bcc1c2a1SAlex Deucher 		else
865bcc1c2a1SAlex Deucher 			args.v3.ucLaneNum = 4;
866bcc1c2a1SAlex Deucher 
867bcc1c2a1SAlex Deucher 		if (dig_connector->linkb) {
868bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucLinkSel = 1;
869bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucEncoderSel = 1;
870bcc1c2a1SAlex Deucher 		}
871bcc1c2a1SAlex Deucher 
872bcc1c2a1SAlex Deucher 		/* Select the PLL for the PHY
873bcc1c2a1SAlex Deucher 		 * DP PHY should be clocked from external src if there is
874bcc1c2a1SAlex Deucher 		 * one.
875bcc1c2a1SAlex Deucher 		 */
876bcc1c2a1SAlex Deucher 		if (encoder->crtc) {
877bcc1c2a1SAlex Deucher 			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
878bcc1c2a1SAlex Deucher 			pll_id = radeon_crtc->pll_id;
879bcc1c2a1SAlex Deucher 		}
880bcc1c2a1SAlex Deucher 		if (is_dp && rdev->clock.dp_extclk)
881bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucRefClkSource = 2; /* external src */
882bcc1c2a1SAlex Deucher 		else
883bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucRefClkSource = pll_id;
884bcc1c2a1SAlex Deucher 
885bcc1c2a1SAlex Deucher 		switch (radeon_encoder->encoder_id) {
886bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
887bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 0;
888bcc1c2a1SAlex Deucher 			break;
889bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
890bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 1;
891bcc1c2a1SAlex Deucher 			break;
892bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
893bcc1c2a1SAlex Deucher 			args.v3.acConfig.ucTransmitterSel = 2;
894bcc1c2a1SAlex Deucher 			break;
895bcc1c2a1SAlex Deucher 		}
896bcc1c2a1SAlex Deucher 
897bcc1c2a1SAlex Deucher 		if (is_dp)
898bcc1c2a1SAlex Deucher 			args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
899bcc1c2a1SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
900bcc1c2a1SAlex Deucher 			if (dig->coherent_mode)
901bcc1c2a1SAlex Deucher 				args.v3.acConfig.fCoherentMode = 1;
902b317a9ceSAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
903b317a9ceSAlex Deucher 				args.v3.acConfig.fDualLinkConnector = 1;
904bcc1c2a1SAlex Deucher 		}
905bcc1c2a1SAlex Deucher 	} else if (ASIC_IS_DCE32(rdev)) {
906d9c9fe36SAlex Deucher 		args.v2.acConfig.ucEncoderSel = dig->dig_encoder;
9071a66c95aSAlex Deucher 		if (dig_connector->linkb)
9081a66c95aSAlex Deucher 			args.v2.acConfig.ucLinkSel = 1;
909771fe6b9SJerome Glisse 
910771fe6b9SJerome Glisse 		switch (radeon_encoder->encoder_id) {
911771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
912771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 0;
913771fe6b9SJerome Glisse 			break;
914771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
915771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 1;
916771fe6b9SJerome Glisse 			break;
917771fe6b9SJerome Glisse 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
918771fe6b9SJerome Glisse 			args.v2.acConfig.ucTransmitterSel = 2;
919771fe6b9SJerome Glisse 			break;
920771fe6b9SJerome Glisse 		}
921771fe6b9SJerome Glisse 
922f92a8b67SAlex Deucher 		if (is_dp)
923f92a8b67SAlex Deucher 			args.v2.acConfig.fCoherentMode = 1;
924f92a8b67SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
925771fe6b9SJerome Glisse 			if (dig->coherent_mode)
926771fe6b9SJerome Glisse 				args.v2.acConfig.fCoherentMode = 1;
927b317a9ceSAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
928b317a9ceSAlex Deucher 				args.v2.acConfig.fDualLinkConnector = 1;
929771fe6b9SJerome Glisse 		}
930771fe6b9SJerome Glisse 	} else {
931771fe6b9SJerome Glisse 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
932771fe6b9SJerome Glisse 
933f28cf339SDave Airlie 		if (dig->dig_encoder)
9341a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
9351a66c95aSAlex Deucher 		else
936771fe6b9SJerome Glisse 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
937f28cf339SDave Airlie 
938d9c9fe36SAlex Deucher 		if ((rdev->flags & RADEON_IS_IGP) &&
939d9c9fe36SAlex Deucher 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
940d9c9fe36SAlex Deucher 			if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
941771fe6b9SJerome Glisse 				if (dig_connector->igp_lane_info & 0x1)
942771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
943771fe6b9SJerome Glisse 				else if (dig_connector->igp_lane_info & 0x2)
944771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
945771fe6b9SJerome Glisse 				else if (dig_connector->igp_lane_info & 0x4)
946771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
947771fe6b9SJerome Glisse 				else if (dig_connector->igp_lane_info & 0x8)
948771fe6b9SJerome Glisse 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
949d9c9fe36SAlex Deucher 			} else {
950d9c9fe36SAlex Deucher 				if (dig_connector->igp_lane_info & 0x3)
951d9c9fe36SAlex Deucher 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
952d9c9fe36SAlex Deucher 				else if (dig_connector->igp_lane_info & 0xc)
953d9c9fe36SAlex Deucher 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
954771fe6b9SJerome Glisse 			}
955771fe6b9SJerome Glisse 		}
9561a66c95aSAlex Deucher 
9571a66c95aSAlex Deucher 		if (dig_connector->linkb)
9581a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
9591a66c95aSAlex Deucher 		else
9601a66c95aSAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
9611a66c95aSAlex Deucher 
962f92a8b67SAlex Deucher 		if (is_dp)
963f92a8b67SAlex Deucher 			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
964f92a8b67SAlex Deucher 		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
965771fe6b9SJerome Glisse 			if (dig->coherent_mode)
966771fe6b9SJerome Glisse 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
967d9c9fe36SAlex Deucher 			if (radeon_encoder->pixel_clock > 165000)
968d9c9fe36SAlex Deucher 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
969771fe6b9SJerome Glisse 		}
970771fe6b9SJerome Glisse 	}
971771fe6b9SJerome Glisse 
972771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
973771fe6b9SJerome Glisse }
974771fe6b9SJerome Glisse 
975771fe6b9SJerome Glisse static void
976771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
977771fe6b9SJerome Glisse {
978771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
979771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
980771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
981771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
982771fe6b9SJerome Glisse 	ENABLE_YUV_PS_ALLOCATION args;
983771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
984771fe6b9SJerome Glisse 	uint32_t temp, reg;
985771fe6b9SJerome Glisse 
986771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
987771fe6b9SJerome Glisse 
988771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
989771fe6b9SJerome Glisse 		reg = R600_BIOS_3_SCRATCH;
990771fe6b9SJerome Glisse 	else
991771fe6b9SJerome Glisse 		reg = RADEON_BIOS_3_SCRATCH;
992771fe6b9SJerome Glisse 
993771fe6b9SJerome Glisse 	/* XXX: fix up scratch reg handling */
994771fe6b9SJerome Glisse 	temp = RREG32(reg);
9954ce001abSDave Airlie 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
996771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
997771fe6b9SJerome Glisse 			     (radeon_crtc->crtc_id << 18)));
9984ce001abSDave Airlie 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
999771fe6b9SJerome Glisse 		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
1000771fe6b9SJerome Glisse 	else
1001771fe6b9SJerome Glisse 		WREG32(reg, 0);
1002771fe6b9SJerome Glisse 
1003771fe6b9SJerome Glisse 	if (enable)
1004771fe6b9SJerome Glisse 		args.ucEnable = ATOM_ENABLE;
1005771fe6b9SJerome Glisse 	args.ucCRTC = radeon_crtc->crtc_id;
1006771fe6b9SJerome Glisse 
1007771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1008771fe6b9SJerome Glisse 
1009771fe6b9SJerome Glisse 	WREG32(reg, temp);
1010771fe6b9SJerome Glisse }
1011771fe6b9SJerome Glisse 
1012771fe6b9SJerome Glisse static void
1013771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1014771fe6b9SJerome Glisse {
1015771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1016771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1017771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1018771fe6b9SJerome Glisse 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1019771fe6b9SJerome Glisse 	int index = 0;
1020771fe6b9SJerome Glisse 	bool is_dig = false;
1021771fe6b9SJerome Glisse 
1022771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1023771fe6b9SJerome Glisse 
1024*d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
10254ce001abSDave Airlie 		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
10264ce001abSDave Airlie 		  radeon_encoder->active_device);
1027771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1028771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1029771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1030771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1031771fe6b9SJerome Glisse 		break;
1032771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1033771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1034771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1035771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1036771fe6b9SJerome Glisse 		is_dig = true;
1037771fe6b9SJerome Glisse 		break;
1038771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1039771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1040771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1041771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1042771fe6b9SJerome Glisse 		break;
1043771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1044771fe6b9SJerome Glisse 		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1045771fe6b9SJerome Glisse 		break;
1046771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1047771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1048771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1049771fe6b9SJerome Glisse 		else
1050771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1051771fe6b9SJerome Glisse 		break;
1052771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1053771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
10548c2a6d73SAlex Deucher 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1055771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
10568c2a6d73SAlex Deucher 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1057771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1058771fe6b9SJerome Glisse 		else
1059771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1060771fe6b9SJerome Glisse 		break;
1061771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1062771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
10638c2a6d73SAlex Deucher 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1064771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
10658c2a6d73SAlex Deucher 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1066771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1067771fe6b9SJerome Glisse 		else
1068771fe6b9SJerome Glisse 			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1069771fe6b9SJerome Glisse 		break;
1070771fe6b9SJerome Glisse 	}
1071771fe6b9SJerome Glisse 
1072771fe6b9SJerome Glisse 	if (is_dig) {
1073771fe6b9SJerome Glisse 		switch (mode) {
1074771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
1075a5f798ceSAlex Deucher 			if (!ASIC_IS_DCE4(rdev))
1076a5f798ceSAlex Deucher 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
1077fb668c2fSAlex Deucher 			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
107858682f10SDave Airlie 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1079fb668c2fSAlex Deucher 
108058682f10SDave Airlie 				dp_link_train(encoder, connector);
1081fb668c2fSAlex Deucher 				if (ASIC_IS_DCE4(rdev))
1082fb668c2fSAlex Deucher 					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
108358682f10SDave Airlie 			}
1084771fe6b9SJerome Glisse 			break;
1085771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1086771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1087771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
1088fb668c2fSAlex Deucher 			if (!ASIC_IS_DCE4(rdev))
108958682f10SDave Airlie 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
1090fb668c2fSAlex Deucher 			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
1091fb668c2fSAlex Deucher 				if (ASIC_IS_DCE4(rdev))
1092fb668c2fSAlex Deucher 					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
1093fb668c2fSAlex Deucher 			}
1094771fe6b9SJerome Glisse 			break;
1095771fe6b9SJerome Glisse 		}
1096771fe6b9SJerome Glisse 	} else {
1097771fe6b9SJerome Glisse 		switch (mode) {
1098771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_ON:
1099771fe6b9SJerome Glisse 			args.ucAction = ATOM_ENABLE;
1100771fe6b9SJerome Glisse 			break;
1101771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_STANDBY:
1102771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_SUSPEND:
1103771fe6b9SJerome Glisse 		case DRM_MODE_DPMS_OFF:
1104771fe6b9SJerome Glisse 			args.ucAction = ATOM_DISABLE;
1105771fe6b9SJerome Glisse 			break;
1106771fe6b9SJerome Glisse 		}
1107771fe6b9SJerome Glisse 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1108771fe6b9SJerome Glisse 	}
1109771fe6b9SJerome Glisse 	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1110c913e23aSRafał Miłecki 
1111771fe6b9SJerome Glisse }
1112771fe6b9SJerome Glisse 
11139ae47867SAlex Deucher union crtc_source_param {
1114771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
1115771fe6b9SJerome Glisse 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
1116771fe6b9SJerome Glisse };
1117771fe6b9SJerome Glisse 
1118771fe6b9SJerome Glisse static void
1119771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
1120771fe6b9SJerome Glisse {
1121771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1122771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1123771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1124771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
11259ae47867SAlex Deucher 	union crtc_source_param args;
1126771fe6b9SJerome Glisse 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1127771fe6b9SJerome Glisse 	uint8_t frev, crev;
1128f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
1129771fe6b9SJerome Glisse 
1130771fe6b9SJerome Glisse 	memset(&args, 0, sizeof(args));
1131771fe6b9SJerome Glisse 
1132a084e6eeSAlex Deucher 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1133a084e6eeSAlex Deucher 		return;
1134771fe6b9SJerome Glisse 
1135771fe6b9SJerome Glisse 	switch (frev) {
1136771fe6b9SJerome Glisse 	case 1:
1137771fe6b9SJerome Glisse 		switch (crev) {
1138771fe6b9SJerome Glisse 		case 1:
1139771fe6b9SJerome Glisse 		default:
1140771fe6b9SJerome Glisse 			if (ASIC_IS_AVIVO(rdev))
1141771fe6b9SJerome Glisse 				args.v1.ucCRTC = radeon_crtc->crtc_id;
1142771fe6b9SJerome Glisse 			else {
1143771fe6b9SJerome Glisse 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
1144771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id;
1145771fe6b9SJerome Glisse 				} else {
1146771fe6b9SJerome Glisse 					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
1147771fe6b9SJerome Glisse 				}
1148771fe6b9SJerome Glisse 			}
1149771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1150771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1151771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1152771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1153771fe6b9SJerome Glisse 				break;
1154771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1155771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1156771fe6b9SJerome Glisse 				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
1157771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1158771fe6b9SJerome Glisse 				else
1159771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1160771fe6b9SJerome Glisse 				break;
1161771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1162771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DDI:
1163771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1164771fe6b9SJerome Glisse 				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1165771fe6b9SJerome Glisse 				break;
1166771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1167771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
11684ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1169771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
11704ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1171771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1172771fe6b9SJerome Glisse 				else
1173771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1174771fe6b9SJerome Glisse 				break;
1175771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1176771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
11774ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1178771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
11794ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1180771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1181771fe6b9SJerome Glisse 				else
1182771fe6b9SJerome Glisse 					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1183771fe6b9SJerome Glisse 				break;
1184771fe6b9SJerome Glisse 			}
1185771fe6b9SJerome Glisse 			break;
1186771fe6b9SJerome Glisse 		case 2:
1187771fe6b9SJerome Glisse 			args.v2.ucCRTC = radeon_crtc->crtc_id;
1188771fe6b9SJerome Glisse 			args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1189771fe6b9SJerome Glisse 			switch (radeon_encoder->encoder_id) {
1190771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1191771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1192771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1193f28cf339SDave Airlie 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1194f28cf339SDave Airlie 				dig = radeon_encoder->enc_priv;
1195bcc1c2a1SAlex Deucher 				switch (dig->dig_encoder) {
1196bcc1c2a1SAlex Deucher 				case 0:
1197771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1198771fe6b9SJerome Glisse 					break;
1199bcc1c2a1SAlex Deucher 				case 1:
1200bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1201bcc1c2a1SAlex Deucher 					break;
1202bcc1c2a1SAlex Deucher 				case 2:
1203bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
1204bcc1c2a1SAlex Deucher 					break;
1205bcc1c2a1SAlex Deucher 				case 3:
1206bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
1207bcc1c2a1SAlex Deucher 					break;
1208bcc1c2a1SAlex Deucher 				case 4:
1209bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
1210bcc1c2a1SAlex Deucher 					break;
1211bcc1c2a1SAlex Deucher 				case 5:
1212bcc1c2a1SAlex Deucher 					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
1213bcc1c2a1SAlex Deucher 					break;
1214bcc1c2a1SAlex Deucher 				}
1215bcc1c2a1SAlex Deucher 				break;
1216771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1217771fe6b9SJerome Glisse 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
1218771fe6b9SJerome Glisse 				break;
1219771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
12204ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1221771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
12224ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1223771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1224771fe6b9SJerome Glisse 				else
1225771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1226771fe6b9SJerome Glisse 				break;
1227771fe6b9SJerome Glisse 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
12284ce001abSDave Airlie 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1229771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
12304ce001abSDave Airlie 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1231771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1232771fe6b9SJerome Glisse 				else
1233771fe6b9SJerome Glisse 					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1234771fe6b9SJerome Glisse 				break;
1235771fe6b9SJerome Glisse 			}
1236771fe6b9SJerome Glisse 			break;
1237771fe6b9SJerome Glisse 		}
1238771fe6b9SJerome Glisse 		break;
1239771fe6b9SJerome Glisse 	default:
1240771fe6b9SJerome Glisse 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1241771fe6b9SJerome Glisse 		break;
1242771fe6b9SJerome Glisse 	}
1243771fe6b9SJerome Glisse 
1244771fe6b9SJerome Glisse 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1245267364acSAlex Deucher 
1246267364acSAlex Deucher 	/* update scratch regs with new routing */
1247267364acSAlex Deucher 	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1248771fe6b9SJerome Glisse }
1249771fe6b9SJerome Glisse 
1250771fe6b9SJerome Glisse static void
1251771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder,
1252771fe6b9SJerome Glisse 			      struct drm_display_mode *mode)
1253771fe6b9SJerome Glisse {
1254771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1255771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1256771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1257771fe6b9SJerome Glisse 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1258771fe6b9SJerome Glisse 
1259771fe6b9SJerome Glisse 	/* Funky macbooks */
1260771fe6b9SJerome Glisse 	if ((dev->pdev->device == 0x71C5) &&
1261771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_vendor == 0x106b) &&
1262771fe6b9SJerome Glisse 	    (dev->pdev->subsystem_device == 0x0080)) {
1263771fe6b9SJerome Glisse 		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1264771fe6b9SJerome Glisse 			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1265771fe6b9SJerome Glisse 
1266771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1267771fe6b9SJerome Glisse 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1268771fe6b9SJerome Glisse 
1269771fe6b9SJerome Glisse 			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1270771fe6b9SJerome Glisse 		}
1271771fe6b9SJerome Glisse 	}
1272771fe6b9SJerome Glisse 
1273771fe6b9SJerome Glisse 	/* set scaler clears this on some chips */
1274bcc1c2a1SAlex Deucher 	/* XXX check DCE4 */
1275ceefedd8SAlex Deucher 	if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) {
1276771fe6b9SJerome Glisse 		if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
1277ceefedd8SAlex Deucher 			WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
1278ceefedd8SAlex Deucher 			       AVIVO_D1MODE_INTERLEAVE_EN);
1279ceefedd8SAlex Deucher 	}
1280771fe6b9SJerome Glisse }
1281771fe6b9SJerome Glisse 
1282f28cf339SDave Airlie static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
1283f28cf339SDave Airlie {
1284f28cf339SDave Airlie 	struct drm_device *dev = encoder->dev;
1285f28cf339SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
1286f28cf339SDave Airlie 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1287f28cf339SDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1288f28cf339SDave Airlie 	struct drm_encoder *test_encoder;
1289f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
1290f28cf339SDave Airlie 	uint32_t dig_enc_in_use = 0;
1291bcc1c2a1SAlex Deucher 
1292bcc1c2a1SAlex Deucher 	if (ASIC_IS_DCE4(rdev)) {
1293bcc1c2a1SAlex Deucher 		struct radeon_connector_atom_dig *dig_connector =
1294bcc1c2a1SAlex Deucher 			radeon_get_atom_connector_priv_from_encoder(encoder);
1295bcc1c2a1SAlex Deucher 
1296bcc1c2a1SAlex Deucher 		switch (radeon_encoder->encoder_id) {
1297bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1298bcc1c2a1SAlex Deucher 			if (dig_connector->linkb)
1299bcc1c2a1SAlex Deucher 				return 1;
1300bcc1c2a1SAlex Deucher 			else
1301bcc1c2a1SAlex Deucher 				return 0;
1302bcc1c2a1SAlex Deucher 			break;
1303bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1304bcc1c2a1SAlex Deucher 			if (dig_connector->linkb)
1305bcc1c2a1SAlex Deucher 				return 3;
1306bcc1c2a1SAlex Deucher 			else
1307bcc1c2a1SAlex Deucher 				return 2;
1308bcc1c2a1SAlex Deucher 			break;
1309bcc1c2a1SAlex Deucher 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1310bcc1c2a1SAlex Deucher 			if (dig_connector->linkb)
1311bcc1c2a1SAlex Deucher 				return 5;
1312bcc1c2a1SAlex Deucher 			else
1313bcc1c2a1SAlex Deucher 				return 4;
1314bcc1c2a1SAlex Deucher 			break;
1315bcc1c2a1SAlex Deucher 		}
1316bcc1c2a1SAlex Deucher 	}
1317bcc1c2a1SAlex Deucher 
1318f28cf339SDave Airlie 	/* on DCE32 and encoder can driver any block so just crtc id */
1319f28cf339SDave Airlie 	if (ASIC_IS_DCE32(rdev)) {
1320f28cf339SDave Airlie 		return radeon_crtc->crtc_id;
1321f28cf339SDave Airlie 	}
1322f28cf339SDave Airlie 
1323f28cf339SDave Airlie 	/* on DCE3 - LVTMA can only be driven by DIGB */
1324f28cf339SDave Airlie 	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
1325f28cf339SDave Airlie 		struct radeon_encoder *radeon_test_encoder;
1326f28cf339SDave Airlie 
1327f28cf339SDave Airlie 		if (encoder == test_encoder)
1328f28cf339SDave Airlie 			continue;
1329f28cf339SDave Airlie 
1330f28cf339SDave Airlie 		if (!radeon_encoder_is_digital(test_encoder))
1331f28cf339SDave Airlie 			continue;
1332f28cf339SDave Airlie 
1333f28cf339SDave Airlie 		radeon_test_encoder = to_radeon_encoder(test_encoder);
1334f28cf339SDave Airlie 		dig = radeon_test_encoder->enc_priv;
1335f28cf339SDave Airlie 
1336f28cf339SDave Airlie 		if (dig->dig_encoder >= 0)
1337f28cf339SDave Airlie 			dig_enc_in_use |= (1 << dig->dig_encoder);
1338f28cf339SDave Airlie 	}
1339f28cf339SDave Airlie 
1340f28cf339SDave Airlie 	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
1341f28cf339SDave Airlie 		if (dig_enc_in_use & 0x2)
1342f28cf339SDave Airlie 			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
1343f28cf339SDave Airlie 		return 1;
1344f28cf339SDave Airlie 	}
1345f28cf339SDave Airlie 	if (!(dig_enc_in_use & 1))
1346f28cf339SDave Airlie 		return 0;
1347f28cf339SDave Airlie 	return 1;
1348f28cf339SDave Airlie }
1349f28cf339SDave Airlie 
1350771fe6b9SJerome Glisse static void
1351771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1352771fe6b9SJerome Glisse 			     struct drm_display_mode *mode,
1353771fe6b9SJerome Glisse 			     struct drm_display_mode *adjusted_mode)
1354771fe6b9SJerome Glisse {
1355771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1356771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1357771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1358771fe6b9SJerome Glisse 
1359771fe6b9SJerome Glisse 	radeon_encoder->pixel_clock = adjusted_mode->clock;
1360771fe6b9SJerome Glisse 
1361c6f8505eSAlex Deucher 	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
13624ce001abSDave Airlie 		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
1363771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, true);
1364771fe6b9SJerome Glisse 		else
1365771fe6b9SJerome Glisse 			atombios_yuv_setup(encoder, false);
1366771fe6b9SJerome Glisse 	}
1367771fe6b9SJerome Glisse 
1368771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1369771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1370771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1371771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1372771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1373771fe6b9SJerome Glisse 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
1374771fe6b9SJerome Glisse 		break;
1375771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1376771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1377771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1378771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1379bcc1c2a1SAlex Deucher 		if (ASIC_IS_DCE4(rdev)) {
1380bcc1c2a1SAlex Deucher 			/* disable the transmitter */
1381bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1382bcc1c2a1SAlex Deucher 			/* setup and enable the encoder */
1383bcc1c2a1SAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP);
1384bcc1c2a1SAlex Deucher 
1385bcc1c2a1SAlex Deucher 			/* init and enable the transmitter */
1386bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
1387bcc1c2a1SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1388bcc1c2a1SAlex Deucher 		} else {
1389771fe6b9SJerome Glisse 			/* disable the encoder and transmitter */
13901a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1391771fe6b9SJerome Glisse 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
1392771fe6b9SJerome Glisse 
1393771fe6b9SJerome Glisse 			/* setup and enable the encoder and transmitter */
1394771fe6b9SJerome Glisse 			atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
13951a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
13961a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
13971a66c95aSAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1398bcc1c2a1SAlex Deucher 		}
1399771fe6b9SJerome Glisse 		break;
1400771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1401771fe6b9SJerome Glisse 		atombios_ddia_setup(encoder, ATOM_ENABLE);
1402771fe6b9SJerome Glisse 		break;
1403771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1404771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1405771fe6b9SJerome Glisse 		atombios_external_tmds_setup(encoder, ATOM_ENABLE);
1406771fe6b9SJerome Glisse 		break;
1407771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1408771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1409771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1410771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1411771fe6b9SJerome Glisse 		atombios_dac_setup(encoder, ATOM_ENABLE);
1412d3a67a43SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
14134ce001abSDave Airlie 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
1414771fe6b9SJerome Glisse 				atombios_tv_setup(encoder, ATOM_ENABLE);
1415d3a67a43SAlex Deucher 			else
1416d3a67a43SAlex Deucher 				atombios_tv_setup(encoder, ATOM_DISABLE);
1417d3a67a43SAlex Deucher 		}
1418771fe6b9SJerome Glisse 		break;
1419771fe6b9SJerome Glisse 	}
1420771fe6b9SJerome Glisse 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
1421dafc3bd5SChristian Koenig 
14222cd6218cSRafał Miłecki 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
14232cd6218cSRafał Miłecki 		r600_hdmi_enable(encoder);
1424dafc3bd5SChristian Koenig 		r600_hdmi_setmode(encoder, adjusted_mode);
1425771fe6b9SJerome Glisse 	}
14262cd6218cSRafał Miłecki }
1427771fe6b9SJerome Glisse 
1428771fe6b9SJerome Glisse static bool
14294ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1430771fe6b9SJerome Glisse {
1431771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1432771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1433771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
14344ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1435771fe6b9SJerome Glisse 
1436771fe6b9SJerome Glisse 	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
1437771fe6b9SJerome Glisse 				       ATOM_DEVICE_CV_SUPPORT |
1438771fe6b9SJerome Glisse 				       ATOM_DEVICE_CRT_SUPPORT)) {
1439771fe6b9SJerome Glisse 		DAC_LOAD_DETECTION_PS_ALLOCATION args;
1440771fe6b9SJerome Glisse 		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1441771fe6b9SJerome Glisse 		uint8_t frev, crev;
1442771fe6b9SJerome Glisse 
1443771fe6b9SJerome Glisse 		memset(&args, 0, sizeof(args));
1444771fe6b9SJerome Glisse 
1445a084e6eeSAlex Deucher 		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1446a084e6eeSAlex Deucher 			return false;
1447771fe6b9SJerome Glisse 
1448771fe6b9SJerome Glisse 		args.sDacload.ucMisc = 0;
1449771fe6b9SJerome Glisse 
1450771fe6b9SJerome Glisse 		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1451771fe6b9SJerome Glisse 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
1452771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_A;
1453771fe6b9SJerome Glisse 		else
1454771fe6b9SJerome Glisse 			args.sDacload.ucDacType = ATOM_DAC_B;
1455771fe6b9SJerome Glisse 
14564ce001abSDave Airlie 		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
1457771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
14584ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
1459771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
14604ce001abSDave Airlie 		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
1461771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
1462771fe6b9SJerome Glisse 			if (crev >= 3)
1463771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
14644ce001abSDave Airlie 		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
1465771fe6b9SJerome Glisse 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
1466771fe6b9SJerome Glisse 			if (crev >= 3)
1467771fe6b9SJerome Glisse 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1468771fe6b9SJerome Glisse 		}
1469771fe6b9SJerome Glisse 
1470771fe6b9SJerome Glisse 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1471771fe6b9SJerome Glisse 
1472771fe6b9SJerome Glisse 		return true;
1473771fe6b9SJerome Glisse 	} else
1474771fe6b9SJerome Glisse 		return false;
1475771fe6b9SJerome Glisse }
1476771fe6b9SJerome Glisse 
1477771fe6b9SJerome Glisse static enum drm_connector_status
1478771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1479771fe6b9SJerome Glisse {
1480771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
1481771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
1482771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
14834ce001abSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1484771fe6b9SJerome Glisse 	uint32_t bios_0_scratch;
1485771fe6b9SJerome Glisse 
14864ce001abSDave Airlie 	if (!atombios_dac_load_detect(encoder, connector)) {
1487*d9fdaafbSDave Airlie 		DRM_DEBUG_KMS("detect returned false \n");
1488771fe6b9SJerome Glisse 		return connector_status_unknown;
1489771fe6b9SJerome Glisse 	}
1490771fe6b9SJerome Glisse 
1491771fe6b9SJerome Glisse 	if (rdev->family >= CHIP_R600)
1492771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
1493771fe6b9SJerome Glisse 	else
1494771fe6b9SJerome Glisse 		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
1495771fe6b9SJerome Glisse 
1496*d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
14974ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
1498771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
1499771fe6b9SJerome Glisse 			return connector_status_connected;
15004ce001abSDave Airlie 	}
15014ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
1502771fe6b9SJerome Glisse 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
1503771fe6b9SJerome Glisse 			return connector_status_connected;
15044ce001abSDave Airlie 	}
15054ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
1506771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
1507771fe6b9SJerome Glisse 			return connector_status_connected;
15084ce001abSDave Airlie 	}
15094ce001abSDave Airlie 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
1510771fe6b9SJerome Glisse 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
1511771fe6b9SJerome Glisse 			return connector_status_connected; /* CTV */
1512771fe6b9SJerome Glisse 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
1513771fe6b9SJerome Glisse 			return connector_status_connected; /* STV */
1514771fe6b9SJerome Glisse 	}
1515771fe6b9SJerome Glisse 	return connector_status_disconnected;
1516771fe6b9SJerome Glisse }
1517771fe6b9SJerome Glisse 
1518771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
1519771fe6b9SJerome Glisse {
1520267364acSAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1521267364acSAlex Deucher 
1522267364acSAlex Deucher 	if (radeon_encoder->active_device &
1523267364acSAlex Deucher 	    (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
1524267364acSAlex Deucher 		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1525267364acSAlex Deucher 		if (dig)
1526267364acSAlex Deucher 			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
1527267364acSAlex Deucher 	}
1528267364acSAlex Deucher 
1529771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, true);
1530771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
1531267364acSAlex Deucher 
1532267364acSAlex Deucher 	/* this is needed for the pll/ss setup to work correctly in some cases */
1533267364acSAlex Deucher 	atombios_set_encoder_crtc_source(encoder);
1534771fe6b9SJerome Glisse }
1535771fe6b9SJerome Glisse 
1536771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
1537771fe6b9SJerome Glisse {
1538771fe6b9SJerome Glisse 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
1539771fe6b9SJerome Glisse 	radeon_atom_output_lock(encoder, false);
1540771fe6b9SJerome Glisse }
1541771fe6b9SJerome Glisse 
15424ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
15434ce001abSDave Airlie {
1544aa961391SAlex Deucher 	struct drm_device *dev = encoder->dev;
1545aa961391SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
15464ce001abSDave Airlie 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1547f28cf339SDave Airlie 	struct radeon_encoder_atom_dig *dig;
15484ce001abSDave Airlie 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
1549f28cf339SDave Airlie 
1550aa961391SAlex Deucher 	switch (radeon_encoder->encoder_id) {
1551aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1552aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1553aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1554aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1555aa961391SAlex Deucher 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
1556aa961391SAlex Deucher 		break;
1557aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1558aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1559aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1560aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1561aa961391SAlex Deucher 		if (ASIC_IS_DCE4(rdev))
1562aa961391SAlex Deucher 			/* disable the transmitter */
1563aa961391SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1564aa961391SAlex Deucher 		else {
1565aa961391SAlex Deucher 			/* disable the encoder and transmitter */
1566aa961391SAlex Deucher 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1567aa961391SAlex Deucher 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
1568aa961391SAlex Deucher 		}
1569aa961391SAlex Deucher 		break;
1570aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1571aa961391SAlex Deucher 		atombios_ddia_setup(encoder, ATOM_DISABLE);
1572aa961391SAlex Deucher 		break;
1573aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1574aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1575aa961391SAlex Deucher 		atombios_external_tmds_setup(encoder, ATOM_DISABLE);
1576aa961391SAlex Deucher 		break;
1577aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1578aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1579aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1580aa961391SAlex Deucher 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1581aa961391SAlex Deucher 		atombios_dac_setup(encoder, ATOM_DISABLE);
15828bf3aae6SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
1583aa961391SAlex Deucher 			atombios_tv_setup(encoder, ATOM_DISABLE);
1584aa961391SAlex Deucher 		break;
1585aa961391SAlex Deucher 	}
1586aa961391SAlex Deucher 
1587f28cf339SDave Airlie 	if (radeon_encoder_is_digital(encoder)) {
15882cd6218cSRafał Miłecki 		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
15892cd6218cSRafał Miłecki 			r600_hdmi_disable(encoder);
1590f28cf339SDave Airlie 		dig = radeon_encoder->enc_priv;
1591f28cf339SDave Airlie 		dig->dig_encoder = -1;
1592f28cf339SDave Airlie 	}
15934ce001abSDave Airlie 	radeon_encoder->active_device = 0;
15944ce001abSDave Airlie }
15954ce001abSDave Airlie 
1596771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
1597771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
1598771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
1599771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
1600771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
1601771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
16024ce001abSDave Airlie 	.disable = radeon_atom_encoder_disable,
1603771fe6b9SJerome Glisse 	/* no detect for TMDS/LVDS yet */
1604771fe6b9SJerome Glisse };
1605771fe6b9SJerome Glisse 
1606771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
1607771fe6b9SJerome Glisse 	.dpms = radeon_atom_encoder_dpms,
1608771fe6b9SJerome Glisse 	.mode_fixup = radeon_atom_mode_fixup,
1609771fe6b9SJerome Glisse 	.prepare = radeon_atom_encoder_prepare,
1610771fe6b9SJerome Glisse 	.mode_set = radeon_atom_encoder_mode_set,
1611771fe6b9SJerome Glisse 	.commit = radeon_atom_encoder_commit,
1612771fe6b9SJerome Glisse 	.detect = radeon_atom_dac_detect,
1613771fe6b9SJerome Glisse };
1614771fe6b9SJerome Glisse 
1615771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder)
1616771fe6b9SJerome Glisse {
1617771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1618771fe6b9SJerome Glisse 	kfree(radeon_encoder->enc_priv);
1619771fe6b9SJerome Glisse 	drm_encoder_cleanup(encoder);
1620771fe6b9SJerome Glisse 	kfree(radeon_encoder);
1621771fe6b9SJerome Glisse }
1622771fe6b9SJerome Glisse 
1623771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
1624771fe6b9SJerome Glisse 	.destroy = radeon_enc_destroy,
1625771fe6b9SJerome Glisse };
1626771fe6b9SJerome Glisse 
16274ce001abSDave Airlie struct radeon_encoder_atom_dac *
16284ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
16294ce001abSDave Airlie {
1630affd8589SAlex Deucher 	struct drm_device *dev = radeon_encoder->base.dev;
1631affd8589SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
16324ce001abSDave Airlie 	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
16334ce001abSDave Airlie 
16344ce001abSDave Airlie 	if (!dac)
16354ce001abSDave Airlie 		return NULL;
16364ce001abSDave Airlie 
1637affd8589SAlex Deucher 	dac->tv_std = radeon_atombios_get_tv_info(rdev);
16384ce001abSDave Airlie 	return dac;
16394ce001abSDave Airlie }
16404ce001abSDave Airlie 
1641771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *
1642771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
1643771fe6b9SJerome Glisse {
1644771fe6b9SJerome Glisse 	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
1645771fe6b9SJerome Glisse 
1646771fe6b9SJerome Glisse 	if (!dig)
1647771fe6b9SJerome Glisse 		return NULL;
1648771fe6b9SJerome Glisse 
1649771fe6b9SJerome Glisse 	/* coherent mode by default */
1650771fe6b9SJerome Glisse 	dig->coherent_mode = true;
1651f28cf339SDave Airlie 	dig->dig_encoder = -1;
1652771fe6b9SJerome Glisse 
1653771fe6b9SJerome Glisse 	return dig;
1654771fe6b9SJerome Glisse }
1655771fe6b9SJerome Glisse 
1656771fe6b9SJerome Glisse void
1657771fe6b9SJerome Glisse radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
1658771fe6b9SJerome Glisse {
1659dfee5614SDave Airlie 	struct radeon_device *rdev = dev->dev_private;
1660771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
1661771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder;
1662771fe6b9SJerome Glisse 
1663771fe6b9SJerome Glisse 	/* see if we already added it */
1664771fe6b9SJerome Glisse 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1665771fe6b9SJerome Glisse 		radeon_encoder = to_radeon_encoder(encoder);
1666771fe6b9SJerome Glisse 		if (radeon_encoder->encoder_id == encoder_id) {
1667771fe6b9SJerome Glisse 			radeon_encoder->devices |= supported_device;
1668771fe6b9SJerome Glisse 			return;
1669771fe6b9SJerome Glisse 		}
1670771fe6b9SJerome Glisse 
1671771fe6b9SJerome Glisse 	}
1672771fe6b9SJerome Glisse 
1673771fe6b9SJerome Glisse 	/* add a new one */
1674771fe6b9SJerome Glisse 	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
1675771fe6b9SJerome Glisse 	if (!radeon_encoder)
1676771fe6b9SJerome Glisse 		return;
1677771fe6b9SJerome Glisse 
1678771fe6b9SJerome Glisse 	encoder = &radeon_encoder->base;
1679bcc1c2a1SAlex Deucher 	switch (rdev->num_crtc) {
1680bcc1c2a1SAlex Deucher 	case 1:
1681dfee5614SDave Airlie 		encoder->possible_crtcs = 0x1;
1682bcc1c2a1SAlex Deucher 		break;
1683bcc1c2a1SAlex Deucher 	case 2:
1684bcc1c2a1SAlex Deucher 	default:
1685771fe6b9SJerome Glisse 		encoder->possible_crtcs = 0x3;
1686bcc1c2a1SAlex Deucher 		break;
1687bcc1c2a1SAlex Deucher 	case 6:
1688bcc1c2a1SAlex Deucher 		encoder->possible_crtcs = 0x3f;
1689bcc1c2a1SAlex Deucher 		break;
1690bcc1c2a1SAlex Deucher 	}
1691771fe6b9SJerome Glisse 
1692771fe6b9SJerome Glisse 	radeon_encoder->enc_priv = NULL;
1693771fe6b9SJerome Glisse 
1694771fe6b9SJerome Glisse 	radeon_encoder->encoder_id = encoder_id;
1695771fe6b9SJerome Glisse 	radeon_encoder->devices = supported_device;
1696c93bb85bSJerome Glisse 	radeon_encoder->rmx_type = RMX_OFF;
1697771fe6b9SJerome Glisse 
1698771fe6b9SJerome Glisse 	switch (radeon_encoder->encoder_id) {
1699771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1700771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1701771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1702771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1703771fe6b9SJerome Glisse 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1704771fe6b9SJerome Glisse 			radeon_encoder->rmx_type = RMX_FULL;
1705771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
1706771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
1707771fe6b9SJerome Glisse 		} else {
1708771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
1709771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
1710771fe6b9SJerome Glisse 		}
1711771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
1712771fe6b9SJerome Glisse 		break;
1713771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1714771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
1715affd8589SAlex Deucher 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
1716771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
1717771fe6b9SJerome Glisse 		break;
1718771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1719771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1720771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1721771fe6b9SJerome Glisse 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
17224ce001abSDave Airlie 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
1723771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
1724771fe6b9SJerome Glisse 		break;
1725771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1726771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1727771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1728771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1729771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1730771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1731771fe6b9SJerome Glisse 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
173260d15f55SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
173360d15f55SAlex Deucher 			radeon_encoder->rmx_type = RMX_FULL;
173460d15f55SAlex Deucher 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
173560d15f55SAlex Deucher 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
173660d15f55SAlex Deucher 		} else {
1737771fe6b9SJerome Glisse 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
1738771fe6b9SJerome Glisse 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
173960d15f55SAlex Deucher 		}
1740771fe6b9SJerome Glisse 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
1741771fe6b9SJerome Glisse 		break;
1742771fe6b9SJerome Glisse 	}
1743771fe6b9SJerome Glisse }
1744