xref: /dflybsd-src/sys/dev/drm/radeon/atombios_encoders.c (revision ce73550bd9805b6ad49cf4c94b5e37aa6922668d)
1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot  * Copyright 2007-11 Advanced Micro Devices, Inc.
3926deccbSFrançois Tigeot  * Copyright 2008 Red Hat Inc.
4926deccbSFrançois Tigeot  *
5926deccbSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
6926deccbSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
7926deccbSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
8926deccbSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9926deccbSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
10926deccbSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
11926deccbSFrançois Tigeot  *
12926deccbSFrançois Tigeot  * The above copyright notice and this permission notice shall be included in
13926deccbSFrançois Tigeot  * all copies or substantial portions of the Software.
14926deccbSFrançois Tigeot  *
15926deccbSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16926deccbSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17926deccbSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18926deccbSFrançois Tigeot  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19926deccbSFrançois Tigeot  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20926deccbSFrançois Tigeot  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21926deccbSFrançois Tigeot  * OTHER DEALINGS IN THE SOFTWARE.
22926deccbSFrançois Tigeot  *
23926deccbSFrançois Tigeot  * Authors: Dave Airlie
24926deccbSFrançois Tigeot  *          Alex Deucher
25926deccbSFrançois Tigeot  */
26926deccbSFrançois Tigeot #include <drm/drmP.h>
27926deccbSFrançois Tigeot #include <drm/drm_crtc_helper.h>
28926deccbSFrançois Tigeot #include <uapi_drm/radeon_drm.h>
29926deccbSFrançois Tigeot #include "radeon.h"
304cd92098Szrj #include "radeon_asic.h"
31926deccbSFrançois Tigeot #include "atom.h"
32926deccbSFrançois Tigeot 
33926deccbSFrançois Tigeot static u8
34926deccbSFrançois Tigeot radeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev)
35926deccbSFrançois Tigeot {
36926deccbSFrançois Tigeot 	u8 backlight_level;
37926deccbSFrançois Tigeot 	u32 bios_2_scratch;
38926deccbSFrançois Tigeot 
39926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
40926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
41926deccbSFrançois Tigeot 	else
42926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
43926deccbSFrançois Tigeot 
44926deccbSFrançois Tigeot 	backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >>
45926deccbSFrançois Tigeot 			   ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
46926deccbSFrançois Tigeot 
47926deccbSFrançois Tigeot 	return backlight_level;
48926deccbSFrançois Tigeot }
49926deccbSFrançois Tigeot 
50926deccbSFrançois Tigeot static void
51926deccbSFrançois Tigeot radeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev,
52926deccbSFrançois Tigeot 				       u8 backlight_level)
53926deccbSFrançois Tigeot {
54926deccbSFrançois Tigeot 	u32 bios_2_scratch;
55926deccbSFrançois Tigeot 
56926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
57926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
58926deccbSFrançois Tigeot 	else
59926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
60926deccbSFrançois Tigeot 
61926deccbSFrançois Tigeot 	bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
62926deccbSFrançois Tigeot 	bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
63926deccbSFrançois Tigeot 			   ATOM_S2_CURRENT_BL_LEVEL_MASK);
64926deccbSFrançois Tigeot 
65926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
66926deccbSFrançois Tigeot 		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
67926deccbSFrançois Tigeot 	else
68926deccbSFrançois Tigeot 		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
69926deccbSFrançois Tigeot }
70926deccbSFrançois Tigeot 
71926deccbSFrançois Tigeot u8
72926deccbSFrançois Tigeot atombios_get_backlight_level(struct radeon_encoder *radeon_encoder)
73926deccbSFrançois Tigeot {
74926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
75926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
76926deccbSFrançois Tigeot 
77926deccbSFrançois Tigeot 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
78926deccbSFrançois Tigeot 		return 0;
79926deccbSFrançois Tigeot 
80926deccbSFrançois Tigeot 	return radeon_atom_get_backlight_level_from_reg(rdev);
81926deccbSFrançois Tigeot }
82926deccbSFrançois Tigeot 
83926deccbSFrançois Tigeot void
84926deccbSFrançois Tigeot atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
85926deccbSFrançois Tigeot {
86926deccbSFrançois Tigeot 	struct drm_encoder *encoder = &radeon_encoder->base;
87926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
88926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
89926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
90926deccbSFrançois Tigeot 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
91926deccbSFrançois Tigeot 	int index;
92926deccbSFrançois Tigeot 
93926deccbSFrançois Tigeot 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
94926deccbSFrançois Tigeot 		return;
95926deccbSFrançois Tigeot 
96926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
97926deccbSFrançois Tigeot 	    radeon_encoder->enc_priv) {
98926deccbSFrançois Tigeot 		dig = radeon_encoder->enc_priv;
99926deccbSFrançois Tigeot 		dig->backlight_level = level;
100926deccbSFrançois Tigeot 		radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level);
101926deccbSFrançois Tigeot 
102926deccbSFrançois Tigeot 		switch (radeon_encoder->encoder_id) {
103926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
104926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
105926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
106926deccbSFrançois Tigeot 			if (dig->backlight_level == 0) {
107926deccbSFrançois Tigeot 				args.ucAction = ATOM_LCD_BLOFF;
108926deccbSFrançois Tigeot 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
109926deccbSFrançois Tigeot 			} else {
110926deccbSFrançois Tigeot 				args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
111926deccbSFrançois Tigeot 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
112926deccbSFrançois Tigeot 				args.ucAction = ATOM_LCD_BLON;
113926deccbSFrançois Tigeot 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
114926deccbSFrançois Tigeot 			}
115926deccbSFrançois Tigeot 			break;
116926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
117926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
118926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
119926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
120926deccbSFrançois Tigeot 			if (dig->backlight_level == 0)
121926deccbSFrançois Tigeot 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
122926deccbSFrançois Tigeot 			else {
123926deccbSFrançois Tigeot 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0);
124926deccbSFrançois Tigeot 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
125926deccbSFrançois Tigeot 			}
126926deccbSFrançois Tigeot 			break;
127926deccbSFrançois Tigeot 		default:
128926deccbSFrançois Tigeot 			break;
129926deccbSFrançois Tigeot 		}
130926deccbSFrançois Tigeot 	}
131926deccbSFrançois Tigeot }
132926deccbSFrançois Tigeot 
133926deccbSFrançois Tigeot #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
134926deccbSFrançois Tigeot 
135*ce73550bSFrançois Tigeot #if 0
136926deccbSFrançois Tigeot static u8 radeon_atom_bl_level(struct backlight_device *bd)
137926deccbSFrançois Tigeot {
138926deccbSFrançois Tigeot 	u8 level;
139926deccbSFrançois Tigeot 
140926deccbSFrançois Tigeot 	/* Convert brightness to hardware level */
141926deccbSFrançois Tigeot 	if (bd->props.brightness < 0)
142926deccbSFrançois Tigeot 		level = 0;
143926deccbSFrançois Tigeot 	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
144926deccbSFrançois Tigeot 		level = RADEON_MAX_BL_LEVEL;
145926deccbSFrançois Tigeot 	else
146926deccbSFrançois Tigeot 		level = bd->props.brightness;
147926deccbSFrançois Tigeot 
148926deccbSFrançois Tigeot 	return level;
149926deccbSFrançois Tigeot }
150926deccbSFrançois Tigeot 
151926deccbSFrançois Tigeot static int radeon_atom_backlight_update_status(struct backlight_device *bd)
152926deccbSFrançois Tigeot {
153926deccbSFrançois Tigeot 	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
154926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = pdata->encoder;
155926deccbSFrançois Tigeot 
156926deccbSFrançois Tigeot 	atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd));
157926deccbSFrançois Tigeot 
158926deccbSFrançois Tigeot 	return 0;
159926deccbSFrançois Tigeot }
160926deccbSFrançois Tigeot 
161926deccbSFrançois Tigeot static int radeon_atom_backlight_get_brightness(struct backlight_device *bd)
162926deccbSFrançois Tigeot {
163926deccbSFrançois Tigeot 	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
164926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = pdata->encoder;
165926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
166926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
167926deccbSFrançois Tigeot 
168926deccbSFrançois Tigeot 	return radeon_atom_get_backlight_level_from_reg(rdev);
169926deccbSFrançois Tigeot }
170926deccbSFrançois Tigeot 
171926deccbSFrançois Tigeot static const struct backlight_ops radeon_atom_backlight_ops = {
172926deccbSFrançois Tigeot 	.get_brightness = radeon_atom_backlight_get_brightness,
173926deccbSFrançois Tigeot 	.update_status	= radeon_atom_backlight_update_status,
174926deccbSFrançois Tigeot };
175*ce73550bSFrançois Tigeot #endif
176926deccbSFrançois Tigeot 
1776a4774b1SImre Vadász /*
1786a4774b1SImre Vadász  * Read max backlight level
1796a4774b1SImre Vadász  */
1806a4774b1SImre Vadász static int
1816a4774b1SImre Vadász sysctl_backlight_max(SYSCTL_HANDLER_ARGS)
1826a4774b1SImre Vadász {
1836a4774b1SImre Vadász 	int err, val;
1846a4774b1SImre Vadász 
1856a4774b1SImre Vadász 	val = RADEON_MAX_BL_LEVEL;
1866a4774b1SImre Vadász 	err = sysctl_handle_int(oidp, &val, 0, req);
1876a4774b1SImre Vadász 	return(err);
1886a4774b1SImre Vadász }
1896a4774b1SImre Vadász 
1906a4774b1SImre Vadász /*
1916a4774b1SImre Vadász  * Read/write backlight level
1926a4774b1SImre Vadász  */
1936a4774b1SImre Vadász static int
1946a4774b1SImre Vadász sysctl_backlight_handler(SYSCTL_HANDLER_ARGS)
1956a4774b1SImre Vadász {
1966a4774b1SImre Vadász 	struct radeon_encoder *encoder;
1976a4774b1SImre Vadász 	struct radeon_encoder_atom_dig *dig;
1986a4774b1SImre Vadász 	int err, val;
1996a4774b1SImre Vadász 
2006a4774b1SImre Vadász 	encoder = (struct radeon_encoder *)arg1;
2016a4774b1SImre Vadász 	dig = encoder->enc_priv;
2026a4774b1SImre Vadász 	val = dig->backlight_level;
2036a4774b1SImre Vadász 
2046a4774b1SImre Vadász 	err = sysctl_handle_int(oidp, &val, 0, req);
2056a4774b1SImre Vadász 	if (err != 0 || req->newptr == NULL) {
2066a4774b1SImre Vadász 		return(err);
2076a4774b1SImre Vadász 	}
2086a4774b1SImre Vadász 	if (dig->backlight_level != val && val >= 0 &&
2096a4774b1SImre Vadász 	    val <= RADEON_MAX_BL_LEVEL) {
2106a4774b1SImre Vadász 		atombios_set_backlight_level(encoder, val);
2116a4774b1SImre Vadász 	}
2126a4774b1SImre Vadász 
2136a4774b1SImre Vadász 	return(err);
2146a4774b1SImre Vadász }
2156a4774b1SImre Vadász 
216926deccbSFrançois Tigeot void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
217926deccbSFrançois Tigeot 				struct drm_connector *drm_connector)
218926deccbSFrançois Tigeot {
2196a4774b1SImre Vadász 	struct drm_device *dev = radeon_encoder->base.dev;
2206a4774b1SImre Vadász 	struct radeon_device *rdev = dev->dev_private;
2216a4774b1SImre Vadász 	struct radeon_encoder_atom_dig *dig;
2226a4774b1SImre Vadász 
2236a4774b1SImre Vadász 	if (!radeon_encoder->enc_priv)
2246a4774b1SImre Vadász 		return;
2256a4774b1SImre Vadász 
2266a4774b1SImre Vadász 	if (!rdev->is_atom_bios)
2276a4774b1SImre Vadász 		return;
2286a4774b1SImre Vadász 
2296a4774b1SImre Vadász 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
2306a4774b1SImre Vadász 		return;
2316a4774b1SImre Vadász 
2326a4774b1SImre Vadász 	dig = radeon_encoder->enc_priv;
2336a4774b1SImre Vadász 	dig->backlight_level = radeon_atom_get_backlight_level_from_reg(rdev);
2346a4774b1SImre Vadász 
2356a4774b1SImre Vadász 	DRM_INFO("radeon atom DIG backlight initialized\n");
2366a4774b1SImre Vadász 
2376a4774b1SImre Vadász 	SYSCTL_ADD_PROC(&drm_connector->dev->sysctl->ctx, &sysctl__hw_children,
2386a4774b1SImre Vadász 			OID_AUTO, "backlight_max",
2396a4774b1SImre Vadász 			CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_ANYBODY,
2406a4774b1SImre Vadász 			radeon_encoder, sizeof(int),
2416a4774b1SImre Vadász 			sysctl_backlight_max,
2426a4774b1SImre Vadász 			"I", "Max backlight level");
2436a4774b1SImre Vadász 	SYSCTL_ADD_PROC(&drm_connector->dev->sysctl->ctx, &sysctl__hw_children,
2446a4774b1SImre Vadász 			OID_AUTO, "backlight_level",
2456a4774b1SImre Vadász 			CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
2466a4774b1SImre Vadász 			radeon_encoder, sizeof(int),
2476a4774b1SImre Vadász 			sysctl_backlight_handler,
2486a4774b1SImre Vadász 			"I", "Backlight level");
2496a4774b1SImre Vadász 	return;
250926deccbSFrançois Tigeot }
251926deccbSFrançois Tigeot 
252*ce73550bSFrançois Tigeot static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder)
253*ce73550bSFrançois Tigeot {
254*ce73550bSFrançois Tigeot #if 0
255*ce73550bSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
256*ce73550bSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
257*ce73550bSFrançois Tigeot 	struct backlight_device *bd = NULL;
258*ce73550bSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
259*ce73550bSFrançois Tigeot 
260*ce73550bSFrançois Tigeot 	if (!radeon_encoder->enc_priv)
261*ce73550bSFrançois Tigeot 		return;
262*ce73550bSFrançois Tigeot 
263*ce73550bSFrançois Tigeot 	if (!rdev->is_atom_bios)
264*ce73550bSFrançois Tigeot 		return;
265*ce73550bSFrançois Tigeot 
266*ce73550bSFrançois Tigeot 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
267*ce73550bSFrançois Tigeot 		return;
268*ce73550bSFrançois Tigeot 
269*ce73550bSFrançois Tigeot 	dig = radeon_encoder->enc_priv;
270*ce73550bSFrançois Tigeot 	bd = dig->bl_dev;
271*ce73550bSFrançois Tigeot 	dig->bl_dev = NULL;
272*ce73550bSFrançois Tigeot 
273*ce73550bSFrançois Tigeot 	if (bd) {
274*ce73550bSFrançois Tigeot 		struct radeon_legacy_backlight_privdata *pdata;
275*ce73550bSFrançois Tigeot 
276*ce73550bSFrançois Tigeot 		pdata = bl_get_data(bd);
277*ce73550bSFrançois Tigeot 		backlight_device_unregister(bd);
278*ce73550bSFrançois Tigeot 		kfree(pdata);
279*ce73550bSFrançois Tigeot 
280*ce73550bSFrançois Tigeot 		DRM_INFO("radeon atom LVDS backlight unloaded\n");
281*ce73550bSFrançois Tigeot 	}
282*ce73550bSFrançois Tigeot #endif
283*ce73550bSFrançois Tigeot }
284*ce73550bSFrançois Tigeot 
285*ce73550bSFrançois Tigeot #else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
286*ce73550bSFrançois Tigeot 
287*ce73550bSFrançois Tigeot void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
288*ce73550bSFrançois Tigeot 				struct drm_connector *drm_connector)
289*ce73550bSFrançois Tigeot {
290*ce73550bSFrançois Tigeot }
291*ce73550bSFrançois Tigeot 
292926deccbSFrançois Tigeot static void radeon_atom_backlight_exit(struct radeon_encoder *encoder)
293926deccbSFrançois Tigeot {
294926deccbSFrançois Tigeot }
295926deccbSFrançois Tigeot 
296926deccbSFrançois Tigeot #endif
297926deccbSFrançois Tigeot 
298926deccbSFrançois Tigeot 
299926deccbSFrançois Tigeot static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
300926deccbSFrançois Tigeot 				   const struct drm_display_mode *mode,
301926deccbSFrançois Tigeot 				   struct drm_display_mode *adjusted_mode)
302926deccbSFrançois Tigeot {
303926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
304926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
305926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
306926deccbSFrançois Tigeot 
307926deccbSFrançois Tigeot 	/* set the active encoder to connector routing */
308926deccbSFrançois Tigeot 	radeon_encoder_set_active_device(encoder);
309926deccbSFrançois Tigeot 	drm_mode_set_crtcinfo(adjusted_mode, 0);
310926deccbSFrançois Tigeot 
311926deccbSFrançois Tigeot 	/* hw bug */
312926deccbSFrançois Tigeot 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
313926deccbSFrançois Tigeot 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
314926deccbSFrançois Tigeot 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
315926deccbSFrançois Tigeot 
316c6f73aabSFrançois Tigeot 	/* get the native mode for scaling */
317c6f73aabSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
318926deccbSFrançois Tigeot 		radeon_panel_mode_fixup(encoder, adjusted_mode);
319c6f73aabSFrançois Tigeot 	} else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
320926deccbSFrançois Tigeot 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
321926deccbSFrançois Tigeot 		if (tv_dac) {
322926deccbSFrançois Tigeot 			if (tv_dac->tv_std == TV_STD_NTSC ||
323926deccbSFrançois Tigeot 			    tv_dac->tv_std == TV_STD_NTSC_J ||
324926deccbSFrançois Tigeot 			    tv_dac->tv_std == TV_STD_PAL_M)
325926deccbSFrançois Tigeot 				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
326926deccbSFrançois Tigeot 			else
327926deccbSFrançois Tigeot 				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
328926deccbSFrançois Tigeot 		}
329c6f73aabSFrançois Tigeot 	} else if (radeon_encoder->rmx_type != RMX_OFF) {
330c6f73aabSFrançois Tigeot 		radeon_panel_mode_fixup(encoder, adjusted_mode);
331926deccbSFrançois Tigeot 	}
332926deccbSFrançois Tigeot 
333926deccbSFrançois Tigeot 	if (ASIC_IS_DCE3(rdev) &&
334926deccbSFrançois Tigeot 	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
335926deccbSFrançois Tigeot 	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
336926deccbSFrançois Tigeot 		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
337926deccbSFrançois Tigeot 		radeon_dp_set_link_config(connector, adjusted_mode);
338926deccbSFrançois Tigeot 	}
339926deccbSFrançois Tigeot 
340926deccbSFrançois Tigeot 	return true;
341926deccbSFrançois Tigeot }
342926deccbSFrançois Tigeot 
343926deccbSFrançois Tigeot static void
344926deccbSFrançois Tigeot atombios_dac_setup(struct drm_encoder *encoder, int action)
345926deccbSFrançois Tigeot {
346926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
347926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
348926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
349926deccbSFrançois Tigeot 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
350926deccbSFrançois Tigeot 	int index = 0;
351926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
352926deccbSFrançois Tigeot 
353926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
354926deccbSFrançois Tigeot 
355926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
356926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
357926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
358926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
359926deccbSFrançois Tigeot 		break;
360926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
361926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
362926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
363926deccbSFrançois Tigeot 		break;
364926deccbSFrançois Tigeot 	}
365926deccbSFrançois Tigeot 
366926deccbSFrançois Tigeot 	args.ucAction = action;
367926deccbSFrançois Tigeot 
368926deccbSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
369926deccbSFrançois Tigeot 		args.ucDacStandard = ATOM_DAC1_PS2;
370926deccbSFrançois Tigeot 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
371926deccbSFrançois Tigeot 		args.ucDacStandard = ATOM_DAC1_CV;
372926deccbSFrançois Tigeot 	else {
373926deccbSFrançois Tigeot 		switch (dac_info->tv_std) {
374926deccbSFrançois Tigeot 		case TV_STD_PAL:
375926deccbSFrançois Tigeot 		case TV_STD_PAL_M:
376926deccbSFrançois Tigeot 		case TV_STD_SCART_PAL:
377926deccbSFrançois Tigeot 		case TV_STD_SECAM:
378926deccbSFrançois Tigeot 		case TV_STD_PAL_CN:
379926deccbSFrançois Tigeot 			args.ucDacStandard = ATOM_DAC1_PAL;
380926deccbSFrançois Tigeot 			break;
381926deccbSFrançois Tigeot 		case TV_STD_NTSC:
382926deccbSFrançois Tigeot 		case TV_STD_NTSC_J:
383926deccbSFrançois Tigeot 		case TV_STD_PAL_60:
384926deccbSFrançois Tigeot 		default:
385926deccbSFrançois Tigeot 			args.ucDacStandard = ATOM_DAC1_NTSC;
386926deccbSFrançois Tigeot 			break;
387926deccbSFrançois Tigeot 		}
388926deccbSFrançois Tigeot 	}
389926deccbSFrançois Tigeot 	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
390926deccbSFrançois Tigeot 
391926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
392926deccbSFrançois Tigeot 
393926deccbSFrançois Tigeot }
394926deccbSFrançois Tigeot 
395926deccbSFrançois Tigeot static void
396926deccbSFrançois Tigeot atombios_tv_setup(struct drm_encoder *encoder, int action)
397926deccbSFrançois Tigeot {
398926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
399926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
400926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
401926deccbSFrançois Tigeot 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
402926deccbSFrançois Tigeot 	int index = 0;
403926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
404926deccbSFrançois Tigeot 
405926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
406926deccbSFrançois Tigeot 
407926deccbSFrançois Tigeot 	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
408926deccbSFrançois Tigeot 
409926deccbSFrançois Tigeot 	args.sTVEncoder.ucAction = action;
410926deccbSFrançois Tigeot 
411926deccbSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
412926deccbSFrançois Tigeot 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
413926deccbSFrançois Tigeot 	else {
414926deccbSFrançois Tigeot 		switch (dac_info->tv_std) {
415926deccbSFrançois Tigeot 		case TV_STD_NTSC:
416926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
417926deccbSFrançois Tigeot 			break;
418926deccbSFrançois Tigeot 		case TV_STD_PAL:
419926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
420926deccbSFrançois Tigeot 			break;
421926deccbSFrançois Tigeot 		case TV_STD_PAL_M:
422926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
423926deccbSFrançois Tigeot 			break;
424926deccbSFrançois Tigeot 		case TV_STD_PAL_60:
425926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
426926deccbSFrançois Tigeot 			break;
427926deccbSFrançois Tigeot 		case TV_STD_NTSC_J:
428926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
429926deccbSFrançois Tigeot 			break;
430926deccbSFrançois Tigeot 		case TV_STD_SCART_PAL:
431926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
432926deccbSFrançois Tigeot 			break;
433926deccbSFrançois Tigeot 		case TV_STD_SECAM:
434926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
435926deccbSFrançois Tigeot 			break;
436926deccbSFrançois Tigeot 		case TV_STD_PAL_CN:
437926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
438926deccbSFrançois Tigeot 			break;
439926deccbSFrançois Tigeot 		default:
440926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
441926deccbSFrançois Tigeot 			break;
442926deccbSFrançois Tigeot 		}
443926deccbSFrançois Tigeot 	}
444926deccbSFrançois Tigeot 
445926deccbSFrançois Tigeot 	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
446926deccbSFrançois Tigeot 
447926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
448926deccbSFrançois Tigeot 
449926deccbSFrançois Tigeot }
450926deccbSFrançois Tigeot 
451926deccbSFrançois Tigeot static u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
452926deccbSFrançois Tigeot {
453926deccbSFrançois Tigeot 	int bpc = 8;
454926deccbSFrançois Tigeot 
455c6f73aabSFrançois Tigeot 	if (encoder->crtc) {
456c6f73aabSFrançois Tigeot 		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
457c6f73aabSFrançois Tigeot 		bpc = radeon_crtc->bpc;
458c6f73aabSFrançois Tigeot 	}
459926deccbSFrançois Tigeot 
460926deccbSFrançois Tigeot 	switch (bpc) {
461926deccbSFrançois Tigeot 	case 0:
462926deccbSFrançois Tigeot 		return PANEL_BPC_UNDEFINE;
463926deccbSFrançois Tigeot 	case 6:
464926deccbSFrançois Tigeot 		return PANEL_6BIT_PER_COLOR;
465926deccbSFrançois Tigeot 	case 8:
466926deccbSFrançois Tigeot 	default:
467926deccbSFrançois Tigeot 		return PANEL_8BIT_PER_COLOR;
468926deccbSFrançois Tigeot 	case 10:
469926deccbSFrançois Tigeot 		return PANEL_10BIT_PER_COLOR;
470926deccbSFrançois Tigeot 	case 12:
471926deccbSFrançois Tigeot 		return PANEL_12BIT_PER_COLOR;
472926deccbSFrançois Tigeot 	case 16:
473926deccbSFrançois Tigeot 		return PANEL_16BIT_PER_COLOR;
474926deccbSFrançois Tigeot 	}
475926deccbSFrançois Tigeot }
476926deccbSFrançois Tigeot 
477926deccbSFrançois Tigeot union dvo_encoder_control {
478926deccbSFrançois Tigeot 	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
479926deccbSFrançois Tigeot 	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
480926deccbSFrançois Tigeot 	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
48157e252bfSMichael Neumann 	DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 dvo_v4;
482926deccbSFrançois Tigeot };
483926deccbSFrançois Tigeot 
484926deccbSFrançois Tigeot void
485926deccbSFrançois Tigeot atombios_dvo_setup(struct drm_encoder *encoder, int action)
486926deccbSFrançois Tigeot {
487926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
488926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
489926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
490926deccbSFrançois Tigeot 	union dvo_encoder_control args;
491926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
492926deccbSFrançois Tigeot 	uint8_t frev, crev;
493926deccbSFrançois Tigeot 
494926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
495926deccbSFrançois Tigeot 
496926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
497926deccbSFrançois Tigeot 		return;
498926deccbSFrançois Tigeot 
499926deccbSFrançois Tigeot 	/* some R4xx chips have the wrong frev */
500926deccbSFrançois Tigeot 	if (rdev->family <= CHIP_RV410)
501926deccbSFrançois Tigeot 		frev = 1;
502926deccbSFrançois Tigeot 
503926deccbSFrançois Tigeot 	switch (frev) {
504926deccbSFrançois Tigeot 	case 1:
505926deccbSFrançois Tigeot 		switch (crev) {
506926deccbSFrançois Tigeot 		case 1:
507926deccbSFrançois Tigeot 			/* R4xx, R5xx */
508926deccbSFrançois Tigeot 			args.ext_tmds.sXTmdsEncoder.ucEnable = action;
509926deccbSFrançois Tigeot 
510926deccbSFrançois Tigeot 			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
511926deccbSFrançois Tigeot 				args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
512926deccbSFrançois Tigeot 
513926deccbSFrançois Tigeot 			args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
514926deccbSFrançois Tigeot 			break;
515926deccbSFrançois Tigeot 		case 2:
516926deccbSFrançois Tigeot 			/* RS600/690/740 */
517926deccbSFrançois Tigeot 			args.dvo.sDVOEncoder.ucAction = action;
518926deccbSFrançois Tigeot 			args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
519926deccbSFrançois Tigeot 			/* DFP1, CRT1, TV1 depending on the type of port */
520926deccbSFrançois Tigeot 			args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
521926deccbSFrançois Tigeot 
522926deccbSFrançois Tigeot 			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
523926deccbSFrançois Tigeot 				args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
524926deccbSFrançois Tigeot 			break;
525926deccbSFrançois Tigeot 		case 3:
526926deccbSFrançois Tigeot 			/* R6xx */
527926deccbSFrançois Tigeot 			args.dvo_v3.ucAction = action;
528926deccbSFrançois Tigeot 			args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
529926deccbSFrançois Tigeot 			args.dvo_v3.ucDVOConfig = 0; /* XXX */
530926deccbSFrançois Tigeot 			break;
53157e252bfSMichael Neumann 		case 4:
53257e252bfSMichael Neumann 			/* DCE8 */
53357e252bfSMichael Neumann 			args.dvo_v4.ucAction = action;
53457e252bfSMichael Neumann 			args.dvo_v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
53557e252bfSMichael Neumann 			args.dvo_v4.ucDVOConfig = 0; /* XXX */
53657e252bfSMichael Neumann 			args.dvo_v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
53757e252bfSMichael Neumann 			break;
538926deccbSFrançois Tigeot 		default:
539926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
540926deccbSFrançois Tigeot 			break;
541926deccbSFrançois Tigeot 		}
542926deccbSFrançois Tigeot 		break;
543926deccbSFrançois Tigeot 	default:
544926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
545926deccbSFrançois Tigeot 		break;
546926deccbSFrançois Tigeot 	}
547926deccbSFrançois Tigeot 
548926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
549926deccbSFrançois Tigeot }
550926deccbSFrançois Tigeot 
551926deccbSFrançois Tigeot union lvds_encoder_control {
552926deccbSFrançois Tigeot 	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
553926deccbSFrançois Tigeot 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
554926deccbSFrançois Tigeot };
555926deccbSFrançois Tigeot 
556926deccbSFrançois Tigeot void
557926deccbSFrançois Tigeot atombios_digital_setup(struct drm_encoder *encoder, int action)
558926deccbSFrançois Tigeot {
559926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
560926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
561926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
562926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
563926deccbSFrançois Tigeot 	union lvds_encoder_control args;
564926deccbSFrançois Tigeot 	int index = 0;
565926deccbSFrançois Tigeot 	int hdmi_detected = 0;
566926deccbSFrançois Tigeot 	uint8_t frev, crev;
567926deccbSFrançois Tigeot 
568926deccbSFrançois Tigeot 	if (!dig)
569926deccbSFrançois Tigeot 		return;
570926deccbSFrançois Tigeot 
571926deccbSFrançois Tigeot 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
572926deccbSFrançois Tigeot 		hdmi_detected = 1;
573926deccbSFrançois Tigeot 
574926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
575926deccbSFrançois Tigeot 
576926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
577926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
578926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
579926deccbSFrançois Tigeot 		break;
580926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
581926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
582926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
583926deccbSFrançois Tigeot 		break;
584926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
585926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
586926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
587926deccbSFrançois Tigeot 		else
588926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
589926deccbSFrançois Tigeot 		break;
590926deccbSFrançois Tigeot 	}
591926deccbSFrançois Tigeot 
592926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
593926deccbSFrançois Tigeot 		return;
594926deccbSFrançois Tigeot 
595926deccbSFrançois Tigeot 	switch (frev) {
596926deccbSFrançois Tigeot 	case 1:
597926deccbSFrançois Tigeot 	case 2:
598926deccbSFrançois Tigeot 		switch (crev) {
599926deccbSFrançois Tigeot 		case 1:
600926deccbSFrançois Tigeot 			args.v1.ucMisc = 0;
601926deccbSFrançois Tigeot 			args.v1.ucAction = action;
602926deccbSFrançois Tigeot 			if (hdmi_detected)
603926deccbSFrançois Tigeot 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
604926deccbSFrançois Tigeot 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
605926deccbSFrançois Tigeot 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
606926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
607926deccbSFrançois Tigeot 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
608926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
609926deccbSFrançois Tigeot 					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
610926deccbSFrançois Tigeot 			} else {
611926deccbSFrançois Tigeot 				if (dig->linkb)
612926deccbSFrançois Tigeot 					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
613926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
614926deccbSFrançois Tigeot 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
615926deccbSFrançois Tigeot 				/*if (pScrn->rgbBits == 8) */
616926deccbSFrançois Tigeot 				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
617926deccbSFrançois Tigeot 			}
618926deccbSFrançois Tigeot 			break;
619926deccbSFrançois Tigeot 		case 2:
620926deccbSFrançois Tigeot 		case 3:
621926deccbSFrançois Tigeot 			args.v2.ucMisc = 0;
622926deccbSFrançois Tigeot 			args.v2.ucAction = action;
623926deccbSFrançois Tigeot 			if (crev == 3) {
624926deccbSFrançois Tigeot 				if (dig->coherent_mode)
625926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
626926deccbSFrançois Tigeot 			}
627926deccbSFrançois Tigeot 			if (hdmi_detected)
628926deccbSFrançois Tigeot 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
629926deccbSFrançois Tigeot 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
630926deccbSFrançois Tigeot 			args.v2.ucTruncate = 0;
631926deccbSFrançois Tigeot 			args.v2.ucSpatial = 0;
632926deccbSFrançois Tigeot 			args.v2.ucTemporal = 0;
633926deccbSFrançois Tigeot 			args.v2.ucFRC = 0;
634926deccbSFrançois Tigeot 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
635926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
636926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
637926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
638926deccbSFrançois Tigeot 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
639926deccbSFrançois Tigeot 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
640926deccbSFrançois Tigeot 						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
641926deccbSFrançois Tigeot 				}
642926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
643926deccbSFrançois Tigeot 					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
644926deccbSFrançois Tigeot 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
645926deccbSFrançois Tigeot 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
646926deccbSFrançois Tigeot 					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
647926deccbSFrançois Tigeot 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
648926deccbSFrançois Tigeot 				}
649926deccbSFrançois Tigeot 			} else {
650926deccbSFrançois Tigeot 				if (dig->linkb)
651926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
652926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
653926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
654926deccbSFrançois Tigeot 			}
655926deccbSFrançois Tigeot 			break;
656926deccbSFrançois Tigeot 		default:
657926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
658926deccbSFrançois Tigeot 			break;
659926deccbSFrançois Tigeot 		}
660926deccbSFrançois Tigeot 		break;
661926deccbSFrançois Tigeot 	default:
662926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
663926deccbSFrançois Tigeot 		break;
664926deccbSFrançois Tigeot 	}
665926deccbSFrançois Tigeot 
666926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
667926deccbSFrançois Tigeot }
668926deccbSFrançois Tigeot 
669926deccbSFrançois Tigeot int
670926deccbSFrançois Tigeot atombios_get_encoder_mode(struct drm_encoder *encoder)
671926deccbSFrançois Tigeot {
672926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
673926deccbSFrançois Tigeot 	struct drm_connector *connector;
674926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector;
675926deccbSFrançois Tigeot 	struct radeon_connector_atom_dig *dig_connector;
676926deccbSFrançois Tigeot 
677926deccbSFrançois Tigeot 	/* dp bridges are always DP */
678926deccbSFrançois Tigeot 	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
679926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_DP;
680926deccbSFrançois Tigeot 
681926deccbSFrançois Tigeot 	/* DVO is always DVO */
682926deccbSFrançois Tigeot 	if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) ||
683926deccbSFrançois Tigeot 	    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
684926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_DVO;
685926deccbSFrançois Tigeot 
686926deccbSFrançois Tigeot 	connector = radeon_get_connector_for_encoder(encoder);
687926deccbSFrançois Tigeot 	/* if we don't have an active device yet, just use one of
688926deccbSFrançois Tigeot 	 * the connectors tied to the encoder.
689926deccbSFrançois Tigeot 	 */
690926deccbSFrançois Tigeot 	if (!connector)
691926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder_init(encoder);
692926deccbSFrançois Tigeot 	radeon_connector = to_radeon_connector(connector);
693926deccbSFrançois Tigeot 
694926deccbSFrançois Tigeot 	switch (connector->connector_type) {
695926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DVII:
696926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
6974cd92098Szrj 		if (radeon_audio != 0) {
6984cd92098Szrj 			if (radeon_connector->use_digital &&
6994cd92098Szrj 			    (radeon_connector->audio == RADEON_AUDIO_ENABLE))
7004cd92098Szrj 				return ATOM_ENCODER_MODE_HDMI;
701c6f73aabSFrançois Tigeot 			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7024cd92098Szrj 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
703926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_HDMI;
704926deccbSFrançois Tigeot 			else if (radeon_connector->use_digital)
705926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_DVI;
706926deccbSFrançois Tigeot 			else
707926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_CRT;
7084cd92098Szrj 		} else if (radeon_connector->use_digital) {
7094cd92098Szrj 			return ATOM_ENCODER_MODE_DVI;
7104cd92098Szrj 		} else {
7114cd92098Szrj 			return ATOM_ENCODER_MODE_CRT;
7124cd92098Szrj 		}
713926deccbSFrançois Tigeot 		break;
714926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DVID:
715926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_HDMIA:
716926deccbSFrançois Tigeot 	default:
7174cd92098Szrj 		if (radeon_audio != 0) {
7184cd92098Szrj 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
7194cd92098Szrj 				return ATOM_ENCODER_MODE_HDMI;
720c6f73aabSFrançois Tigeot 			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7214cd92098Szrj 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
722926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_HDMI;
723926deccbSFrançois Tigeot 			else
724926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_DVI;
7254cd92098Szrj 		} else {
7264cd92098Szrj 			return ATOM_ENCODER_MODE_DVI;
7274cd92098Szrj 		}
728926deccbSFrançois Tigeot 		break;
729926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_LVDS:
730926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_LVDS;
731926deccbSFrançois Tigeot 		break;
732926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DisplayPort:
733926deccbSFrançois Tigeot 		dig_connector = radeon_connector->con_priv;
734926deccbSFrançois Tigeot 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
7354cd92098Szrj 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
736926deccbSFrançois Tigeot 			return ATOM_ENCODER_MODE_DP;
7374cd92098Szrj 		} else if (radeon_audio != 0) {
7384cd92098Szrj 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
7394cd92098Szrj 				return ATOM_ENCODER_MODE_HDMI;
740c6f73aabSFrançois Tigeot 			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7414cd92098Szrj 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
742926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_HDMI;
743926deccbSFrançois Tigeot 			else
744926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_DVI;
7454cd92098Szrj 		} else {
7464cd92098Szrj 			return ATOM_ENCODER_MODE_DVI;
7474cd92098Szrj 		}
748926deccbSFrançois Tigeot 		break;
749926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_eDP:
750926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_DP;
751926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DVIA:
752926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_VGA:
753926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_CRT;
754926deccbSFrançois Tigeot 		break;
755926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_Composite:
756926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_SVIDEO:
757926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_9PinDIN:
758926deccbSFrançois Tigeot 		/* fix me */
759926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_TV;
760926deccbSFrançois Tigeot 		/*return ATOM_ENCODER_MODE_CV;*/
761926deccbSFrançois Tigeot 		break;
762926deccbSFrançois Tigeot 	}
763926deccbSFrançois Tigeot }
764926deccbSFrançois Tigeot 
765926deccbSFrançois Tigeot /*
766926deccbSFrançois Tigeot  * DIG Encoder/Transmitter Setup
767926deccbSFrançois Tigeot  *
768926deccbSFrançois Tigeot  * DCE 3.0/3.1
769926deccbSFrançois Tigeot  * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
770926deccbSFrançois Tigeot  * Supports up to 3 digital outputs
771926deccbSFrançois Tigeot  * - 2 DIG encoder blocks.
772926deccbSFrançois Tigeot  * DIG1 can drive UNIPHY link A or link B
773926deccbSFrançois Tigeot  * DIG2 can drive UNIPHY link B or LVTMA
774926deccbSFrançois Tigeot  *
775926deccbSFrançois Tigeot  * DCE 3.2
776926deccbSFrançois Tigeot  * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
777926deccbSFrançois Tigeot  * Supports up to 5 digital outputs
778926deccbSFrançois Tigeot  * - 2 DIG encoder blocks.
779926deccbSFrançois Tigeot  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
780926deccbSFrançois Tigeot  *
781926deccbSFrançois Tigeot  * DCE 4.0/5.0/6.0
782926deccbSFrançois Tigeot  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
783926deccbSFrançois Tigeot  * Supports up to 6 digital outputs
784926deccbSFrançois Tigeot  * - 6 DIG encoder blocks.
785926deccbSFrançois Tigeot  * - DIG to PHY mapping is hardcoded
786926deccbSFrançois Tigeot  * DIG1 drives UNIPHY0 link A, A+B
787926deccbSFrançois Tigeot  * DIG2 drives UNIPHY0 link B
788926deccbSFrançois Tigeot  * DIG3 drives UNIPHY1 link A, A+B
789926deccbSFrançois Tigeot  * DIG4 drives UNIPHY1 link B
790926deccbSFrançois Tigeot  * DIG5 drives UNIPHY2 link A, A+B
791926deccbSFrançois Tigeot  * DIG6 drives UNIPHY2 link B
792926deccbSFrançois Tigeot  *
793926deccbSFrançois Tigeot  * DCE 4.1
794926deccbSFrançois Tigeot  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
795926deccbSFrançois Tigeot  * Supports up to 6 digital outputs
796926deccbSFrançois Tigeot  * - 2 DIG encoder blocks.
797926deccbSFrançois Tigeot  * llano
798926deccbSFrançois Tigeot  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
799926deccbSFrançois Tigeot  * ontario
800926deccbSFrançois Tigeot  * DIG1 drives UNIPHY0/1/2 link A
801926deccbSFrançois Tigeot  * DIG2 drives UNIPHY0/1/2 link B
802926deccbSFrançois Tigeot  *
803926deccbSFrançois Tigeot  * Routing
804926deccbSFrançois Tigeot  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
805926deccbSFrançois Tigeot  * Examples:
806926deccbSFrançois Tigeot  * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
807926deccbSFrançois Tigeot  * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
808926deccbSFrançois Tigeot  * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
809926deccbSFrançois Tigeot  * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
810926deccbSFrançois Tigeot  */
811926deccbSFrançois Tigeot 
812926deccbSFrançois Tigeot union dig_encoder_control {
813926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
814926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
815926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
816926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
817926deccbSFrançois Tigeot };
818926deccbSFrançois Tigeot 
819926deccbSFrançois Tigeot void
820ee479021SImre Vadász atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
821926deccbSFrançois Tigeot {
822926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
823926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
824926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
825926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
826926deccbSFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
827926deccbSFrançois Tigeot 	union dig_encoder_control args;
828926deccbSFrançois Tigeot 	int index = 0;
829926deccbSFrançois Tigeot 	uint8_t frev, crev;
830926deccbSFrançois Tigeot 	int dp_clock = 0;
831926deccbSFrançois Tigeot 	int dp_lane_count = 0;
832926deccbSFrançois Tigeot 	int hpd_id = RADEON_HPD_NONE;
833926deccbSFrançois Tigeot 
834926deccbSFrançois Tigeot 	if (connector) {
835926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
836926deccbSFrançois Tigeot 		struct radeon_connector_atom_dig *dig_connector =
837926deccbSFrançois Tigeot 			radeon_connector->con_priv;
838926deccbSFrançois Tigeot 
839926deccbSFrançois Tigeot 		dp_clock = dig_connector->dp_clock;
840926deccbSFrançois Tigeot 		dp_lane_count = dig_connector->dp_lane_count;
841926deccbSFrançois Tigeot 		hpd_id = radeon_connector->hpd.hpd;
842926deccbSFrançois Tigeot 	}
843926deccbSFrançois Tigeot 
844926deccbSFrançois Tigeot 	/* no dig encoder assigned */
845926deccbSFrançois Tigeot 	if (dig->dig_encoder == -1)
846926deccbSFrançois Tigeot 		return;
847926deccbSFrançois Tigeot 
848926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
849926deccbSFrançois Tigeot 
850926deccbSFrançois Tigeot 	if (ASIC_IS_DCE4(rdev))
851926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
852926deccbSFrançois Tigeot 	else {
853926deccbSFrançois Tigeot 		if (dig->dig_encoder)
854926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
855926deccbSFrançois Tigeot 		else
856926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
857926deccbSFrançois Tigeot 	}
858926deccbSFrançois Tigeot 
859926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
860926deccbSFrançois Tigeot 		return;
861926deccbSFrançois Tigeot 
862926deccbSFrançois Tigeot 	switch (frev) {
863926deccbSFrançois Tigeot 	case 1:
864926deccbSFrançois Tigeot 		switch (crev) {
865926deccbSFrançois Tigeot 		case 1:
866926deccbSFrançois Tigeot 			args.v1.ucAction = action;
867926deccbSFrançois Tigeot 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
868926deccbSFrançois Tigeot 			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
869926deccbSFrançois Tigeot 				args.v3.ucPanelMode = panel_mode;
870926deccbSFrançois Tigeot 			else
871926deccbSFrançois Tigeot 				args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
872926deccbSFrançois Tigeot 
873926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
874926deccbSFrançois Tigeot 				args.v1.ucLaneNum = dp_lane_count;
875926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
876926deccbSFrançois Tigeot 				args.v1.ucLaneNum = 8;
877926deccbSFrançois Tigeot 			else
878926deccbSFrançois Tigeot 				args.v1.ucLaneNum = 4;
879926deccbSFrançois Tigeot 
880ee479021SImre Vadász 			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
881ee479021SImre Vadász 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
882926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
883926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
884926deccbSFrançois Tigeot 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
885926deccbSFrançois Tigeot 				break;
886926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
887926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
888926deccbSFrançois Tigeot 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
889926deccbSFrançois Tigeot 				break;
890926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
891926deccbSFrançois Tigeot 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
892926deccbSFrançois Tigeot 				break;
893926deccbSFrançois Tigeot 			}
894926deccbSFrançois Tigeot 			if (dig->linkb)
895926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
896926deccbSFrançois Tigeot 			else
897926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
898926deccbSFrançois Tigeot 			break;
899926deccbSFrançois Tigeot 		case 2:
900926deccbSFrançois Tigeot 		case 3:
901926deccbSFrançois Tigeot 			args.v3.ucAction = action;
902926deccbSFrançois Tigeot 			args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
903926deccbSFrançois Tigeot 			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
904926deccbSFrançois Tigeot 				args.v3.ucPanelMode = panel_mode;
905926deccbSFrançois Tigeot 			else
906926deccbSFrançois Tigeot 				args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
907926deccbSFrançois Tigeot 
908926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode))
909926deccbSFrançois Tigeot 				args.v3.ucLaneNum = dp_lane_count;
910926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
911926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 8;
912926deccbSFrançois Tigeot 			else
913926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 4;
914926deccbSFrançois Tigeot 
915926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
916926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
917926deccbSFrançois Tigeot 			args.v3.acConfig.ucDigSel = dig->dig_encoder;
918926deccbSFrançois Tigeot 			args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
919926deccbSFrançois Tigeot 			break;
920926deccbSFrançois Tigeot 		case 4:
921926deccbSFrançois Tigeot 			args.v4.ucAction = action;
922926deccbSFrançois Tigeot 			args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
923926deccbSFrançois Tigeot 			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
924926deccbSFrançois Tigeot 				args.v4.ucPanelMode = panel_mode;
925926deccbSFrançois Tigeot 			else
926926deccbSFrançois Tigeot 				args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
927926deccbSFrançois Tigeot 
928926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode))
929926deccbSFrançois Tigeot 				args.v4.ucLaneNum = dp_lane_count;
930926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
931926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 8;
932926deccbSFrançois Tigeot 			else
933926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 4;
934926deccbSFrançois Tigeot 
935926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) {
93657e252bfSMichael Neumann 				if (dp_clock == 540000)
937926deccbSFrançois Tigeot 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
93857e252bfSMichael Neumann 				else if (dp_clock == 324000)
93957e252bfSMichael Neumann 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ;
94057e252bfSMichael Neumann 				else if (dp_clock == 270000)
94157e252bfSMichael Neumann 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
94257e252bfSMichael Neumann 				else
94357e252bfSMichael Neumann 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
944926deccbSFrançois Tigeot 			}
945926deccbSFrançois Tigeot 			args.v4.acConfig.ucDigSel = dig->dig_encoder;
946926deccbSFrançois Tigeot 			args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
947926deccbSFrançois Tigeot 			if (hpd_id == RADEON_HPD_NONE)
948926deccbSFrançois Tigeot 				args.v4.ucHPD_ID = 0;
949926deccbSFrançois Tigeot 			else
950926deccbSFrançois Tigeot 				args.v4.ucHPD_ID = hpd_id + 1;
951926deccbSFrançois Tigeot 			break;
952926deccbSFrançois Tigeot 		default:
953926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
954926deccbSFrançois Tigeot 			break;
955926deccbSFrançois Tigeot 		}
956926deccbSFrançois Tigeot 		break;
957926deccbSFrançois Tigeot 	default:
958926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
959926deccbSFrançois Tigeot 		break;
960926deccbSFrançois Tigeot 	}
961926deccbSFrançois Tigeot 
962926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
963926deccbSFrançois Tigeot 
964926deccbSFrançois Tigeot }
965926deccbSFrançois Tigeot 
966926deccbSFrançois Tigeot union dig_transmitter_control {
967926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
968926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
969926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
970926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
971926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
972926deccbSFrançois Tigeot };
973926deccbSFrançois Tigeot 
974926deccbSFrançois Tigeot void
975ee479021SImre Vadász atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
976926deccbSFrançois Tigeot {
977926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
978926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
979926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
980926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
981926deccbSFrançois Tigeot 	struct drm_connector *connector;
982926deccbSFrançois Tigeot 	union dig_transmitter_control args;
983926deccbSFrançois Tigeot 	int index = 0;
984926deccbSFrançois Tigeot 	uint8_t frev, crev;
985926deccbSFrançois Tigeot 	bool is_dp = false;
986926deccbSFrançois Tigeot 	int pll_id = 0;
987926deccbSFrançois Tigeot 	int dp_clock = 0;
988926deccbSFrançois Tigeot 	int dp_lane_count = 0;
989926deccbSFrançois Tigeot 	int connector_object_id = 0;
990926deccbSFrançois Tigeot 	int igp_lane_info = 0;
991926deccbSFrançois Tigeot 	int dig_encoder = dig->dig_encoder;
992926deccbSFrançois Tigeot 	int hpd_id = RADEON_HPD_NONE;
993926deccbSFrançois Tigeot 
994926deccbSFrançois Tigeot 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
995926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder_init(encoder);
996926deccbSFrançois Tigeot 		/* just needed to avoid bailing in the encoder check.  the encoder
997926deccbSFrançois Tigeot 		 * isn't used for init
998926deccbSFrançois Tigeot 		 */
999926deccbSFrançois Tigeot 		dig_encoder = 0;
1000926deccbSFrançois Tigeot 	} else
1001926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder(encoder);
1002926deccbSFrançois Tigeot 
1003926deccbSFrançois Tigeot 	if (connector) {
1004926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1005926deccbSFrançois Tigeot 		struct radeon_connector_atom_dig *dig_connector =
1006926deccbSFrançois Tigeot 			radeon_connector->con_priv;
1007926deccbSFrançois Tigeot 
1008926deccbSFrançois Tigeot 		hpd_id = radeon_connector->hpd.hpd;
1009926deccbSFrançois Tigeot 		dp_clock = dig_connector->dp_clock;
1010926deccbSFrançois Tigeot 		dp_lane_count = dig_connector->dp_lane_count;
1011926deccbSFrançois Tigeot 		connector_object_id =
1012926deccbSFrançois Tigeot 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1013926deccbSFrançois Tigeot 		igp_lane_info = dig_connector->igp_lane_info;
1014926deccbSFrançois Tigeot 	}
1015926deccbSFrançois Tigeot 
1016926deccbSFrançois Tigeot 	if (encoder->crtc) {
1017926deccbSFrançois Tigeot 		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1018926deccbSFrançois Tigeot 		pll_id = radeon_crtc->pll_id;
1019926deccbSFrançois Tigeot 	}
1020926deccbSFrançois Tigeot 
1021926deccbSFrançois Tigeot 	/* no dig encoder assigned */
1022926deccbSFrançois Tigeot 	if (dig_encoder == -1)
1023926deccbSFrançois Tigeot 		return;
1024926deccbSFrançois Tigeot 
1025926deccbSFrançois Tigeot 	if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
1026926deccbSFrançois Tigeot 		is_dp = true;
1027926deccbSFrançois Tigeot 
1028926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1029926deccbSFrançois Tigeot 
1030926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
1031926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1032926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1033926deccbSFrançois Tigeot 		break;
1034926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1035926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1036926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
103757e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1038926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1039926deccbSFrançois Tigeot 		break;
1040926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1041926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
1042926deccbSFrançois Tigeot 		break;
1043926deccbSFrançois Tigeot 	}
1044926deccbSFrançois Tigeot 
1045926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1046926deccbSFrançois Tigeot 		return;
1047926deccbSFrançois Tigeot 
1048926deccbSFrançois Tigeot 	switch (frev) {
1049926deccbSFrançois Tigeot 	case 1:
1050926deccbSFrançois Tigeot 		switch (crev) {
1051926deccbSFrançois Tigeot 		case 1:
1052926deccbSFrançois Tigeot 			args.v1.ucAction = action;
1053926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1054926deccbSFrançois Tigeot 				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
1055926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1056926deccbSFrançois Tigeot 				args.v1.asMode.ucLaneSel = lane_num;
1057926deccbSFrançois Tigeot 				args.v1.asMode.ucLaneSet = lane_set;
1058926deccbSFrançois Tigeot 			} else {
1059926deccbSFrançois Tigeot 				if (is_dp)
1060926deccbSFrançois Tigeot 					args.v1.usPixelClock = cpu_to_le16(dp_clock / 10);
1061926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1062926deccbSFrançois Tigeot 					args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1063926deccbSFrançois Tigeot 				else
1064926deccbSFrançois Tigeot 					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1065926deccbSFrançois Tigeot 			}
1066926deccbSFrançois Tigeot 
1067926deccbSFrançois Tigeot 			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1068926deccbSFrançois Tigeot 
1069926deccbSFrançois Tigeot 			if (dig_encoder)
1070926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
1071926deccbSFrançois Tigeot 			else
1072926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1073926deccbSFrançois Tigeot 
1074926deccbSFrançois Tigeot 			if ((rdev->flags & RADEON_IS_IGP) &&
1075926deccbSFrançois Tigeot 			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1076926deccbSFrançois Tigeot 				if (is_dp ||
1077926deccbSFrançois Tigeot 				    !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
1078926deccbSFrançois Tigeot 					if (igp_lane_info & 0x1)
1079926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
1080926deccbSFrançois Tigeot 					else if (igp_lane_info & 0x2)
1081926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
1082926deccbSFrançois Tigeot 					else if (igp_lane_info & 0x4)
1083926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
1084926deccbSFrançois Tigeot 					else if (igp_lane_info & 0x8)
1085926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1086926deccbSFrançois Tigeot 				} else {
1087926deccbSFrançois Tigeot 					if (igp_lane_info & 0x3)
1088926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
1089926deccbSFrançois Tigeot 					else if (igp_lane_info & 0xc)
1090926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1091926deccbSFrançois Tigeot 				}
1092926deccbSFrançois Tigeot 			}
1093926deccbSFrançois Tigeot 
1094926deccbSFrançois Tigeot 			if (dig->linkb)
1095926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
1096926deccbSFrançois Tigeot 			else
1097926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
1098926deccbSFrançois Tigeot 
1099926deccbSFrançois Tigeot 			if (is_dp)
1100926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1101926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1102926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1103926deccbSFrançois Tigeot 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1104926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1105926deccbSFrançois Tigeot 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1106926deccbSFrançois Tigeot 			}
1107926deccbSFrançois Tigeot 			break;
1108926deccbSFrançois Tigeot 		case 2:
1109926deccbSFrançois Tigeot 			args.v2.ucAction = action;
1110926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1111926deccbSFrançois Tigeot 				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
1112926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1113926deccbSFrançois Tigeot 				args.v2.asMode.ucLaneSel = lane_num;
1114926deccbSFrançois Tigeot 				args.v2.asMode.ucLaneSet = lane_set;
1115926deccbSFrançois Tigeot 			} else {
1116926deccbSFrançois Tigeot 				if (is_dp)
1117926deccbSFrançois Tigeot 					args.v2.usPixelClock = cpu_to_le16(dp_clock / 10);
1118926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1119926deccbSFrançois Tigeot 					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1120926deccbSFrançois Tigeot 				else
1121926deccbSFrançois Tigeot 					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1122926deccbSFrançois Tigeot 			}
1123926deccbSFrançois Tigeot 
1124926deccbSFrançois Tigeot 			args.v2.acConfig.ucEncoderSel = dig_encoder;
1125926deccbSFrançois Tigeot 			if (dig->linkb)
1126926deccbSFrançois Tigeot 				args.v2.acConfig.ucLinkSel = 1;
1127926deccbSFrançois Tigeot 
1128926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1129926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1130926deccbSFrançois Tigeot 				args.v2.acConfig.ucTransmitterSel = 0;
1131926deccbSFrançois Tigeot 				break;
1132926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1133926deccbSFrançois Tigeot 				args.v2.acConfig.ucTransmitterSel = 1;
1134926deccbSFrançois Tigeot 				break;
1135926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1136926deccbSFrançois Tigeot 				args.v2.acConfig.ucTransmitterSel = 2;
1137926deccbSFrançois Tigeot 				break;
1138926deccbSFrançois Tigeot 			}
1139926deccbSFrançois Tigeot 
1140926deccbSFrançois Tigeot 			if (is_dp) {
1141926deccbSFrançois Tigeot 				args.v2.acConfig.fCoherentMode = 1;
1142926deccbSFrançois Tigeot 				args.v2.acConfig.fDPConnector = 1;
1143926deccbSFrançois Tigeot 			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1144926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1145926deccbSFrançois Tigeot 					args.v2.acConfig.fCoherentMode = 1;
1146926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1147926deccbSFrançois Tigeot 					args.v2.acConfig.fDualLinkConnector = 1;
1148926deccbSFrançois Tigeot 			}
1149926deccbSFrançois Tigeot 			break;
1150926deccbSFrançois Tigeot 		case 3:
1151926deccbSFrançois Tigeot 			args.v3.ucAction = action;
1152926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1153926deccbSFrançois Tigeot 				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
1154926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1155926deccbSFrançois Tigeot 				args.v3.asMode.ucLaneSel = lane_num;
1156926deccbSFrançois Tigeot 				args.v3.asMode.ucLaneSet = lane_set;
1157926deccbSFrançois Tigeot 			} else {
1158926deccbSFrançois Tigeot 				if (is_dp)
1159926deccbSFrançois Tigeot 					args.v3.usPixelClock = cpu_to_le16(dp_clock / 10);
1160926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1161926deccbSFrançois Tigeot 					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1162926deccbSFrançois Tigeot 				else
1163926deccbSFrançois Tigeot 					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1164926deccbSFrançois Tigeot 			}
1165926deccbSFrançois Tigeot 
1166926deccbSFrançois Tigeot 			if (is_dp)
1167926deccbSFrançois Tigeot 				args.v3.ucLaneNum = dp_lane_count;
1168926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1169926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 8;
1170926deccbSFrançois Tigeot 			else
1171926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 4;
1172926deccbSFrançois Tigeot 
1173926deccbSFrançois Tigeot 			if (dig->linkb)
1174926deccbSFrançois Tigeot 				args.v3.acConfig.ucLinkSel = 1;
1175926deccbSFrançois Tigeot 			if (dig_encoder & 1)
1176926deccbSFrançois Tigeot 				args.v3.acConfig.ucEncoderSel = 1;
1177926deccbSFrançois Tigeot 
1178926deccbSFrançois Tigeot 			/* Select the PLL for the PHY
1179926deccbSFrançois Tigeot 			 * DP PHY should be clocked from external src if there is
1180926deccbSFrançois Tigeot 			 * one.
1181926deccbSFrançois Tigeot 			 */
1182926deccbSFrançois Tigeot 			/* On DCE4, if there is an external clock, it generates the DP ref clock */
1183926deccbSFrançois Tigeot 			if (is_dp && rdev->clock.dp_extclk)
1184926deccbSFrançois Tigeot 				args.v3.acConfig.ucRefClkSource = 2; /* external src */
1185926deccbSFrançois Tigeot 			else
1186926deccbSFrançois Tigeot 				args.v3.acConfig.ucRefClkSource = pll_id;
1187926deccbSFrançois Tigeot 
1188926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1189926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1190926deccbSFrançois Tigeot 				args.v3.acConfig.ucTransmitterSel = 0;
1191926deccbSFrançois Tigeot 				break;
1192926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1193926deccbSFrançois Tigeot 				args.v3.acConfig.ucTransmitterSel = 1;
1194926deccbSFrançois Tigeot 				break;
1195926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1196926deccbSFrançois Tigeot 				args.v3.acConfig.ucTransmitterSel = 2;
1197926deccbSFrançois Tigeot 				break;
1198926deccbSFrançois Tigeot 			}
1199926deccbSFrançois Tigeot 
1200926deccbSFrançois Tigeot 			if (is_dp)
1201926deccbSFrançois Tigeot 				args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
1202926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1203926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1204926deccbSFrançois Tigeot 					args.v3.acConfig.fCoherentMode = 1;
1205926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1206926deccbSFrançois Tigeot 					args.v3.acConfig.fDualLinkConnector = 1;
1207926deccbSFrançois Tigeot 			}
1208926deccbSFrançois Tigeot 			break;
1209926deccbSFrançois Tigeot 		case 4:
1210926deccbSFrançois Tigeot 			args.v4.ucAction = action;
1211926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1212926deccbSFrançois Tigeot 				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
1213926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1214926deccbSFrançois Tigeot 				args.v4.asMode.ucLaneSel = lane_num;
1215926deccbSFrançois Tigeot 				args.v4.asMode.ucLaneSet = lane_set;
1216926deccbSFrançois Tigeot 			} else {
1217926deccbSFrançois Tigeot 				if (is_dp)
1218926deccbSFrançois Tigeot 					args.v4.usPixelClock = cpu_to_le16(dp_clock / 10);
1219926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1220926deccbSFrançois Tigeot 					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1221926deccbSFrançois Tigeot 				else
1222926deccbSFrançois Tigeot 					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1223926deccbSFrançois Tigeot 			}
1224926deccbSFrançois Tigeot 
1225926deccbSFrançois Tigeot 			if (is_dp)
1226926deccbSFrançois Tigeot 				args.v4.ucLaneNum = dp_lane_count;
1227926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1228926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 8;
1229926deccbSFrançois Tigeot 			else
1230926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 4;
1231926deccbSFrançois Tigeot 
1232926deccbSFrançois Tigeot 			if (dig->linkb)
1233926deccbSFrançois Tigeot 				args.v4.acConfig.ucLinkSel = 1;
1234926deccbSFrançois Tigeot 			if (dig_encoder & 1)
1235926deccbSFrançois Tigeot 				args.v4.acConfig.ucEncoderSel = 1;
1236926deccbSFrançois Tigeot 
1237926deccbSFrançois Tigeot 			/* Select the PLL for the PHY
1238926deccbSFrançois Tigeot 			 * DP PHY should be clocked from external src if there is
1239926deccbSFrançois Tigeot 			 * one.
1240926deccbSFrançois Tigeot 			 */
1241926deccbSFrançois Tigeot 			/* On DCE5 DCPLL usually generates the DP ref clock */
1242926deccbSFrançois Tigeot 			if (is_dp) {
1243926deccbSFrançois Tigeot 				if (rdev->clock.dp_extclk)
1244926deccbSFrançois Tigeot 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
1245926deccbSFrançois Tigeot 				else
1246926deccbSFrançois Tigeot 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
1247926deccbSFrançois Tigeot 			} else
1248926deccbSFrançois Tigeot 				args.v4.acConfig.ucRefClkSource = pll_id;
1249926deccbSFrançois Tigeot 
1250926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1251926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1252926deccbSFrançois Tigeot 				args.v4.acConfig.ucTransmitterSel = 0;
1253926deccbSFrançois Tigeot 				break;
1254926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1255926deccbSFrançois Tigeot 				args.v4.acConfig.ucTransmitterSel = 1;
1256926deccbSFrançois Tigeot 				break;
1257926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1258926deccbSFrançois Tigeot 				args.v4.acConfig.ucTransmitterSel = 2;
1259926deccbSFrançois Tigeot 				break;
1260926deccbSFrançois Tigeot 			}
1261926deccbSFrançois Tigeot 
1262926deccbSFrançois Tigeot 			if (is_dp)
1263926deccbSFrançois Tigeot 				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
1264926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1265926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1266926deccbSFrançois Tigeot 					args.v4.acConfig.fCoherentMode = 1;
1267926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1268926deccbSFrançois Tigeot 					args.v4.acConfig.fDualLinkConnector = 1;
1269926deccbSFrançois Tigeot 			}
1270926deccbSFrançois Tigeot 			break;
1271926deccbSFrançois Tigeot 		case 5:
1272926deccbSFrançois Tigeot 			args.v5.ucAction = action;
1273926deccbSFrançois Tigeot 			if (is_dp)
1274926deccbSFrançois Tigeot 				args.v5.usSymClock = cpu_to_le16(dp_clock / 10);
1275926deccbSFrançois Tigeot 			else
1276926deccbSFrançois Tigeot 				args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1277926deccbSFrançois Tigeot 
1278926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1279926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1280926deccbSFrançois Tigeot 				if (dig->linkb)
1281926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1282926deccbSFrançois Tigeot 				else
1283926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1284926deccbSFrançois Tigeot 				break;
1285926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1286926deccbSFrançois Tigeot 				if (dig->linkb)
1287926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1288926deccbSFrançois Tigeot 				else
1289926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1290926deccbSFrançois Tigeot 				break;
1291926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1292926deccbSFrançois Tigeot 				if (dig->linkb)
1293926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1294926deccbSFrançois Tigeot 				else
1295926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1296926deccbSFrançois Tigeot 				break;
129757e252bfSMichael Neumann 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
129857e252bfSMichael Neumann 				args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG;
129957e252bfSMichael Neumann 				break;
1300926deccbSFrançois Tigeot 			}
1301926deccbSFrançois Tigeot 			if (is_dp)
1302926deccbSFrançois Tigeot 				args.v5.ucLaneNum = dp_lane_count;
1303c6f73aabSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1304926deccbSFrançois Tigeot 				args.v5.ucLaneNum = 8;
1305926deccbSFrançois Tigeot 			else
1306926deccbSFrançois Tigeot 				args.v5.ucLaneNum = 4;
1307926deccbSFrançois Tigeot 			args.v5.ucConnObjId = connector_object_id;
1308926deccbSFrançois Tigeot 			args.v5.ucDigMode = atombios_get_encoder_mode(encoder);
1309926deccbSFrançois Tigeot 
1310926deccbSFrançois Tigeot 			if (is_dp && rdev->clock.dp_extclk)
1311926deccbSFrançois Tigeot 				args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK;
1312926deccbSFrançois Tigeot 			else
1313926deccbSFrançois Tigeot 				args.v5.asConfig.ucPhyClkSrcId = pll_id;
1314926deccbSFrançois Tigeot 
1315926deccbSFrançois Tigeot 			if (is_dp)
1316926deccbSFrançois Tigeot 				args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */
1317926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1318926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1319926deccbSFrançois Tigeot 					args.v5.asConfig.ucCoherentMode = 1;
1320926deccbSFrançois Tigeot 			}
1321926deccbSFrançois Tigeot 			if (hpd_id == RADEON_HPD_NONE)
1322926deccbSFrançois Tigeot 				args.v5.asConfig.ucHPDSel = 0;
1323926deccbSFrançois Tigeot 			else
1324926deccbSFrançois Tigeot 				args.v5.asConfig.ucHPDSel = hpd_id + 1;
1325ee479021SImre Vadász 			args.v5.ucDigEncoderSel = 1 << dig_encoder;
1326926deccbSFrançois Tigeot 			args.v5.ucDPLaneSet = lane_set;
1327926deccbSFrançois Tigeot 			break;
1328926deccbSFrançois Tigeot 		default:
1329926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1330926deccbSFrançois Tigeot 			break;
1331926deccbSFrançois Tigeot 		}
1332926deccbSFrançois Tigeot 		break;
1333926deccbSFrançois Tigeot 	default:
1334926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1335926deccbSFrançois Tigeot 		break;
1336926deccbSFrançois Tigeot 	}
1337926deccbSFrançois Tigeot 
1338926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1339926deccbSFrançois Tigeot }
1340926deccbSFrançois Tigeot 
1341926deccbSFrançois Tigeot bool
1342926deccbSFrançois Tigeot atombios_set_edp_panel_power(struct drm_connector *connector, int action)
1343926deccbSFrançois Tigeot {
1344926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1345926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_connector->base.dev;
1346926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1347926deccbSFrançois Tigeot 	union dig_transmitter_control args;
1348926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1349926deccbSFrançois Tigeot 	uint8_t frev, crev;
1350926deccbSFrançois Tigeot 
1351926deccbSFrançois Tigeot 	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
1352926deccbSFrançois Tigeot 		goto done;
1353926deccbSFrançois Tigeot 
1354926deccbSFrançois Tigeot 	if (!ASIC_IS_DCE4(rdev))
1355926deccbSFrançois Tigeot 		goto done;
1356926deccbSFrançois Tigeot 
1357926deccbSFrançois Tigeot 	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
1358926deccbSFrançois Tigeot 	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
1359926deccbSFrançois Tigeot 		goto done;
1360926deccbSFrançois Tigeot 
1361926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1362926deccbSFrançois Tigeot 		goto done;
1363926deccbSFrançois Tigeot 
1364926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1365926deccbSFrançois Tigeot 
1366926deccbSFrançois Tigeot 	args.v1.ucAction = action;
1367926deccbSFrançois Tigeot 
1368926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1369926deccbSFrançois Tigeot 
1370926deccbSFrançois Tigeot 	/* wait for the panel to power up */
1371926deccbSFrançois Tigeot 	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
1372926deccbSFrançois Tigeot 		int i;
1373926deccbSFrançois Tigeot 
1374926deccbSFrançois Tigeot 		for (i = 0; i < 300; i++) {
1375926deccbSFrançois Tigeot 			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
1376926deccbSFrançois Tigeot 				return true;
1377c4ef309bSzrj 			mdelay(1);
1378926deccbSFrançois Tigeot 		}
1379926deccbSFrançois Tigeot 		return false;
1380926deccbSFrançois Tigeot 	}
1381926deccbSFrançois Tigeot done:
1382926deccbSFrançois Tigeot 	return true;
1383926deccbSFrançois Tigeot }
1384926deccbSFrançois Tigeot 
1385926deccbSFrançois Tigeot union external_encoder_control {
1386926deccbSFrançois Tigeot 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
1387926deccbSFrançois Tigeot 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
1388926deccbSFrançois Tigeot };
1389926deccbSFrançois Tigeot 
1390926deccbSFrançois Tigeot static void
1391926deccbSFrançois Tigeot atombios_external_encoder_setup(struct drm_encoder *encoder,
1392926deccbSFrançois Tigeot 				struct drm_encoder *ext_encoder,
1393926deccbSFrançois Tigeot 				int action)
1394926deccbSFrançois Tigeot {
1395926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1396926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1397926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1398926deccbSFrançois Tigeot 	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
1399926deccbSFrançois Tigeot 	union external_encoder_control args;
1400926deccbSFrançois Tigeot 	struct drm_connector *connector;
1401926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
1402926deccbSFrançois Tigeot 	u8 frev, crev;
1403926deccbSFrançois Tigeot 	int dp_clock = 0;
1404926deccbSFrançois Tigeot 	int dp_lane_count = 0;
1405926deccbSFrançois Tigeot 	int connector_object_id = 0;
1406926deccbSFrançois Tigeot 	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
1407926deccbSFrançois Tigeot 
1408926deccbSFrançois Tigeot 	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1409926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder_init(encoder);
1410926deccbSFrançois Tigeot 	else
1411926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder(encoder);
1412926deccbSFrançois Tigeot 
1413926deccbSFrançois Tigeot 	if (connector) {
1414926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1415926deccbSFrançois Tigeot 		struct radeon_connector_atom_dig *dig_connector =
1416926deccbSFrançois Tigeot 			radeon_connector->con_priv;
1417926deccbSFrançois Tigeot 
1418926deccbSFrançois Tigeot 		dp_clock = dig_connector->dp_clock;
1419926deccbSFrançois Tigeot 		dp_lane_count = dig_connector->dp_lane_count;
1420926deccbSFrançois Tigeot 		connector_object_id =
1421926deccbSFrançois Tigeot 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1422926deccbSFrançois Tigeot 	}
1423926deccbSFrançois Tigeot 
1424926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1425926deccbSFrançois Tigeot 
1426926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1427926deccbSFrançois Tigeot 		return;
1428926deccbSFrançois Tigeot 
1429926deccbSFrançois Tigeot 	switch (frev) {
1430926deccbSFrançois Tigeot 	case 1:
1431926deccbSFrançois Tigeot 		/* no params on frev 1 */
1432926deccbSFrançois Tigeot 		break;
1433926deccbSFrançois Tigeot 	case 2:
1434926deccbSFrançois Tigeot 		switch (crev) {
1435926deccbSFrançois Tigeot 		case 1:
1436926deccbSFrançois Tigeot 		case 2:
1437926deccbSFrançois Tigeot 			args.v1.sDigEncoder.ucAction = action;
1438926deccbSFrançois Tigeot 			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1439926deccbSFrançois Tigeot 			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1440926deccbSFrançois Tigeot 
1441926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
1442926deccbSFrançois Tigeot 				if (dp_clock == 270000)
1443926deccbSFrançois Tigeot 					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
1444926deccbSFrançois Tigeot 				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
1445926deccbSFrançois Tigeot 			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1446926deccbSFrançois Tigeot 				args.v1.sDigEncoder.ucLaneNum = 8;
1447926deccbSFrançois Tigeot 			else
1448926deccbSFrançois Tigeot 				args.v1.sDigEncoder.ucLaneNum = 4;
1449926deccbSFrançois Tigeot 			break;
1450926deccbSFrançois Tigeot 		case 3:
1451926deccbSFrançois Tigeot 			args.v3.sExtEncoder.ucAction = action;
1452926deccbSFrançois Tigeot 			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1453926deccbSFrançois Tigeot 				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
1454926deccbSFrançois Tigeot 			else
1455926deccbSFrançois Tigeot 				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1456926deccbSFrançois Tigeot 			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1457926deccbSFrançois Tigeot 
1458926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
1459926deccbSFrançois Tigeot 				if (dp_clock == 270000)
1460926deccbSFrançois Tigeot 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1461926deccbSFrançois Tigeot 				else if (dp_clock == 540000)
1462926deccbSFrançois Tigeot 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1463926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
1464926deccbSFrançois Tigeot 			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1465926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucLaneNum = 8;
1466926deccbSFrançois Tigeot 			else
1467926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucLaneNum = 4;
1468926deccbSFrançois Tigeot 			switch (ext_enum) {
1469926deccbSFrançois Tigeot 			case GRAPH_OBJECT_ENUM_ID1:
1470926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1471926deccbSFrançois Tigeot 				break;
1472926deccbSFrançois Tigeot 			case GRAPH_OBJECT_ENUM_ID2:
1473926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1474926deccbSFrançois Tigeot 				break;
1475926deccbSFrançois Tigeot 			case GRAPH_OBJECT_ENUM_ID3:
1476926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1477926deccbSFrançois Tigeot 				break;
1478926deccbSFrançois Tigeot 			}
1479926deccbSFrançois Tigeot 			args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder);
1480926deccbSFrançois Tigeot 			break;
1481926deccbSFrançois Tigeot 		default:
1482926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1483926deccbSFrançois Tigeot 			return;
1484926deccbSFrançois Tigeot 		}
1485926deccbSFrançois Tigeot 		break;
1486926deccbSFrançois Tigeot 	default:
1487926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1488926deccbSFrançois Tigeot 		return;
1489926deccbSFrançois Tigeot 	}
1490926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1491926deccbSFrançois Tigeot }
1492926deccbSFrançois Tigeot 
1493926deccbSFrançois Tigeot static void
1494926deccbSFrançois Tigeot atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
1495926deccbSFrançois Tigeot {
1496926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1497926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1498926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1499926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1500926deccbSFrançois Tigeot 	ENABLE_YUV_PS_ALLOCATION args;
1501926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
1502926deccbSFrançois Tigeot 	uint32_t temp, reg;
1503926deccbSFrançois Tigeot 
1504926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1505926deccbSFrançois Tigeot 
1506926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
1507926deccbSFrançois Tigeot 		reg = R600_BIOS_3_SCRATCH;
1508926deccbSFrançois Tigeot 	else
1509926deccbSFrançois Tigeot 		reg = RADEON_BIOS_3_SCRATCH;
1510926deccbSFrançois Tigeot 
1511926deccbSFrançois Tigeot 	/* XXX: fix up scratch reg handling */
1512926deccbSFrançois Tigeot 	temp = RREG32(reg);
1513926deccbSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1514926deccbSFrançois Tigeot 		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
1515926deccbSFrançois Tigeot 			     (radeon_crtc->crtc_id << 18)));
1516926deccbSFrançois Tigeot 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1517926deccbSFrançois Tigeot 		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
1518926deccbSFrançois Tigeot 	else
1519926deccbSFrançois Tigeot 		WREG32(reg, 0);
1520926deccbSFrançois Tigeot 
1521926deccbSFrançois Tigeot 	if (enable)
1522926deccbSFrançois Tigeot 		args.ucEnable = ATOM_ENABLE;
1523926deccbSFrançois Tigeot 	args.ucCRTC = radeon_crtc->crtc_id;
1524926deccbSFrançois Tigeot 
1525926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1526926deccbSFrançois Tigeot 
1527926deccbSFrançois Tigeot 	WREG32(reg, temp);
1528926deccbSFrançois Tigeot }
1529926deccbSFrançois Tigeot 
1530926deccbSFrançois Tigeot static void
1531926deccbSFrançois Tigeot radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
1532926deccbSFrançois Tigeot {
1533926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1534926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1535926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1536926deccbSFrançois Tigeot 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1537926deccbSFrançois Tigeot 	int index = 0;
1538926deccbSFrançois Tigeot 
1539926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1540926deccbSFrançois Tigeot 
1541926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
1542926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1543926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1544926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1545926deccbSFrançois Tigeot 		break;
1546926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1547926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1548926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1549926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1550926deccbSFrançois Tigeot 		break;
1551926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1552926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1553926deccbSFrançois Tigeot 		break;
1554926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1555926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1556926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1557926deccbSFrançois Tigeot 		else
1558926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1559926deccbSFrançois Tigeot 		break;
1560926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1561926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1562926deccbSFrançois Tigeot 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1563926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1564926deccbSFrançois Tigeot 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1565926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1566926deccbSFrançois Tigeot 		else
1567926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1568926deccbSFrançois Tigeot 		break;
1569926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1570926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1571926deccbSFrançois Tigeot 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1572926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1573926deccbSFrançois Tigeot 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1574926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1575926deccbSFrançois Tigeot 		else
1576926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1577926deccbSFrançois Tigeot 		break;
1578926deccbSFrançois Tigeot 	default:
1579926deccbSFrançois Tigeot 		return;
1580926deccbSFrançois Tigeot 	}
1581926deccbSFrançois Tigeot 
1582926deccbSFrançois Tigeot 	switch (mode) {
1583926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_ON:
1584926deccbSFrançois Tigeot 		args.ucAction = ATOM_ENABLE;
1585926deccbSFrançois Tigeot 		/* workaround for DVOOutputControl on some RS690 systems */
1586926deccbSFrançois Tigeot 		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
1587926deccbSFrançois Tigeot 			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
1588926deccbSFrançois Tigeot 			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
1589926deccbSFrançois Tigeot 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1590926deccbSFrançois Tigeot 			WREG32(RADEON_BIOS_3_SCRATCH, reg);
1591926deccbSFrançois Tigeot 		} else
1592926deccbSFrançois Tigeot 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1593926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1594926deccbSFrançois Tigeot 			args.ucAction = ATOM_LCD_BLON;
1595926deccbSFrançois Tigeot 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1596926deccbSFrançois Tigeot 		}
1597926deccbSFrançois Tigeot 		break;
1598926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_STANDBY:
1599926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_SUSPEND:
1600926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_OFF:
1601926deccbSFrançois Tigeot 		args.ucAction = ATOM_DISABLE;
1602926deccbSFrançois Tigeot 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1603926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1604926deccbSFrançois Tigeot 			args.ucAction = ATOM_LCD_BLOFF;
1605926deccbSFrançois Tigeot 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1606926deccbSFrançois Tigeot 		}
1607926deccbSFrançois Tigeot 		break;
1608926deccbSFrançois Tigeot 	}
1609926deccbSFrançois Tigeot }
1610926deccbSFrançois Tigeot 
1611926deccbSFrançois Tigeot static void
1612926deccbSFrançois Tigeot radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
1613926deccbSFrançois Tigeot {
1614926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1615926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1616926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1617926deccbSFrançois Tigeot 	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
1618926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1619926deccbSFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1620926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = NULL;
1621926deccbSFrançois Tigeot 	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
1622c6f73aabSFrançois Tigeot 	bool travis_quirk = false;
1623926deccbSFrançois Tigeot 
1624926deccbSFrançois Tigeot 	if (connector) {
1625926deccbSFrançois Tigeot 		radeon_connector = to_radeon_connector(connector);
1626926deccbSFrançois Tigeot 		radeon_dig_connector = radeon_connector->con_priv;
1627c6f73aabSFrançois Tigeot 		if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
1628c6f73aabSFrançois Tigeot 		     ENCODER_OBJECT_ID_TRAVIS) &&
1629c6f73aabSFrançois Tigeot 		    (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
1630c6f73aabSFrançois Tigeot 		    !ASIC_IS_DCE5(rdev))
1631c6f73aabSFrançois Tigeot 			travis_quirk = true;
1632926deccbSFrançois Tigeot 	}
1633926deccbSFrançois Tigeot 
1634926deccbSFrançois Tigeot 	switch (mode) {
1635926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_ON:
1636926deccbSFrançois Tigeot 		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
1637926deccbSFrançois Tigeot 			if (!connector)
1638926deccbSFrançois Tigeot 				dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
1639926deccbSFrançois Tigeot 			else
1640926deccbSFrançois Tigeot 				dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
1641926deccbSFrançois Tigeot 
1642926deccbSFrançois Tigeot 			/* setup and enable the encoder */
1643926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1644926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder,
1645926deccbSFrançois Tigeot 						   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
1646926deccbSFrançois Tigeot 						   dig->panel_mode);
1647926deccbSFrançois Tigeot 			if (ext_encoder) {
1648926deccbSFrançois Tigeot 				if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
1649926deccbSFrançois Tigeot 					atombios_external_encoder_setup(encoder, ext_encoder,
1650926deccbSFrançois Tigeot 									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
1651926deccbSFrançois Tigeot 			}
1652926deccbSFrançois Tigeot 		} else if (ASIC_IS_DCE4(rdev)) {
1653926deccbSFrançois Tigeot 			/* setup and enable the encoder */
1654926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1655926deccbSFrançois Tigeot 		} else {
1656926deccbSFrançois Tigeot 			/* setup and enable the encoder and transmitter */
1657926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
1658926deccbSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
1659926deccbSFrançois Tigeot 		}
1660926deccbSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1661926deccbSFrançois Tigeot 			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1662926deccbSFrançois Tigeot 				atombios_set_edp_panel_power(connector,
1663926deccbSFrançois Tigeot 							     ATOM_TRANSMITTER_ACTION_POWER_ON);
1664926deccbSFrançois Tigeot 				radeon_dig_connector->edp_on = true;
1665926deccbSFrançois Tigeot 			}
1666c6f73aabSFrançois Tigeot 		}
1667c6f73aabSFrançois Tigeot 		/* enable the transmitter */
1668c6f73aabSFrançois Tigeot 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1669c6f73aabSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1670c6f73aabSFrançois Tigeot 			/* DP_SET_POWER_D0 is set in radeon_dp_link_train */
1671926deccbSFrançois Tigeot 			radeon_dp_link_train(encoder, connector);
1672926deccbSFrançois Tigeot 			if (ASIC_IS_DCE4(rdev))
1673926deccbSFrançois Tigeot 				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
1674926deccbSFrançois Tigeot 		}
1675ee479021SImre Vadász 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1676c6f73aabSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder,
1677c6f73aabSFrançois Tigeot 						       ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
1678c6f73aabSFrançois Tigeot 		if (ext_encoder)
1679c6f73aabSFrançois Tigeot 			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
1680926deccbSFrançois Tigeot 		break;
1681926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_STANDBY:
1682926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_SUSPEND:
1683926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_OFF:
1684c6f73aabSFrançois Tigeot 		if (ASIC_IS_DCE4(rdev)) {
1685c6f73aabSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
1686c6f73aabSFrançois Tigeot 				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
1687c6f73aabSFrançois Tigeot 		}
1688c6f73aabSFrançois Tigeot 		if (ext_encoder)
1689c6f73aabSFrançois Tigeot 			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
1690c6f73aabSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1691c6f73aabSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder,
1692c6f73aabSFrançois Tigeot 						       ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1693c6f73aabSFrançois Tigeot 
1694c6f73aabSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
1695c6f73aabSFrançois Tigeot 		    connector && !travis_quirk)
1696c6f73aabSFrançois Tigeot 			radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
1697c6f73aabSFrançois Tigeot 		if (ASIC_IS_DCE4(rdev)) {
1698926deccbSFrançois Tigeot 			/* disable the transmitter */
1699c6f73aabSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder,
1700c6f73aabSFrançois Tigeot 						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1701926deccbSFrançois Tigeot 		} else {
1702926deccbSFrançois Tigeot 			/* disable the encoder and transmitter */
1703c6f73aabSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder,
1704c6f73aabSFrançois Tigeot 						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1705926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
1706926deccbSFrançois Tigeot 		}
1707926deccbSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1708c6f73aabSFrançois Tigeot 			if (travis_quirk)
1709c6f73aabSFrançois Tigeot 				radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
1710926deccbSFrançois Tigeot 			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1711926deccbSFrançois Tigeot 				atombios_set_edp_panel_power(connector,
1712926deccbSFrançois Tigeot 							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
1713926deccbSFrançois Tigeot 				radeon_dig_connector->edp_on = false;
1714926deccbSFrançois Tigeot 			}
1715926deccbSFrançois Tigeot 		}
1716926deccbSFrançois Tigeot 		break;
1717926deccbSFrançois Tigeot 	}
1718926deccbSFrançois Tigeot }
1719926deccbSFrançois Tigeot 
1720926deccbSFrançois Tigeot static void
1721926deccbSFrançois Tigeot radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1722926deccbSFrançois Tigeot {
1723926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1724926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1725926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1726926deccbSFrançois Tigeot 
1727926deccbSFrançois Tigeot 	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
1728926deccbSFrançois Tigeot 		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
1729926deccbSFrançois Tigeot 		  radeon_encoder->active_device);
1730926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
1731926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1732926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1733926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1734926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1735926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1736926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1737926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1738926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1739926deccbSFrançois Tigeot 		radeon_atom_encoder_dpms_avivo(encoder, mode);
1740926deccbSFrançois Tigeot 		break;
1741926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1742926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1743926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
174457e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1745926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1746926deccbSFrançois Tigeot 		radeon_atom_encoder_dpms_dig(encoder, mode);
1747926deccbSFrançois Tigeot 		break;
1748926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1749926deccbSFrançois Tigeot 		if (ASIC_IS_DCE5(rdev)) {
1750926deccbSFrançois Tigeot 			switch (mode) {
1751926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_ON:
1752926deccbSFrançois Tigeot 				atombios_dvo_setup(encoder, ATOM_ENABLE);
1753926deccbSFrançois Tigeot 				break;
1754926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_STANDBY:
1755926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_SUSPEND:
1756926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_OFF:
1757926deccbSFrançois Tigeot 				atombios_dvo_setup(encoder, ATOM_DISABLE);
1758926deccbSFrançois Tigeot 				break;
1759926deccbSFrançois Tigeot 			}
1760926deccbSFrançois Tigeot 		} else if (ASIC_IS_DCE3(rdev))
1761926deccbSFrançois Tigeot 			radeon_atom_encoder_dpms_dig(encoder, mode);
1762926deccbSFrançois Tigeot 		else
1763926deccbSFrançois Tigeot 			radeon_atom_encoder_dpms_avivo(encoder, mode);
1764926deccbSFrançois Tigeot 		break;
1765926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1766926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1767926deccbSFrançois Tigeot 		if (ASIC_IS_DCE5(rdev)) {
1768926deccbSFrançois Tigeot 			switch (mode) {
1769926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_ON:
1770926deccbSFrançois Tigeot 				atombios_dac_setup(encoder, ATOM_ENABLE);
1771926deccbSFrançois Tigeot 				break;
1772926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_STANDBY:
1773926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_SUSPEND:
1774926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_OFF:
1775926deccbSFrançois Tigeot 				atombios_dac_setup(encoder, ATOM_DISABLE);
1776926deccbSFrançois Tigeot 				break;
1777926deccbSFrançois Tigeot 			}
1778926deccbSFrançois Tigeot 		} else
1779926deccbSFrançois Tigeot 			radeon_atom_encoder_dpms_avivo(encoder, mode);
1780926deccbSFrançois Tigeot 		break;
1781926deccbSFrançois Tigeot 	default:
1782926deccbSFrançois Tigeot 		return;
1783926deccbSFrançois Tigeot 	}
1784926deccbSFrançois Tigeot 
1785926deccbSFrançois Tigeot 	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1786926deccbSFrançois Tigeot 
1787926deccbSFrançois Tigeot }
1788926deccbSFrançois Tigeot 
1789926deccbSFrançois Tigeot union crtc_source_param {
1790926deccbSFrançois Tigeot 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
1791926deccbSFrançois Tigeot 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
1792926deccbSFrançois Tigeot };
1793926deccbSFrançois Tigeot 
1794926deccbSFrançois Tigeot static void
1795926deccbSFrançois Tigeot atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
1796926deccbSFrançois Tigeot {
1797926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1798926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1799926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1800926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1801926deccbSFrançois Tigeot 	union crtc_source_param args;
1802926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1803926deccbSFrançois Tigeot 	uint8_t frev, crev;
1804926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
1805926deccbSFrançois Tigeot 
1806926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1807926deccbSFrançois Tigeot 
1808926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1809926deccbSFrançois Tigeot 		return;
1810926deccbSFrançois Tigeot 
1811926deccbSFrançois Tigeot 	switch (frev) {
1812926deccbSFrançois Tigeot 	case 1:
1813926deccbSFrançois Tigeot 		switch (crev) {
1814926deccbSFrançois Tigeot 		case 1:
1815926deccbSFrançois Tigeot 		default:
1816926deccbSFrançois Tigeot 			if (ASIC_IS_AVIVO(rdev))
1817926deccbSFrançois Tigeot 				args.v1.ucCRTC = radeon_crtc->crtc_id;
1818926deccbSFrançois Tigeot 			else {
1819926deccbSFrançois Tigeot 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
1820926deccbSFrançois Tigeot 					args.v1.ucCRTC = radeon_crtc->crtc_id;
1821926deccbSFrançois Tigeot 				} else {
1822926deccbSFrançois Tigeot 					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
1823926deccbSFrançois Tigeot 				}
1824926deccbSFrançois Tigeot 			}
1825926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1826926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1827926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1828926deccbSFrançois Tigeot 				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1829926deccbSFrançois Tigeot 				break;
1830926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1831926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1832926deccbSFrançois Tigeot 				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
1833926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1834926deccbSFrançois Tigeot 				else
1835926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1836926deccbSFrançois Tigeot 				break;
1837926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1838926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DDI:
1839926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1840926deccbSFrançois Tigeot 				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1841926deccbSFrançois Tigeot 				break;
1842926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1843926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1844926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1845926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
1846926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1847926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1848926deccbSFrançois Tigeot 				else
1849926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1850926deccbSFrançois Tigeot 				break;
1851926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1852926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1853926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1854926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
1855926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1856926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1857926deccbSFrançois Tigeot 				else
1858926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1859926deccbSFrançois Tigeot 				break;
1860926deccbSFrançois Tigeot 			}
1861926deccbSFrançois Tigeot 			break;
1862926deccbSFrançois Tigeot 		case 2:
1863926deccbSFrançois Tigeot 			args.v2.ucCRTC = radeon_crtc->crtc_id;
1864926deccbSFrançois Tigeot 			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
1865926deccbSFrançois Tigeot 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1866926deccbSFrançois Tigeot 
1867926deccbSFrançois Tigeot 				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
1868926deccbSFrançois Tigeot 					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
1869926deccbSFrançois Tigeot 				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
1870926deccbSFrançois Tigeot 					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
1871926deccbSFrançois Tigeot 				else
1872926deccbSFrançois Tigeot 					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1873c6f73aabSFrançois Tigeot 			} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1874c6f73aabSFrançois Tigeot 				args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
1875c6f73aabSFrançois Tigeot 			} else {
1876926deccbSFrançois Tigeot 				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1877c6f73aabSFrançois Tigeot 			}
1878926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1879926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1880926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1881926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
188257e252bfSMichael Neumann 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1883926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1884926deccbSFrançois Tigeot 				dig = radeon_encoder->enc_priv;
1885926deccbSFrançois Tigeot 				switch (dig->dig_encoder) {
1886926deccbSFrançois Tigeot 				case 0:
1887926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1888926deccbSFrançois Tigeot 					break;
1889926deccbSFrançois Tigeot 				case 1:
1890926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1891926deccbSFrançois Tigeot 					break;
1892926deccbSFrançois Tigeot 				case 2:
1893926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
1894926deccbSFrançois Tigeot 					break;
1895926deccbSFrançois Tigeot 				case 3:
1896926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
1897926deccbSFrançois Tigeot 					break;
1898926deccbSFrançois Tigeot 				case 4:
1899926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
1900926deccbSFrançois Tigeot 					break;
1901926deccbSFrançois Tigeot 				case 5:
1902926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
1903926deccbSFrançois Tigeot 					break;
190457e252bfSMichael Neumann 				case 6:
190557e252bfSMichael Neumann 					args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
190657e252bfSMichael Neumann 					break;
1907926deccbSFrançois Tigeot 				}
1908926deccbSFrançois Tigeot 				break;
1909926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1910926deccbSFrançois Tigeot 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
1911926deccbSFrançois Tigeot 				break;
1912926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1913926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1914926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1915926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1916926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1917926deccbSFrançois Tigeot 				else
1918926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1919926deccbSFrançois Tigeot 				break;
1920926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1921926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1922926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1923926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1924926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1925926deccbSFrançois Tigeot 				else
1926926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1927926deccbSFrançois Tigeot 				break;
1928926deccbSFrançois Tigeot 			}
1929926deccbSFrançois Tigeot 			break;
1930926deccbSFrançois Tigeot 		}
1931926deccbSFrançois Tigeot 		break;
1932926deccbSFrançois Tigeot 	default:
1933926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1934926deccbSFrançois Tigeot 		return;
1935926deccbSFrançois Tigeot 	}
1936926deccbSFrançois Tigeot 
1937926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1938926deccbSFrançois Tigeot 
1939926deccbSFrançois Tigeot 	/* update scratch regs with new routing */
1940926deccbSFrançois Tigeot 	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1941926deccbSFrançois Tigeot }
1942926deccbSFrançois Tigeot 
1943926deccbSFrançois Tigeot static void
1944926deccbSFrançois Tigeot atombios_apply_encoder_quirks(struct drm_encoder *encoder,
1945926deccbSFrançois Tigeot 			      struct drm_display_mode *mode)
1946926deccbSFrançois Tigeot {
1947926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1948926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1949926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1950926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1951926deccbSFrançois Tigeot 
1952926deccbSFrançois Tigeot 	/* Funky macbooks */
1953c6f73aabSFrançois Tigeot 	if ((dev->pdev->device == 0x71C5) &&
1954c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_vendor == 0x106b) &&
1955c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_device == 0x0080)) {
1956926deccbSFrançois Tigeot 		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1957926deccbSFrançois Tigeot 			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1958926deccbSFrançois Tigeot 
1959926deccbSFrançois Tigeot 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1960926deccbSFrançois Tigeot 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1961926deccbSFrançois Tigeot 
1962926deccbSFrançois Tigeot 			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1963926deccbSFrançois Tigeot 		}
1964926deccbSFrançois Tigeot 	}
1965926deccbSFrançois Tigeot 
1966926deccbSFrançois Tigeot 	/* set scaler clears this on some chips */
1967926deccbSFrançois Tigeot 	if (ASIC_IS_AVIVO(rdev) &&
1968926deccbSFrançois Tigeot 	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
196957e252bfSMichael Neumann 		if (ASIC_IS_DCE8(rdev)) {
197057e252bfSMichael Neumann 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
197157e252bfSMichael Neumann 				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset,
197257e252bfSMichael Neumann 				       CIK_INTERLEAVE_EN);
197357e252bfSMichael Neumann 			else
197457e252bfSMichael Neumann 				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
197557e252bfSMichael Neumann 		} else if (ASIC_IS_DCE4(rdev)) {
1976926deccbSFrançois Tigeot 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1977926deccbSFrançois Tigeot 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
1978926deccbSFrançois Tigeot 				       EVERGREEN_INTERLEAVE_EN);
1979926deccbSFrançois Tigeot 			else
1980926deccbSFrançois Tigeot 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1981926deccbSFrançois Tigeot 		} else {
1982926deccbSFrançois Tigeot 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1983926deccbSFrançois Tigeot 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
1984926deccbSFrançois Tigeot 				       AVIVO_D1MODE_INTERLEAVE_EN);
1985926deccbSFrançois Tigeot 			else
1986926deccbSFrançois Tigeot 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1987926deccbSFrançois Tigeot 		}
1988926deccbSFrançois Tigeot 	}
1989926deccbSFrançois Tigeot }
1990926deccbSFrançois Tigeot 
1991ee479021SImre Vadász static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
1992926deccbSFrançois Tigeot {
1993926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1994926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1995926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1996926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1997926deccbSFrançois Tigeot 	struct drm_encoder *test_encoder;
1998926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1999926deccbSFrançois Tigeot 	uint32_t dig_enc_in_use = 0;
2000926deccbSFrançois Tigeot 
2001926deccbSFrançois Tigeot 	if (ASIC_IS_DCE6(rdev)) {
2002926deccbSFrançois Tigeot 		/* DCE6 */
2003926deccbSFrançois Tigeot 		switch (radeon_encoder->encoder_id) {
2004926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2005926deccbSFrançois Tigeot 			if (dig->linkb)
2006ee479021SImre Vadász 				return 1;
2007926deccbSFrançois Tigeot 			else
2008ee479021SImre Vadász 				return 0;
2009926deccbSFrançois Tigeot 			break;
2010926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2011926deccbSFrançois Tigeot 			if (dig->linkb)
2012ee479021SImre Vadász 				return 3;
2013926deccbSFrançois Tigeot 			else
2014ee479021SImre Vadász 				return 2;
2015926deccbSFrançois Tigeot 			break;
2016926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2017926deccbSFrançois Tigeot 			if (dig->linkb)
2018ee479021SImre Vadász 				return 5;
2019926deccbSFrançois Tigeot 			else
2020ee479021SImre Vadász 				return 4;
2021926deccbSFrançois Tigeot 			break;
202257e252bfSMichael Neumann 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2023ee479021SImre Vadász 			return 6;
202457e252bfSMichael Neumann 			break;
2025926deccbSFrançois Tigeot 		}
2026926deccbSFrançois Tigeot 	} else if (ASIC_IS_DCE4(rdev)) {
2027926deccbSFrançois Tigeot 		/* DCE4/5 */
2028926deccbSFrançois Tigeot 		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
2029926deccbSFrançois Tigeot 			/* ontario follows DCE4 */
2030926deccbSFrançois Tigeot 			if (rdev->family == CHIP_PALM) {
2031926deccbSFrançois Tigeot 				if (dig->linkb)
2032ee479021SImre Vadász 					return 1;
2033926deccbSFrançois Tigeot 				else
2034ee479021SImre Vadász 					return 0;
2035926deccbSFrançois Tigeot 			} else
2036926deccbSFrançois Tigeot 				/* llano follows DCE3.2 */
2037ee479021SImre Vadász 				return radeon_crtc->crtc_id;
2038926deccbSFrançois Tigeot 		} else {
2039926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
2040926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2041926deccbSFrançois Tigeot 				if (dig->linkb)
2042ee479021SImre Vadász 					return 1;
2043926deccbSFrançois Tigeot 				else
2044ee479021SImre Vadász 					return 0;
2045926deccbSFrançois Tigeot 				break;
2046926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2047926deccbSFrançois Tigeot 				if (dig->linkb)
2048ee479021SImre Vadász 					return 3;
2049926deccbSFrançois Tigeot 				else
2050ee479021SImre Vadász 					return 2;
2051926deccbSFrançois Tigeot 				break;
2052926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2053926deccbSFrançois Tigeot 				if (dig->linkb)
2054ee479021SImre Vadász 					return 5;
2055926deccbSFrançois Tigeot 				else
2056ee479021SImre Vadász 					return 4;
2057926deccbSFrançois Tigeot 				break;
2058926deccbSFrançois Tigeot 			}
2059926deccbSFrançois Tigeot 		}
2060926deccbSFrançois Tigeot 	}
2061926deccbSFrançois Tigeot 
2062926deccbSFrançois Tigeot 	/* on DCE32 and encoder can driver any block so just crtc id */
2063926deccbSFrançois Tigeot 	if (ASIC_IS_DCE32(rdev)) {
2064ee479021SImre Vadász 		return radeon_crtc->crtc_id;
2065926deccbSFrançois Tigeot 	}
2066926deccbSFrançois Tigeot 
2067926deccbSFrançois Tigeot 	/* on DCE3 - LVTMA can only be driven by DIGB */
2068926deccbSFrançois Tigeot 	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
2069926deccbSFrançois Tigeot 		struct radeon_encoder *radeon_test_encoder;
2070926deccbSFrançois Tigeot 
2071926deccbSFrançois Tigeot 		if (encoder == test_encoder)
2072926deccbSFrançois Tigeot 			continue;
2073926deccbSFrançois Tigeot 
2074926deccbSFrançois Tigeot 		if (!radeon_encoder_is_digital(test_encoder))
2075926deccbSFrançois Tigeot 			continue;
2076926deccbSFrançois Tigeot 
2077926deccbSFrançois Tigeot 		radeon_test_encoder = to_radeon_encoder(test_encoder);
2078926deccbSFrançois Tigeot 		dig = radeon_test_encoder->enc_priv;
2079926deccbSFrançois Tigeot 
2080926deccbSFrançois Tigeot 		if (dig->dig_encoder >= 0)
2081926deccbSFrançois Tigeot 			dig_enc_in_use |= (1 << dig->dig_encoder);
2082926deccbSFrançois Tigeot 	}
2083926deccbSFrançois Tigeot 
2084926deccbSFrançois Tigeot 	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
2085926deccbSFrançois Tigeot 		if (dig_enc_in_use & 0x2)
2086926deccbSFrançois Tigeot 			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
2087926deccbSFrançois Tigeot 		return 1;
2088926deccbSFrançois Tigeot 	}
2089926deccbSFrançois Tigeot 	if (!(dig_enc_in_use & 1))
2090926deccbSFrançois Tigeot 		return 0;
2091926deccbSFrançois Tigeot 	return 1;
2092926deccbSFrançois Tigeot }
2093926deccbSFrançois Tigeot 
2094926deccbSFrançois Tigeot /* This only needs to be called once at startup */
2095926deccbSFrançois Tigeot void
2096926deccbSFrançois Tigeot radeon_atom_encoder_init(struct radeon_device *rdev)
2097926deccbSFrançois Tigeot {
2098926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
2099926deccbSFrançois Tigeot 	struct drm_encoder *encoder;
2100926deccbSFrançois Tigeot 
2101926deccbSFrançois Tigeot 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2102926deccbSFrançois Tigeot 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2103926deccbSFrançois Tigeot 		struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2104926deccbSFrançois Tigeot 
2105926deccbSFrançois Tigeot 		switch (radeon_encoder->encoder_id) {
2106926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2107926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2108926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
210957e252bfSMichael Neumann 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2110926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2111926deccbSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
2112926deccbSFrançois Tigeot 			break;
2113926deccbSFrançois Tigeot 		default:
2114926deccbSFrançois Tigeot 			break;
2115926deccbSFrançois Tigeot 		}
2116926deccbSFrançois Tigeot 
2117926deccbSFrançois Tigeot 		if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)))
2118926deccbSFrançois Tigeot 			atombios_external_encoder_setup(encoder, ext_encoder,
2119926deccbSFrançois Tigeot 							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
2120926deccbSFrançois Tigeot 	}
2121926deccbSFrançois Tigeot }
2122926deccbSFrançois Tigeot 
2123926deccbSFrançois Tigeot static void
2124926deccbSFrançois Tigeot radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
2125926deccbSFrançois Tigeot 			     struct drm_display_mode *mode,
2126926deccbSFrançois Tigeot 			     struct drm_display_mode *adjusted_mode)
2127926deccbSFrançois Tigeot {
2128926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2129926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2130926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2131926deccbSFrançois Tigeot 
2132926deccbSFrançois Tigeot 	radeon_encoder->pixel_clock = adjusted_mode->clock;
2133926deccbSFrançois Tigeot 
2134926deccbSFrançois Tigeot 	/* need to call this here rather than in prepare() since we need some crtc info */
2135926deccbSFrançois Tigeot 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2136926deccbSFrançois Tigeot 
2137926deccbSFrançois Tigeot 	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
2138926deccbSFrançois Tigeot 		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
2139926deccbSFrançois Tigeot 			atombios_yuv_setup(encoder, true);
2140926deccbSFrançois Tigeot 		else
2141926deccbSFrançois Tigeot 			atombios_yuv_setup(encoder, false);
2142926deccbSFrançois Tigeot 	}
2143926deccbSFrançois Tigeot 
2144926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
2145926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2146926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2147926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2148926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2149926deccbSFrançois Tigeot 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
2150926deccbSFrançois Tigeot 		break;
2151926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2152926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2153926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
215457e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2155926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2156926deccbSFrançois Tigeot 		/* handled in dpms */
2157926deccbSFrançois Tigeot 		break;
2158926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2159926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2160926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2161926deccbSFrançois Tigeot 		atombios_dvo_setup(encoder, ATOM_ENABLE);
2162926deccbSFrançois Tigeot 		break;
2163926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2164926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2165926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2166926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2167926deccbSFrançois Tigeot 		atombios_dac_setup(encoder, ATOM_ENABLE);
2168926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
2169926deccbSFrançois Tigeot 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2170926deccbSFrançois Tigeot 				atombios_tv_setup(encoder, ATOM_ENABLE);
2171926deccbSFrançois Tigeot 			else
2172926deccbSFrançois Tigeot 				atombios_tv_setup(encoder, ATOM_DISABLE);
2173926deccbSFrançois Tigeot 		}
2174926deccbSFrançois Tigeot 		break;
2175926deccbSFrançois Tigeot 	}
2176926deccbSFrançois Tigeot 
2177926deccbSFrançois Tigeot 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
2178926deccbSFrançois Tigeot 
2179ee479021SImre Vadász 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
2180ee479021SImre Vadász 		if (rdev->asic->display.hdmi_enable)
2181ee479021SImre Vadász 			radeon_hdmi_enable(rdev, encoder, true);
2182ee479021SImre Vadász 		if (rdev->asic->display.hdmi_setmode)
2183ee479021SImre Vadász 			radeon_hdmi_setmode(rdev, encoder, adjusted_mode);
2184ee479021SImre Vadász 	}
2185926deccbSFrançois Tigeot }
2186926deccbSFrançois Tigeot 
2187926deccbSFrançois Tigeot static bool
2188926deccbSFrançois Tigeot atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2189926deccbSFrançois Tigeot {
2190926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2191926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2192926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2193926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2194926deccbSFrançois Tigeot 
2195926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
2196926deccbSFrançois Tigeot 				       ATOM_DEVICE_CV_SUPPORT |
2197926deccbSFrançois Tigeot 				       ATOM_DEVICE_CRT_SUPPORT)) {
2198926deccbSFrançois Tigeot 		DAC_LOAD_DETECTION_PS_ALLOCATION args;
2199926deccbSFrançois Tigeot 		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
2200926deccbSFrançois Tigeot 		uint8_t frev, crev;
2201926deccbSFrançois Tigeot 
2202926deccbSFrançois Tigeot 		memset(&args, 0, sizeof(args));
2203926deccbSFrançois Tigeot 
2204926deccbSFrançois Tigeot 		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2205926deccbSFrançois Tigeot 			return false;
2206926deccbSFrançois Tigeot 
2207926deccbSFrançois Tigeot 		args.sDacload.ucMisc = 0;
2208926deccbSFrançois Tigeot 
2209926deccbSFrançois Tigeot 		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
2210926deccbSFrançois Tigeot 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
2211926deccbSFrançois Tigeot 			args.sDacload.ucDacType = ATOM_DAC_A;
2212926deccbSFrançois Tigeot 		else
2213926deccbSFrançois Tigeot 			args.sDacload.ucDacType = ATOM_DAC_B;
2214926deccbSFrançois Tigeot 
2215926deccbSFrançois Tigeot 		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
2216926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
2217926deccbSFrançois Tigeot 		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
2218926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
2219926deccbSFrançois Tigeot 		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2220926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
2221926deccbSFrançois Tigeot 			if (crev >= 3)
2222926deccbSFrançois Tigeot 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
2223926deccbSFrançois Tigeot 		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2224926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
2225926deccbSFrançois Tigeot 			if (crev >= 3)
2226926deccbSFrançois Tigeot 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
2227926deccbSFrançois Tigeot 		}
2228926deccbSFrançois Tigeot 
2229926deccbSFrançois Tigeot 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2230926deccbSFrançois Tigeot 
2231926deccbSFrançois Tigeot 		return true;
2232926deccbSFrançois Tigeot 	} else
2233926deccbSFrançois Tigeot 		return false;
2234926deccbSFrançois Tigeot }
2235926deccbSFrançois Tigeot 
2236926deccbSFrançois Tigeot static enum drm_connector_status
2237926deccbSFrançois Tigeot radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2238926deccbSFrançois Tigeot {
2239926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2240926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2241926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2242926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2243926deccbSFrançois Tigeot 	uint32_t bios_0_scratch;
2244926deccbSFrançois Tigeot 
2245926deccbSFrançois Tigeot 	if (!atombios_dac_load_detect(encoder, connector)) {
2246926deccbSFrançois Tigeot 		DRM_DEBUG_KMS("detect returned false \n");
2247926deccbSFrançois Tigeot 		return connector_status_unknown;
2248926deccbSFrançois Tigeot 	}
2249926deccbSFrançois Tigeot 
2250926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
2251926deccbSFrançois Tigeot 		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2252926deccbSFrançois Tigeot 	else
2253926deccbSFrançois Tigeot 		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
2254926deccbSFrançois Tigeot 
2255926deccbSFrançois Tigeot 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
2256926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2257926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2258926deccbSFrançois Tigeot 			return connector_status_connected;
2259926deccbSFrançois Tigeot 	}
2260926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2261926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2262926deccbSFrançois Tigeot 			return connector_status_connected;
2263926deccbSFrançois Tigeot 	}
2264926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2265926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2266926deccbSFrançois Tigeot 			return connector_status_connected;
2267926deccbSFrançois Tigeot 	}
2268926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2269926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2270926deccbSFrançois Tigeot 			return connector_status_connected; /* CTV */
2271926deccbSFrançois Tigeot 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2272926deccbSFrançois Tigeot 			return connector_status_connected; /* STV */
2273926deccbSFrançois Tigeot 	}
2274926deccbSFrançois Tigeot 	return connector_status_disconnected;
2275926deccbSFrançois Tigeot }
2276926deccbSFrançois Tigeot 
2277926deccbSFrançois Tigeot static enum drm_connector_status
2278926deccbSFrançois Tigeot radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2279926deccbSFrançois Tigeot {
2280926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2281926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2282926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2283926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2284926deccbSFrançois Tigeot 	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2285926deccbSFrançois Tigeot 	u32 bios_0_scratch;
2286926deccbSFrançois Tigeot 
2287926deccbSFrançois Tigeot 	if (!ASIC_IS_DCE4(rdev))
2288926deccbSFrançois Tigeot 		return connector_status_unknown;
2289926deccbSFrançois Tigeot 
2290926deccbSFrançois Tigeot 	if (!ext_encoder)
2291926deccbSFrançois Tigeot 		return connector_status_unknown;
2292926deccbSFrançois Tigeot 
2293926deccbSFrançois Tigeot 	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
2294926deccbSFrançois Tigeot 		return connector_status_unknown;
2295926deccbSFrançois Tigeot 
2296926deccbSFrançois Tigeot 	/* load detect on the dp bridge */
2297926deccbSFrançois Tigeot 	atombios_external_encoder_setup(encoder, ext_encoder,
2298926deccbSFrançois Tigeot 					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
2299926deccbSFrançois Tigeot 
2300926deccbSFrançois Tigeot 	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2301926deccbSFrançois Tigeot 
2302926deccbSFrançois Tigeot 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
2303926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2304926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2305926deccbSFrançois Tigeot 			return connector_status_connected;
2306926deccbSFrançois Tigeot 	}
2307926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2308926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2309926deccbSFrançois Tigeot 			return connector_status_connected;
2310926deccbSFrançois Tigeot 	}
2311926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2312926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2313926deccbSFrançois Tigeot 			return connector_status_connected;
2314926deccbSFrançois Tigeot 	}
2315926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2316926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2317926deccbSFrançois Tigeot 			return connector_status_connected; /* CTV */
2318926deccbSFrançois Tigeot 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2319926deccbSFrançois Tigeot 			return connector_status_connected; /* STV */
2320926deccbSFrançois Tigeot 	}
2321926deccbSFrançois Tigeot 	return connector_status_disconnected;
2322926deccbSFrançois Tigeot }
2323926deccbSFrançois Tigeot 
2324926deccbSFrançois Tigeot void
2325926deccbSFrançois Tigeot radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
2326926deccbSFrançois Tigeot {
2327926deccbSFrançois Tigeot 	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2328926deccbSFrançois Tigeot 
2329926deccbSFrançois Tigeot 	if (ext_encoder)
2330926deccbSFrançois Tigeot 		/* ddc_setup on the dp bridge */
2331926deccbSFrançois Tigeot 		atombios_external_encoder_setup(encoder, ext_encoder,
2332926deccbSFrançois Tigeot 						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
2333926deccbSFrançois Tigeot 
2334926deccbSFrançois Tigeot }
2335926deccbSFrançois Tigeot 
2336926deccbSFrançois Tigeot static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
2337926deccbSFrançois Tigeot {
2338926deccbSFrançois Tigeot 	struct radeon_device *rdev = encoder->dev->dev_private;
2339926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2340926deccbSFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
2341926deccbSFrançois Tigeot 
2342926deccbSFrançois Tigeot 	if ((radeon_encoder->active_device &
2343926deccbSFrançois Tigeot 	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
2344926deccbSFrançois Tigeot 	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
2345926deccbSFrançois Tigeot 	     ENCODER_OBJECT_ID_NONE)) {
2346926deccbSFrançois Tigeot 		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
2347926deccbSFrançois Tigeot 		if (dig) {
2348ee479021SImre Vadász 			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
2349926deccbSFrançois Tigeot 			if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
2350926deccbSFrançois Tigeot 				if (rdev->family >= CHIP_R600)
2351926deccbSFrançois Tigeot 					dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
2352926deccbSFrançois Tigeot 				else
2353926deccbSFrançois Tigeot 					/* RS600/690/740 have only 1 afmt block */
2354926deccbSFrançois Tigeot 					dig->afmt = rdev->mode_info.afmt[0];
2355926deccbSFrançois Tigeot 			}
2356926deccbSFrançois Tigeot 		}
2357926deccbSFrançois Tigeot 	}
2358926deccbSFrançois Tigeot 
2359926deccbSFrançois Tigeot 	radeon_atom_output_lock(encoder, true);
2360926deccbSFrançois Tigeot 
2361926deccbSFrançois Tigeot 	if (connector) {
2362926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2363926deccbSFrançois Tigeot 
2364926deccbSFrançois Tigeot 		/* select the clock/data port if it uses a router */
2365926deccbSFrançois Tigeot 		if (radeon_connector->router.cd_valid)
2366926deccbSFrançois Tigeot 			radeon_router_select_cd_port(radeon_connector);
2367926deccbSFrançois Tigeot 
2368926deccbSFrançois Tigeot 		/* turn eDP panel on for mode set */
2369926deccbSFrançois Tigeot 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
2370926deccbSFrançois Tigeot 			atombios_set_edp_panel_power(connector,
2371926deccbSFrançois Tigeot 						     ATOM_TRANSMITTER_ACTION_POWER_ON);
2372926deccbSFrançois Tigeot 	}
2373926deccbSFrançois Tigeot 
2374926deccbSFrançois Tigeot 	/* this is needed for the pll/ss setup to work correctly in some cases */
2375926deccbSFrançois Tigeot 	atombios_set_encoder_crtc_source(encoder);
2376c6f73aabSFrançois Tigeot 	/* set up the FMT blocks */
2377c6f73aabSFrançois Tigeot 	if (ASIC_IS_DCE8(rdev))
2378c6f73aabSFrançois Tigeot 		dce8_program_fmt(encoder);
2379c6f73aabSFrançois Tigeot 	else if (ASIC_IS_DCE4(rdev))
2380c6f73aabSFrançois Tigeot 		dce4_program_fmt(encoder);
2381c6f73aabSFrançois Tigeot 	else if (ASIC_IS_DCE3(rdev))
2382c6f73aabSFrançois Tigeot 		dce3_program_fmt(encoder);
2383c6f73aabSFrançois Tigeot 	else if (ASIC_IS_AVIVO(rdev))
2384c6f73aabSFrançois Tigeot 		avivo_program_fmt(encoder);
2385926deccbSFrançois Tigeot }
2386926deccbSFrançois Tigeot 
2387926deccbSFrançois Tigeot static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
2388926deccbSFrançois Tigeot {
2389926deccbSFrançois Tigeot 	/* need to call this here as we need the crtc set up */
2390926deccbSFrançois Tigeot 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
2391926deccbSFrançois Tigeot 	radeon_atom_output_lock(encoder, false);
2392926deccbSFrançois Tigeot }
2393926deccbSFrançois Tigeot 
2394926deccbSFrançois Tigeot static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
2395926deccbSFrançois Tigeot {
2396926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2397926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2398926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2399926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
2400926deccbSFrançois Tigeot 
2401926deccbSFrançois Tigeot 	/* check for pre-DCE3 cards with shared encoders;
2402926deccbSFrançois Tigeot 	 * can't really use the links individually, so don't disable
2403926deccbSFrançois Tigeot 	 * the encoder if it's in use by another connector
2404926deccbSFrançois Tigeot 	 */
2405926deccbSFrançois Tigeot 	if (!ASIC_IS_DCE3(rdev)) {
2406926deccbSFrançois Tigeot 		struct drm_encoder *other_encoder;
2407926deccbSFrançois Tigeot 		struct radeon_encoder *other_radeon_encoder;
2408926deccbSFrançois Tigeot 
2409926deccbSFrançois Tigeot 		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
2410926deccbSFrançois Tigeot 			other_radeon_encoder = to_radeon_encoder(other_encoder);
2411926deccbSFrançois Tigeot 			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
2412926deccbSFrançois Tigeot 			    drm_helper_encoder_in_use(other_encoder))
2413926deccbSFrançois Tigeot 				goto disable_done;
2414926deccbSFrançois Tigeot 		}
2415926deccbSFrançois Tigeot 	}
2416926deccbSFrançois Tigeot 
2417926deccbSFrançois Tigeot 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2418926deccbSFrançois Tigeot 
2419926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
2420926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2421926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2422926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2423926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2424926deccbSFrançois Tigeot 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
2425926deccbSFrançois Tigeot 		break;
2426926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2427926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2428926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
242957e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2430926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2431926deccbSFrançois Tigeot 		/* handled in dpms */
2432926deccbSFrançois Tigeot 		break;
2433926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2434926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2435926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2436926deccbSFrançois Tigeot 		atombios_dvo_setup(encoder, ATOM_DISABLE);
2437926deccbSFrançois Tigeot 		break;
2438926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2439926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2440926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2441926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2442926deccbSFrançois Tigeot 		atombios_dac_setup(encoder, ATOM_DISABLE);
2443926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2444926deccbSFrançois Tigeot 			atombios_tv_setup(encoder, ATOM_DISABLE);
2445926deccbSFrançois Tigeot 		break;
2446926deccbSFrançois Tigeot 	}
2447926deccbSFrançois Tigeot 
2448926deccbSFrançois Tigeot disable_done:
2449926deccbSFrançois Tigeot 	if (radeon_encoder_is_digital(encoder)) {
2450f43cf1b1SMichael Neumann 		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
2451f43cf1b1SMichael Neumann 			if (rdev->asic->display.hdmi_enable)
2452f43cf1b1SMichael Neumann 				radeon_hdmi_enable(rdev, encoder, false);
2453f43cf1b1SMichael Neumann 		}
2454926deccbSFrançois Tigeot 		dig = radeon_encoder->enc_priv;
2455926deccbSFrançois Tigeot 		dig->dig_encoder = -1;
2456926deccbSFrançois Tigeot 	}
2457926deccbSFrançois Tigeot 	radeon_encoder->active_device = 0;
2458926deccbSFrançois Tigeot }
2459926deccbSFrançois Tigeot 
2460926deccbSFrançois Tigeot /* these are handled by the primary encoders */
2461926deccbSFrançois Tigeot static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
2462926deccbSFrançois Tigeot {
2463926deccbSFrançois Tigeot 
2464926deccbSFrançois Tigeot }
2465926deccbSFrançois Tigeot 
2466926deccbSFrançois Tigeot static void radeon_atom_ext_commit(struct drm_encoder *encoder)
2467926deccbSFrançois Tigeot {
2468926deccbSFrançois Tigeot 
2469926deccbSFrançois Tigeot }
2470926deccbSFrançois Tigeot 
2471926deccbSFrançois Tigeot static void
2472926deccbSFrançois Tigeot radeon_atom_ext_mode_set(struct drm_encoder *encoder,
2473926deccbSFrançois Tigeot 			 struct drm_display_mode *mode,
2474926deccbSFrançois Tigeot 			 struct drm_display_mode *adjusted_mode)
2475926deccbSFrançois Tigeot {
2476926deccbSFrançois Tigeot 
2477926deccbSFrançois Tigeot }
2478926deccbSFrançois Tigeot 
2479926deccbSFrançois Tigeot static void radeon_atom_ext_disable(struct drm_encoder *encoder)
2480926deccbSFrançois Tigeot {
2481926deccbSFrançois Tigeot 
2482926deccbSFrançois Tigeot }
2483926deccbSFrançois Tigeot 
2484926deccbSFrançois Tigeot static void
2485926deccbSFrançois Tigeot radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
2486926deccbSFrançois Tigeot {
2487926deccbSFrançois Tigeot 
2488926deccbSFrançois Tigeot }
2489926deccbSFrançois Tigeot 
2490926deccbSFrançois Tigeot static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
2491926deccbSFrançois Tigeot 				       const struct drm_display_mode *mode,
2492926deccbSFrançois Tigeot 				       struct drm_display_mode *adjusted_mode)
2493926deccbSFrançois Tigeot {
2494926deccbSFrançois Tigeot 	return true;
2495926deccbSFrançois Tigeot }
2496926deccbSFrançois Tigeot 
2497926deccbSFrançois Tigeot static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
2498926deccbSFrançois Tigeot 	.dpms = radeon_atom_ext_dpms,
2499926deccbSFrançois Tigeot 	.mode_fixup = radeon_atom_ext_mode_fixup,
2500926deccbSFrançois Tigeot 	.prepare = radeon_atom_ext_prepare,
2501926deccbSFrançois Tigeot 	.mode_set = radeon_atom_ext_mode_set,
2502926deccbSFrançois Tigeot 	.commit = radeon_atom_ext_commit,
2503926deccbSFrançois Tigeot 	.disable = radeon_atom_ext_disable,
2504926deccbSFrançois Tigeot 	/* no detect for TMDS/LVDS yet */
2505926deccbSFrançois Tigeot };
2506926deccbSFrançois Tigeot 
2507926deccbSFrançois Tigeot static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
2508926deccbSFrançois Tigeot 	.dpms = radeon_atom_encoder_dpms,
2509926deccbSFrançois Tigeot 	.mode_fixup = radeon_atom_mode_fixup,
2510926deccbSFrançois Tigeot 	.prepare = radeon_atom_encoder_prepare,
2511926deccbSFrançois Tigeot 	.mode_set = radeon_atom_encoder_mode_set,
2512926deccbSFrançois Tigeot 	.commit = radeon_atom_encoder_commit,
2513926deccbSFrançois Tigeot 	.disable = radeon_atom_encoder_disable,
2514926deccbSFrançois Tigeot 	.detect = radeon_atom_dig_detect,
2515926deccbSFrançois Tigeot };
2516926deccbSFrançois Tigeot 
2517926deccbSFrançois Tigeot static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
2518926deccbSFrançois Tigeot 	.dpms = radeon_atom_encoder_dpms,
2519926deccbSFrançois Tigeot 	.mode_fixup = radeon_atom_mode_fixup,
2520926deccbSFrançois Tigeot 	.prepare = radeon_atom_encoder_prepare,
2521926deccbSFrançois Tigeot 	.mode_set = radeon_atom_encoder_mode_set,
2522926deccbSFrançois Tigeot 	.commit = radeon_atom_encoder_commit,
2523926deccbSFrançois Tigeot 	.detect = radeon_atom_dac_detect,
2524926deccbSFrançois Tigeot };
2525926deccbSFrançois Tigeot 
2526926deccbSFrançois Tigeot void radeon_enc_destroy(struct drm_encoder *encoder)
2527926deccbSFrançois Tigeot {
2528926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2529926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
2530926deccbSFrançois Tigeot 		radeon_atom_backlight_exit(radeon_encoder);
2531c4ef309bSzrj 	kfree(radeon_encoder->enc_priv);
2532926deccbSFrançois Tigeot 	drm_encoder_cleanup(encoder);
2533c4ef309bSzrj 	kfree(radeon_encoder);
2534926deccbSFrançois Tigeot }
2535926deccbSFrançois Tigeot 
2536926deccbSFrançois Tigeot static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
2537926deccbSFrançois Tigeot 	.destroy = radeon_enc_destroy,
2538926deccbSFrançois Tigeot };
2539926deccbSFrançois Tigeot 
2540926deccbSFrançois Tigeot static struct radeon_encoder_atom_dac *
2541926deccbSFrançois Tigeot radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
2542926deccbSFrançois Tigeot {
2543926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
2544926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2545c4ef309bSzrj 	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
2546926deccbSFrançois Tigeot 
2547926deccbSFrançois Tigeot 	if (!dac)
2548926deccbSFrançois Tigeot 		return NULL;
2549926deccbSFrançois Tigeot 
2550926deccbSFrançois Tigeot 	dac->tv_std = radeon_atombios_get_tv_info(rdev);
2551926deccbSFrançois Tigeot 	return dac;
2552926deccbSFrançois Tigeot }
2553926deccbSFrançois Tigeot 
2554926deccbSFrançois Tigeot static struct radeon_encoder_atom_dig *
2555926deccbSFrançois Tigeot radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
2556926deccbSFrançois Tigeot {
2557926deccbSFrançois Tigeot 	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
2558c4ef309bSzrj 	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
2559926deccbSFrançois Tigeot 
2560926deccbSFrançois Tigeot 	if (!dig)
2561926deccbSFrançois Tigeot 		return NULL;
2562926deccbSFrançois Tigeot 
2563926deccbSFrançois Tigeot 	/* coherent mode by default */
2564926deccbSFrançois Tigeot 	dig->coherent_mode = true;
2565926deccbSFrançois Tigeot 	dig->dig_encoder = -1;
2566926deccbSFrançois Tigeot 
2567926deccbSFrançois Tigeot 	if (encoder_enum == 2)
2568926deccbSFrançois Tigeot 		dig->linkb = true;
2569926deccbSFrançois Tigeot 	else
2570926deccbSFrançois Tigeot 		dig->linkb = false;
2571926deccbSFrançois Tigeot 
2572926deccbSFrançois Tigeot 	return dig;
2573926deccbSFrançois Tigeot }
2574926deccbSFrançois Tigeot 
2575926deccbSFrançois Tigeot void
2576926deccbSFrançois Tigeot radeon_add_atom_encoder(struct drm_device *dev,
2577926deccbSFrançois Tigeot 			uint32_t encoder_enum,
2578926deccbSFrançois Tigeot 			uint32_t supported_device,
2579926deccbSFrançois Tigeot 			u16 caps)
2580926deccbSFrançois Tigeot {
2581926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2582926deccbSFrançois Tigeot 	struct drm_encoder *encoder;
2583926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder;
2584926deccbSFrançois Tigeot 
2585926deccbSFrançois Tigeot 	/* see if we already added it */
2586926deccbSFrançois Tigeot 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2587926deccbSFrançois Tigeot 		radeon_encoder = to_radeon_encoder(encoder);
2588926deccbSFrançois Tigeot 		if (radeon_encoder->encoder_enum == encoder_enum) {
2589926deccbSFrançois Tigeot 			radeon_encoder->devices |= supported_device;
2590926deccbSFrançois Tigeot 			return;
2591926deccbSFrançois Tigeot 		}
2592926deccbSFrançois Tigeot 
2593926deccbSFrançois Tigeot 	}
2594926deccbSFrançois Tigeot 
2595926deccbSFrançois Tigeot 	/* add a new one */
2596c4ef309bSzrj 	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
2597926deccbSFrançois Tigeot 	if (!radeon_encoder)
2598926deccbSFrançois Tigeot 		return;
2599926deccbSFrançois Tigeot 
2600926deccbSFrançois Tigeot 	encoder = &radeon_encoder->base;
2601926deccbSFrançois Tigeot 	switch (rdev->num_crtc) {
2602926deccbSFrançois Tigeot 	case 1:
2603926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0x1;
2604926deccbSFrançois Tigeot 		break;
2605926deccbSFrançois Tigeot 	case 2:
2606926deccbSFrançois Tigeot 	default:
2607926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0x3;
2608926deccbSFrançois Tigeot 		break;
2609926deccbSFrançois Tigeot 	case 4:
2610926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0xf;
2611926deccbSFrançois Tigeot 		break;
2612926deccbSFrançois Tigeot 	case 6:
2613926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0x3f;
2614926deccbSFrançois Tigeot 		break;
2615926deccbSFrançois Tigeot 	}
2616926deccbSFrançois Tigeot 
2617926deccbSFrançois Tigeot 	radeon_encoder->enc_priv = NULL;
2618926deccbSFrançois Tigeot 
2619926deccbSFrançois Tigeot 	radeon_encoder->encoder_enum = encoder_enum;
2620926deccbSFrançois Tigeot 	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
2621926deccbSFrançois Tigeot 	radeon_encoder->devices = supported_device;
2622926deccbSFrançois Tigeot 	radeon_encoder->rmx_type = RMX_OFF;
2623926deccbSFrançois Tigeot 	radeon_encoder->underscan_type = UNDERSCAN_OFF;
2624926deccbSFrançois Tigeot 	radeon_encoder->is_ext_encoder = false;
2625926deccbSFrançois Tigeot 	radeon_encoder->caps = caps;
2626926deccbSFrançois Tigeot 
2627926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
2628926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2629926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2630926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2631926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2632926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2633926deccbSFrançois Tigeot 			radeon_encoder->rmx_type = RMX_FULL;
2634aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2635aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_LVDS, NULL);
2636926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2637926deccbSFrançois Tigeot 		} else {
2638aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2639aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_TMDS, NULL);
2640926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2641926deccbSFrançois Tigeot 		}
2642926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2643926deccbSFrançois Tigeot 		break;
2644926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2645aee94f86SFrançois Tigeot 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2646aee94f86SFrançois Tigeot 				 DRM_MODE_ENCODER_DAC, NULL);
2647926deccbSFrançois Tigeot 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2648926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2649926deccbSFrançois Tigeot 		break;
2650926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2651926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2652926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2653aee94f86SFrançois Tigeot 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2654aee94f86SFrançois Tigeot 				 DRM_MODE_ENCODER_TVDAC, NULL);
2655926deccbSFrançois Tigeot 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2656926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2657926deccbSFrançois Tigeot 		break;
2658926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2659926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2660926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2661926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2662926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2663926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2664926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
266557e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2666926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2667926deccbSFrançois Tigeot 			radeon_encoder->rmx_type = RMX_FULL;
2668aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2669aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_LVDS, NULL);
2670926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2671926deccbSFrançois Tigeot 		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
2672aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2673aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_DAC, NULL);
2674926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2675926deccbSFrançois Tigeot 		} else {
2676aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2677aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_TMDS, NULL);
2678926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2679926deccbSFrançois Tigeot 		}
2680926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2681926deccbSFrançois Tigeot 		break;
2682926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_SI170B:
2683926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_CH7303:
2684926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2685926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2686926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_TITFP513:
2687926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_VT1623:
2688926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_HDMI_SI1930:
2689926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_TRAVIS:
2690926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_NUTMEG:
2691926deccbSFrançois Tigeot 		/* these are handled by the primary encoders */
2692926deccbSFrançois Tigeot 		radeon_encoder->is_ext_encoder = true;
2693926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
2694aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2695aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_LVDS, NULL);
2696926deccbSFrançois Tigeot 		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
2697aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2698aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_DAC, NULL);
2699926deccbSFrançois Tigeot 		else
2700aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2701aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_TMDS, NULL);
2702926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
2703926deccbSFrançois Tigeot 		break;
2704926deccbSFrançois Tigeot 	}
2705926deccbSFrançois Tigeot }
2706