xref: /dflybsd-src/sys/dev/drm/radeon/atombios_encoders.c (revision a85cb24f18e3804e75ab8bcda7692564d0563317)
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>
2883b4b9b9SFrançois Tigeot #include <drm/radeon_drm.h>
29926deccbSFrançois Tigeot #include "radeon.h"
30c59a5c48SFrançois Tigeot #include "radeon_audio.h"
314cd92098Szrj #include "radeon_asic.h"
32926deccbSFrançois Tigeot #include "atom.h"
33*a85cb24fSFrançois Tigeot #include <linux/backlight.h>
34c59a5c48SFrançois Tigeot #include <linux/dmi.h>
35926deccbSFrançois Tigeot 
36926deccbSFrançois Tigeot static u8
radeon_atom_get_backlight_level_from_reg(struct radeon_device * rdev)37926deccbSFrançois Tigeot radeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev)
38926deccbSFrançois Tigeot {
39926deccbSFrançois Tigeot 	u8 backlight_level;
40926deccbSFrançois Tigeot 	u32 bios_2_scratch;
41926deccbSFrançois Tigeot 
42926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
43926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
44926deccbSFrançois Tigeot 	else
45926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
46926deccbSFrançois Tigeot 
47926deccbSFrançois Tigeot 	backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >>
48926deccbSFrançois Tigeot 			   ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
49926deccbSFrançois Tigeot 
50926deccbSFrançois Tigeot 	return backlight_level;
51926deccbSFrançois Tigeot }
52926deccbSFrançois Tigeot 
53926deccbSFrançois Tigeot static void
radeon_atom_set_backlight_level_to_reg(struct radeon_device * rdev,u8 backlight_level)54926deccbSFrançois Tigeot radeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev,
55926deccbSFrançois Tigeot 				       u8 backlight_level)
56926deccbSFrançois Tigeot {
57926deccbSFrançois Tigeot 	u32 bios_2_scratch;
58926deccbSFrançois Tigeot 
59926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
60926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
61926deccbSFrançois Tigeot 	else
62926deccbSFrançois Tigeot 		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
63926deccbSFrançois Tigeot 
64926deccbSFrançois Tigeot 	bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
65926deccbSFrançois Tigeot 	bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
66926deccbSFrançois Tigeot 			   ATOM_S2_CURRENT_BL_LEVEL_MASK);
67926deccbSFrançois Tigeot 
68926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
69926deccbSFrançois Tigeot 		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
70926deccbSFrançois Tigeot 	else
71926deccbSFrançois Tigeot 		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
72926deccbSFrançois Tigeot }
73926deccbSFrançois Tigeot 
74926deccbSFrançois Tigeot u8
atombios_get_backlight_level(struct radeon_encoder * radeon_encoder)75926deccbSFrançois Tigeot atombios_get_backlight_level(struct radeon_encoder *radeon_encoder)
76926deccbSFrançois Tigeot {
77926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
78926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
79926deccbSFrançois Tigeot 
80926deccbSFrançois Tigeot 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
81926deccbSFrançois Tigeot 		return 0;
82926deccbSFrançois Tigeot 
83926deccbSFrançois Tigeot 	return radeon_atom_get_backlight_level_from_reg(rdev);
84926deccbSFrançois Tigeot }
85926deccbSFrançois Tigeot 
86926deccbSFrançois Tigeot void
atombios_set_backlight_level(struct radeon_encoder * radeon_encoder,u8 level)87926deccbSFrançois Tigeot atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
88926deccbSFrançois Tigeot {
89926deccbSFrançois Tigeot 	struct drm_encoder *encoder = &radeon_encoder->base;
90926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
91926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
92926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
93926deccbSFrançois Tigeot 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
94926deccbSFrançois Tigeot 	int index;
95926deccbSFrançois Tigeot 
96926deccbSFrançois Tigeot 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
97926deccbSFrançois Tigeot 		return;
98926deccbSFrançois Tigeot 
99926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
100926deccbSFrançois Tigeot 	    radeon_encoder->enc_priv) {
101926deccbSFrançois Tigeot 		dig = radeon_encoder->enc_priv;
102926deccbSFrançois Tigeot 		dig->backlight_level = level;
103926deccbSFrançois Tigeot 		radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level);
104926deccbSFrançois Tigeot 
105926deccbSFrançois Tigeot 		switch (radeon_encoder->encoder_id) {
106926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
107926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
108926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
109926deccbSFrançois Tigeot 			if (dig->backlight_level == 0) {
110926deccbSFrançois Tigeot 				args.ucAction = ATOM_LCD_BLOFF;
111926deccbSFrançois Tigeot 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
112926deccbSFrançois Tigeot 			} else {
113926deccbSFrançois Tigeot 				args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
114926deccbSFrançois Tigeot 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
115926deccbSFrançois Tigeot 				args.ucAction = ATOM_LCD_BLON;
116926deccbSFrançois Tigeot 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
117926deccbSFrançois Tigeot 			}
118926deccbSFrançois Tigeot 			break;
119926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
120926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
121926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
122926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
123c59a5c48SFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
124926deccbSFrançois Tigeot 			if (dig->backlight_level == 0)
125926deccbSFrançois Tigeot 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
126926deccbSFrançois Tigeot 			else {
127926deccbSFrançois Tigeot 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0);
128926deccbSFrançois Tigeot 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
129926deccbSFrançois Tigeot 			}
130926deccbSFrançois Tigeot 			break;
131926deccbSFrançois Tigeot 		default:
132926deccbSFrançois Tigeot 			break;
133926deccbSFrançois Tigeot 		}
134926deccbSFrançois Tigeot 	}
135926deccbSFrançois Tigeot }
136926deccbSFrançois Tigeot 
137926deccbSFrançois Tigeot #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
138926deccbSFrançois Tigeot 
139ce73550bSFrançois Tigeot #if 0
140926deccbSFrançois Tigeot static u8 radeon_atom_bl_level(struct backlight_device *bd)
141926deccbSFrançois Tigeot {
142926deccbSFrançois Tigeot 	u8 level;
143926deccbSFrançois Tigeot 
144926deccbSFrançois Tigeot 	/* Convert brightness to hardware level */
145926deccbSFrançois Tigeot 	if (bd->props.brightness < 0)
146926deccbSFrançois Tigeot 		level = 0;
147926deccbSFrançois Tigeot 	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
148926deccbSFrançois Tigeot 		level = RADEON_MAX_BL_LEVEL;
149926deccbSFrançois Tigeot 	else
150926deccbSFrançois Tigeot 		level = bd->props.brightness;
151926deccbSFrançois Tigeot 
152926deccbSFrançois Tigeot 	return level;
153926deccbSFrançois Tigeot }
154926deccbSFrançois Tigeot 
155926deccbSFrançois Tigeot static int radeon_atom_backlight_update_status(struct backlight_device *bd)
156926deccbSFrançois Tigeot {
157926deccbSFrançois Tigeot 	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
158926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = pdata->encoder;
159926deccbSFrançois Tigeot 
160926deccbSFrançois Tigeot 	atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd));
161926deccbSFrançois Tigeot 
162926deccbSFrançois Tigeot 	return 0;
163926deccbSFrançois Tigeot }
164926deccbSFrançois Tigeot 
165926deccbSFrançois Tigeot static int radeon_atom_backlight_get_brightness(struct backlight_device *bd)
166926deccbSFrançois Tigeot {
167926deccbSFrançois Tigeot 	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
168926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = pdata->encoder;
169926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
170926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
171926deccbSFrançois Tigeot 
172926deccbSFrançois Tigeot 	return radeon_atom_get_backlight_level_from_reg(rdev);
173926deccbSFrançois Tigeot }
174926deccbSFrançois Tigeot 
175926deccbSFrançois Tigeot static const struct backlight_ops radeon_atom_backlight_ops = {
176926deccbSFrançois Tigeot 	.get_brightness = radeon_atom_backlight_get_brightness,
177926deccbSFrançois Tigeot 	.update_status	= radeon_atom_backlight_update_status,
178926deccbSFrançois Tigeot };
179ce73550bSFrançois Tigeot #endif
180926deccbSFrançois Tigeot 
1816a4774b1SImre Vadász /*
1826a4774b1SImre Vadász  * Read max backlight level
1836a4774b1SImre Vadász  */
1846a4774b1SImre Vadász static int
sysctl_backlight_max(SYSCTL_HANDLER_ARGS)1856a4774b1SImre Vadász sysctl_backlight_max(SYSCTL_HANDLER_ARGS)
1866a4774b1SImre Vadász {
1876a4774b1SImre Vadász 	int err, val;
1886a4774b1SImre Vadász 
1896a4774b1SImre Vadász 	val = RADEON_MAX_BL_LEVEL;
1906a4774b1SImre Vadász 	err = sysctl_handle_int(oidp, &val, 0, req);
1916a4774b1SImre Vadász 	return(err);
1926a4774b1SImre Vadász }
1936a4774b1SImre Vadász 
1946a4774b1SImre Vadász /*
1956a4774b1SImre Vadász  * Read/write backlight level
1966a4774b1SImre Vadász  */
1976a4774b1SImre Vadász static int
sysctl_backlight_handler(SYSCTL_HANDLER_ARGS)1986a4774b1SImre Vadász sysctl_backlight_handler(SYSCTL_HANDLER_ARGS)
1996a4774b1SImre Vadász {
2006a4774b1SImre Vadász 	struct radeon_encoder *encoder;
2016a4774b1SImre Vadász 	struct radeon_encoder_atom_dig *dig;
2026a4774b1SImre Vadász 	int err, val;
2036a4774b1SImre Vadász 
2046a4774b1SImre Vadász 	encoder = (struct radeon_encoder *)arg1;
2056a4774b1SImre Vadász 	dig = encoder->enc_priv;
2066a4774b1SImre Vadász 	val = dig->backlight_level;
2076a4774b1SImre Vadász 
2086a4774b1SImre Vadász 	err = sysctl_handle_int(oidp, &val, 0, req);
2096a4774b1SImre Vadász 	if (err != 0 || req->newptr == NULL) {
2106a4774b1SImre Vadász 		return(err);
2116a4774b1SImre Vadász 	}
2126a4774b1SImre Vadász 	if (dig->backlight_level != val && val >= 0 &&
2136a4774b1SImre Vadász 	    val <= RADEON_MAX_BL_LEVEL) {
2146a4774b1SImre Vadász 		atombios_set_backlight_level(encoder, val);
2156a4774b1SImre Vadász 	}
2166a4774b1SImre Vadász 
2176a4774b1SImre Vadász 	return(err);
2186a4774b1SImre Vadász }
2196a4774b1SImre Vadász 
radeon_atom_backlight_init(struct radeon_encoder * radeon_encoder,struct drm_connector * drm_connector)220926deccbSFrançois Tigeot void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
221926deccbSFrançois Tigeot 				struct drm_connector *drm_connector)
222926deccbSFrançois Tigeot {
2236a4774b1SImre Vadász 	struct drm_device *dev = radeon_encoder->base.dev;
2246a4774b1SImre Vadász 	struct radeon_device *rdev = dev->dev_private;
225*a85cb24fSFrançois Tigeot #if 0
226*a85cb24fSFrançois Tigeot 	struct backlight_device *bd;
227*a85cb24fSFrançois Tigeot #endif
228*a85cb24fSFrançois Tigeot 	struct backlight_properties props;
229*a85cb24fSFrançois Tigeot 	struct radeon_backlight_privdata *pdata;
2306a4774b1SImre Vadász 	struct radeon_encoder_atom_dig *dig;
231*a85cb24fSFrançois Tigeot 	char bl_name[16];
232*a85cb24fSFrançois Tigeot 
233*a85cb24fSFrançois Tigeot 	/* Mac laptops with multiple GPUs use the gmux driver for backlight
234*a85cb24fSFrançois Tigeot 	 * so don't register a backlight device
235*a85cb24fSFrançois Tigeot 	 */
236*a85cb24fSFrançois Tigeot 	if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
237*a85cb24fSFrançois Tigeot 	    (rdev->pdev->device == 0x6741))
238*a85cb24fSFrançois Tigeot 		return;
2396a4774b1SImre Vadász 
2406a4774b1SImre Vadász 	if (!radeon_encoder->enc_priv)
2416a4774b1SImre Vadász 		return;
2426a4774b1SImre Vadász 
2436a4774b1SImre Vadász 	if (!rdev->is_atom_bios)
2446a4774b1SImre Vadász 		return;
2456a4774b1SImre Vadász 
2466a4774b1SImre Vadász 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
2476a4774b1SImre Vadász 		return;
2486a4774b1SImre Vadász 
249*a85cb24fSFrançois Tigeot 	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), M_DRM,
250*a85cb24fSFrançois Tigeot 			GFP_KERNEL);
251*a85cb24fSFrançois Tigeot 	if (!pdata) {
252*a85cb24fSFrançois Tigeot 		DRM_ERROR("Memory allocation failed\n");
253*a85cb24fSFrançois Tigeot 		goto error;
254*a85cb24fSFrançois Tigeot 	}
255*a85cb24fSFrançois Tigeot 
256*a85cb24fSFrançois Tigeot 	memset(&props, 0, sizeof(props));
257*a85cb24fSFrançois Tigeot 	props.max_brightness = RADEON_MAX_BL_LEVEL;
258*a85cb24fSFrançois Tigeot 	props.type = BACKLIGHT_RAW;
259*a85cb24fSFrançois Tigeot 	snprintf(bl_name, sizeof(bl_name),
260*a85cb24fSFrançois Tigeot 		 "radeon_bl%d", dev->primary->index);
261*a85cb24fSFrançois Tigeot #if 0
262*a85cb24fSFrançois Tigeot 	bd = backlight_device_register(bl_name, drm_connector->kdev,
263*a85cb24fSFrançois Tigeot 				       pdata, &radeon_atom_backlight_ops, &props);
264*a85cb24fSFrançois Tigeot 	if (IS_ERR(bd)) {
265*a85cb24fSFrançois Tigeot 		DRM_ERROR("Backlight registration failed\n");
266*a85cb24fSFrançois Tigeot 		goto error;
267*a85cb24fSFrançois Tigeot 	}
268*a85cb24fSFrançois Tigeot #endif
269*a85cb24fSFrançois Tigeot 
270*a85cb24fSFrançois Tigeot 	pdata->encoder = radeon_encoder;
271*a85cb24fSFrançois Tigeot 
2726a4774b1SImre Vadász 	dig = radeon_encoder->enc_priv;
273*a85cb24fSFrançois Tigeot #if 0
274*a85cb24fSFrançois Tigeot 	dig->bl_dev = bd;
275*a85cb24fSFrançois Tigeot 
276*a85cb24fSFrançois Tigeot 	bd->props.brightness = radeon_atom_backlight_get_brightness(bd);
277*a85cb24fSFrançois Tigeot 	/* Set a reasonable default here if the level is 0 otherwise
278*a85cb24fSFrançois Tigeot 	 * fbdev will attempt to turn the backlight on after console
279*a85cb24fSFrançois Tigeot 	 * unblanking and it will try and restore 0 which turns the backlight
280*a85cb24fSFrançois Tigeot 	 * off again.
281*a85cb24fSFrançois Tigeot 	 */
282*a85cb24fSFrançois Tigeot 	if (bd->props.brightness == 0)
283*a85cb24fSFrançois Tigeot 		bd->props.brightness = RADEON_MAX_BL_LEVEL;
284*a85cb24fSFrançois Tigeot 	bd->props.power = FB_BLANK_UNBLANK;
285*a85cb24fSFrançois Tigeot 	backlight_update_status(bd);
286*a85cb24fSFrançois Tigeot #endif
2876a4774b1SImre Vadász 
2886a4774b1SImre Vadász 	DRM_INFO("radeon atom DIG backlight initialized\n");
289c59a5c48SFrançois Tigeot 	rdev->mode_info.bl_encoder = radeon_encoder;
2906a4774b1SImre Vadász 
2916a4774b1SImre Vadász 	SYSCTL_ADD_PROC(&drm_connector->dev->sysctl->ctx, &sysctl__hw_children,
2926a4774b1SImre Vadász 			OID_AUTO, "backlight_max",
2936a4774b1SImre Vadász 			CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_ANYBODY,
2946a4774b1SImre Vadász 			radeon_encoder, sizeof(int),
2956a4774b1SImre Vadász 			sysctl_backlight_max,
2966a4774b1SImre Vadász 			"I", "Max backlight level");
2976a4774b1SImre Vadász 	SYSCTL_ADD_PROC(&drm_connector->dev->sysctl->ctx, &sysctl__hw_children,
2986a4774b1SImre Vadász 			OID_AUTO, "backlight_level",
2996a4774b1SImre Vadász 			CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
3006a4774b1SImre Vadász 			radeon_encoder, sizeof(int),
3016a4774b1SImre Vadász 			sysctl_backlight_handler,
3026a4774b1SImre Vadász 			"I", "Backlight level");
303*a85cb24fSFrançois Tigeot 
304*a85cb24fSFrançois Tigeot 	return;
305*a85cb24fSFrançois Tigeot 
306*a85cb24fSFrançois Tigeot error:
307*a85cb24fSFrançois Tigeot 	kfree(pdata);
3086a4774b1SImre Vadász 	return;
309926deccbSFrançois Tigeot }
310926deccbSFrançois Tigeot 
radeon_atom_backlight_exit(struct radeon_encoder * radeon_encoder)311ce73550bSFrançois Tigeot static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder)
312ce73550bSFrançois Tigeot {
313ce73550bSFrançois Tigeot #if 0
314ce73550bSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
315ce73550bSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
316ce73550bSFrançois Tigeot 	struct backlight_device *bd = NULL;
317ce73550bSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
318ce73550bSFrançois Tigeot 
319ce73550bSFrançois Tigeot 	if (!radeon_encoder->enc_priv)
320ce73550bSFrançois Tigeot 		return;
321ce73550bSFrançois Tigeot 
322ce73550bSFrançois Tigeot 	if (!rdev->is_atom_bios)
323ce73550bSFrançois Tigeot 		return;
324ce73550bSFrançois Tigeot 
325ce73550bSFrançois Tigeot 	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
326ce73550bSFrançois Tigeot 		return;
327ce73550bSFrançois Tigeot 
328ce73550bSFrançois Tigeot 	dig = radeon_encoder->enc_priv;
329ce73550bSFrançois Tigeot 	bd = dig->bl_dev;
330ce73550bSFrançois Tigeot 	dig->bl_dev = NULL;
331ce73550bSFrançois Tigeot 
332ce73550bSFrançois Tigeot 	if (bd) {
333ce73550bSFrançois Tigeot 		struct radeon_legacy_backlight_privdata *pdata;
334ce73550bSFrançois Tigeot 
335ce73550bSFrançois Tigeot 		pdata = bl_get_data(bd);
336ce73550bSFrançois Tigeot 		backlight_device_unregister(bd);
337ce73550bSFrançois Tigeot 		kfree(pdata);
338ce73550bSFrançois Tigeot 
339ce73550bSFrançois Tigeot 		DRM_INFO("radeon atom LVDS backlight unloaded\n");
340ce73550bSFrançois Tigeot 	}
341ce73550bSFrançois Tigeot #endif
342ce73550bSFrançois Tigeot }
343ce73550bSFrançois Tigeot 
344ce73550bSFrançois Tigeot #else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
345ce73550bSFrançois Tigeot 
radeon_atom_backlight_init(struct radeon_encoder * encoder)346*a85cb24fSFrançois Tigeot void radeon_atom_backlight_init(struct radeon_encoder *encoder)
347ce73550bSFrançois Tigeot {
348ce73550bSFrançois Tigeot }
349ce73550bSFrançois Tigeot 
radeon_atom_backlight_exit(struct radeon_encoder * encoder)350926deccbSFrançois Tigeot static void radeon_atom_backlight_exit(struct radeon_encoder *encoder)
351926deccbSFrançois Tigeot {
352926deccbSFrançois Tigeot }
353926deccbSFrançois Tigeot 
354926deccbSFrançois Tigeot #endif
355926deccbSFrançois Tigeot 
radeon_atom_mode_fixup(struct drm_encoder * encoder,const struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)356926deccbSFrançois Tigeot static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
357926deccbSFrançois Tigeot 				   const struct drm_display_mode *mode,
358926deccbSFrançois Tigeot 				   struct drm_display_mode *adjusted_mode)
359926deccbSFrançois Tigeot {
360926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
361926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
362926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
363926deccbSFrançois Tigeot 
364926deccbSFrançois Tigeot 	/* set the active encoder to connector routing */
365926deccbSFrançois Tigeot 	radeon_encoder_set_active_device(encoder);
366926deccbSFrançois Tigeot 	drm_mode_set_crtcinfo(adjusted_mode, 0);
367926deccbSFrançois Tigeot 
368926deccbSFrançois Tigeot 	/* hw bug */
369926deccbSFrançois Tigeot 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
370926deccbSFrançois Tigeot 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
371926deccbSFrançois Tigeot 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
372926deccbSFrançois Tigeot 
373c59a5c48SFrançois Tigeot 	/* vertical FP must be at least 1 */
374c59a5c48SFrançois Tigeot 	if (mode->crtc_vsync_start == mode->crtc_vdisplay)
375c59a5c48SFrançois Tigeot 		adjusted_mode->crtc_vsync_start++;
376c59a5c48SFrançois Tigeot 
377c6f73aabSFrançois Tigeot 	/* get the native mode for scaling */
378c6f73aabSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
379926deccbSFrançois Tigeot 		radeon_panel_mode_fixup(encoder, adjusted_mode);
380c6f73aabSFrançois Tigeot 	} else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
381926deccbSFrançois Tigeot 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
382926deccbSFrançois Tigeot 		if (tv_dac) {
383926deccbSFrançois Tigeot 			if (tv_dac->tv_std == TV_STD_NTSC ||
384926deccbSFrançois Tigeot 			    tv_dac->tv_std == TV_STD_NTSC_J ||
385926deccbSFrançois Tigeot 			    tv_dac->tv_std == TV_STD_PAL_M)
386926deccbSFrançois Tigeot 				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
387926deccbSFrançois Tigeot 			else
388926deccbSFrançois Tigeot 				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
389926deccbSFrançois Tigeot 		}
390c6f73aabSFrançois Tigeot 	} else if (radeon_encoder->rmx_type != RMX_OFF) {
391c6f73aabSFrançois Tigeot 		radeon_panel_mode_fixup(encoder, adjusted_mode);
392926deccbSFrançois Tigeot 	}
393926deccbSFrançois Tigeot 
394926deccbSFrançois Tigeot 	if (ASIC_IS_DCE3(rdev) &&
395926deccbSFrançois Tigeot 	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
396926deccbSFrançois Tigeot 	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
397926deccbSFrançois Tigeot 		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
398926deccbSFrançois Tigeot 		radeon_dp_set_link_config(connector, adjusted_mode);
399926deccbSFrançois Tigeot 	}
400926deccbSFrançois Tigeot 
401926deccbSFrançois Tigeot 	return true;
402926deccbSFrançois Tigeot }
403926deccbSFrançois Tigeot 
404926deccbSFrançois Tigeot static void
atombios_dac_setup(struct drm_encoder * encoder,int action)405926deccbSFrançois Tigeot atombios_dac_setup(struct drm_encoder *encoder, int action)
406926deccbSFrançois Tigeot {
407926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
408926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
409926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
410926deccbSFrançois Tigeot 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
411926deccbSFrançois Tigeot 	int index = 0;
412926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
413926deccbSFrançois Tigeot 
414926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
415926deccbSFrançois Tigeot 
416926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
417926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
418926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
419926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
420926deccbSFrançois Tigeot 		break;
421926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
422926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
423926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
424926deccbSFrançois Tigeot 		break;
425926deccbSFrançois Tigeot 	}
426926deccbSFrançois Tigeot 
427926deccbSFrançois Tigeot 	args.ucAction = action;
428926deccbSFrançois Tigeot 
429926deccbSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
430926deccbSFrançois Tigeot 		args.ucDacStandard = ATOM_DAC1_PS2;
431926deccbSFrançois Tigeot 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
432926deccbSFrançois Tigeot 		args.ucDacStandard = ATOM_DAC1_CV;
433926deccbSFrançois Tigeot 	else {
434926deccbSFrançois Tigeot 		switch (dac_info->tv_std) {
435926deccbSFrançois Tigeot 		case TV_STD_PAL:
436926deccbSFrançois Tigeot 		case TV_STD_PAL_M:
437926deccbSFrançois Tigeot 		case TV_STD_SCART_PAL:
438926deccbSFrançois Tigeot 		case TV_STD_SECAM:
439926deccbSFrançois Tigeot 		case TV_STD_PAL_CN:
440926deccbSFrançois Tigeot 			args.ucDacStandard = ATOM_DAC1_PAL;
441926deccbSFrançois Tigeot 			break;
442926deccbSFrançois Tigeot 		case TV_STD_NTSC:
443926deccbSFrançois Tigeot 		case TV_STD_NTSC_J:
444926deccbSFrançois Tigeot 		case TV_STD_PAL_60:
445926deccbSFrançois Tigeot 		default:
446926deccbSFrançois Tigeot 			args.ucDacStandard = ATOM_DAC1_NTSC;
447926deccbSFrançois Tigeot 			break;
448926deccbSFrançois Tigeot 		}
449926deccbSFrançois Tigeot 	}
450926deccbSFrançois Tigeot 	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
451926deccbSFrançois Tigeot 
452926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
453926deccbSFrançois Tigeot 
454926deccbSFrançois Tigeot }
455926deccbSFrançois Tigeot 
456926deccbSFrançois Tigeot static void
atombios_tv_setup(struct drm_encoder * encoder,int action)457926deccbSFrançois Tigeot atombios_tv_setup(struct drm_encoder *encoder, int action)
458926deccbSFrançois Tigeot {
459926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
460926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
461926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
462926deccbSFrançois Tigeot 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
463926deccbSFrançois Tigeot 	int index = 0;
464926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
465926deccbSFrançois Tigeot 
466926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
467926deccbSFrançois Tigeot 
468926deccbSFrançois Tigeot 	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
469926deccbSFrançois Tigeot 
470926deccbSFrançois Tigeot 	args.sTVEncoder.ucAction = action;
471926deccbSFrançois Tigeot 
472926deccbSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
473926deccbSFrançois Tigeot 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
474926deccbSFrançois Tigeot 	else {
475926deccbSFrançois Tigeot 		switch (dac_info->tv_std) {
476926deccbSFrançois Tigeot 		case TV_STD_NTSC:
477926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
478926deccbSFrançois Tigeot 			break;
479926deccbSFrançois Tigeot 		case TV_STD_PAL:
480926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
481926deccbSFrançois Tigeot 			break;
482926deccbSFrançois Tigeot 		case TV_STD_PAL_M:
483926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
484926deccbSFrançois Tigeot 			break;
485926deccbSFrançois Tigeot 		case TV_STD_PAL_60:
486926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
487926deccbSFrançois Tigeot 			break;
488926deccbSFrançois Tigeot 		case TV_STD_NTSC_J:
489926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
490926deccbSFrançois Tigeot 			break;
491926deccbSFrançois Tigeot 		case TV_STD_SCART_PAL:
492926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
493926deccbSFrançois Tigeot 			break;
494926deccbSFrançois Tigeot 		case TV_STD_SECAM:
495926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
496926deccbSFrançois Tigeot 			break;
497926deccbSFrançois Tigeot 		case TV_STD_PAL_CN:
498926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
499926deccbSFrançois Tigeot 			break;
500926deccbSFrançois Tigeot 		default:
501926deccbSFrançois Tigeot 			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
502926deccbSFrançois Tigeot 			break;
503926deccbSFrançois Tigeot 		}
504926deccbSFrançois Tigeot 	}
505926deccbSFrançois Tigeot 
506926deccbSFrançois Tigeot 	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
507926deccbSFrançois Tigeot 
508926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
509926deccbSFrançois Tigeot 
510926deccbSFrançois Tigeot }
511926deccbSFrançois Tigeot 
radeon_atom_get_bpc(struct drm_encoder * encoder)512926deccbSFrançois Tigeot static u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
513926deccbSFrançois Tigeot {
514926deccbSFrançois Tigeot 	int bpc = 8;
515926deccbSFrançois Tigeot 
516c6f73aabSFrançois Tigeot 	if (encoder->crtc) {
517c6f73aabSFrançois Tigeot 		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
518c6f73aabSFrançois Tigeot 		bpc = radeon_crtc->bpc;
519c6f73aabSFrançois Tigeot 	}
520926deccbSFrançois Tigeot 
521926deccbSFrançois Tigeot 	switch (bpc) {
522926deccbSFrançois Tigeot 	case 0:
523926deccbSFrançois Tigeot 		return PANEL_BPC_UNDEFINE;
524926deccbSFrançois Tigeot 	case 6:
525926deccbSFrançois Tigeot 		return PANEL_6BIT_PER_COLOR;
526926deccbSFrançois Tigeot 	case 8:
527926deccbSFrançois Tigeot 	default:
528926deccbSFrançois Tigeot 		return PANEL_8BIT_PER_COLOR;
529926deccbSFrançois Tigeot 	case 10:
530926deccbSFrançois Tigeot 		return PANEL_10BIT_PER_COLOR;
531926deccbSFrançois Tigeot 	case 12:
532926deccbSFrançois Tigeot 		return PANEL_12BIT_PER_COLOR;
533926deccbSFrançois Tigeot 	case 16:
534926deccbSFrançois Tigeot 		return PANEL_16BIT_PER_COLOR;
535926deccbSFrançois Tigeot 	}
536926deccbSFrançois Tigeot }
537926deccbSFrançois Tigeot 
538926deccbSFrançois Tigeot union dvo_encoder_control {
539926deccbSFrançois Tigeot 	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
540926deccbSFrançois Tigeot 	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
541926deccbSFrançois Tigeot 	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
54257e252bfSMichael Neumann 	DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 dvo_v4;
543926deccbSFrançois Tigeot };
544926deccbSFrançois Tigeot 
545926deccbSFrançois Tigeot void
atombios_dvo_setup(struct drm_encoder * encoder,int action)546926deccbSFrançois Tigeot atombios_dvo_setup(struct drm_encoder *encoder, int action)
547926deccbSFrançois Tigeot {
548926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
549926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
550926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
551926deccbSFrançois Tigeot 	union dvo_encoder_control args;
552926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
553926deccbSFrançois Tigeot 	uint8_t frev, crev;
554926deccbSFrançois Tigeot 
555926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
556926deccbSFrançois Tigeot 
557926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
558926deccbSFrançois Tigeot 		return;
559926deccbSFrançois Tigeot 
560926deccbSFrançois Tigeot 	/* some R4xx chips have the wrong frev */
561926deccbSFrançois Tigeot 	if (rdev->family <= CHIP_RV410)
562926deccbSFrançois Tigeot 		frev = 1;
563926deccbSFrançois Tigeot 
564926deccbSFrançois Tigeot 	switch (frev) {
565926deccbSFrançois Tigeot 	case 1:
566926deccbSFrançois Tigeot 		switch (crev) {
567926deccbSFrançois Tigeot 		case 1:
568926deccbSFrançois Tigeot 			/* R4xx, R5xx */
569926deccbSFrançois Tigeot 			args.ext_tmds.sXTmdsEncoder.ucEnable = action;
570926deccbSFrançois Tigeot 
571926deccbSFrançois Tigeot 			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
572926deccbSFrançois Tigeot 				args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
573926deccbSFrançois Tigeot 
574926deccbSFrançois Tigeot 			args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
575926deccbSFrançois Tigeot 			break;
576926deccbSFrançois Tigeot 		case 2:
577926deccbSFrançois Tigeot 			/* RS600/690/740 */
578926deccbSFrançois Tigeot 			args.dvo.sDVOEncoder.ucAction = action;
579926deccbSFrançois Tigeot 			args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
580926deccbSFrançois Tigeot 			/* DFP1, CRT1, TV1 depending on the type of port */
581926deccbSFrançois Tigeot 			args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
582926deccbSFrançois Tigeot 
583926deccbSFrançois Tigeot 			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
584926deccbSFrançois Tigeot 				args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
585926deccbSFrançois Tigeot 			break;
586926deccbSFrançois Tigeot 		case 3:
587926deccbSFrançois Tigeot 			/* R6xx */
588926deccbSFrançois Tigeot 			args.dvo_v3.ucAction = action;
589926deccbSFrançois Tigeot 			args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
590926deccbSFrançois Tigeot 			args.dvo_v3.ucDVOConfig = 0; /* XXX */
591926deccbSFrançois Tigeot 			break;
59257e252bfSMichael Neumann 		case 4:
59357e252bfSMichael Neumann 			/* DCE8 */
59457e252bfSMichael Neumann 			args.dvo_v4.ucAction = action;
59557e252bfSMichael Neumann 			args.dvo_v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
59657e252bfSMichael Neumann 			args.dvo_v4.ucDVOConfig = 0; /* XXX */
59757e252bfSMichael Neumann 			args.dvo_v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
59857e252bfSMichael Neumann 			break;
599926deccbSFrançois Tigeot 		default:
600926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
601926deccbSFrançois Tigeot 			break;
602926deccbSFrançois Tigeot 		}
603926deccbSFrançois Tigeot 		break;
604926deccbSFrançois Tigeot 	default:
605926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
606926deccbSFrançois Tigeot 		break;
607926deccbSFrançois Tigeot 	}
608926deccbSFrançois Tigeot 
609926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
610926deccbSFrançois Tigeot }
611926deccbSFrançois Tigeot 
612926deccbSFrançois Tigeot union lvds_encoder_control {
613926deccbSFrançois Tigeot 	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
614926deccbSFrançois Tigeot 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
615926deccbSFrançois Tigeot };
616926deccbSFrançois Tigeot 
617926deccbSFrançois Tigeot void
atombios_digital_setup(struct drm_encoder * encoder,int action)618926deccbSFrançois Tigeot atombios_digital_setup(struct drm_encoder *encoder, int action)
619926deccbSFrançois Tigeot {
620926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
621926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
622926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
623926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
624926deccbSFrançois Tigeot 	union lvds_encoder_control args;
625926deccbSFrançois Tigeot 	int index = 0;
626926deccbSFrançois Tigeot 	int hdmi_detected = 0;
627926deccbSFrançois Tigeot 	uint8_t frev, crev;
628926deccbSFrançois Tigeot 
629926deccbSFrançois Tigeot 	if (!dig)
630926deccbSFrançois Tigeot 		return;
631926deccbSFrançois Tigeot 
632926deccbSFrançois Tigeot 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
633926deccbSFrançois Tigeot 		hdmi_detected = 1;
634926deccbSFrançois Tigeot 
635926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
636926deccbSFrançois Tigeot 
637926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
638926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
639926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
640926deccbSFrançois Tigeot 		break;
641926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
642926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
643926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
644926deccbSFrançois Tigeot 		break;
645926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
646926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
647926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
648926deccbSFrançois Tigeot 		else
649926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
650926deccbSFrançois Tigeot 		break;
651926deccbSFrançois Tigeot 	}
652926deccbSFrançois Tigeot 
653926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
654926deccbSFrançois Tigeot 		return;
655926deccbSFrançois Tigeot 
656926deccbSFrançois Tigeot 	switch (frev) {
657926deccbSFrançois Tigeot 	case 1:
658926deccbSFrançois Tigeot 	case 2:
659926deccbSFrançois Tigeot 		switch (crev) {
660926deccbSFrançois Tigeot 		case 1:
661926deccbSFrançois Tigeot 			args.v1.ucMisc = 0;
662926deccbSFrançois Tigeot 			args.v1.ucAction = action;
663926deccbSFrançois Tigeot 			if (hdmi_detected)
664926deccbSFrançois Tigeot 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
665926deccbSFrançois Tigeot 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
666926deccbSFrançois Tigeot 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
667926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
668926deccbSFrançois Tigeot 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
669926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
670926deccbSFrançois Tigeot 					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
671926deccbSFrançois Tigeot 			} else {
672926deccbSFrançois Tigeot 				if (dig->linkb)
673926deccbSFrançois Tigeot 					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
674926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
675926deccbSFrançois Tigeot 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
676926deccbSFrançois Tigeot 				/*if (pScrn->rgbBits == 8) */
677926deccbSFrançois Tigeot 				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
678926deccbSFrançois Tigeot 			}
679926deccbSFrançois Tigeot 			break;
680926deccbSFrançois Tigeot 		case 2:
681926deccbSFrançois Tigeot 		case 3:
682926deccbSFrançois Tigeot 			args.v2.ucMisc = 0;
683926deccbSFrançois Tigeot 			args.v2.ucAction = action;
684926deccbSFrançois Tigeot 			if (crev == 3) {
685926deccbSFrançois Tigeot 				if (dig->coherent_mode)
686926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
687926deccbSFrançois Tigeot 			}
688926deccbSFrançois Tigeot 			if (hdmi_detected)
689926deccbSFrançois Tigeot 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
690926deccbSFrançois Tigeot 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
691926deccbSFrançois Tigeot 			args.v2.ucTruncate = 0;
692926deccbSFrançois Tigeot 			args.v2.ucSpatial = 0;
693926deccbSFrançois Tigeot 			args.v2.ucTemporal = 0;
694926deccbSFrançois Tigeot 			args.v2.ucFRC = 0;
695926deccbSFrançois Tigeot 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
696926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
697926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
698926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
699926deccbSFrançois Tigeot 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
700926deccbSFrançois Tigeot 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
701926deccbSFrançois Tigeot 						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
702926deccbSFrançois Tigeot 				}
703926deccbSFrançois Tigeot 				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
704926deccbSFrançois Tigeot 					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
705926deccbSFrançois Tigeot 					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
706926deccbSFrançois Tigeot 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
707926deccbSFrançois Tigeot 					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
708926deccbSFrançois Tigeot 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
709926deccbSFrançois Tigeot 				}
710926deccbSFrançois Tigeot 			} else {
711926deccbSFrançois Tigeot 				if (dig->linkb)
712926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
713926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
714926deccbSFrançois Tigeot 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
715926deccbSFrançois Tigeot 			}
716926deccbSFrançois Tigeot 			break;
717926deccbSFrançois Tigeot 		default:
718926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
719926deccbSFrançois Tigeot 			break;
720926deccbSFrançois Tigeot 		}
721926deccbSFrançois Tigeot 		break;
722926deccbSFrançois Tigeot 	default:
723926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
724926deccbSFrançois Tigeot 		break;
725926deccbSFrançois Tigeot 	}
726926deccbSFrançois Tigeot 
727926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
728926deccbSFrançois Tigeot }
729926deccbSFrançois Tigeot 
730926deccbSFrançois Tigeot int
atombios_get_encoder_mode(struct drm_encoder * encoder)731926deccbSFrançois Tigeot atombios_get_encoder_mode(struct drm_encoder *encoder)
732926deccbSFrançois Tigeot {
733c59a5c48SFrançois Tigeot 	struct drm_device *dev = encoder->dev;
734c59a5c48SFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
735926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
736926deccbSFrançois Tigeot 	struct drm_connector *connector;
737926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector;
738926deccbSFrançois Tigeot 	struct radeon_connector_atom_dig *dig_connector;
739c59a5c48SFrançois Tigeot 	struct radeon_encoder_atom_dig *dig_enc;
740926deccbSFrançois Tigeot 
741c59a5c48SFrançois Tigeot 	if (radeon_encoder_is_digital(encoder)) {
742c59a5c48SFrançois Tigeot 		dig_enc = radeon_encoder->enc_priv;
743c59a5c48SFrançois Tigeot 		if (dig_enc->active_mst_links)
744c59a5c48SFrançois Tigeot 			return ATOM_ENCODER_MODE_DP_MST;
745c59a5c48SFrançois Tigeot 	}
746c59a5c48SFrançois Tigeot 	if (radeon_encoder->is_mst_encoder || radeon_encoder->offset)
747c59a5c48SFrançois Tigeot 		return ATOM_ENCODER_MODE_DP_MST;
748926deccbSFrançois Tigeot 	/* dp bridges are always DP */
749926deccbSFrançois Tigeot 	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
750926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_DP;
751926deccbSFrançois Tigeot 
752926deccbSFrançois Tigeot 	/* DVO is always DVO */
753926deccbSFrançois Tigeot 	if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) ||
754926deccbSFrançois Tigeot 	    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
755926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_DVO;
756926deccbSFrançois Tigeot 
757926deccbSFrançois Tigeot 	connector = radeon_get_connector_for_encoder(encoder);
758926deccbSFrançois Tigeot 	/* if we don't have an active device yet, just use one of
759926deccbSFrançois Tigeot 	 * the connectors tied to the encoder.
760926deccbSFrançois Tigeot 	 */
761926deccbSFrançois Tigeot 	if (!connector)
762926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder_init(encoder);
763926deccbSFrançois Tigeot 	radeon_connector = to_radeon_connector(connector);
764926deccbSFrançois Tigeot 
765926deccbSFrançois Tigeot 	switch (connector->connector_type) {
766926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DVII:
767926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
7684cd92098Szrj 		if (radeon_audio != 0) {
7694cd92098Szrj 			if (radeon_connector->use_digital &&
7704cd92098Szrj 			    (radeon_connector->audio == RADEON_AUDIO_ENABLE))
7714cd92098Szrj 				return ATOM_ENCODER_MODE_HDMI;
772c6f73aabSFrançois Tigeot 			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7734cd92098Szrj 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
774926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_HDMI;
775926deccbSFrançois Tigeot 			else if (radeon_connector->use_digital)
776926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_DVI;
777926deccbSFrançois Tigeot 			else
778926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_CRT;
7794cd92098Szrj 		} else if (radeon_connector->use_digital) {
7804cd92098Szrj 			return ATOM_ENCODER_MODE_DVI;
7814cd92098Szrj 		} else {
7824cd92098Szrj 			return ATOM_ENCODER_MODE_CRT;
7834cd92098Szrj 		}
784926deccbSFrançois Tigeot 		break;
785926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DVID:
786926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_HDMIA:
787926deccbSFrançois Tigeot 	default:
7884cd92098Szrj 		if (radeon_audio != 0) {
7894cd92098Szrj 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
7904cd92098Szrj 				return ATOM_ENCODER_MODE_HDMI;
791c6f73aabSFrançois Tigeot 			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7924cd92098Szrj 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
793926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_HDMI;
794926deccbSFrançois Tigeot 			else
795926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_DVI;
7964cd92098Szrj 		} else {
7974cd92098Szrj 			return ATOM_ENCODER_MODE_DVI;
7984cd92098Szrj 		}
799926deccbSFrançois Tigeot 		break;
800926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_LVDS:
801926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_LVDS;
802926deccbSFrançois Tigeot 		break;
803926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DisplayPort:
804926deccbSFrançois Tigeot 		dig_connector = radeon_connector->con_priv;
805926deccbSFrançois Tigeot 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
8064cd92098Szrj 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
807c59a5c48SFrançois Tigeot 			if (radeon_audio != 0 &&
808c59a5c48SFrançois Tigeot 			    drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
809c59a5c48SFrançois Tigeot 			    ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
810c59a5c48SFrançois Tigeot 				return ATOM_ENCODER_MODE_DP_AUDIO;
811926deccbSFrançois Tigeot 			return ATOM_ENCODER_MODE_DP;
8124cd92098Szrj 		} else if (radeon_audio != 0) {
8134cd92098Szrj 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
8144cd92098Szrj 				return ATOM_ENCODER_MODE_HDMI;
815c6f73aabSFrançois Tigeot 			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
8164cd92098Szrj 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
817926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_HDMI;
818926deccbSFrançois Tigeot 			else
819926deccbSFrançois Tigeot 				return ATOM_ENCODER_MODE_DVI;
8204cd92098Szrj 		} else {
8214cd92098Szrj 			return ATOM_ENCODER_MODE_DVI;
8224cd92098Szrj 		}
823926deccbSFrançois Tigeot 		break;
824926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_eDP:
825c59a5c48SFrançois Tigeot 		if (radeon_audio != 0 &&
826c59a5c48SFrançois Tigeot 		    drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
827c59a5c48SFrançois Tigeot 		    ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
828c59a5c48SFrançois Tigeot 			return ATOM_ENCODER_MODE_DP_AUDIO;
829926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_DP;
830926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_DVIA:
831926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_VGA:
832926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_CRT;
833926deccbSFrançois Tigeot 		break;
834926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_Composite:
835926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_SVIDEO:
836926deccbSFrançois Tigeot 	case DRM_MODE_CONNECTOR_9PinDIN:
837926deccbSFrançois Tigeot 		/* fix me */
838926deccbSFrançois Tigeot 		return ATOM_ENCODER_MODE_TV;
839926deccbSFrançois Tigeot 		/*return ATOM_ENCODER_MODE_CV;*/
840926deccbSFrançois Tigeot 		break;
841926deccbSFrançois Tigeot 	}
842926deccbSFrançois Tigeot }
843926deccbSFrançois Tigeot 
844926deccbSFrançois Tigeot /*
845926deccbSFrançois Tigeot  * DIG Encoder/Transmitter Setup
846926deccbSFrançois Tigeot  *
847926deccbSFrançois Tigeot  * DCE 3.0/3.1
848926deccbSFrançois Tigeot  * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
849926deccbSFrançois Tigeot  * Supports up to 3 digital outputs
850926deccbSFrançois Tigeot  * - 2 DIG encoder blocks.
851926deccbSFrançois Tigeot  * DIG1 can drive UNIPHY link A or link B
852926deccbSFrançois Tigeot  * DIG2 can drive UNIPHY link B or LVTMA
853926deccbSFrançois Tigeot  *
854926deccbSFrançois Tigeot  * DCE 3.2
855926deccbSFrançois Tigeot  * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
856926deccbSFrançois Tigeot  * Supports up to 5 digital outputs
857926deccbSFrançois Tigeot  * - 2 DIG encoder blocks.
858926deccbSFrançois Tigeot  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
859926deccbSFrançois Tigeot  *
860926deccbSFrançois Tigeot  * DCE 4.0/5.0/6.0
861926deccbSFrançois Tigeot  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
862926deccbSFrançois Tigeot  * Supports up to 6 digital outputs
863926deccbSFrançois Tigeot  * - 6 DIG encoder blocks.
864926deccbSFrançois Tigeot  * - DIG to PHY mapping is hardcoded
865926deccbSFrançois Tigeot  * DIG1 drives UNIPHY0 link A, A+B
866926deccbSFrançois Tigeot  * DIG2 drives UNIPHY0 link B
867926deccbSFrançois Tigeot  * DIG3 drives UNIPHY1 link A, A+B
868926deccbSFrançois Tigeot  * DIG4 drives UNIPHY1 link B
869926deccbSFrançois Tigeot  * DIG5 drives UNIPHY2 link A, A+B
870926deccbSFrançois Tigeot  * DIG6 drives UNIPHY2 link B
871926deccbSFrançois Tigeot  *
872926deccbSFrançois Tigeot  * DCE 4.1
873926deccbSFrançois Tigeot  * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
874926deccbSFrançois Tigeot  * Supports up to 6 digital outputs
875926deccbSFrançois Tigeot  * - 2 DIG encoder blocks.
876926deccbSFrançois Tigeot  * llano
877926deccbSFrançois Tigeot  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
878926deccbSFrançois Tigeot  * ontario
879926deccbSFrançois Tigeot  * DIG1 drives UNIPHY0/1/2 link A
880926deccbSFrançois Tigeot  * DIG2 drives UNIPHY0/1/2 link B
881926deccbSFrançois Tigeot  *
882926deccbSFrançois Tigeot  * Routing
883926deccbSFrançois Tigeot  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
884926deccbSFrançois Tigeot  * Examples:
885926deccbSFrançois Tigeot  * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
886926deccbSFrançois Tigeot  * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
887926deccbSFrançois Tigeot  * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
888926deccbSFrançois Tigeot  * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
889926deccbSFrançois Tigeot  */
890926deccbSFrançois Tigeot 
891926deccbSFrançois Tigeot union dig_encoder_control {
892926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
893926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
894926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
895926deccbSFrançois Tigeot 	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
896926deccbSFrançois Tigeot };
897926deccbSFrançois Tigeot 
898926deccbSFrançois Tigeot void
atombios_dig_encoder_setup2(struct drm_encoder * encoder,int action,int panel_mode,int enc_override)899c59a5c48SFrançois Tigeot atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override)
900926deccbSFrançois Tigeot {
901926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
902926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
903926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
904926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
905926deccbSFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
906926deccbSFrançois Tigeot 	union dig_encoder_control args;
907926deccbSFrançois Tigeot 	int index = 0;
908926deccbSFrançois Tigeot 	uint8_t frev, crev;
909926deccbSFrançois Tigeot 	int dp_clock = 0;
910926deccbSFrançois Tigeot 	int dp_lane_count = 0;
911926deccbSFrançois Tigeot 	int hpd_id = RADEON_HPD_NONE;
912926deccbSFrançois Tigeot 
913926deccbSFrançois Tigeot 	if (connector) {
914926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
915926deccbSFrançois Tigeot 		struct radeon_connector_atom_dig *dig_connector =
916926deccbSFrançois Tigeot 			radeon_connector->con_priv;
917926deccbSFrançois Tigeot 
918926deccbSFrançois Tigeot 		dp_clock = dig_connector->dp_clock;
919926deccbSFrançois Tigeot 		dp_lane_count = dig_connector->dp_lane_count;
920926deccbSFrançois Tigeot 		hpd_id = radeon_connector->hpd.hpd;
921926deccbSFrançois Tigeot 	}
922926deccbSFrançois Tigeot 
923926deccbSFrançois Tigeot 	/* no dig encoder assigned */
924926deccbSFrançois Tigeot 	if (dig->dig_encoder == -1)
925926deccbSFrançois Tigeot 		return;
926926deccbSFrançois Tigeot 
927926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
928926deccbSFrançois Tigeot 
929926deccbSFrançois Tigeot 	if (ASIC_IS_DCE4(rdev))
930926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
931926deccbSFrançois Tigeot 	else {
932926deccbSFrançois Tigeot 		if (dig->dig_encoder)
933926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
934926deccbSFrançois Tigeot 		else
935926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
936926deccbSFrançois Tigeot 	}
937926deccbSFrançois Tigeot 
938926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
939926deccbSFrançois Tigeot 		return;
940926deccbSFrançois Tigeot 
941926deccbSFrançois Tigeot 	switch (frev) {
942926deccbSFrançois Tigeot 	case 1:
943926deccbSFrançois Tigeot 		switch (crev) {
944926deccbSFrançois Tigeot 		case 1:
945926deccbSFrançois Tigeot 			args.v1.ucAction = action;
946926deccbSFrançois Tigeot 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
947926deccbSFrançois Tigeot 			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
948926deccbSFrançois Tigeot 				args.v3.ucPanelMode = panel_mode;
949926deccbSFrançois Tigeot 			else
950926deccbSFrançois Tigeot 				args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
951926deccbSFrançois Tigeot 
952926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
953926deccbSFrançois Tigeot 				args.v1.ucLaneNum = dp_lane_count;
954926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
955926deccbSFrançois Tigeot 				args.v1.ucLaneNum = 8;
956926deccbSFrançois Tigeot 			else
957926deccbSFrançois Tigeot 				args.v1.ucLaneNum = 4;
958926deccbSFrançois Tigeot 
959926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
960926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
961926deccbSFrançois Tigeot 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
962926deccbSFrançois Tigeot 				break;
963926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
964926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
965926deccbSFrançois Tigeot 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
966926deccbSFrançois Tigeot 				break;
967926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
968926deccbSFrançois Tigeot 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
969926deccbSFrançois Tigeot 				break;
970926deccbSFrançois Tigeot 			}
971926deccbSFrançois Tigeot 			if (dig->linkb)
972926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
973926deccbSFrançois Tigeot 			else
974926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
975c59a5c48SFrançois Tigeot 
976c59a5c48SFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
977c59a5c48SFrançois Tigeot 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
978c59a5c48SFrançois Tigeot 
979926deccbSFrançois Tigeot 			break;
980926deccbSFrançois Tigeot 		case 2:
981926deccbSFrançois Tigeot 		case 3:
982926deccbSFrançois Tigeot 			args.v3.ucAction = action;
983926deccbSFrançois Tigeot 			args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
984926deccbSFrançois Tigeot 			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
985926deccbSFrançois Tigeot 				args.v3.ucPanelMode = panel_mode;
986926deccbSFrançois Tigeot 			else
987926deccbSFrançois Tigeot 				args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
988926deccbSFrançois Tigeot 
989926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode))
990926deccbSFrançois Tigeot 				args.v3.ucLaneNum = dp_lane_count;
991926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
992926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 8;
993926deccbSFrançois Tigeot 			else
994926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 4;
995926deccbSFrançois Tigeot 
996926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
997926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
998c59a5c48SFrançois Tigeot 			if (enc_override != -1)
999c59a5c48SFrançois Tigeot 				args.v3.acConfig.ucDigSel = enc_override;
1000c59a5c48SFrançois Tigeot 			else
1001926deccbSFrançois Tigeot 				args.v3.acConfig.ucDigSel = dig->dig_encoder;
1002926deccbSFrançois Tigeot 			args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
1003926deccbSFrançois Tigeot 			break;
1004926deccbSFrançois Tigeot 		case 4:
1005926deccbSFrançois Tigeot 			args.v4.ucAction = action;
1006926deccbSFrançois Tigeot 			args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1007926deccbSFrançois Tigeot 			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
1008926deccbSFrançois Tigeot 				args.v4.ucPanelMode = panel_mode;
1009926deccbSFrançois Tigeot 			else
1010926deccbSFrançois Tigeot 				args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
1011926deccbSFrançois Tigeot 
1012926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode))
1013926deccbSFrançois Tigeot 				args.v4.ucLaneNum = dp_lane_count;
1014926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1015926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 8;
1016926deccbSFrançois Tigeot 			else
1017926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 4;
1018926deccbSFrançois Tigeot 
1019926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) {
102057e252bfSMichael Neumann 				if (dp_clock == 540000)
1021926deccbSFrançois Tigeot 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
102257e252bfSMichael Neumann 				else if (dp_clock == 324000)
102357e252bfSMichael Neumann 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ;
102457e252bfSMichael Neumann 				else if (dp_clock == 270000)
102557e252bfSMichael Neumann 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
102657e252bfSMichael Neumann 				else
102757e252bfSMichael Neumann 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
1028926deccbSFrançois Tigeot 			}
1029c59a5c48SFrançois Tigeot 
1030c59a5c48SFrançois Tigeot 			if (enc_override != -1)
1031c59a5c48SFrançois Tigeot 				args.v4.acConfig.ucDigSel = enc_override;
1032c59a5c48SFrançois Tigeot 			else
1033926deccbSFrançois Tigeot 				args.v4.acConfig.ucDigSel = dig->dig_encoder;
1034926deccbSFrançois Tigeot 			args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
1035926deccbSFrançois Tigeot 			if (hpd_id == RADEON_HPD_NONE)
1036926deccbSFrançois Tigeot 				args.v4.ucHPD_ID = 0;
1037926deccbSFrançois Tigeot 			else
1038926deccbSFrançois Tigeot 				args.v4.ucHPD_ID = hpd_id + 1;
1039926deccbSFrançois Tigeot 			break;
1040926deccbSFrançois Tigeot 		default:
1041926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1042926deccbSFrançois Tigeot 			break;
1043926deccbSFrançois Tigeot 		}
1044926deccbSFrançois Tigeot 		break;
1045926deccbSFrançois Tigeot 	default:
1046926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1047926deccbSFrançois Tigeot 		break;
1048926deccbSFrançois Tigeot 	}
1049926deccbSFrançois Tigeot 
1050926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1051926deccbSFrançois Tigeot 
1052926deccbSFrançois Tigeot }
1053926deccbSFrançois Tigeot 
1054c59a5c48SFrançois Tigeot void
atombios_dig_encoder_setup(struct drm_encoder * encoder,int action,int panel_mode)1055c59a5c48SFrançois Tigeot atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
1056c59a5c48SFrançois Tigeot {
1057c59a5c48SFrançois Tigeot 	atombios_dig_encoder_setup2(encoder, action, panel_mode, -1);
1058c59a5c48SFrançois Tigeot }
1059c59a5c48SFrançois Tigeot 
1060926deccbSFrançois Tigeot union dig_transmitter_control {
1061926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
1062926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
1063926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
1064926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
1065926deccbSFrançois Tigeot 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
1066926deccbSFrançois Tigeot };
1067926deccbSFrançois Tigeot 
1068926deccbSFrançois Tigeot void
atombios_dig_transmitter_setup2(struct drm_encoder * encoder,int action,uint8_t lane_num,uint8_t lane_set,int fe)1069c59a5c48SFrançois Tigeot atombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe)
1070926deccbSFrançois Tigeot {
1071926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1072926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1073926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1074926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1075926deccbSFrançois Tigeot 	struct drm_connector *connector;
1076926deccbSFrançois Tigeot 	union dig_transmitter_control args;
1077926deccbSFrançois Tigeot 	int index = 0;
1078926deccbSFrançois Tigeot 	uint8_t frev, crev;
1079926deccbSFrançois Tigeot 	bool is_dp = false;
1080926deccbSFrançois Tigeot 	int pll_id = 0;
1081926deccbSFrançois Tigeot 	int dp_clock = 0;
1082926deccbSFrançois Tigeot 	int dp_lane_count = 0;
1083926deccbSFrançois Tigeot 	int connector_object_id = 0;
1084926deccbSFrançois Tigeot 	int igp_lane_info = 0;
1085926deccbSFrançois Tigeot 	int dig_encoder = dig->dig_encoder;
1086926deccbSFrançois Tigeot 	int hpd_id = RADEON_HPD_NONE;
1087926deccbSFrançois Tigeot 
1088926deccbSFrançois Tigeot 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1089926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder_init(encoder);
1090926deccbSFrançois Tigeot 		/* just needed to avoid bailing in the encoder check.  the encoder
1091926deccbSFrançois Tigeot 		 * isn't used for init
1092926deccbSFrançois Tigeot 		 */
1093926deccbSFrançois Tigeot 		dig_encoder = 0;
1094926deccbSFrançois Tigeot 	} else
1095926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder(encoder);
1096926deccbSFrançois Tigeot 
1097926deccbSFrançois Tigeot 	if (connector) {
1098926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1099926deccbSFrançois Tigeot 		struct radeon_connector_atom_dig *dig_connector =
1100926deccbSFrançois Tigeot 			radeon_connector->con_priv;
1101926deccbSFrançois Tigeot 
1102926deccbSFrançois Tigeot 		hpd_id = radeon_connector->hpd.hpd;
1103926deccbSFrançois Tigeot 		dp_clock = dig_connector->dp_clock;
1104926deccbSFrançois Tigeot 		dp_lane_count = dig_connector->dp_lane_count;
1105926deccbSFrançois Tigeot 		connector_object_id =
1106926deccbSFrançois Tigeot 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1107926deccbSFrançois Tigeot 		igp_lane_info = dig_connector->igp_lane_info;
1108926deccbSFrançois Tigeot 	}
1109926deccbSFrançois Tigeot 
1110926deccbSFrançois Tigeot 	if (encoder->crtc) {
1111926deccbSFrançois Tigeot 		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1112926deccbSFrançois Tigeot 		pll_id = radeon_crtc->pll_id;
1113926deccbSFrançois Tigeot 	}
1114926deccbSFrançois Tigeot 
1115926deccbSFrançois Tigeot 	/* no dig encoder assigned */
1116926deccbSFrançois Tigeot 	if (dig_encoder == -1)
1117926deccbSFrançois Tigeot 		return;
1118926deccbSFrançois Tigeot 
1119926deccbSFrançois Tigeot 	if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
1120926deccbSFrançois Tigeot 		is_dp = true;
1121926deccbSFrançois Tigeot 
1122926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1123926deccbSFrançois Tigeot 
1124926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
1125926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1126926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1127926deccbSFrançois Tigeot 		break;
1128926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1129926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1130926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
113157e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1132926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1133926deccbSFrançois Tigeot 		break;
1134926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1135926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
1136926deccbSFrançois Tigeot 		break;
1137926deccbSFrançois Tigeot 	}
1138926deccbSFrançois Tigeot 
1139926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1140926deccbSFrançois Tigeot 		return;
1141926deccbSFrançois Tigeot 
1142926deccbSFrançois Tigeot 	switch (frev) {
1143926deccbSFrançois Tigeot 	case 1:
1144926deccbSFrançois Tigeot 		switch (crev) {
1145926deccbSFrançois Tigeot 		case 1:
1146926deccbSFrançois Tigeot 			args.v1.ucAction = action;
1147926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1148926deccbSFrançois Tigeot 				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
1149926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1150926deccbSFrançois Tigeot 				args.v1.asMode.ucLaneSel = lane_num;
1151926deccbSFrançois Tigeot 				args.v1.asMode.ucLaneSet = lane_set;
1152926deccbSFrançois Tigeot 			} else {
1153926deccbSFrançois Tigeot 				if (is_dp)
1154926deccbSFrançois Tigeot 					args.v1.usPixelClock = cpu_to_le16(dp_clock / 10);
1155926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1156926deccbSFrançois Tigeot 					args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1157926deccbSFrançois Tigeot 				else
1158926deccbSFrançois Tigeot 					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1159926deccbSFrançois Tigeot 			}
1160926deccbSFrançois Tigeot 
1161926deccbSFrançois Tigeot 			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1162926deccbSFrançois Tigeot 
1163926deccbSFrançois Tigeot 			if (dig_encoder)
1164926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
1165926deccbSFrançois Tigeot 			else
1166926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1167926deccbSFrançois Tigeot 
1168926deccbSFrançois Tigeot 			if ((rdev->flags & RADEON_IS_IGP) &&
1169926deccbSFrançois Tigeot 			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1170926deccbSFrançois Tigeot 				if (is_dp ||
1171926deccbSFrançois Tigeot 				    !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
1172926deccbSFrançois Tigeot 					if (igp_lane_info & 0x1)
1173926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
1174926deccbSFrançois Tigeot 					else if (igp_lane_info & 0x2)
1175926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
1176926deccbSFrançois Tigeot 					else if (igp_lane_info & 0x4)
1177926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
1178926deccbSFrançois Tigeot 					else if (igp_lane_info & 0x8)
1179926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1180926deccbSFrançois Tigeot 				} else {
1181926deccbSFrançois Tigeot 					if (igp_lane_info & 0x3)
1182926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
1183926deccbSFrançois Tigeot 					else if (igp_lane_info & 0xc)
1184926deccbSFrançois Tigeot 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1185926deccbSFrançois Tigeot 				}
1186926deccbSFrançois Tigeot 			}
1187926deccbSFrançois Tigeot 
1188926deccbSFrançois Tigeot 			if (dig->linkb)
1189926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
1190926deccbSFrançois Tigeot 			else
1191926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
1192926deccbSFrançois Tigeot 
1193926deccbSFrançois Tigeot 			if (is_dp)
1194926deccbSFrançois Tigeot 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1195926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1196926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1197926deccbSFrançois Tigeot 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1198926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1199926deccbSFrançois Tigeot 					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1200926deccbSFrançois Tigeot 			}
1201926deccbSFrançois Tigeot 			break;
1202926deccbSFrançois Tigeot 		case 2:
1203926deccbSFrançois Tigeot 			args.v2.ucAction = action;
1204926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1205926deccbSFrançois Tigeot 				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
1206926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1207926deccbSFrançois Tigeot 				args.v2.asMode.ucLaneSel = lane_num;
1208926deccbSFrançois Tigeot 				args.v2.asMode.ucLaneSet = lane_set;
1209926deccbSFrançois Tigeot 			} else {
1210926deccbSFrançois Tigeot 				if (is_dp)
1211926deccbSFrançois Tigeot 					args.v2.usPixelClock = cpu_to_le16(dp_clock / 10);
1212926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1213926deccbSFrançois Tigeot 					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1214926deccbSFrançois Tigeot 				else
1215926deccbSFrançois Tigeot 					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1216926deccbSFrançois Tigeot 			}
1217926deccbSFrançois Tigeot 
1218926deccbSFrançois Tigeot 			args.v2.acConfig.ucEncoderSel = dig_encoder;
1219926deccbSFrançois Tigeot 			if (dig->linkb)
1220926deccbSFrançois Tigeot 				args.v2.acConfig.ucLinkSel = 1;
1221926deccbSFrançois Tigeot 
1222926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1223926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1224926deccbSFrançois Tigeot 				args.v2.acConfig.ucTransmitterSel = 0;
1225926deccbSFrançois Tigeot 				break;
1226926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1227926deccbSFrançois Tigeot 				args.v2.acConfig.ucTransmitterSel = 1;
1228926deccbSFrançois Tigeot 				break;
1229926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1230926deccbSFrançois Tigeot 				args.v2.acConfig.ucTransmitterSel = 2;
1231926deccbSFrançois Tigeot 				break;
1232926deccbSFrançois Tigeot 			}
1233926deccbSFrançois Tigeot 
1234926deccbSFrançois Tigeot 			if (is_dp) {
1235926deccbSFrançois Tigeot 				args.v2.acConfig.fCoherentMode = 1;
1236926deccbSFrançois Tigeot 				args.v2.acConfig.fDPConnector = 1;
1237926deccbSFrançois Tigeot 			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1238926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1239926deccbSFrançois Tigeot 					args.v2.acConfig.fCoherentMode = 1;
1240926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1241926deccbSFrançois Tigeot 					args.v2.acConfig.fDualLinkConnector = 1;
1242926deccbSFrançois Tigeot 			}
1243926deccbSFrançois Tigeot 			break;
1244926deccbSFrançois Tigeot 		case 3:
1245926deccbSFrançois Tigeot 			args.v3.ucAction = action;
1246926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1247926deccbSFrançois Tigeot 				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
1248926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1249926deccbSFrançois Tigeot 				args.v3.asMode.ucLaneSel = lane_num;
1250926deccbSFrançois Tigeot 				args.v3.asMode.ucLaneSet = lane_set;
1251926deccbSFrançois Tigeot 			} else {
1252926deccbSFrançois Tigeot 				if (is_dp)
1253926deccbSFrançois Tigeot 					args.v3.usPixelClock = cpu_to_le16(dp_clock / 10);
1254926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1255926deccbSFrançois Tigeot 					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1256926deccbSFrançois Tigeot 				else
1257926deccbSFrançois Tigeot 					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1258926deccbSFrançois Tigeot 			}
1259926deccbSFrançois Tigeot 
1260926deccbSFrançois Tigeot 			if (is_dp)
1261926deccbSFrançois Tigeot 				args.v3.ucLaneNum = dp_lane_count;
1262926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1263926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 8;
1264926deccbSFrançois Tigeot 			else
1265926deccbSFrançois Tigeot 				args.v3.ucLaneNum = 4;
1266926deccbSFrançois Tigeot 
1267926deccbSFrançois Tigeot 			if (dig->linkb)
1268926deccbSFrançois Tigeot 				args.v3.acConfig.ucLinkSel = 1;
1269926deccbSFrançois Tigeot 			if (dig_encoder & 1)
1270926deccbSFrançois Tigeot 				args.v3.acConfig.ucEncoderSel = 1;
1271926deccbSFrançois Tigeot 
1272926deccbSFrançois Tigeot 			/* Select the PLL for the PHY
1273926deccbSFrançois Tigeot 			 * DP PHY should be clocked from external src if there is
1274926deccbSFrançois Tigeot 			 * one.
1275926deccbSFrançois Tigeot 			 */
1276926deccbSFrançois Tigeot 			/* On DCE4, if there is an external clock, it generates the DP ref clock */
1277926deccbSFrançois Tigeot 			if (is_dp && rdev->clock.dp_extclk)
1278926deccbSFrançois Tigeot 				args.v3.acConfig.ucRefClkSource = 2; /* external src */
1279926deccbSFrançois Tigeot 			else
1280926deccbSFrançois Tigeot 				args.v3.acConfig.ucRefClkSource = pll_id;
1281926deccbSFrançois Tigeot 
1282926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1283926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1284926deccbSFrançois Tigeot 				args.v3.acConfig.ucTransmitterSel = 0;
1285926deccbSFrançois Tigeot 				break;
1286926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1287926deccbSFrançois Tigeot 				args.v3.acConfig.ucTransmitterSel = 1;
1288926deccbSFrançois Tigeot 				break;
1289926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1290926deccbSFrançois Tigeot 				args.v3.acConfig.ucTransmitterSel = 2;
1291926deccbSFrançois Tigeot 				break;
1292926deccbSFrançois Tigeot 			}
1293926deccbSFrançois Tigeot 
1294926deccbSFrançois Tigeot 			if (is_dp)
1295926deccbSFrançois Tigeot 				args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
1296926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1297926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1298926deccbSFrançois Tigeot 					args.v3.acConfig.fCoherentMode = 1;
1299926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1300926deccbSFrançois Tigeot 					args.v3.acConfig.fDualLinkConnector = 1;
1301926deccbSFrançois Tigeot 			}
1302926deccbSFrançois Tigeot 			break;
1303926deccbSFrançois Tigeot 		case 4:
1304926deccbSFrançois Tigeot 			args.v4.ucAction = action;
1305926deccbSFrançois Tigeot 			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1306926deccbSFrançois Tigeot 				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
1307926deccbSFrançois Tigeot 			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1308926deccbSFrançois Tigeot 				args.v4.asMode.ucLaneSel = lane_num;
1309926deccbSFrançois Tigeot 				args.v4.asMode.ucLaneSet = lane_set;
1310926deccbSFrançois Tigeot 			} else {
1311926deccbSFrançois Tigeot 				if (is_dp)
1312926deccbSFrançois Tigeot 					args.v4.usPixelClock = cpu_to_le16(dp_clock / 10);
1313926deccbSFrançois Tigeot 				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1314926deccbSFrançois Tigeot 					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1315926deccbSFrançois Tigeot 				else
1316926deccbSFrançois Tigeot 					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1317926deccbSFrançois Tigeot 			}
1318926deccbSFrançois Tigeot 
1319926deccbSFrançois Tigeot 			if (is_dp)
1320926deccbSFrançois Tigeot 				args.v4.ucLaneNum = dp_lane_count;
1321926deccbSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1322926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 8;
1323926deccbSFrançois Tigeot 			else
1324926deccbSFrançois Tigeot 				args.v4.ucLaneNum = 4;
1325926deccbSFrançois Tigeot 
1326926deccbSFrançois Tigeot 			if (dig->linkb)
1327926deccbSFrançois Tigeot 				args.v4.acConfig.ucLinkSel = 1;
1328926deccbSFrançois Tigeot 			if (dig_encoder & 1)
1329926deccbSFrançois Tigeot 				args.v4.acConfig.ucEncoderSel = 1;
1330926deccbSFrançois Tigeot 
1331926deccbSFrançois Tigeot 			/* Select the PLL for the PHY
1332926deccbSFrançois Tigeot 			 * DP PHY should be clocked from external src if there is
1333926deccbSFrançois Tigeot 			 * one.
1334926deccbSFrançois Tigeot 			 */
1335926deccbSFrançois Tigeot 			/* On DCE5 DCPLL usually generates the DP ref clock */
1336926deccbSFrançois Tigeot 			if (is_dp) {
1337926deccbSFrançois Tigeot 				if (rdev->clock.dp_extclk)
1338926deccbSFrançois Tigeot 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
1339926deccbSFrançois Tigeot 				else
1340926deccbSFrançois Tigeot 					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
1341926deccbSFrançois Tigeot 			} else
1342926deccbSFrançois Tigeot 				args.v4.acConfig.ucRefClkSource = pll_id;
1343926deccbSFrançois Tigeot 
1344926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1345926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1346926deccbSFrançois Tigeot 				args.v4.acConfig.ucTransmitterSel = 0;
1347926deccbSFrançois Tigeot 				break;
1348926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1349926deccbSFrançois Tigeot 				args.v4.acConfig.ucTransmitterSel = 1;
1350926deccbSFrançois Tigeot 				break;
1351926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1352926deccbSFrançois Tigeot 				args.v4.acConfig.ucTransmitterSel = 2;
1353926deccbSFrançois Tigeot 				break;
1354926deccbSFrançois Tigeot 			}
1355926deccbSFrançois Tigeot 
1356926deccbSFrançois Tigeot 			if (is_dp)
1357926deccbSFrançois Tigeot 				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
1358926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1359926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1360926deccbSFrançois Tigeot 					args.v4.acConfig.fCoherentMode = 1;
1361926deccbSFrançois Tigeot 				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1362926deccbSFrançois Tigeot 					args.v4.acConfig.fDualLinkConnector = 1;
1363926deccbSFrançois Tigeot 			}
1364926deccbSFrançois Tigeot 			break;
1365926deccbSFrançois Tigeot 		case 5:
1366926deccbSFrançois Tigeot 			args.v5.ucAction = action;
1367926deccbSFrançois Tigeot 			if (is_dp)
1368926deccbSFrançois Tigeot 				args.v5.usSymClock = cpu_to_le16(dp_clock / 10);
1369926deccbSFrançois Tigeot 			else
1370926deccbSFrançois Tigeot 				args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1371926deccbSFrançois Tigeot 
1372926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1373926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1374926deccbSFrançois Tigeot 				if (dig->linkb)
1375926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1376926deccbSFrançois Tigeot 				else
1377926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1378926deccbSFrançois Tigeot 				break;
1379926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1380926deccbSFrançois Tigeot 				if (dig->linkb)
1381926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1382926deccbSFrançois Tigeot 				else
1383926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1384926deccbSFrançois Tigeot 				break;
1385926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1386926deccbSFrançois Tigeot 				if (dig->linkb)
1387926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1388926deccbSFrançois Tigeot 				else
1389926deccbSFrançois Tigeot 					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1390926deccbSFrançois Tigeot 				break;
139157e252bfSMichael Neumann 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
139257e252bfSMichael Neumann 				args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG;
139357e252bfSMichael Neumann 				break;
1394926deccbSFrançois Tigeot 			}
1395926deccbSFrançois Tigeot 			if (is_dp)
1396926deccbSFrançois Tigeot 				args.v5.ucLaneNum = dp_lane_count;
1397c6f73aabSFrançois Tigeot 			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1398926deccbSFrançois Tigeot 				args.v5.ucLaneNum = 8;
1399926deccbSFrançois Tigeot 			else
1400926deccbSFrançois Tigeot 				args.v5.ucLaneNum = 4;
1401926deccbSFrançois Tigeot 			args.v5.ucConnObjId = connector_object_id;
1402926deccbSFrançois Tigeot 			args.v5.ucDigMode = atombios_get_encoder_mode(encoder);
1403926deccbSFrançois Tigeot 
1404926deccbSFrançois Tigeot 			if (is_dp && rdev->clock.dp_extclk)
1405926deccbSFrançois Tigeot 				args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK;
1406926deccbSFrançois Tigeot 			else
1407926deccbSFrançois Tigeot 				args.v5.asConfig.ucPhyClkSrcId = pll_id;
1408926deccbSFrançois Tigeot 
1409926deccbSFrançois Tigeot 			if (is_dp)
1410926deccbSFrançois Tigeot 				args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */
1411926deccbSFrançois Tigeot 			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1412926deccbSFrançois Tigeot 				if (dig->coherent_mode)
1413926deccbSFrançois Tigeot 					args.v5.asConfig.ucCoherentMode = 1;
1414926deccbSFrançois Tigeot 			}
1415926deccbSFrançois Tigeot 			if (hpd_id == RADEON_HPD_NONE)
1416926deccbSFrançois Tigeot 				args.v5.asConfig.ucHPDSel = 0;
1417926deccbSFrançois Tigeot 			else
1418926deccbSFrançois Tigeot 				args.v5.asConfig.ucHPDSel = hpd_id + 1;
1419c59a5c48SFrançois Tigeot 			args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder);
1420926deccbSFrançois Tigeot 			args.v5.ucDPLaneSet = lane_set;
1421926deccbSFrançois Tigeot 			break;
1422926deccbSFrançois Tigeot 		default:
1423926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1424926deccbSFrançois Tigeot 			break;
1425926deccbSFrançois Tigeot 		}
1426926deccbSFrançois Tigeot 		break;
1427926deccbSFrançois Tigeot 	default:
1428926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1429926deccbSFrançois Tigeot 		break;
1430926deccbSFrançois Tigeot 	}
1431926deccbSFrançois Tigeot 
1432926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1433926deccbSFrançois Tigeot }
1434926deccbSFrançois Tigeot 
1435c59a5c48SFrançois Tigeot void
atombios_dig_transmitter_setup(struct drm_encoder * encoder,int action,uint8_t lane_num,uint8_t lane_set)1436c59a5c48SFrançois Tigeot atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
1437c59a5c48SFrançois Tigeot {
1438c59a5c48SFrançois Tigeot 	atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1);
1439c59a5c48SFrançois Tigeot }
1440c59a5c48SFrançois Tigeot 
1441926deccbSFrançois Tigeot bool
atombios_set_edp_panel_power(struct drm_connector * connector,int action)1442926deccbSFrançois Tigeot atombios_set_edp_panel_power(struct drm_connector *connector, int action)
1443926deccbSFrançois Tigeot {
1444926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1445926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_connector->base.dev;
1446926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1447926deccbSFrançois Tigeot 	union dig_transmitter_control args;
1448926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1449926deccbSFrançois Tigeot 	uint8_t frev, crev;
1450926deccbSFrançois Tigeot 
1451926deccbSFrançois Tigeot 	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
1452926deccbSFrançois Tigeot 		goto done;
1453926deccbSFrançois Tigeot 
1454926deccbSFrançois Tigeot 	if (!ASIC_IS_DCE4(rdev))
1455926deccbSFrançois Tigeot 		goto done;
1456926deccbSFrançois Tigeot 
1457926deccbSFrançois Tigeot 	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
1458926deccbSFrançois Tigeot 	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
1459926deccbSFrançois Tigeot 		goto done;
1460926deccbSFrançois Tigeot 
1461926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1462926deccbSFrançois Tigeot 		goto done;
1463926deccbSFrançois Tigeot 
1464926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1465926deccbSFrançois Tigeot 
1466926deccbSFrançois Tigeot 	args.v1.ucAction = action;
1467926deccbSFrançois Tigeot 
1468926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1469926deccbSFrançois Tigeot 
1470926deccbSFrançois Tigeot 	/* wait for the panel to power up */
1471926deccbSFrançois Tigeot 	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
1472926deccbSFrançois Tigeot 		int i;
1473926deccbSFrançois Tigeot 
1474926deccbSFrançois Tigeot 		for (i = 0; i < 300; i++) {
1475926deccbSFrançois Tigeot 			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
1476926deccbSFrançois Tigeot 				return true;
1477c4ef309bSzrj 			mdelay(1);
1478926deccbSFrançois Tigeot 		}
1479926deccbSFrançois Tigeot 		return false;
1480926deccbSFrançois Tigeot 	}
1481926deccbSFrançois Tigeot done:
1482926deccbSFrançois Tigeot 	return true;
1483926deccbSFrançois Tigeot }
1484926deccbSFrançois Tigeot 
1485926deccbSFrançois Tigeot union external_encoder_control {
1486926deccbSFrançois Tigeot 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
1487926deccbSFrançois Tigeot 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
1488926deccbSFrançois Tigeot };
1489926deccbSFrançois Tigeot 
1490926deccbSFrançois Tigeot static void
atombios_external_encoder_setup(struct drm_encoder * encoder,struct drm_encoder * ext_encoder,int action)1491926deccbSFrançois Tigeot atombios_external_encoder_setup(struct drm_encoder *encoder,
1492926deccbSFrançois Tigeot 				struct drm_encoder *ext_encoder,
1493926deccbSFrançois Tigeot 				int action)
1494926deccbSFrançois Tigeot {
1495926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1496926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1497926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1498926deccbSFrançois Tigeot 	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
1499926deccbSFrançois Tigeot 	union external_encoder_control args;
1500926deccbSFrançois Tigeot 	struct drm_connector *connector;
1501926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
1502926deccbSFrançois Tigeot 	u8 frev, crev;
1503926deccbSFrançois Tigeot 	int dp_clock = 0;
1504926deccbSFrançois Tigeot 	int dp_lane_count = 0;
1505926deccbSFrançois Tigeot 	int connector_object_id = 0;
1506926deccbSFrançois Tigeot 	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
1507926deccbSFrançois Tigeot 
1508926deccbSFrançois Tigeot 	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1509926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder_init(encoder);
1510926deccbSFrançois Tigeot 	else
1511926deccbSFrançois Tigeot 		connector = radeon_get_connector_for_encoder(encoder);
1512926deccbSFrançois Tigeot 
1513926deccbSFrançois Tigeot 	if (connector) {
1514926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1515926deccbSFrançois Tigeot 		struct radeon_connector_atom_dig *dig_connector =
1516926deccbSFrançois Tigeot 			radeon_connector->con_priv;
1517926deccbSFrançois Tigeot 
1518926deccbSFrançois Tigeot 		dp_clock = dig_connector->dp_clock;
1519926deccbSFrançois Tigeot 		dp_lane_count = dig_connector->dp_lane_count;
1520926deccbSFrançois Tigeot 		connector_object_id =
1521926deccbSFrançois Tigeot 			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1522926deccbSFrançois Tigeot 	}
1523926deccbSFrançois Tigeot 
1524926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1525926deccbSFrançois Tigeot 
1526926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1527926deccbSFrançois Tigeot 		return;
1528926deccbSFrançois Tigeot 
1529926deccbSFrançois Tigeot 	switch (frev) {
1530926deccbSFrançois Tigeot 	case 1:
1531926deccbSFrançois Tigeot 		/* no params on frev 1 */
1532926deccbSFrançois Tigeot 		break;
1533926deccbSFrançois Tigeot 	case 2:
1534926deccbSFrançois Tigeot 		switch (crev) {
1535926deccbSFrançois Tigeot 		case 1:
1536926deccbSFrançois Tigeot 		case 2:
1537926deccbSFrançois Tigeot 			args.v1.sDigEncoder.ucAction = action;
1538926deccbSFrançois Tigeot 			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1539926deccbSFrançois Tigeot 			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1540926deccbSFrançois Tigeot 
1541926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
1542926deccbSFrançois Tigeot 				if (dp_clock == 270000)
1543926deccbSFrançois Tigeot 					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
1544926deccbSFrançois Tigeot 				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
1545926deccbSFrançois Tigeot 			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1546926deccbSFrançois Tigeot 				args.v1.sDigEncoder.ucLaneNum = 8;
1547926deccbSFrançois Tigeot 			else
1548926deccbSFrançois Tigeot 				args.v1.sDigEncoder.ucLaneNum = 4;
1549926deccbSFrançois Tigeot 			break;
1550926deccbSFrançois Tigeot 		case 3:
1551926deccbSFrançois Tigeot 			args.v3.sExtEncoder.ucAction = action;
1552926deccbSFrançois Tigeot 			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1553926deccbSFrançois Tigeot 				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
1554926deccbSFrançois Tigeot 			else
1555926deccbSFrançois Tigeot 				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1556926deccbSFrançois Tigeot 			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1557926deccbSFrançois Tigeot 
1558926deccbSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
1559926deccbSFrançois Tigeot 				if (dp_clock == 270000)
1560926deccbSFrançois Tigeot 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1561926deccbSFrançois Tigeot 				else if (dp_clock == 540000)
1562926deccbSFrançois Tigeot 					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1563926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
1564926deccbSFrançois Tigeot 			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1565926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucLaneNum = 8;
1566926deccbSFrançois Tigeot 			else
1567926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucLaneNum = 4;
1568926deccbSFrançois Tigeot 			switch (ext_enum) {
1569926deccbSFrançois Tigeot 			case GRAPH_OBJECT_ENUM_ID1:
1570926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1571926deccbSFrançois Tigeot 				break;
1572926deccbSFrançois Tigeot 			case GRAPH_OBJECT_ENUM_ID2:
1573926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1574926deccbSFrançois Tigeot 				break;
1575926deccbSFrançois Tigeot 			case GRAPH_OBJECT_ENUM_ID3:
1576926deccbSFrançois Tigeot 				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1577926deccbSFrançois Tigeot 				break;
1578926deccbSFrançois Tigeot 			}
1579926deccbSFrançois Tigeot 			args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder);
1580926deccbSFrançois Tigeot 			break;
1581926deccbSFrançois Tigeot 		default:
1582926deccbSFrançois Tigeot 			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1583926deccbSFrançois Tigeot 			return;
1584926deccbSFrançois Tigeot 		}
1585926deccbSFrançois Tigeot 		break;
1586926deccbSFrançois Tigeot 	default:
1587926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1588926deccbSFrançois Tigeot 		return;
1589926deccbSFrançois Tigeot 	}
1590926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1591926deccbSFrançois Tigeot }
1592926deccbSFrançois Tigeot 
1593926deccbSFrançois Tigeot static void
atombios_yuv_setup(struct drm_encoder * encoder,bool enable)1594926deccbSFrançois Tigeot atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
1595926deccbSFrançois Tigeot {
1596926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1597926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1598926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1599926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1600926deccbSFrançois Tigeot 	ENABLE_YUV_PS_ALLOCATION args;
1601926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
1602926deccbSFrançois Tigeot 	uint32_t temp, reg;
1603926deccbSFrançois Tigeot 
1604926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1605926deccbSFrançois Tigeot 
1606926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
1607926deccbSFrançois Tigeot 		reg = R600_BIOS_3_SCRATCH;
1608926deccbSFrançois Tigeot 	else
1609926deccbSFrançois Tigeot 		reg = RADEON_BIOS_3_SCRATCH;
1610926deccbSFrançois Tigeot 
1611926deccbSFrançois Tigeot 	/* XXX: fix up scratch reg handling */
1612926deccbSFrançois Tigeot 	temp = RREG32(reg);
1613926deccbSFrançois Tigeot 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1614926deccbSFrançois Tigeot 		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
1615926deccbSFrançois Tigeot 			     (radeon_crtc->crtc_id << 18)));
1616926deccbSFrançois Tigeot 	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1617926deccbSFrançois Tigeot 		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
1618926deccbSFrançois Tigeot 	else
1619926deccbSFrançois Tigeot 		WREG32(reg, 0);
1620926deccbSFrançois Tigeot 
1621926deccbSFrançois Tigeot 	if (enable)
1622926deccbSFrançois Tigeot 		args.ucEnable = ATOM_ENABLE;
1623926deccbSFrançois Tigeot 	args.ucCRTC = radeon_crtc->crtc_id;
1624926deccbSFrançois Tigeot 
1625926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1626926deccbSFrançois Tigeot 
1627926deccbSFrançois Tigeot 	WREG32(reg, temp);
1628926deccbSFrançois Tigeot }
1629926deccbSFrançois Tigeot 
1630926deccbSFrançois Tigeot static void
radeon_atom_encoder_dpms_avivo(struct drm_encoder * encoder,int mode)1631926deccbSFrançois Tigeot radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
1632926deccbSFrançois Tigeot {
1633926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1634926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1635926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1636926deccbSFrançois Tigeot 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1637926deccbSFrançois Tigeot 	int index = 0;
1638926deccbSFrançois Tigeot 
1639926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1640926deccbSFrançois Tigeot 
1641926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
1642926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1643926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1644926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1645926deccbSFrançois Tigeot 		break;
1646926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1647926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1648926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1649926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1650926deccbSFrançois Tigeot 		break;
1651926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1652926deccbSFrançois Tigeot 		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1653926deccbSFrançois Tigeot 		break;
1654926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1655926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1656926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1657926deccbSFrançois Tigeot 		else
1658926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1659926deccbSFrançois Tigeot 		break;
1660926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1661926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1662926deccbSFrançois Tigeot 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1663926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1664926deccbSFrançois Tigeot 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1665926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1666926deccbSFrançois Tigeot 		else
1667926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1668926deccbSFrançois Tigeot 		break;
1669926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1670926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1671926deccbSFrançois Tigeot 		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1672926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1673926deccbSFrançois Tigeot 		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1674926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1675926deccbSFrançois Tigeot 		else
1676926deccbSFrançois Tigeot 			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1677926deccbSFrançois Tigeot 		break;
1678926deccbSFrançois Tigeot 	default:
1679926deccbSFrançois Tigeot 		return;
1680926deccbSFrançois Tigeot 	}
1681926deccbSFrançois Tigeot 
1682926deccbSFrançois Tigeot 	switch (mode) {
1683926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_ON:
1684926deccbSFrançois Tigeot 		args.ucAction = ATOM_ENABLE;
1685926deccbSFrançois Tigeot 		/* workaround for DVOOutputControl on some RS690 systems */
1686926deccbSFrançois Tigeot 		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
1687926deccbSFrançois Tigeot 			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
1688926deccbSFrançois Tigeot 			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
1689926deccbSFrançois Tigeot 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1690926deccbSFrançois Tigeot 			WREG32(RADEON_BIOS_3_SCRATCH, reg);
1691926deccbSFrançois Tigeot 		} else
1692926deccbSFrançois Tigeot 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1693926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1694c59a5c48SFrançois Tigeot 			if (rdev->mode_info.bl_encoder) {
1695c59a5c48SFrançois Tigeot 				struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1696c59a5c48SFrançois Tigeot 
1697c59a5c48SFrançois Tigeot 				atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
1698c59a5c48SFrançois Tigeot 			} else {
1699926deccbSFrançois Tigeot 				args.ucAction = ATOM_LCD_BLON;
1700926deccbSFrançois Tigeot 				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1701926deccbSFrançois Tigeot 			}
1702c59a5c48SFrançois Tigeot 		}
1703926deccbSFrançois Tigeot 		break;
1704926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_STANDBY:
1705926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_SUSPEND:
1706926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_OFF:
1707926deccbSFrançois Tigeot 		args.ucAction = ATOM_DISABLE;
1708926deccbSFrançois Tigeot 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1709926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1710926deccbSFrançois Tigeot 			args.ucAction = ATOM_LCD_BLOFF;
1711926deccbSFrançois Tigeot 			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1712926deccbSFrançois Tigeot 		}
1713926deccbSFrançois Tigeot 		break;
1714926deccbSFrançois Tigeot 	}
1715926deccbSFrançois Tigeot }
1716926deccbSFrançois Tigeot 
1717926deccbSFrançois Tigeot static void
radeon_atom_encoder_dpms_dig(struct drm_encoder * encoder,int mode)1718926deccbSFrançois Tigeot radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
1719926deccbSFrançois Tigeot {
1720926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1721926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1722926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1723926deccbSFrançois Tigeot 	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
1724926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1725926deccbSFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1726926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = NULL;
1727926deccbSFrançois Tigeot 	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
1728c6f73aabSFrançois Tigeot 	bool travis_quirk = false;
1729926deccbSFrançois Tigeot 
1730926deccbSFrançois Tigeot 	if (connector) {
1731926deccbSFrançois Tigeot 		radeon_connector = to_radeon_connector(connector);
1732926deccbSFrançois Tigeot 		radeon_dig_connector = radeon_connector->con_priv;
1733c6f73aabSFrançois Tigeot 		if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
1734c6f73aabSFrançois Tigeot 		     ENCODER_OBJECT_ID_TRAVIS) &&
1735c6f73aabSFrançois Tigeot 		    (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
1736c6f73aabSFrançois Tigeot 		    !ASIC_IS_DCE5(rdev))
1737c6f73aabSFrançois Tigeot 			travis_quirk = true;
1738926deccbSFrançois Tigeot 	}
1739926deccbSFrançois Tigeot 
1740926deccbSFrançois Tigeot 	switch (mode) {
1741926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_ON:
1742926deccbSFrançois Tigeot 		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
1743926deccbSFrançois Tigeot 			if (!connector)
1744926deccbSFrançois Tigeot 				dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
1745926deccbSFrançois Tigeot 			else
1746926deccbSFrançois Tigeot 				dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
1747926deccbSFrançois Tigeot 
1748926deccbSFrançois Tigeot 			/* setup and enable the encoder */
1749926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1750926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder,
1751926deccbSFrançois Tigeot 						   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
1752926deccbSFrançois Tigeot 						   dig->panel_mode);
1753926deccbSFrançois Tigeot 			if (ext_encoder) {
1754926deccbSFrançois Tigeot 				if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
1755926deccbSFrançois Tigeot 					atombios_external_encoder_setup(encoder, ext_encoder,
1756926deccbSFrançois Tigeot 									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
1757926deccbSFrançois Tigeot 			}
1758926deccbSFrançois Tigeot 		} else if (ASIC_IS_DCE4(rdev)) {
1759926deccbSFrançois Tigeot 			/* setup and enable the encoder */
1760926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1761926deccbSFrançois Tigeot 		} else {
1762926deccbSFrançois Tigeot 			/* setup and enable the encoder and transmitter */
1763926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
1764926deccbSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
1765926deccbSFrançois Tigeot 		}
1766926deccbSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1767926deccbSFrançois Tigeot 			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1768926deccbSFrançois Tigeot 				atombios_set_edp_panel_power(connector,
1769926deccbSFrançois Tigeot 							     ATOM_TRANSMITTER_ACTION_POWER_ON);
1770926deccbSFrançois Tigeot 				radeon_dig_connector->edp_on = true;
1771926deccbSFrançois Tigeot 			}
1772c6f73aabSFrançois Tigeot 		}
1773c6f73aabSFrançois Tigeot 		/* enable the transmitter */
1774c6f73aabSFrançois Tigeot 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1775c6f73aabSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1776c6f73aabSFrançois Tigeot 			/* DP_SET_POWER_D0 is set in radeon_dp_link_train */
1777926deccbSFrançois Tigeot 			radeon_dp_link_train(encoder, connector);
1778926deccbSFrançois Tigeot 			if (ASIC_IS_DCE4(rdev))
1779926deccbSFrançois Tigeot 				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
1780926deccbSFrançois Tigeot 		}
1781c59a5c48SFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1782c59a5c48SFrançois Tigeot 			if (rdev->mode_info.bl_encoder)
1783c59a5c48SFrançois Tigeot 				atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
1784c59a5c48SFrançois Tigeot 			else
1785c6f73aabSFrançois Tigeot 				atombios_dig_transmitter_setup(encoder,
1786c6f73aabSFrançois Tigeot 							       ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
1787c59a5c48SFrançois Tigeot 		}
1788c6f73aabSFrançois Tigeot 		if (ext_encoder)
1789c6f73aabSFrançois Tigeot 			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
1790926deccbSFrançois Tigeot 		break;
1791926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_STANDBY:
1792926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_SUSPEND:
1793926deccbSFrançois Tigeot 	case DRM_MODE_DPMS_OFF:
1794c59a5c48SFrançois Tigeot 
1795c59a5c48SFrançois Tigeot 		/* don't power off encoders with active MST links */
1796c59a5c48SFrançois Tigeot 		if (dig->active_mst_links)
1797c59a5c48SFrançois Tigeot 			return;
1798c59a5c48SFrançois Tigeot 
1799c6f73aabSFrançois Tigeot 		if (ASIC_IS_DCE4(rdev)) {
1800c6f73aabSFrançois Tigeot 			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
1801c6f73aabSFrançois Tigeot 				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
1802c6f73aabSFrançois Tigeot 		}
1803c6f73aabSFrançois Tigeot 		if (ext_encoder)
1804c6f73aabSFrançois Tigeot 			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
1805c6f73aabSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1806c6f73aabSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder,
1807c6f73aabSFrançois Tigeot 						       ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1808c6f73aabSFrançois Tigeot 
1809c6f73aabSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
1810c6f73aabSFrançois Tigeot 		    connector && !travis_quirk)
1811c6f73aabSFrançois Tigeot 			radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
1812c6f73aabSFrançois Tigeot 		if (ASIC_IS_DCE4(rdev)) {
1813926deccbSFrançois Tigeot 			/* disable the transmitter */
1814c6f73aabSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder,
1815c6f73aabSFrançois Tigeot 						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1816926deccbSFrançois Tigeot 		} else {
1817926deccbSFrançois Tigeot 			/* disable the encoder and transmitter */
1818c6f73aabSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder,
1819c6f73aabSFrançois Tigeot 						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1820926deccbSFrançois Tigeot 			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
1821926deccbSFrançois Tigeot 		}
1822926deccbSFrançois Tigeot 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1823c6f73aabSFrançois Tigeot 			if (travis_quirk)
1824c6f73aabSFrançois Tigeot 				radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
1825926deccbSFrançois Tigeot 			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1826926deccbSFrançois Tigeot 				atombios_set_edp_panel_power(connector,
1827926deccbSFrançois Tigeot 							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
1828926deccbSFrançois Tigeot 				radeon_dig_connector->edp_on = false;
1829926deccbSFrançois Tigeot 			}
1830926deccbSFrançois Tigeot 		}
1831926deccbSFrançois Tigeot 		break;
1832926deccbSFrançois Tigeot 	}
1833926deccbSFrançois Tigeot }
1834926deccbSFrançois Tigeot 
1835926deccbSFrançois Tigeot static void
radeon_atom_encoder_dpms(struct drm_encoder * encoder,int mode)1836926deccbSFrançois Tigeot radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1837926deccbSFrançois Tigeot {
1838926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1839926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1840926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1841c59a5c48SFrançois Tigeot 	int encoder_mode = atombios_get_encoder_mode(encoder);
1842926deccbSFrançois Tigeot 
1843926deccbSFrançois Tigeot 	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
1844926deccbSFrançois Tigeot 		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
1845926deccbSFrançois Tigeot 		  radeon_encoder->active_device);
1846c59a5c48SFrançois Tigeot 
1847c59a5c48SFrançois Tigeot 	if ((radeon_audio != 0) &&
1848c59a5c48SFrançois Tigeot 	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
1849c59a5c48SFrançois Tigeot 	     ENCODER_MODE_IS_DP(encoder_mode)))
1850c59a5c48SFrançois Tigeot 		radeon_audio_dpms(encoder, mode);
1851c59a5c48SFrançois Tigeot 
1852926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
1853926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1854926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1855926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1856926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1857926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1858926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1859926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1860926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1861926deccbSFrançois Tigeot 		radeon_atom_encoder_dpms_avivo(encoder, mode);
1862926deccbSFrançois Tigeot 		break;
1863926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1864926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1865926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
186657e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1867926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1868926deccbSFrançois Tigeot 		radeon_atom_encoder_dpms_dig(encoder, mode);
1869926deccbSFrançois Tigeot 		break;
1870926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1871926deccbSFrançois Tigeot 		if (ASIC_IS_DCE5(rdev)) {
1872926deccbSFrançois Tigeot 			switch (mode) {
1873926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_ON:
1874926deccbSFrançois Tigeot 				atombios_dvo_setup(encoder, ATOM_ENABLE);
1875926deccbSFrançois Tigeot 				break;
1876926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_STANDBY:
1877926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_SUSPEND:
1878926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_OFF:
1879926deccbSFrançois Tigeot 				atombios_dvo_setup(encoder, ATOM_DISABLE);
1880926deccbSFrançois Tigeot 				break;
1881926deccbSFrançois Tigeot 			}
1882926deccbSFrançois Tigeot 		} else if (ASIC_IS_DCE3(rdev))
1883926deccbSFrançois Tigeot 			radeon_atom_encoder_dpms_dig(encoder, mode);
1884926deccbSFrançois Tigeot 		else
1885926deccbSFrançois Tigeot 			radeon_atom_encoder_dpms_avivo(encoder, mode);
1886926deccbSFrançois Tigeot 		break;
1887926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1888926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1889926deccbSFrançois Tigeot 		if (ASIC_IS_DCE5(rdev)) {
1890926deccbSFrançois Tigeot 			switch (mode) {
1891926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_ON:
1892926deccbSFrançois Tigeot 				atombios_dac_setup(encoder, ATOM_ENABLE);
1893926deccbSFrançois Tigeot 				break;
1894926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_STANDBY:
1895926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_SUSPEND:
1896926deccbSFrançois Tigeot 			case DRM_MODE_DPMS_OFF:
1897926deccbSFrançois Tigeot 				atombios_dac_setup(encoder, ATOM_DISABLE);
1898926deccbSFrançois Tigeot 				break;
1899926deccbSFrançois Tigeot 			}
1900926deccbSFrançois Tigeot 		} else
1901926deccbSFrançois Tigeot 			radeon_atom_encoder_dpms_avivo(encoder, mode);
1902926deccbSFrançois Tigeot 		break;
1903926deccbSFrançois Tigeot 	default:
1904926deccbSFrançois Tigeot 		return;
1905926deccbSFrançois Tigeot 	}
1906926deccbSFrançois Tigeot 
1907926deccbSFrançois Tigeot 	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1908926deccbSFrançois Tigeot 
1909926deccbSFrançois Tigeot }
1910926deccbSFrançois Tigeot 
1911926deccbSFrançois Tigeot union crtc_source_param {
1912926deccbSFrançois Tigeot 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
1913926deccbSFrançois Tigeot 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
1914926deccbSFrançois Tigeot };
1915926deccbSFrançois Tigeot 
1916926deccbSFrançois Tigeot static void
atombios_set_encoder_crtc_source(struct drm_encoder * encoder)1917926deccbSFrançois Tigeot atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
1918926deccbSFrançois Tigeot {
1919926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
1920926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1921926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1922926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1923926deccbSFrançois Tigeot 	union crtc_source_param args;
1924926deccbSFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1925926deccbSFrançois Tigeot 	uint8_t frev, crev;
1926926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
1927926deccbSFrançois Tigeot 
1928926deccbSFrançois Tigeot 	memset(&args, 0, sizeof(args));
1929926deccbSFrançois Tigeot 
1930926deccbSFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1931926deccbSFrançois Tigeot 		return;
1932926deccbSFrançois Tigeot 
1933926deccbSFrançois Tigeot 	switch (frev) {
1934926deccbSFrançois Tigeot 	case 1:
1935926deccbSFrançois Tigeot 		switch (crev) {
1936926deccbSFrançois Tigeot 		case 1:
1937926deccbSFrançois Tigeot 		default:
1938926deccbSFrançois Tigeot 			if (ASIC_IS_AVIVO(rdev))
1939926deccbSFrançois Tigeot 				args.v1.ucCRTC = radeon_crtc->crtc_id;
1940926deccbSFrançois Tigeot 			else {
1941926deccbSFrançois Tigeot 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
1942926deccbSFrançois Tigeot 					args.v1.ucCRTC = radeon_crtc->crtc_id;
1943926deccbSFrançois Tigeot 				} else {
1944926deccbSFrançois Tigeot 					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
1945926deccbSFrançois Tigeot 				}
1946926deccbSFrançois Tigeot 			}
1947926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
1948926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1949926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1950926deccbSFrançois Tigeot 				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1951926deccbSFrançois Tigeot 				break;
1952926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1953926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1954926deccbSFrançois Tigeot 				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
1955926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1956926deccbSFrançois Tigeot 				else
1957926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1958926deccbSFrançois Tigeot 				break;
1959926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1960926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DDI:
1961926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1962926deccbSFrançois Tigeot 				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1963926deccbSFrançois Tigeot 				break;
1964926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1965926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1966926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1967926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
1968926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1969926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1970926deccbSFrançois Tigeot 				else
1971926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1972926deccbSFrançois Tigeot 				break;
1973926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1974926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1975926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1976926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
1977926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1978926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1979926deccbSFrançois Tigeot 				else
1980926deccbSFrançois Tigeot 					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1981926deccbSFrançois Tigeot 				break;
1982926deccbSFrançois Tigeot 			}
1983926deccbSFrançois Tigeot 			break;
1984926deccbSFrançois Tigeot 		case 2:
1985926deccbSFrançois Tigeot 			args.v2.ucCRTC = radeon_crtc->crtc_id;
1986926deccbSFrançois Tigeot 			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
1987926deccbSFrançois Tigeot 				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1988926deccbSFrançois Tigeot 
1989926deccbSFrançois Tigeot 				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
1990926deccbSFrançois Tigeot 					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
1991926deccbSFrançois Tigeot 				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
1992926deccbSFrançois Tigeot 					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
1993926deccbSFrançois Tigeot 				else
1994926deccbSFrançois Tigeot 					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1995c6f73aabSFrançois Tigeot 			} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1996c6f73aabSFrançois Tigeot 				args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
1997c6f73aabSFrançois Tigeot 			} else {
1998926deccbSFrançois Tigeot 				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1999c6f73aabSFrançois Tigeot 			}
2000926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
2001926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2002926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2003926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
200457e252bfSMichael Neumann 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2005926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2006926deccbSFrançois Tigeot 				dig = radeon_encoder->enc_priv;
2007926deccbSFrançois Tigeot 				switch (dig->dig_encoder) {
2008926deccbSFrançois Tigeot 				case 0:
2009926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
2010926deccbSFrançois Tigeot 					break;
2011926deccbSFrançois Tigeot 				case 1:
2012926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
2013926deccbSFrançois Tigeot 					break;
2014926deccbSFrançois Tigeot 				case 2:
2015926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
2016926deccbSFrançois Tigeot 					break;
2017926deccbSFrançois Tigeot 				case 3:
2018926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
2019926deccbSFrançois Tigeot 					break;
2020926deccbSFrançois Tigeot 				case 4:
2021926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
2022926deccbSFrançois Tigeot 					break;
2023926deccbSFrançois Tigeot 				case 5:
2024926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
2025926deccbSFrançois Tigeot 					break;
202657e252bfSMichael Neumann 				case 6:
202757e252bfSMichael Neumann 					args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
202857e252bfSMichael Neumann 					break;
2029926deccbSFrançois Tigeot 				}
2030926deccbSFrançois Tigeot 				break;
2031926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2032926deccbSFrançois Tigeot 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
2033926deccbSFrançois Tigeot 				break;
2034926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2035926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
2036926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
2037926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
2038926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
2039926deccbSFrançois Tigeot 				else
2040926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
2041926deccbSFrançois Tigeot 				break;
2042926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2043926deccbSFrançois Tigeot 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
2044926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
2045926deccbSFrançois Tigeot 				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
2046926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
2047926deccbSFrançois Tigeot 				else
2048926deccbSFrançois Tigeot 					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
2049926deccbSFrançois Tigeot 				break;
2050926deccbSFrançois Tigeot 			}
2051926deccbSFrançois Tigeot 			break;
2052926deccbSFrançois Tigeot 		}
2053926deccbSFrançois Tigeot 		break;
2054926deccbSFrançois Tigeot 	default:
2055926deccbSFrançois Tigeot 		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
2056926deccbSFrançois Tigeot 		return;
2057926deccbSFrançois Tigeot 	}
2058926deccbSFrançois Tigeot 
2059926deccbSFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2060926deccbSFrançois Tigeot 
2061926deccbSFrançois Tigeot 	/* update scratch regs with new routing */
2062926deccbSFrançois Tigeot 	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
2063926deccbSFrançois Tigeot }
2064926deccbSFrançois Tigeot 
2065c59a5c48SFrançois Tigeot void
atombios_set_mst_encoder_crtc_source(struct drm_encoder * encoder,int fe)2066c59a5c48SFrançois Tigeot atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe)
2067c59a5c48SFrançois Tigeot {
2068c59a5c48SFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2069c59a5c48SFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2070c59a5c48SFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
2071c59a5c48SFrançois Tigeot 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
2072c59a5c48SFrançois Tigeot 	uint8_t frev, crev;
2073c59a5c48SFrançois Tigeot 	union crtc_source_param args;
2074c59a5c48SFrançois Tigeot 
2075c59a5c48SFrançois Tigeot 	memset(&args, 0, sizeof(args));
2076c59a5c48SFrançois Tigeot 
2077c59a5c48SFrançois Tigeot 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2078c59a5c48SFrançois Tigeot 		return;
2079c59a5c48SFrançois Tigeot 
2080c59a5c48SFrançois Tigeot 	if (frev != 1 && crev != 2)
2081c59a5c48SFrançois Tigeot 		DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev);
2082c59a5c48SFrançois Tigeot 
2083c59a5c48SFrançois Tigeot 	args.v2.ucCRTC = radeon_crtc->crtc_id;
2084c59a5c48SFrançois Tigeot 	args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST;
2085c59a5c48SFrançois Tigeot 
2086c59a5c48SFrançois Tigeot 	switch (fe) {
2087c59a5c48SFrançois Tigeot 	case 0:
2088c59a5c48SFrançois Tigeot 		args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
2089c59a5c48SFrançois Tigeot 		break;
2090c59a5c48SFrançois Tigeot 	case 1:
2091c59a5c48SFrançois Tigeot 		args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
2092c59a5c48SFrançois Tigeot 		break;
2093c59a5c48SFrançois Tigeot 	case 2:
2094c59a5c48SFrançois Tigeot 		args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
2095c59a5c48SFrançois Tigeot 		break;
2096c59a5c48SFrançois Tigeot 	case 3:
2097c59a5c48SFrançois Tigeot 		args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
2098c59a5c48SFrançois Tigeot 		break;
2099c59a5c48SFrançois Tigeot 	case 4:
2100c59a5c48SFrançois Tigeot 		args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
2101c59a5c48SFrançois Tigeot 		break;
2102c59a5c48SFrançois Tigeot 	case 5:
2103c59a5c48SFrançois Tigeot 		args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
2104c59a5c48SFrançois Tigeot 		break;
2105c59a5c48SFrançois Tigeot 	case 6:
2106c59a5c48SFrançois Tigeot 		args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
2107c59a5c48SFrançois Tigeot 		break;
2108c59a5c48SFrançois Tigeot 	}
2109c59a5c48SFrançois Tigeot 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2110c59a5c48SFrançois Tigeot }
2111c59a5c48SFrançois Tigeot 
2112926deccbSFrançois Tigeot static void
atombios_apply_encoder_quirks(struct drm_encoder * encoder,struct drm_display_mode * mode)2113926deccbSFrançois Tigeot atombios_apply_encoder_quirks(struct drm_encoder *encoder,
2114926deccbSFrançois Tigeot 			      struct drm_display_mode *mode)
2115926deccbSFrançois Tigeot {
2116926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2117926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2118926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2119926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
2120926deccbSFrançois Tigeot 
2121926deccbSFrançois Tigeot 	/* Funky macbooks */
2122c6f73aabSFrançois Tigeot 	if ((dev->pdev->device == 0x71C5) &&
2123c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_vendor == 0x106b) &&
2124c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_device == 0x0080)) {
2125926deccbSFrançois Tigeot 		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
2126926deccbSFrançois Tigeot 			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
2127926deccbSFrançois Tigeot 
2128926deccbSFrançois Tigeot 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
2129926deccbSFrançois Tigeot 			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
2130926deccbSFrançois Tigeot 
2131926deccbSFrançois Tigeot 			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
2132926deccbSFrançois Tigeot 		}
2133926deccbSFrançois Tigeot 	}
2134926deccbSFrançois Tigeot 
2135926deccbSFrançois Tigeot 	/* set scaler clears this on some chips */
2136926deccbSFrançois Tigeot 	if (ASIC_IS_AVIVO(rdev) &&
2137926deccbSFrançois Tigeot 	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
213857e252bfSMichael Neumann 		if (ASIC_IS_DCE8(rdev)) {
213957e252bfSMichael Neumann 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
214057e252bfSMichael Neumann 				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset,
214157e252bfSMichael Neumann 				       CIK_INTERLEAVE_EN);
214257e252bfSMichael Neumann 			else
214357e252bfSMichael Neumann 				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
214457e252bfSMichael Neumann 		} else if (ASIC_IS_DCE4(rdev)) {
2145926deccbSFrançois Tigeot 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
2146926deccbSFrançois Tigeot 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
2147926deccbSFrançois Tigeot 				       EVERGREEN_INTERLEAVE_EN);
2148926deccbSFrançois Tigeot 			else
2149926deccbSFrançois Tigeot 				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
2150926deccbSFrançois Tigeot 		} else {
2151926deccbSFrançois Tigeot 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
2152926deccbSFrançois Tigeot 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
2153926deccbSFrançois Tigeot 				       AVIVO_D1MODE_INTERLEAVE_EN);
2154926deccbSFrançois Tigeot 			else
2155926deccbSFrançois Tigeot 				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
2156926deccbSFrançois Tigeot 		}
2157926deccbSFrançois Tigeot 	}
2158926deccbSFrançois Tigeot }
2159926deccbSFrançois Tigeot 
radeon_atom_release_dig_encoder(struct radeon_device * rdev,int enc_idx)2160c59a5c48SFrançois Tigeot void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx)
2161c59a5c48SFrançois Tigeot {
2162c59a5c48SFrançois Tigeot 	if (enc_idx < 0)
2163c59a5c48SFrançois Tigeot 		return;
2164c59a5c48SFrançois Tigeot 	rdev->mode_info.active_encoders &= ~(1 << enc_idx);
2165c59a5c48SFrançois Tigeot }
2166c59a5c48SFrançois Tigeot 
radeon_atom_pick_dig_encoder(struct drm_encoder * encoder,int fe_idx)2167c59a5c48SFrançois Tigeot int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
2168926deccbSFrançois Tigeot {
2169926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2170926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2171926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
2172926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2173926deccbSFrançois Tigeot 	struct drm_encoder *test_encoder;
2174926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
2175926deccbSFrançois Tigeot 	uint32_t dig_enc_in_use = 0;
2176c59a5c48SFrançois Tigeot 	int enc_idx = -1;
2177926deccbSFrançois Tigeot 
2178c59a5c48SFrançois Tigeot 	if (fe_idx >= 0) {
2179c59a5c48SFrançois Tigeot 		enc_idx = fe_idx;
2180c59a5c48SFrançois Tigeot 		goto assigned;
2181c59a5c48SFrançois Tigeot 	}
2182926deccbSFrançois Tigeot 	if (ASIC_IS_DCE6(rdev)) {
2183926deccbSFrançois Tigeot 		/* DCE6 */
2184926deccbSFrançois Tigeot 		switch (radeon_encoder->encoder_id) {
2185926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2186926deccbSFrançois Tigeot 			if (dig->linkb)
2187c59a5c48SFrançois Tigeot 				enc_idx = 1;
2188926deccbSFrançois Tigeot 			else
2189c59a5c48SFrançois Tigeot 				enc_idx = 0;
2190926deccbSFrançois Tigeot 			break;
2191926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2192926deccbSFrançois Tigeot 			if (dig->linkb)
2193c59a5c48SFrançois Tigeot 				enc_idx = 3;
2194926deccbSFrançois Tigeot 			else
2195c59a5c48SFrançois Tigeot 				enc_idx = 2;
2196926deccbSFrançois Tigeot 			break;
2197926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2198926deccbSFrançois Tigeot 			if (dig->linkb)
2199c59a5c48SFrançois Tigeot 				enc_idx = 5;
2200926deccbSFrançois Tigeot 			else
2201c59a5c48SFrançois Tigeot 				enc_idx = 4;
2202926deccbSFrançois Tigeot 			break;
220357e252bfSMichael Neumann 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2204c59a5c48SFrançois Tigeot 			enc_idx = 6;
220557e252bfSMichael Neumann 			break;
2206926deccbSFrançois Tigeot 		}
2207c59a5c48SFrançois Tigeot 		goto assigned;
2208926deccbSFrançois Tigeot 	} else if (ASIC_IS_DCE4(rdev)) {
2209926deccbSFrançois Tigeot 		/* DCE4/5 */
2210926deccbSFrançois Tigeot 		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
2211926deccbSFrançois Tigeot 			/* ontario follows DCE4 */
2212926deccbSFrançois Tigeot 			if (rdev->family == CHIP_PALM) {
2213926deccbSFrançois Tigeot 				if (dig->linkb)
2214c59a5c48SFrançois Tigeot 					enc_idx = 1;
2215926deccbSFrançois Tigeot 				else
2216c59a5c48SFrançois Tigeot 					enc_idx = 0;
2217926deccbSFrançois Tigeot 			} else
2218926deccbSFrançois Tigeot 				/* llano follows DCE3.2 */
2219c59a5c48SFrançois Tigeot 				enc_idx = radeon_crtc->crtc_id;
2220926deccbSFrançois Tigeot 		} else {
2221926deccbSFrançois Tigeot 			switch (radeon_encoder->encoder_id) {
2222926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2223926deccbSFrançois Tigeot 				if (dig->linkb)
2224c59a5c48SFrançois Tigeot 					enc_idx = 1;
2225926deccbSFrançois Tigeot 				else
2226c59a5c48SFrançois Tigeot 					enc_idx = 0;
2227926deccbSFrançois Tigeot 				break;
2228926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2229926deccbSFrançois Tigeot 				if (dig->linkb)
2230c59a5c48SFrançois Tigeot 					enc_idx = 3;
2231926deccbSFrançois Tigeot 				else
2232c59a5c48SFrançois Tigeot 					enc_idx = 2;
2233926deccbSFrançois Tigeot 				break;
2234926deccbSFrançois Tigeot 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2235926deccbSFrançois Tigeot 				if (dig->linkb)
2236c59a5c48SFrançois Tigeot 					enc_idx = 5;
2237926deccbSFrançois Tigeot 				else
2238c59a5c48SFrançois Tigeot 					enc_idx = 4;
2239926deccbSFrançois Tigeot 				break;
2240926deccbSFrançois Tigeot 			}
2241926deccbSFrançois Tigeot 		}
2242c59a5c48SFrançois Tigeot 		goto assigned;
2243926deccbSFrançois Tigeot 	}
2244926deccbSFrançois Tigeot 
2245c59a5c48SFrançois Tigeot 	/*
2246c59a5c48SFrançois Tigeot 	 * On DCE32 any encoder can drive any block so usually just use crtc id,
2247c59a5c48SFrançois Tigeot 	 * but Apple thinks different at least on iMac10,1, so there use linkb,
2248c59a5c48SFrançois Tigeot 	 * otherwise the internal eDP panel will stay dark.
2249c59a5c48SFrançois Tigeot 	 */
2250926deccbSFrançois Tigeot 	if (ASIC_IS_DCE32(rdev)) {
2251c59a5c48SFrançois Tigeot 		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1"))
2252c59a5c48SFrançois Tigeot 			enc_idx = (dig->linkb) ? 1 : 0;
2253c59a5c48SFrançois Tigeot 		else
2254c59a5c48SFrançois Tigeot 			enc_idx = radeon_crtc->crtc_id;
2255c59a5c48SFrançois Tigeot 
2256c59a5c48SFrançois Tigeot 		goto assigned;
2257926deccbSFrançois Tigeot 	}
2258926deccbSFrançois Tigeot 
2259926deccbSFrançois Tigeot 	/* on DCE3 - LVTMA can only be driven by DIGB */
2260926deccbSFrançois Tigeot 	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
2261926deccbSFrançois Tigeot 		struct radeon_encoder *radeon_test_encoder;
2262926deccbSFrançois Tigeot 
2263926deccbSFrançois Tigeot 		if (encoder == test_encoder)
2264926deccbSFrançois Tigeot 			continue;
2265926deccbSFrançois Tigeot 
2266926deccbSFrançois Tigeot 		if (!radeon_encoder_is_digital(test_encoder))
2267926deccbSFrançois Tigeot 			continue;
2268926deccbSFrançois Tigeot 
2269926deccbSFrançois Tigeot 		radeon_test_encoder = to_radeon_encoder(test_encoder);
2270926deccbSFrançois Tigeot 		dig = radeon_test_encoder->enc_priv;
2271926deccbSFrançois Tigeot 
2272926deccbSFrançois Tigeot 		if (dig->dig_encoder >= 0)
2273926deccbSFrançois Tigeot 			dig_enc_in_use |= (1 << dig->dig_encoder);
2274926deccbSFrançois Tigeot 	}
2275926deccbSFrançois Tigeot 
2276926deccbSFrançois Tigeot 	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
2277926deccbSFrançois Tigeot 		if (dig_enc_in_use & 0x2)
2278926deccbSFrançois Tigeot 			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
2279926deccbSFrançois Tigeot 		return 1;
2280926deccbSFrançois Tigeot 	}
2281926deccbSFrançois Tigeot 	if (!(dig_enc_in_use & 1))
2282926deccbSFrançois Tigeot 		return 0;
2283926deccbSFrançois Tigeot 	return 1;
2284c59a5c48SFrançois Tigeot 
2285c59a5c48SFrançois Tigeot assigned:
2286c59a5c48SFrançois Tigeot 	if (enc_idx == -1) {
2287c59a5c48SFrançois Tigeot 		DRM_ERROR("Got encoder index incorrect - returning 0\n");
2288c59a5c48SFrançois Tigeot 		return 0;
2289c59a5c48SFrançois Tigeot 	}
2290c59a5c48SFrançois Tigeot 	if (rdev->mode_info.active_encoders & (1 << enc_idx)) {
2291c59a5c48SFrançois Tigeot 		DRM_ERROR("chosen encoder in use %d\n", enc_idx);
2292c59a5c48SFrançois Tigeot 	}
2293c59a5c48SFrançois Tigeot 	rdev->mode_info.active_encoders |= (1 << enc_idx);
2294c59a5c48SFrançois Tigeot 	return enc_idx;
2295926deccbSFrançois Tigeot }
2296926deccbSFrançois Tigeot 
2297926deccbSFrançois Tigeot /* This only needs to be called once at startup */
2298926deccbSFrançois Tigeot void
radeon_atom_encoder_init(struct radeon_device * rdev)2299926deccbSFrançois Tigeot radeon_atom_encoder_init(struct radeon_device *rdev)
2300926deccbSFrançois Tigeot {
2301926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
2302926deccbSFrançois Tigeot 	struct drm_encoder *encoder;
2303926deccbSFrançois Tigeot 
2304926deccbSFrançois Tigeot 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2305926deccbSFrançois Tigeot 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2306926deccbSFrançois Tigeot 		struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2307926deccbSFrançois Tigeot 
2308926deccbSFrançois Tigeot 		switch (radeon_encoder->encoder_id) {
2309926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2310926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2311926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
231257e252bfSMichael Neumann 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2313926deccbSFrançois Tigeot 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2314926deccbSFrançois Tigeot 			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
2315926deccbSFrançois Tigeot 			break;
2316926deccbSFrançois Tigeot 		default:
2317926deccbSFrançois Tigeot 			break;
2318926deccbSFrançois Tigeot 		}
2319926deccbSFrançois Tigeot 
2320926deccbSFrançois Tigeot 		if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)))
2321926deccbSFrançois Tigeot 			atombios_external_encoder_setup(encoder, ext_encoder,
2322926deccbSFrançois Tigeot 							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
2323926deccbSFrançois Tigeot 	}
2324926deccbSFrançois Tigeot }
2325926deccbSFrançois Tigeot 
2326926deccbSFrançois Tigeot static void
radeon_atom_encoder_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)2327926deccbSFrançois Tigeot radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
2328926deccbSFrançois Tigeot 			     struct drm_display_mode *mode,
2329926deccbSFrançois Tigeot 			     struct drm_display_mode *adjusted_mode)
2330926deccbSFrançois Tigeot {
2331926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2332926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2333926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2334c59a5c48SFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
2335c59a5c48SFrançois Tigeot 	int encoder_mode;
2336926deccbSFrançois Tigeot 
2337926deccbSFrançois Tigeot 	radeon_encoder->pixel_clock = adjusted_mode->clock;
2338926deccbSFrançois Tigeot 
2339926deccbSFrançois Tigeot 	/* need to call this here rather than in prepare() since we need some crtc info */
2340926deccbSFrançois Tigeot 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2341926deccbSFrançois Tigeot 
2342926deccbSFrançois Tigeot 	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
2343926deccbSFrançois Tigeot 		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
2344926deccbSFrançois Tigeot 			atombios_yuv_setup(encoder, true);
2345926deccbSFrançois Tigeot 		else
2346926deccbSFrançois Tigeot 			atombios_yuv_setup(encoder, false);
2347926deccbSFrançois Tigeot 	}
2348926deccbSFrançois Tigeot 
2349926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
2350926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2351926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2352926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2353926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2354926deccbSFrançois Tigeot 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
2355926deccbSFrançois Tigeot 		break;
2356926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2357926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2358926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
235957e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2360926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2361926deccbSFrançois Tigeot 		/* handled in dpms */
2362926deccbSFrançois Tigeot 		break;
2363926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2364926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2365926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2366926deccbSFrançois Tigeot 		atombios_dvo_setup(encoder, ATOM_ENABLE);
2367926deccbSFrançois Tigeot 		break;
2368926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2369926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2370926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2371926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2372926deccbSFrançois Tigeot 		atombios_dac_setup(encoder, ATOM_ENABLE);
2373926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
2374926deccbSFrançois Tigeot 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2375926deccbSFrançois Tigeot 				atombios_tv_setup(encoder, ATOM_ENABLE);
2376926deccbSFrançois Tigeot 			else
2377926deccbSFrançois Tigeot 				atombios_tv_setup(encoder, ATOM_DISABLE);
2378926deccbSFrançois Tigeot 		}
2379926deccbSFrançois Tigeot 		break;
2380926deccbSFrançois Tigeot 	}
2381926deccbSFrançois Tigeot 
2382926deccbSFrançois Tigeot 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
2383926deccbSFrançois Tigeot 
2384c59a5c48SFrançois Tigeot 	encoder_mode = atombios_get_encoder_mode(encoder);
2385c59a5c48SFrançois Tigeot 	if (connector && (radeon_audio != 0) &&
2386c59a5c48SFrançois Tigeot 	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
2387c59a5c48SFrançois Tigeot 	     ENCODER_MODE_IS_DP(encoder_mode)))
2388c59a5c48SFrançois Tigeot 		radeon_audio_mode_set(encoder, adjusted_mode);
2389926deccbSFrançois Tigeot }
2390926deccbSFrançois Tigeot 
2391926deccbSFrançois Tigeot static bool
atombios_dac_load_detect(struct drm_encoder * encoder,struct drm_connector * connector)2392926deccbSFrançois Tigeot atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2393926deccbSFrançois Tigeot {
2394926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2395926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2396926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2397926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2398926deccbSFrançois Tigeot 
2399926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
2400926deccbSFrançois Tigeot 				       ATOM_DEVICE_CV_SUPPORT |
2401926deccbSFrançois Tigeot 				       ATOM_DEVICE_CRT_SUPPORT)) {
2402926deccbSFrançois Tigeot 		DAC_LOAD_DETECTION_PS_ALLOCATION args;
2403926deccbSFrançois Tigeot 		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
2404926deccbSFrançois Tigeot 		uint8_t frev, crev;
2405926deccbSFrançois Tigeot 
2406926deccbSFrançois Tigeot 		memset(&args, 0, sizeof(args));
2407926deccbSFrançois Tigeot 
2408926deccbSFrançois Tigeot 		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2409926deccbSFrançois Tigeot 			return false;
2410926deccbSFrançois Tigeot 
2411926deccbSFrançois Tigeot 		args.sDacload.ucMisc = 0;
2412926deccbSFrançois Tigeot 
2413926deccbSFrançois Tigeot 		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
2414926deccbSFrançois Tigeot 		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
2415926deccbSFrançois Tigeot 			args.sDacload.ucDacType = ATOM_DAC_A;
2416926deccbSFrançois Tigeot 		else
2417926deccbSFrançois Tigeot 			args.sDacload.ucDacType = ATOM_DAC_B;
2418926deccbSFrançois Tigeot 
2419926deccbSFrançois Tigeot 		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
2420926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
2421926deccbSFrançois Tigeot 		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
2422926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
2423926deccbSFrançois Tigeot 		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2424926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
2425926deccbSFrançois Tigeot 			if (crev >= 3)
2426926deccbSFrançois Tigeot 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
2427926deccbSFrançois Tigeot 		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2428926deccbSFrançois Tigeot 			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
2429926deccbSFrançois Tigeot 			if (crev >= 3)
2430926deccbSFrançois Tigeot 				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
2431926deccbSFrançois Tigeot 		}
2432926deccbSFrançois Tigeot 
2433926deccbSFrançois Tigeot 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2434926deccbSFrançois Tigeot 
2435926deccbSFrançois Tigeot 		return true;
2436926deccbSFrançois Tigeot 	} else
2437926deccbSFrançois Tigeot 		return false;
2438926deccbSFrançois Tigeot }
2439926deccbSFrançois Tigeot 
2440926deccbSFrançois Tigeot static enum drm_connector_status
radeon_atom_dac_detect(struct drm_encoder * encoder,struct drm_connector * connector)2441926deccbSFrançois Tigeot radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2442926deccbSFrançois Tigeot {
2443926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2444926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2445926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2446926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2447926deccbSFrançois Tigeot 	uint32_t bios_0_scratch;
2448926deccbSFrançois Tigeot 
2449926deccbSFrançois Tigeot 	if (!atombios_dac_load_detect(encoder, connector)) {
2450926deccbSFrançois Tigeot 		DRM_DEBUG_KMS("detect returned false \n");
2451926deccbSFrançois Tigeot 		return connector_status_unknown;
2452926deccbSFrançois Tigeot 	}
2453926deccbSFrançois Tigeot 
2454926deccbSFrançois Tigeot 	if (rdev->family >= CHIP_R600)
2455926deccbSFrançois Tigeot 		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2456926deccbSFrançois Tigeot 	else
2457926deccbSFrançois Tigeot 		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
2458926deccbSFrançois Tigeot 
2459926deccbSFrançois Tigeot 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
2460926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2461926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2462926deccbSFrançois Tigeot 			return connector_status_connected;
2463926deccbSFrançois Tigeot 	}
2464926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2465926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2466926deccbSFrançois Tigeot 			return connector_status_connected;
2467926deccbSFrançois Tigeot 	}
2468926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2469926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2470926deccbSFrançois Tigeot 			return connector_status_connected;
2471926deccbSFrançois Tigeot 	}
2472926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2473926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2474926deccbSFrançois Tigeot 			return connector_status_connected; /* CTV */
2475926deccbSFrançois Tigeot 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2476926deccbSFrançois Tigeot 			return connector_status_connected; /* STV */
2477926deccbSFrançois Tigeot 	}
2478926deccbSFrançois Tigeot 	return connector_status_disconnected;
2479926deccbSFrançois Tigeot }
2480926deccbSFrançois Tigeot 
2481926deccbSFrançois Tigeot static enum drm_connector_status
radeon_atom_dig_detect(struct drm_encoder * encoder,struct drm_connector * connector)2482926deccbSFrançois Tigeot radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2483926deccbSFrançois Tigeot {
2484926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2485926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2486926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2487926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2488926deccbSFrançois Tigeot 	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2489926deccbSFrançois Tigeot 	u32 bios_0_scratch;
2490926deccbSFrançois Tigeot 
2491926deccbSFrançois Tigeot 	if (!ASIC_IS_DCE4(rdev))
2492926deccbSFrançois Tigeot 		return connector_status_unknown;
2493926deccbSFrançois Tigeot 
2494926deccbSFrançois Tigeot 	if (!ext_encoder)
2495926deccbSFrançois Tigeot 		return connector_status_unknown;
2496926deccbSFrançois Tigeot 
2497926deccbSFrançois Tigeot 	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
2498926deccbSFrançois Tigeot 		return connector_status_unknown;
2499926deccbSFrançois Tigeot 
2500926deccbSFrançois Tigeot 	/* load detect on the dp bridge */
2501926deccbSFrançois Tigeot 	atombios_external_encoder_setup(encoder, ext_encoder,
2502926deccbSFrançois Tigeot 					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
2503926deccbSFrançois Tigeot 
2504926deccbSFrançois Tigeot 	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2505926deccbSFrançois Tigeot 
2506926deccbSFrançois Tigeot 	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
2507926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2508926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2509926deccbSFrançois Tigeot 			return connector_status_connected;
2510926deccbSFrançois Tigeot 	}
2511926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2512926deccbSFrançois Tigeot 		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2513926deccbSFrançois Tigeot 			return connector_status_connected;
2514926deccbSFrançois Tigeot 	}
2515926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2516926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2517926deccbSFrançois Tigeot 			return connector_status_connected;
2518926deccbSFrançois Tigeot 	}
2519926deccbSFrançois Tigeot 	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2520926deccbSFrançois Tigeot 		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2521926deccbSFrançois Tigeot 			return connector_status_connected; /* CTV */
2522926deccbSFrançois Tigeot 		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2523926deccbSFrançois Tigeot 			return connector_status_connected; /* STV */
2524926deccbSFrançois Tigeot 	}
2525926deccbSFrançois Tigeot 	return connector_status_disconnected;
2526926deccbSFrançois Tigeot }
2527926deccbSFrançois Tigeot 
2528926deccbSFrançois Tigeot void
radeon_atom_ext_encoder_setup_ddc(struct drm_encoder * encoder)2529926deccbSFrançois Tigeot radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
2530926deccbSFrançois Tigeot {
2531926deccbSFrançois Tigeot 	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2532926deccbSFrançois Tigeot 
2533926deccbSFrançois Tigeot 	if (ext_encoder)
2534926deccbSFrançois Tigeot 		/* ddc_setup on the dp bridge */
2535926deccbSFrançois Tigeot 		atombios_external_encoder_setup(encoder, ext_encoder,
2536926deccbSFrançois Tigeot 						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
2537926deccbSFrançois Tigeot 
2538926deccbSFrançois Tigeot }
2539926deccbSFrançois Tigeot 
radeon_atom_encoder_prepare(struct drm_encoder * encoder)2540926deccbSFrançois Tigeot static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
2541926deccbSFrançois Tigeot {
2542926deccbSFrançois Tigeot 	struct radeon_device *rdev = encoder->dev->dev_private;
2543926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2544926deccbSFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
2545926deccbSFrançois Tigeot 
2546926deccbSFrançois Tigeot 	if ((radeon_encoder->active_device &
2547926deccbSFrançois Tigeot 	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
2548926deccbSFrançois Tigeot 	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
2549926deccbSFrançois Tigeot 	     ENCODER_OBJECT_ID_NONE)) {
2550926deccbSFrançois Tigeot 		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
2551926deccbSFrançois Tigeot 		if (dig) {
2552c59a5c48SFrançois Tigeot 			if (dig->dig_encoder >= 0)
2553c59a5c48SFrançois Tigeot 				radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
2554c59a5c48SFrançois Tigeot 			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1);
2555926deccbSFrançois Tigeot 			if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
2556926deccbSFrançois Tigeot 				if (rdev->family >= CHIP_R600)
2557926deccbSFrançois Tigeot 					dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
2558926deccbSFrançois Tigeot 				else
2559926deccbSFrançois Tigeot 					/* RS600/690/740 have only 1 afmt block */
2560926deccbSFrançois Tigeot 					dig->afmt = rdev->mode_info.afmt[0];
2561926deccbSFrançois Tigeot 			}
2562926deccbSFrançois Tigeot 		}
2563926deccbSFrançois Tigeot 	}
2564926deccbSFrançois Tigeot 
2565926deccbSFrançois Tigeot 	radeon_atom_output_lock(encoder, true);
2566926deccbSFrançois Tigeot 
2567926deccbSFrançois Tigeot 	if (connector) {
2568926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2569926deccbSFrançois Tigeot 
2570926deccbSFrançois Tigeot 		/* select the clock/data port if it uses a router */
2571926deccbSFrançois Tigeot 		if (radeon_connector->router.cd_valid)
2572926deccbSFrançois Tigeot 			radeon_router_select_cd_port(radeon_connector);
2573926deccbSFrançois Tigeot 
2574926deccbSFrançois Tigeot 		/* turn eDP panel on for mode set */
2575926deccbSFrançois Tigeot 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
2576926deccbSFrançois Tigeot 			atombios_set_edp_panel_power(connector,
2577926deccbSFrançois Tigeot 						     ATOM_TRANSMITTER_ACTION_POWER_ON);
2578926deccbSFrançois Tigeot 	}
2579926deccbSFrançois Tigeot 
2580926deccbSFrançois Tigeot 	/* this is needed for the pll/ss setup to work correctly in some cases */
2581926deccbSFrançois Tigeot 	atombios_set_encoder_crtc_source(encoder);
2582c6f73aabSFrançois Tigeot 	/* set up the FMT blocks */
2583c6f73aabSFrançois Tigeot 	if (ASIC_IS_DCE8(rdev))
2584c6f73aabSFrançois Tigeot 		dce8_program_fmt(encoder);
2585c6f73aabSFrançois Tigeot 	else if (ASIC_IS_DCE4(rdev))
2586c6f73aabSFrançois Tigeot 		dce4_program_fmt(encoder);
2587c6f73aabSFrançois Tigeot 	else if (ASIC_IS_DCE3(rdev))
2588c6f73aabSFrançois Tigeot 		dce3_program_fmt(encoder);
2589c6f73aabSFrançois Tigeot 	else if (ASIC_IS_AVIVO(rdev))
2590c6f73aabSFrançois Tigeot 		avivo_program_fmt(encoder);
2591926deccbSFrançois Tigeot }
2592926deccbSFrançois Tigeot 
radeon_atom_encoder_commit(struct drm_encoder * encoder)2593926deccbSFrançois Tigeot static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
2594926deccbSFrançois Tigeot {
2595926deccbSFrançois Tigeot 	/* need to call this here as we need the crtc set up */
2596926deccbSFrançois Tigeot 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
2597926deccbSFrançois Tigeot 	radeon_atom_output_lock(encoder, false);
2598926deccbSFrançois Tigeot }
2599926deccbSFrançois Tigeot 
radeon_atom_encoder_disable(struct drm_encoder * encoder)2600926deccbSFrançois Tigeot static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
2601926deccbSFrançois Tigeot {
2602926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2603926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2604926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2605926deccbSFrançois Tigeot 	struct radeon_encoder_atom_dig *dig;
2606926deccbSFrançois Tigeot 
2607926deccbSFrançois Tigeot 	/* check for pre-DCE3 cards with shared encoders;
2608926deccbSFrançois Tigeot 	 * can't really use the links individually, so don't disable
2609926deccbSFrançois Tigeot 	 * the encoder if it's in use by another connector
2610926deccbSFrançois Tigeot 	 */
2611926deccbSFrançois Tigeot 	if (!ASIC_IS_DCE3(rdev)) {
2612926deccbSFrançois Tigeot 		struct drm_encoder *other_encoder;
2613926deccbSFrançois Tigeot 		struct radeon_encoder *other_radeon_encoder;
2614926deccbSFrançois Tigeot 
2615926deccbSFrançois Tigeot 		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
2616926deccbSFrançois Tigeot 			other_radeon_encoder = to_radeon_encoder(other_encoder);
2617926deccbSFrançois Tigeot 			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
2618926deccbSFrançois Tigeot 			    drm_helper_encoder_in_use(other_encoder))
2619926deccbSFrançois Tigeot 				goto disable_done;
2620926deccbSFrançois Tigeot 		}
2621926deccbSFrançois Tigeot 	}
2622926deccbSFrançois Tigeot 
2623926deccbSFrançois Tigeot 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2624926deccbSFrançois Tigeot 
2625926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
2626926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2627926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2628926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2629926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2630926deccbSFrançois Tigeot 		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
2631926deccbSFrançois Tigeot 		break;
2632926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2633926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2634926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
263557e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2636926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2637926deccbSFrançois Tigeot 		/* handled in dpms */
2638926deccbSFrançois Tigeot 		break;
2639926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2640926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2641926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2642926deccbSFrançois Tigeot 		atombios_dvo_setup(encoder, ATOM_DISABLE);
2643926deccbSFrançois Tigeot 		break;
2644926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2645926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2646926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2647926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2648926deccbSFrançois Tigeot 		atombios_dac_setup(encoder, ATOM_DISABLE);
2649926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2650926deccbSFrançois Tigeot 			atombios_tv_setup(encoder, ATOM_DISABLE);
2651926deccbSFrançois Tigeot 		break;
2652926deccbSFrançois Tigeot 	}
2653926deccbSFrançois Tigeot 
2654926deccbSFrançois Tigeot disable_done:
2655926deccbSFrançois Tigeot 	if (radeon_encoder_is_digital(encoder)) {
2656f43cf1b1SMichael Neumann 		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
2657f43cf1b1SMichael Neumann 			if (rdev->asic->display.hdmi_enable)
2658f43cf1b1SMichael Neumann 				radeon_hdmi_enable(rdev, encoder, false);
2659f43cf1b1SMichael Neumann 		}
2660c59a5c48SFrançois Tigeot 		if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST) {
2661926deccbSFrançois Tigeot 			dig = radeon_encoder->enc_priv;
2662c59a5c48SFrançois Tigeot 			radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
2663926deccbSFrançois Tigeot 			dig->dig_encoder = -1;
2664c59a5c48SFrançois Tigeot 			radeon_encoder->active_device = 0;
2665926deccbSFrançois Tigeot 		}
2666c59a5c48SFrançois Tigeot 	} else
2667926deccbSFrançois Tigeot 		radeon_encoder->active_device = 0;
2668926deccbSFrançois Tigeot }
2669926deccbSFrançois Tigeot 
2670926deccbSFrançois Tigeot /* these are handled by the primary encoders */
radeon_atom_ext_prepare(struct drm_encoder * encoder)2671926deccbSFrançois Tigeot static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
2672926deccbSFrançois Tigeot {
2673926deccbSFrançois Tigeot 
2674926deccbSFrançois Tigeot }
2675926deccbSFrançois Tigeot 
radeon_atom_ext_commit(struct drm_encoder * encoder)2676926deccbSFrançois Tigeot static void radeon_atom_ext_commit(struct drm_encoder *encoder)
2677926deccbSFrançois Tigeot {
2678926deccbSFrançois Tigeot 
2679926deccbSFrançois Tigeot }
2680926deccbSFrançois Tigeot 
2681926deccbSFrançois Tigeot static void
radeon_atom_ext_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)2682926deccbSFrançois Tigeot radeon_atom_ext_mode_set(struct drm_encoder *encoder,
2683926deccbSFrançois Tigeot 			 struct drm_display_mode *mode,
2684926deccbSFrançois Tigeot 			 struct drm_display_mode *adjusted_mode)
2685926deccbSFrançois Tigeot {
2686926deccbSFrançois Tigeot 
2687926deccbSFrançois Tigeot }
2688926deccbSFrançois Tigeot 
radeon_atom_ext_disable(struct drm_encoder * encoder)2689926deccbSFrançois Tigeot static void radeon_atom_ext_disable(struct drm_encoder *encoder)
2690926deccbSFrançois Tigeot {
2691926deccbSFrançois Tigeot 
2692926deccbSFrançois Tigeot }
2693926deccbSFrançois Tigeot 
2694926deccbSFrançois Tigeot static void
radeon_atom_ext_dpms(struct drm_encoder * encoder,int mode)2695926deccbSFrançois Tigeot radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
2696926deccbSFrançois Tigeot {
2697926deccbSFrançois Tigeot 
2698926deccbSFrançois Tigeot }
2699926deccbSFrançois Tigeot 
2700926deccbSFrançois Tigeot static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
2701926deccbSFrançois Tigeot 	.dpms = radeon_atom_ext_dpms,
2702926deccbSFrançois Tigeot 	.prepare = radeon_atom_ext_prepare,
2703926deccbSFrançois Tigeot 	.mode_set = radeon_atom_ext_mode_set,
2704926deccbSFrançois Tigeot 	.commit = radeon_atom_ext_commit,
2705926deccbSFrançois Tigeot 	.disable = radeon_atom_ext_disable,
2706926deccbSFrançois Tigeot 	/* no detect for TMDS/LVDS yet */
2707926deccbSFrançois Tigeot };
2708926deccbSFrançois Tigeot 
2709926deccbSFrançois Tigeot static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
2710926deccbSFrançois Tigeot 	.dpms = radeon_atom_encoder_dpms,
2711926deccbSFrançois Tigeot 	.mode_fixup = radeon_atom_mode_fixup,
2712926deccbSFrançois Tigeot 	.prepare = radeon_atom_encoder_prepare,
2713926deccbSFrançois Tigeot 	.mode_set = radeon_atom_encoder_mode_set,
2714926deccbSFrançois Tigeot 	.commit = radeon_atom_encoder_commit,
2715926deccbSFrançois Tigeot 	.disable = radeon_atom_encoder_disable,
2716926deccbSFrançois Tigeot 	.detect = radeon_atom_dig_detect,
2717926deccbSFrançois Tigeot };
2718926deccbSFrançois Tigeot 
2719926deccbSFrançois Tigeot static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
2720926deccbSFrançois Tigeot 	.dpms = radeon_atom_encoder_dpms,
2721926deccbSFrançois Tigeot 	.mode_fixup = radeon_atom_mode_fixup,
2722926deccbSFrançois Tigeot 	.prepare = radeon_atom_encoder_prepare,
2723926deccbSFrançois Tigeot 	.mode_set = radeon_atom_encoder_mode_set,
2724926deccbSFrançois Tigeot 	.commit = radeon_atom_encoder_commit,
2725926deccbSFrançois Tigeot 	.detect = radeon_atom_dac_detect,
2726926deccbSFrançois Tigeot };
2727926deccbSFrançois Tigeot 
radeon_enc_destroy(struct drm_encoder * encoder)2728926deccbSFrançois Tigeot void radeon_enc_destroy(struct drm_encoder *encoder)
2729926deccbSFrançois Tigeot {
2730926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2731926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
2732926deccbSFrançois Tigeot 		radeon_atom_backlight_exit(radeon_encoder);
2733c4ef309bSzrj 	kfree(radeon_encoder->enc_priv);
2734926deccbSFrançois Tigeot 	drm_encoder_cleanup(encoder);
2735c4ef309bSzrj 	kfree(radeon_encoder);
2736926deccbSFrançois Tigeot }
2737926deccbSFrançois Tigeot 
2738926deccbSFrançois Tigeot static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
2739926deccbSFrançois Tigeot 	.destroy = radeon_enc_destroy,
2740926deccbSFrançois Tigeot };
2741926deccbSFrançois Tigeot 
2742926deccbSFrançois Tigeot static struct radeon_encoder_atom_dac *
radeon_atombios_set_dac_info(struct radeon_encoder * radeon_encoder)2743926deccbSFrançois Tigeot radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
2744926deccbSFrançois Tigeot {
2745926deccbSFrançois Tigeot 	struct drm_device *dev = radeon_encoder->base.dev;
2746926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2747c4ef309bSzrj 	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
2748926deccbSFrançois Tigeot 
2749926deccbSFrançois Tigeot 	if (!dac)
2750926deccbSFrançois Tigeot 		return NULL;
2751926deccbSFrançois Tigeot 
2752926deccbSFrançois Tigeot 	dac->tv_std = radeon_atombios_get_tv_info(rdev);
2753926deccbSFrançois Tigeot 	return dac;
2754926deccbSFrançois Tigeot }
2755926deccbSFrançois Tigeot 
2756926deccbSFrançois Tigeot static struct radeon_encoder_atom_dig *
radeon_atombios_set_dig_info(struct radeon_encoder * radeon_encoder)2757926deccbSFrançois Tigeot radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
2758926deccbSFrançois Tigeot {
2759926deccbSFrançois Tigeot 	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
2760c4ef309bSzrj 	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
2761926deccbSFrançois Tigeot 
2762926deccbSFrançois Tigeot 	if (!dig)
2763926deccbSFrançois Tigeot 		return NULL;
2764926deccbSFrançois Tigeot 
2765926deccbSFrançois Tigeot 	/* coherent mode by default */
2766926deccbSFrançois Tigeot 	dig->coherent_mode = true;
2767926deccbSFrançois Tigeot 	dig->dig_encoder = -1;
2768926deccbSFrançois Tigeot 
2769926deccbSFrançois Tigeot 	if (encoder_enum == 2)
2770926deccbSFrançois Tigeot 		dig->linkb = true;
2771926deccbSFrançois Tigeot 	else
2772926deccbSFrançois Tigeot 		dig->linkb = false;
2773926deccbSFrançois Tigeot 
2774926deccbSFrançois Tigeot 	return dig;
2775926deccbSFrançois Tigeot }
2776926deccbSFrançois Tigeot 
2777926deccbSFrançois Tigeot void
radeon_add_atom_encoder(struct drm_device * dev,uint32_t encoder_enum,uint32_t supported_device,u16 caps)2778926deccbSFrançois Tigeot radeon_add_atom_encoder(struct drm_device *dev,
2779926deccbSFrançois Tigeot 			uint32_t encoder_enum,
2780926deccbSFrançois Tigeot 			uint32_t supported_device,
2781926deccbSFrançois Tigeot 			u16 caps)
2782926deccbSFrançois Tigeot {
2783926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2784926deccbSFrançois Tigeot 	struct drm_encoder *encoder;
2785926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder;
2786926deccbSFrançois Tigeot 
2787926deccbSFrançois Tigeot 	/* see if we already added it */
2788926deccbSFrançois Tigeot 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2789926deccbSFrançois Tigeot 		radeon_encoder = to_radeon_encoder(encoder);
2790926deccbSFrançois Tigeot 		if (radeon_encoder->encoder_enum == encoder_enum) {
2791926deccbSFrançois Tigeot 			radeon_encoder->devices |= supported_device;
2792926deccbSFrançois Tigeot 			return;
2793926deccbSFrançois Tigeot 		}
2794926deccbSFrançois Tigeot 
2795926deccbSFrançois Tigeot 	}
2796926deccbSFrançois Tigeot 
2797926deccbSFrançois Tigeot 	/* add a new one */
2798c4ef309bSzrj 	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
2799926deccbSFrançois Tigeot 	if (!radeon_encoder)
2800926deccbSFrançois Tigeot 		return;
2801926deccbSFrançois Tigeot 
2802926deccbSFrançois Tigeot 	encoder = &radeon_encoder->base;
2803926deccbSFrançois Tigeot 	switch (rdev->num_crtc) {
2804926deccbSFrançois Tigeot 	case 1:
2805926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0x1;
2806926deccbSFrançois Tigeot 		break;
2807926deccbSFrançois Tigeot 	case 2:
2808926deccbSFrançois Tigeot 	default:
2809926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0x3;
2810926deccbSFrançois Tigeot 		break;
2811926deccbSFrançois Tigeot 	case 4:
2812926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0xf;
2813926deccbSFrançois Tigeot 		break;
2814926deccbSFrançois Tigeot 	case 6:
2815926deccbSFrançois Tigeot 		encoder->possible_crtcs = 0x3f;
2816926deccbSFrançois Tigeot 		break;
2817926deccbSFrançois Tigeot 	}
2818926deccbSFrançois Tigeot 
2819926deccbSFrançois Tigeot 	radeon_encoder->enc_priv = NULL;
2820926deccbSFrançois Tigeot 
2821926deccbSFrançois Tigeot 	radeon_encoder->encoder_enum = encoder_enum;
2822926deccbSFrançois Tigeot 	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
2823926deccbSFrançois Tigeot 	radeon_encoder->devices = supported_device;
2824926deccbSFrançois Tigeot 	radeon_encoder->rmx_type = RMX_OFF;
2825926deccbSFrançois Tigeot 	radeon_encoder->underscan_type = UNDERSCAN_OFF;
2826926deccbSFrançois Tigeot 	radeon_encoder->is_ext_encoder = false;
2827926deccbSFrançois Tigeot 	radeon_encoder->caps = caps;
2828926deccbSFrançois Tigeot 
2829926deccbSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
2830926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2831926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2832926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2833926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2834926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2835926deccbSFrançois Tigeot 			radeon_encoder->rmx_type = RMX_FULL;
2836aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2837aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_LVDS, NULL);
2838926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2839926deccbSFrançois Tigeot 		} else {
2840aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2841aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_TMDS, NULL);
2842926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2843926deccbSFrançois Tigeot 		}
2844926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2845926deccbSFrançois Tigeot 		break;
2846926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2847aee94f86SFrançois Tigeot 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2848aee94f86SFrançois Tigeot 				 DRM_MODE_ENCODER_DAC, NULL);
2849926deccbSFrançois Tigeot 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2850926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2851926deccbSFrançois Tigeot 		break;
2852926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2853926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2854926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2855aee94f86SFrançois Tigeot 		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2856aee94f86SFrançois Tigeot 				 DRM_MODE_ENCODER_TVDAC, NULL);
2857926deccbSFrançois Tigeot 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2858926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2859926deccbSFrançois Tigeot 		break;
2860926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2861926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2862926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2863926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2864926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2865926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2866926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
286757e252bfSMichael Neumann 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
2868926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2869926deccbSFrançois Tigeot 			radeon_encoder->rmx_type = RMX_FULL;
2870aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2871aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_LVDS, NULL);
2872926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2873926deccbSFrançois Tigeot 		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
2874aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2875aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_DAC, NULL);
2876926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2877926deccbSFrançois Tigeot 		} else {
2878aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2879aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_TMDS, NULL);
2880926deccbSFrançois Tigeot 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2881926deccbSFrançois Tigeot 		}
2882926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2883926deccbSFrançois Tigeot 		break;
2884926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_SI170B:
2885926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_CH7303:
2886926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2887926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2888926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_TITFP513:
2889926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_VT1623:
2890926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_HDMI_SI1930:
2891926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_TRAVIS:
2892926deccbSFrançois Tigeot 	case ENCODER_OBJECT_ID_NUTMEG:
2893926deccbSFrançois Tigeot 		/* these are handled by the primary encoders */
2894926deccbSFrançois Tigeot 		radeon_encoder->is_ext_encoder = true;
2895926deccbSFrançois Tigeot 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
2896aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2897aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_LVDS, NULL);
2898926deccbSFrançois Tigeot 		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
2899aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2900aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_DAC, NULL);
2901926deccbSFrançois Tigeot 		else
2902aee94f86SFrançois Tigeot 			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
2903aee94f86SFrançois Tigeot 					 DRM_MODE_ENCODER_TMDS, NULL);
2904926deccbSFrançois Tigeot 		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
2905926deccbSFrançois Tigeot 		break;
2906926deccbSFrançois Tigeot 	}
2907926deccbSFrançois Tigeot }
2908