1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2007-11 Advanced Micro Devices, Inc.
3254885Sdumbbell * Copyright 2008 Red Hat Inc.
4254885Sdumbbell *
5254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
6254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
7254885Sdumbbell * to deal in the Software without restriction, including without limitation
8254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
10254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
11254885Sdumbbell *
12254885Sdumbbell * The above copyright notice and this permission notice shall be included in
13254885Sdumbbell * all copies or substantial portions of the Software.
14254885Sdumbbell *
15254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
22254885Sdumbbell *
23254885Sdumbbell * Authors: Dave Airlie
24254885Sdumbbell *          Alex Deucher
25254885Sdumbbell */
26254885Sdumbbell
27254885Sdumbbell#include <sys/cdefs.h>
28254885Sdumbbell__FBSDID("$FreeBSD$");
29254885Sdumbbell
30254885Sdumbbell#include <dev/drm2/drmP.h>
31254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h>
32254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
33254885Sdumbbell#include "radeon.h"
34254885Sdumbbell#include "radeon_asic.h" /* Declares several prototypes; clang is pleased. */
35254885Sdumbbell#include "atom.h"
36254885Sdumbbell
37254885Sdumbbellstatic u8
38254885Sdumbbellradeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev)
39254885Sdumbbell{
40254885Sdumbbell	u8 backlight_level;
41254885Sdumbbell	u32 bios_2_scratch;
42254885Sdumbbell
43254885Sdumbbell	if (rdev->family >= CHIP_R600)
44254885Sdumbbell		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
45254885Sdumbbell	else
46254885Sdumbbell		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
47254885Sdumbbell
48254885Sdumbbell	backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >>
49254885Sdumbbell			   ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
50254885Sdumbbell
51254885Sdumbbell	return backlight_level;
52254885Sdumbbell}
53254885Sdumbbell
54254885Sdumbbellstatic void
55254885Sdumbbellradeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev,
56254885Sdumbbell				       u8 backlight_level)
57254885Sdumbbell{
58254885Sdumbbell	u32 bios_2_scratch;
59254885Sdumbbell
60254885Sdumbbell	if (rdev->family >= CHIP_R600)
61254885Sdumbbell		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
62254885Sdumbbell	else
63254885Sdumbbell		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
64254885Sdumbbell
65254885Sdumbbell	bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
66254885Sdumbbell	bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
67254885Sdumbbell			   ATOM_S2_CURRENT_BL_LEVEL_MASK);
68254885Sdumbbell
69254885Sdumbbell	if (rdev->family >= CHIP_R600)
70254885Sdumbbell		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
71254885Sdumbbell	else
72254885Sdumbbell		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
73254885Sdumbbell}
74254885Sdumbbell
75254885Sdumbbellu8
76254885Sdumbbellatombios_get_backlight_level(struct radeon_encoder *radeon_encoder)
77254885Sdumbbell{
78254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
79254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
80254885Sdumbbell
81254885Sdumbbell	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
82254885Sdumbbell		return 0;
83254885Sdumbbell
84254885Sdumbbell	return radeon_atom_get_backlight_level_from_reg(rdev);
85254885Sdumbbell}
86254885Sdumbbell
87254885Sdumbbellvoid
88254885Sdumbbellatombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
89254885Sdumbbell{
90254885Sdumbbell	struct drm_encoder *encoder = &radeon_encoder->base;
91254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
92254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
93254885Sdumbbell	struct radeon_encoder_atom_dig *dig;
94254885Sdumbbell	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
95254885Sdumbbell	int index;
96254885Sdumbbell
97254885Sdumbbell	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
98254885Sdumbbell		return;
99254885Sdumbbell
100254885Sdumbbell	if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
101254885Sdumbbell	    radeon_encoder->enc_priv) {
102254885Sdumbbell		dig = radeon_encoder->enc_priv;
103254885Sdumbbell		dig->backlight_level = level;
104254885Sdumbbell		radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level);
105254885Sdumbbell
106254885Sdumbbell		switch (radeon_encoder->encoder_id) {
107254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
108254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
109254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
110254885Sdumbbell			if (dig->backlight_level == 0) {
111254885Sdumbbell				args.ucAction = ATOM_LCD_BLOFF;
112254885Sdumbbell				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
113254885Sdumbbell			} else {
114254885Sdumbbell				args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
115254885Sdumbbell				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
116254885Sdumbbell				args.ucAction = ATOM_LCD_BLON;
117254885Sdumbbell				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
118254885Sdumbbell			}
119254885Sdumbbell			break;
120254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
121254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
122254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
123254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
124254885Sdumbbell			if (dig->backlight_level == 0)
125254885Sdumbbell				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
126254885Sdumbbell			else {
127254885Sdumbbell				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0);
128254885Sdumbbell				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
129254885Sdumbbell			}
130254885Sdumbbell			break;
131254885Sdumbbell		default:
132254885Sdumbbell			break;
133254885Sdumbbell		}
134254885Sdumbbell	}
135254885Sdumbbell}
136254885Sdumbbell
137254885Sdumbbell#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
138254885Sdumbbell
139254885Sdumbbellstatic u8 radeon_atom_bl_level(struct backlight_device *bd)
140254885Sdumbbell{
141254885Sdumbbell	u8 level;
142254885Sdumbbell
143254885Sdumbbell	/* Convert brightness to hardware level */
144254885Sdumbbell	if (bd->props.brightness < 0)
145254885Sdumbbell		level = 0;
146254885Sdumbbell	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
147254885Sdumbbell		level = RADEON_MAX_BL_LEVEL;
148254885Sdumbbell	else
149254885Sdumbbell		level = bd->props.brightness;
150254885Sdumbbell
151254885Sdumbbell	return level;
152254885Sdumbbell}
153254885Sdumbbell
154254885Sdumbbellstatic int radeon_atom_backlight_update_status(struct backlight_device *bd)
155254885Sdumbbell{
156254885Sdumbbell	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
157254885Sdumbbell	struct radeon_encoder *radeon_encoder = pdata->encoder;
158254885Sdumbbell
159254885Sdumbbell	atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd));
160254885Sdumbbell
161254885Sdumbbell	return 0;
162254885Sdumbbell}
163254885Sdumbbell
164254885Sdumbbellstatic int radeon_atom_backlight_get_brightness(struct backlight_device *bd)
165254885Sdumbbell{
166254885Sdumbbell	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
167254885Sdumbbell	struct radeon_encoder *radeon_encoder = pdata->encoder;
168254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
169254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
170254885Sdumbbell
171254885Sdumbbell	return radeon_atom_get_backlight_level_from_reg(rdev);
172254885Sdumbbell}
173254885Sdumbbell
174254885Sdumbbellstatic const struct backlight_ops radeon_atom_backlight_ops = {
175254885Sdumbbell	.get_brightness = radeon_atom_backlight_get_brightness,
176254885Sdumbbell	.update_status	= radeon_atom_backlight_update_status,
177254885Sdumbbell};
178254885Sdumbbell
179254885Sdumbbellvoid radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
180254885Sdumbbell				struct drm_connector *drm_connector)
181254885Sdumbbell{
182254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
183254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
184254885Sdumbbell	struct backlight_device *bd;
185254885Sdumbbell	struct backlight_properties props;
186254885Sdumbbell	struct radeon_backlight_privdata *pdata;
187254885Sdumbbell	struct radeon_encoder_atom_dig *dig;
188254885Sdumbbell	u8 backlight_level;
189254885Sdumbbell	char bl_name[16];
190254885Sdumbbell
191254885Sdumbbell	if (!radeon_encoder->enc_priv)
192254885Sdumbbell		return;
193254885Sdumbbell
194254885Sdumbbell	if (!rdev->is_atom_bios)
195254885Sdumbbell		return;
196254885Sdumbbell
197254885Sdumbbell	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
198254885Sdumbbell		return;
199254885Sdumbbell
200280183Sdumbbell	pdata = malloc(sizeof(struct radeon_backlight_privdata), DRM_MEM_DRIVER, M_NOWAIT);
201254885Sdumbbell	if (!pdata) {
202254885Sdumbbell		DRM_ERROR("Memory allocation failed\n");
203254885Sdumbbell		goto error;
204254885Sdumbbell	}
205254885Sdumbbell
206254885Sdumbbell	memset(&props, 0, sizeof(props));
207254885Sdumbbell	props.max_brightness = RADEON_MAX_BL_LEVEL;
208254885Sdumbbell	props.type = BACKLIGHT_RAW;
209254885Sdumbbell	snprintf(bl_name, sizeof(bl_name),
210254885Sdumbbell		 "radeon_bl%d", dev->primary->index);
211254885Sdumbbell	bd = backlight_device_register(bl_name, &drm_connector->kdev,
212254885Sdumbbell				       pdata, &radeon_atom_backlight_ops, &props);
213254885Sdumbbell	if (IS_ERR(bd)) {
214254885Sdumbbell		DRM_ERROR("Backlight registration failed\n");
215254885Sdumbbell		goto error;
216254885Sdumbbell	}
217254885Sdumbbell
218254885Sdumbbell	pdata->encoder = radeon_encoder;
219254885Sdumbbell
220254885Sdumbbell	backlight_level = radeon_atom_get_backlight_level_from_reg(rdev);
221254885Sdumbbell
222254885Sdumbbell	dig = radeon_encoder->enc_priv;
223254885Sdumbbell	dig->bl_dev = bd;
224254885Sdumbbell
225254885Sdumbbell	bd->props.brightness = radeon_atom_backlight_get_brightness(bd);
226254885Sdumbbell	bd->props.power = FB_BLANK_UNBLANK;
227254885Sdumbbell	backlight_update_status(bd);
228254885Sdumbbell
229254885Sdumbbell	DRM_INFO("radeon atom DIG backlight initialized\n");
230254885Sdumbbell
231254885Sdumbbell	return;
232254885Sdumbbell
233254885Sdumbbellerror:
234254885Sdumbbell	free(pdata, DRM_MEM_DRIVER);
235254885Sdumbbell	return;
236254885Sdumbbell}
237254885Sdumbbell
238254885Sdumbbellstatic void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder)
239254885Sdumbbell{
240254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
241254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
242254885Sdumbbell	struct backlight_device *bd = NULL;
243254885Sdumbbell	struct radeon_encoder_atom_dig *dig;
244254885Sdumbbell
245254885Sdumbbell	if (!radeon_encoder->enc_priv)
246254885Sdumbbell		return;
247254885Sdumbbell
248254885Sdumbbell	if (!rdev->is_atom_bios)
249254885Sdumbbell		return;
250254885Sdumbbell
251254885Sdumbbell	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
252254885Sdumbbell		return;
253254885Sdumbbell
254254885Sdumbbell	dig = radeon_encoder->enc_priv;
255254885Sdumbbell	bd = dig->bl_dev;
256254885Sdumbbell	dig->bl_dev = NULL;
257254885Sdumbbell
258254885Sdumbbell	if (bd) {
259254885Sdumbbell		struct radeon_legacy_backlight_privdata *pdata;
260254885Sdumbbell
261254885Sdumbbell		pdata = bl_get_data(bd);
262254885Sdumbbell		backlight_device_unregister(bd);
263254885Sdumbbell		free(pdata, DRM_MEM_DRIVER);
264254885Sdumbbell
265254885Sdumbbell		DRM_INFO("radeon atom LVDS backlight unloaded\n");
266254885Sdumbbell	}
267254885Sdumbbell}
268254885Sdumbbell
269254885Sdumbbell#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
270254885Sdumbbell
271254885Sdumbbellvoid radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
272254885Sdumbbell				struct drm_connector *drm_connector)
273254885Sdumbbell{
274254885Sdumbbell}
275254885Sdumbbell
276254885Sdumbbellstatic void radeon_atom_backlight_exit(struct radeon_encoder *encoder)
277254885Sdumbbell{
278254885Sdumbbell}
279254885Sdumbbell
280254885Sdumbbell#endif
281254885Sdumbbell
282280183Sdumbbell#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
283280183Sdumbbell/* evil but including atombios.h is much worse */
284280183Sdumbbellbool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
285280183Sdumbbell				struct drm_display_mode *mode);
286280183Sdumbbell#endif
287254885Sdumbbell
288280183Sdumbbell
289254885Sdumbbellstatic inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
290254885Sdumbbell{
291254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
292254885Sdumbbell	switch (radeon_encoder->encoder_id) {
293254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
294254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
295254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
296254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
297254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
298254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
299254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DDI:
300254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
301254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
302254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
303254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
304254885Sdumbbell		return true;
305254885Sdumbbell	default:
306254885Sdumbbell		return false;
307254885Sdumbbell	}
308254885Sdumbbell}
309254885Sdumbbell
310254885Sdumbbellstatic bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
311280183Sdumbbell				   const struct drm_display_mode *mode,
312254885Sdumbbell				   struct drm_display_mode *adjusted_mode)
313254885Sdumbbell{
314254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
315254885Sdumbbell	struct drm_device *dev = encoder->dev;
316254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
317254885Sdumbbell
318254885Sdumbbell	/* set the active encoder to connector routing */
319254885Sdumbbell	radeon_encoder_set_active_device(encoder);
320254885Sdumbbell	drm_mode_set_crtcinfo(adjusted_mode, 0);
321254885Sdumbbell
322254885Sdumbbell	/* hw bug */
323254885Sdumbbell	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
324254885Sdumbbell	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
325254885Sdumbbell		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
326254885Sdumbbell
327254885Sdumbbell	/* get the native mode for LVDS */
328254885Sdumbbell	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
329254885Sdumbbell		radeon_panel_mode_fixup(encoder, adjusted_mode);
330254885Sdumbbell
331254885Sdumbbell	/* get the native mode for TV */
332254885Sdumbbell	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
333254885Sdumbbell		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
334254885Sdumbbell		if (tv_dac) {
335254885Sdumbbell			if (tv_dac->tv_std == TV_STD_NTSC ||
336254885Sdumbbell			    tv_dac->tv_std == TV_STD_NTSC_J ||
337254885Sdumbbell			    tv_dac->tv_std == TV_STD_PAL_M)
338254885Sdumbbell				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
339254885Sdumbbell			else
340254885Sdumbbell				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
341254885Sdumbbell		}
342254885Sdumbbell	}
343254885Sdumbbell
344254885Sdumbbell	if (ASIC_IS_DCE3(rdev) &&
345254885Sdumbbell	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
346254885Sdumbbell	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
347254885Sdumbbell		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
348254885Sdumbbell		radeon_dp_set_link_config(connector, adjusted_mode);
349254885Sdumbbell	}
350254885Sdumbbell
351254885Sdumbbell	return true;
352254885Sdumbbell}
353254885Sdumbbell
354254885Sdumbbellstatic void
355254885Sdumbbellatombios_dac_setup(struct drm_encoder *encoder, int action)
356254885Sdumbbell{
357254885Sdumbbell	struct drm_device *dev = encoder->dev;
358254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
359254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
360254885Sdumbbell	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
361254885Sdumbbell	int index = 0;
362254885Sdumbbell	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
363254885Sdumbbell
364254885Sdumbbell	memset(&args, 0, sizeof(args));
365254885Sdumbbell
366254885Sdumbbell	switch (radeon_encoder->encoder_id) {
367254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
368254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
369254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
370254885Sdumbbell		break;
371254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
372254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
373254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
374254885Sdumbbell		break;
375254885Sdumbbell	}
376254885Sdumbbell
377254885Sdumbbell	args.ucAction = action;
378254885Sdumbbell
379254885Sdumbbell	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
380254885Sdumbbell		args.ucDacStandard = ATOM_DAC1_PS2;
381254885Sdumbbell	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
382254885Sdumbbell		args.ucDacStandard = ATOM_DAC1_CV;
383254885Sdumbbell	else {
384254885Sdumbbell		switch (dac_info->tv_std) {
385254885Sdumbbell		case TV_STD_PAL:
386254885Sdumbbell		case TV_STD_PAL_M:
387254885Sdumbbell		case TV_STD_SCART_PAL:
388254885Sdumbbell		case TV_STD_SECAM:
389254885Sdumbbell		case TV_STD_PAL_CN:
390254885Sdumbbell			args.ucDacStandard = ATOM_DAC1_PAL;
391254885Sdumbbell			break;
392254885Sdumbbell		case TV_STD_NTSC:
393254885Sdumbbell		case TV_STD_NTSC_J:
394254885Sdumbbell		case TV_STD_PAL_60:
395254885Sdumbbell		default:
396254885Sdumbbell			args.ucDacStandard = ATOM_DAC1_NTSC;
397254885Sdumbbell			break;
398254885Sdumbbell		}
399254885Sdumbbell	}
400254885Sdumbbell	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
401254885Sdumbbell
402254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
403254885Sdumbbell
404254885Sdumbbell}
405254885Sdumbbell
406254885Sdumbbellstatic void
407254885Sdumbbellatombios_tv_setup(struct drm_encoder *encoder, int action)
408254885Sdumbbell{
409254885Sdumbbell	struct drm_device *dev = encoder->dev;
410254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
411254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
412254885Sdumbbell	TV_ENCODER_CONTROL_PS_ALLOCATION args;
413254885Sdumbbell	int index = 0;
414254885Sdumbbell	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
415254885Sdumbbell
416254885Sdumbbell	memset(&args, 0, sizeof(args));
417254885Sdumbbell
418254885Sdumbbell	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
419254885Sdumbbell
420254885Sdumbbell	args.sTVEncoder.ucAction = action;
421254885Sdumbbell
422254885Sdumbbell	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
423254885Sdumbbell		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
424254885Sdumbbell	else {
425254885Sdumbbell		switch (dac_info->tv_std) {
426254885Sdumbbell		case TV_STD_NTSC:
427254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
428254885Sdumbbell			break;
429254885Sdumbbell		case TV_STD_PAL:
430254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
431254885Sdumbbell			break;
432254885Sdumbbell		case TV_STD_PAL_M:
433254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
434254885Sdumbbell			break;
435254885Sdumbbell		case TV_STD_PAL_60:
436254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
437254885Sdumbbell			break;
438254885Sdumbbell		case TV_STD_NTSC_J:
439254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
440254885Sdumbbell			break;
441254885Sdumbbell		case TV_STD_SCART_PAL:
442254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
443254885Sdumbbell			break;
444254885Sdumbbell		case TV_STD_SECAM:
445254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
446254885Sdumbbell			break;
447254885Sdumbbell		case TV_STD_PAL_CN:
448254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
449254885Sdumbbell			break;
450254885Sdumbbell		default:
451254885Sdumbbell			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
452254885Sdumbbell			break;
453254885Sdumbbell		}
454254885Sdumbbell	}
455254885Sdumbbell
456254885Sdumbbell	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
457254885Sdumbbell
458254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
459254885Sdumbbell
460254885Sdumbbell}
461254885Sdumbbell
462254885Sdumbbellstatic u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
463254885Sdumbbell{
464254885Sdumbbell	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
465254885Sdumbbell	int bpc = 8;
466254885Sdumbbell
467254885Sdumbbell	if (connector)
468254885Sdumbbell		bpc = radeon_get_monitor_bpc(connector);
469254885Sdumbbell
470254885Sdumbbell	switch (bpc) {
471254885Sdumbbell	case 0:
472254885Sdumbbell		return PANEL_BPC_UNDEFINE;
473254885Sdumbbell	case 6:
474254885Sdumbbell		return PANEL_6BIT_PER_COLOR;
475254885Sdumbbell	case 8:
476254885Sdumbbell	default:
477254885Sdumbbell		return PANEL_8BIT_PER_COLOR;
478254885Sdumbbell	case 10:
479254885Sdumbbell		return PANEL_10BIT_PER_COLOR;
480254885Sdumbbell	case 12:
481254885Sdumbbell		return PANEL_12BIT_PER_COLOR;
482254885Sdumbbell	case 16:
483254885Sdumbbell		return PANEL_16BIT_PER_COLOR;
484254885Sdumbbell	}
485254885Sdumbbell}
486254885Sdumbbell
487254885Sdumbbell
488254885Sdumbbellunion dvo_encoder_control {
489254885Sdumbbell	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
490254885Sdumbbell	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
491254885Sdumbbell	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
492254885Sdumbbell};
493254885Sdumbbell
494254885Sdumbbellvoid
495254885Sdumbbellatombios_dvo_setup(struct drm_encoder *encoder, int action)
496254885Sdumbbell{
497254885Sdumbbell	struct drm_device *dev = encoder->dev;
498254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
499254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
500254885Sdumbbell	union dvo_encoder_control args;
501254885Sdumbbell	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
502254885Sdumbbell	uint8_t frev, crev;
503254885Sdumbbell
504254885Sdumbbell	memset(&args, 0, sizeof(args));
505254885Sdumbbell
506254885Sdumbbell	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
507254885Sdumbbell		return;
508254885Sdumbbell
509254885Sdumbbell	/* some R4xx chips have the wrong frev */
510254885Sdumbbell	if (rdev->family <= CHIP_RV410)
511254885Sdumbbell		frev = 1;
512254885Sdumbbell
513254885Sdumbbell	switch (frev) {
514254885Sdumbbell	case 1:
515254885Sdumbbell		switch (crev) {
516254885Sdumbbell		case 1:
517254885Sdumbbell			/* R4xx, R5xx */
518254885Sdumbbell			args.ext_tmds.sXTmdsEncoder.ucEnable = action;
519254885Sdumbbell
520254885Sdumbbell			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
521254885Sdumbbell				args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
522254885Sdumbbell
523254885Sdumbbell			args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
524254885Sdumbbell			break;
525254885Sdumbbell		case 2:
526254885Sdumbbell			/* RS600/690/740 */
527254885Sdumbbell			args.dvo.sDVOEncoder.ucAction = action;
528254885Sdumbbell			args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
529254885Sdumbbell			/* DFP1, CRT1, TV1 depending on the type of port */
530254885Sdumbbell			args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
531254885Sdumbbell
532254885Sdumbbell			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
533254885Sdumbbell				args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
534254885Sdumbbell			break;
535254885Sdumbbell		case 3:
536254885Sdumbbell			/* R6xx */
537254885Sdumbbell			args.dvo_v3.ucAction = action;
538254885Sdumbbell			args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
539254885Sdumbbell			args.dvo_v3.ucDVOConfig = 0; /* XXX */
540254885Sdumbbell			break;
541254885Sdumbbell		default:
542254885Sdumbbell			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
543254885Sdumbbell			break;
544254885Sdumbbell		}
545254885Sdumbbell		break;
546254885Sdumbbell	default:
547254885Sdumbbell		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
548254885Sdumbbell		break;
549254885Sdumbbell	}
550254885Sdumbbell
551254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
552254885Sdumbbell}
553254885Sdumbbell
554254885Sdumbbellunion lvds_encoder_control {
555254885Sdumbbell	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
556254885Sdumbbell	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
557254885Sdumbbell};
558254885Sdumbbell
559254885Sdumbbellvoid
560254885Sdumbbellatombios_digital_setup(struct drm_encoder *encoder, int action)
561254885Sdumbbell{
562254885Sdumbbell	struct drm_device *dev = encoder->dev;
563254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
564254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
565254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
566254885Sdumbbell	union lvds_encoder_control args;
567254885Sdumbbell	int index = 0;
568254885Sdumbbell	int hdmi_detected = 0;
569254885Sdumbbell	uint8_t frev, crev;
570254885Sdumbbell
571254885Sdumbbell	if (!dig)
572254885Sdumbbell		return;
573254885Sdumbbell
574254885Sdumbbell	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
575254885Sdumbbell		hdmi_detected = 1;
576254885Sdumbbell
577254885Sdumbbell	memset(&args, 0, sizeof(args));
578254885Sdumbbell
579254885Sdumbbell	switch (radeon_encoder->encoder_id) {
580254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
581254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
582254885Sdumbbell		break;
583254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
584254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
585254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
586254885Sdumbbell		break;
587254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
588254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
589254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
590254885Sdumbbell		else
591254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
592254885Sdumbbell		break;
593254885Sdumbbell	}
594254885Sdumbbell
595254885Sdumbbell	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
596254885Sdumbbell		return;
597254885Sdumbbell
598254885Sdumbbell	switch (frev) {
599254885Sdumbbell	case 1:
600254885Sdumbbell	case 2:
601254885Sdumbbell		switch (crev) {
602254885Sdumbbell		case 1:
603254885Sdumbbell			args.v1.ucMisc = 0;
604254885Sdumbbell			args.v1.ucAction = action;
605254885Sdumbbell			if (hdmi_detected)
606254885Sdumbbell				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
607254885Sdumbbell			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
608254885Sdumbbell			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
609254885Sdumbbell				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
610254885Sdumbbell					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
611254885Sdumbbell				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
612254885Sdumbbell					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
613254885Sdumbbell			} else {
614254885Sdumbbell				if (dig->linkb)
615254885Sdumbbell					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
616254885Sdumbbell				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
617254885Sdumbbell					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
618254885Sdumbbell				/*if (pScrn->rgbBits == 8) */
619254885Sdumbbell				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
620254885Sdumbbell			}
621254885Sdumbbell			break;
622254885Sdumbbell		case 2:
623254885Sdumbbell		case 3:
624254885Sdumbbell			args.v2.ucMisc = 0;
625254885Sdumbbell			args.v2.ucAction = action;
626254885Sdumbbell			if (crev == 3) {
627254885Sdumbbell				if (dig->coherent_mode)
628254885Sdumbbell					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
629254885Sdumbbell			}
630254885Sdumbbell			if (hdmi_detected)
631254885Sdumbbell				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
632254885Sdumbbell			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
633254885Sdumbbell			args.v2.ucTruncate = 0;
634254885Sdumbbell			args.v2.ucSpatial = 0;
635254885Sdumbbell			args.v2.ucTemporal = 0;
636254885Sdumbbell			args.v2.ucFRC = 0;
637254885Sdumbbell			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
638254885Sdumbbell				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
639254885Sdumbbell					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
640254885Sdumbbell				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
641254885Sdumbbell					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
642254885Sdumbbell					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
643254885Sdumbbell						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
644254885Sdumbbell				}
645254885Sdumbbell				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
646254885Sdumbbell					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
647254885Sdumbbell					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
648254885Sdumbbell						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
649254885Sdumbbell					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
650254885Sdumbbell						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
651254885Sdumbbell				}
652254885Sdumbbell			} else {
653254885Sdumbbell				if (dig->linkb)
654254885Sdumbbell					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
655254885Sdumbbell				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
656254885Sdumbbell					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
657254885Sdumbbell			}
658254885Sdumbbell			break;
659254885Sdumbbell		default:
660254885Sdumbbell			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
661254885Sdumbbell			break;
662254885Sdumbbell		}
663254885Sdumbbell		break;
664254885Sdumbbell	default:
665254885Sdumbbell		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
666254885Sdumbbell		break;
667254885Sdumbbell	}
668254885Sdumbbell
669254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
670254885Sdumbbell}
671254885Sdumbbell
672254885Sdumbbellint
673254885Sdumbbellatombios_get_encoder_mode(struct drm_encoder *encoder)
674254885Sdumbbell{
675254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
676254885Sdumbbell	struct drm_connector *connector;
677254885Sdumbbell	struct radeon_connector *radeon_connector;
678254885Sdumbbell	struct radeon_connector_atom_dig *dig_connector;
679254885Sdumbbell
680254885Sdumbbell	/* dp bridges are always DP */
681254885Sdumbbell	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
682254885Sdumbbell		return ATOM_ENCODER_MODE_DP;
683254885Sdumbbell
684254885Sdumbbell	/* DVO is always DVO */
685254885Sdumbbell	if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) ||
686254885Sdumbbell	    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
687254885Sdumbbell		return ATOM_ENCODER_MODE_DVO;
688254885Sdumbbell
689254885Sdumbbell	connector = radeon_get_connector_for_encoder(encoder);
690254885Sdumbbell	/* if we don't have an active device yet, just use one of
691254885Sdumbbell	 * the connectors tied to the encoder.
692254885Sdumbbell	 */
693254885Sdumbbell	if (!connector)
694254885Sdumbbell		connector = radeon_get_connector_for_encoder_init(encoder);
695254885Sdumbbell	radeon_connector = to_radeon_connector(connector);
696254885Sdumbbell
697254885Sdumbbell	switch (connector->connector_type) {
698254885Sdumbbell	case DRM_MODE_CONNECTOR_DVII:
699254885Sdumbbell	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
700254885Sdumbbell		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
701254885Sdumbbell		    radeon_audio)
702254885Sdumbbell			return ATOM_ENCODER_MODE_HDMI;
703254885Sdumbbell		else if (radeon_connector->use_digital)
704254885Sdumbbell			return ATOM_ENCODER_MODE_DVI;
705254885Sdumbbell		else
706254885Sdumbbell			return ATOM_ENCODER_MODE_CRT;
707254885Sdumbbell		break;
708254885Sdumbbell	case DRM_MODE_CONNECTOR_DVID:
709254885Sdumbbell	case DRM_MODE_CONNECTOR_HDMIA:
710254885Sdumbbell	default:
711254885Sdumbbell		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
712254885Sdumbbell		    radeon_audio)
713254885Sdumbbell			return ATOM_ENCODER_MODE_HDMI;
714254885Sdumbbell		else
715254885Sdumbbell			return ATOM_ENCODER_MODE_DVI;
716254885Sdumbbell		break;
717254885Sdumbbell	case DRM_MODE_CONNECTOR_LVDS:
718254885Sdumbbell		return ATOM_ENCODER_MODE_LVDS;
719254885Sdumbbell		break;
720254885Sdumbbell	case DRM_MODE_CONNECTOR_DisplayPort:
721254885Sdumbbell		dig_connector = radeon_connector->con_priv;
722254885Sdumbbell		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
723254885Sdumbbell		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
724254885Sdumbbell			return ATOM_ENCODER_MODE_DP;
725254885Sdumbbell		else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
726254885Sdumbbell			 radeon_audio)
727254885Sdumbbell			return ATOM_ENCODER_MODE_HDMI;
728254885Sdumbbell		else
729254885Sdumbbell			return ATOM_ENCODER_MODE_DVI;
730254885Sdumbbell		break;
731254885Sdumbbell	case DRM_MODE_CONNECTOR_eDP:
732254885Sdumbbell		return ATOM_ENCODER_MODE_DP;
733254885Sdumbbell	case DRM_MODE_CONNECTOR_DVIA:
734254885Sdumbbell	case DRM_MODE_CONNECTOR_VGA:
735254885Sdumbbell		return ATOM_ENCODER_MODE_CRT;
736254885Sdumbbell		break;
737254885Sdumbbell	case DRM_MODE_CONNECTOR_Composite:
738254885Sdumbbell	case DRM_MODE_CONNECTOR_SVIDEO:
739254885Sdumbbell	case DRM_MODE_CONNECTOR_9PinDIN:
740254885Sdumbbell		/* fix me */
741254885Sdumbbell		return ATOM_ENCODER_MODE_TV;
742254885Sdumbbell		/*return ATOM_ENCODER_MODE_CV;*/
743254885Sdumbbell		break;
744254885Sdumbbell	}
745254885Sdumbbell}
746254885Sdumbbell
747254885Sdumbbell/*
748254885Sdumbbell * DIG Encoder/Transmitter Setup
749254885Sdumbbell *
750254885Sdumbbell * DCE 3.0/3.1
751254885Sdumbbell * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
752254885Sdumbbell * Supports up to 3 digital outputs
753254885Sdumbbell * - 2 DIG encoder blocks.
754254885Sdumbbell * DIG1 can drive UNIPHY link A or link B
755254885Sdumbbell * DIG2 can drive UNIPHY link B or LVTMA
756254885Sdumbbell *
757254885Sdumbbell * DCE 3.2
758254885Sdumbbell * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
759254885Sdumbbell * Supports up to 5 digital outputs
760254885Sdumbbell * - 2 DIG encoder blocks.
761254885Sdumbbell * DIG1/2 can drive UNIPHY0/1/2 link A or link B
762254885Sdumbbell *
763254885Sdumbbell * DCE 4.0/5.0/6.0
764254885Sdumbbell * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
765254885Sdumbbell * Supports up to 6 digital outputs
766254885Sdumbbell * - 6 DIG encoder blocks.
767254885Sdumbbell * - DIG to PHY mapping is hardcoded
768254885Sdumbbell * DIG1 drives UNIPHY0 link A, A+B
769254885Sdumbbell * DIG2 drives UNIPHY0 link B
770254885Sdumbbell * DIG3 drives UNIPHY1 link A, A+B
771254885Sdumbbell * DIG4 drives UNIPHY1 link B
772254885Sdumbbell * DIG5 drives UNIPHY2 link A, A+B
773254885Sdumbbell * DIG6 drives UNIPHY2 link B
774254885Sdumbbell *
775254885Sdumbbell * DCE 4.1
776254885Sdumbbell * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
777254885Sdumbbell * Supports up to 6 digital outputs
778254885Sdumbbell * - 2 DIG encoder blocks.
779254885Sdumbbell * llano
780254885Sdumbbell * DIG1/2 can drive UNIPHY0/1/2 link A or link B
781254885Sdumbbell * ontario
782254885Sdumbbell * DIG1 drives UNIPHY0/1/2 link A
783254885Sdumbbell * DIG2 drives UNIPHY0/1/2 link B
784254885Sdumbbell *
785254885Sdumbbell * Routing
786254885Sdumbbell * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
787254885Sdumbbell * Examples:
788254885Sdumbbell * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
789254885Sdumbbell * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
790254885Sdumbbell * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
791254885Sdumbbell * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
792254885Sdumbbell */
793254885Sdumbbell
794254885Sdumbbellunion dig_encoder_control {
795254885Sdumbbell	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
796254885Sdumbbell	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
797254885Sdumbbell	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
798254885Sdumbbell	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
799254885Sdumbbell};
800254885Sdumbbell
801254885Sdumbbellvoid
802254885Sdumbbellatombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
803254885Sdumbbell{
804254885Sdumbbell	struct drm_device *dev = encoder->dev;
805254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
806254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
807254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
808254885Sdumbbell	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
809254885Sdumbbell	union dig_encoder_control args;
810254885Sdumbbell	int index = 0;
811254885Sdumbbell	uint8_t frev, crev;
812254885Sdumbbell	int dp_clock = 0;
813254885Sdumbbell	int dp_lane_count = 0;
814254885Sdumbbell	int hpd_id = RADEON_HPD_NONE;
815254885Sdumbbell
816254885Sdumbbell	if (connector) {
817254885Sdumbbell		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
818254885Sdumbbell		struct radeon_connector_atom_dig *dig_connector =
819254885Sdumbbell			radeon_connector->con_priv;
820254885Sdumbbell
821254885Sdumbbell		dp_clock = dig_connector->dp_clock;
822254885Sdumbbell		dp_lane_count = dig_connector->dp_lane_count;
823254885Sdumbbell		hpd_id = radeon_connector->hpd.hpd;
824254885Sdumbbell	}
825254885Sdumbbell
826254885Sdumbbell	/* no dig encoder assigned */
827254885Sdumbbell	if (dig->dig_encoder == -1)
828254885Sdumbbell		return;
829254885Sdumbbell
830254885Sdumbbell	memset(&args, 0, sizeof(args));
831254885Sdumbbell
832254885Sdumbbell	if (ASIC_IS_DCE4(rdev))
833254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
834254885Sdumbbell	else {
835254885Sdumbbell		if (dig->dig_encoder)
836254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
837254885Sdumbbell		else
838254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
839254885Sdumbbell	}
840254885Sdumbbell
841254885Sdumbbell	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
842254885Sdumbbell		return;
843254885Sdumbbell
844254885Sdumbbell	switch (frev) {
845254885Sdumbbell	case 1:
846254885Sdumbbell		switch (crev) {
847254885Sdumbbell		case 1:
848254885Sdumbbell			args.v1.ucAction = action;
849254885Sdumbbell			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
850254885Sdumbbell			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
851254885Sdumbbell				args.v3.ucPanelMode = panel_mode;
852254885Sdumbbell			else
853254885Sdumbbell				args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
854254885Sdumbbell
855254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
856254885Sdumbbell				args.v1.ucLaneNum = dp_lane_count;
857254885Sdumbbell			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
858254885Sdumbbell				args.v1.ucLaneNum = 8;
859254885Sdumbbell			else
860254885Sdumbbell				args.v1.ucLaneNum = 4;
861254885Sdumbbell
862254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
863254885Sdumbbell				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
864254885Sdumbbell			switch (radeon_encoder->encoder_id) {
865254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
866254885Sdumbbell				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
867254885Sdumbbell				break;
868254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
869254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
870254885Sdumbbell				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
871254885Sdumbbell				break;
872254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
873254885Sdumbbell				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
874254885Sdumbbell				break;
875254885Sdumbbell			}
876254885Sdumbbell			if (dig->linkb)
877254885Sdumbbell				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
878254885Sdumbbell			else
879254885Sdumbbell				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
880254885Sdumbbell			break;
881254885Sdumbbell		case 2:
882254885Sdumbbell		case 3:
883254885Sdumbbell			args.v3.ucAction = action;
884254885Sdumbbell			args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
885254885Sdumbbell			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
886254885Sdumbbell				args.v3.ucPanelMode = panel_mode;
887254885Sdumbbell			else
888254885Sdumbbell				args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
889254885Sdumbbell
890254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode))
891254885Sdumbbell				args.v3.ucLaneNum = dp_lane_count;
892254885Sdumbbell			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
893254885Sdumbbell				args.v3.ucLaneNum = 8;
894254885Sdumbbell			else
895254885Sdumbbell				args.v3.ucLaneNum = 4;
896254885Sdumbbell
897254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
898254885Sdumbbell				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
899254885Sdumbbell			args.v3.acConfig.ucDigSel = dig->dig_encoder;
900254885Sdumbbell			args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
901254885Sdumbbell			break;
902254885Sdumbbell		case 4:
903254885Sdumbbell			args.v4.ucAction = action;
904254885Sdumbbell			args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
905254885Sdumbbell			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
906254885Sdumbbell				args.v4.ucPanelMode = panel_mode;
907254885Sdumbbell			else
908254885Sdumbbell				args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
909254885Sdumbbell
910254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode))
911254885Sdumbbell				args.v4.ucLaneNum = dp_lane_count;
912254885Sdumbbell			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
913254885Sdumbbell				args.v4.ucLaneNum = 8;
914254885Sdumbbell			else
915254885Sdumbbell				args.v4.ucLaneNum = 4;
916254885Sdumbbell
917254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) {
918254885Sdumbbell				if (dp_clock == 270000)
919254885Sdumbbell					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
920254885Sdumbbell				else if (dp_clock == 540000)
921254885Sdumbbell					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
922254885Sdumbbell			}
923254885Sdumbbell			args.v4.acConfig.ucDigSel = dig->dig_encoder;
924254885Sdumbbell			args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
925254885Sdumbbell			if (hpd_id == RADEON_HPD_NONE)
926254885Sdumbbell				args.v4.ucHPD_ID = 0;
927254885Sdumbbell			else
928254885Sdumbbell				args.v4.ucHPD_ID = hpd_id + 1;
929254885Sdumbbell			break;
930254885Sdumbbell		default:
931254885Sdumbbell			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
932254885Sdumbbell			break;
933254885Sdumbbell		}
934254885Sdumbbell		break;
935254885Sdumbbell	default:
936254885Sdumbbell		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
937254885Sdumbbell		break;
938254885Sdumbbell	}
939254885Sdumbbell
940254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
941254885Sdumbbell
942254885Sdumbbell}
943254885Sdumbbell
944254885Sdumbbellunion dig_transmitter_control {
945254885Sdumbbell	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
946254885Sdumbbell	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
947254885Sdumbbell	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
948254885Sdumbbell	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
949254885Sdumbbell	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
950254885Sdumbbell};
951254885Sdumbbell
952254885Sdumbbellvoid
953254885Sdumbbellatombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
954254885Sdumbbell{
955254885Sdumbbell	struct drm_device *dev = encoder->dev;
956254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
957254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
958254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
959254885Sdumbbell	struct drm_connector *connector;
960254885Sdumbbell	union dig_transmitter_control args;
961254885Sdumbbell	int index = 0;
962254885Sdumbbell	uint8_t frev, crev;
963254885Sdumbbell	bool is_dp = false;
964254885Sdumbbell	int pll_id = 0;
965254885Sdumbbell	int dp_clock = 0;
966254885Sdumbbell	int dp_lane_count = 0;
967254885Sdumbbell	int connector_object_id = 0;
968254885Sdumbbell	int igp_lane_info = 0;
969254885Sdumbbell	int dig_encoder = dig->dig_encoder;
970254885Sdumbbell	int hpd_id = RADEON_HPD_NONE;
971254885Sdumbbell
972254885Sdumbbell	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
973254885Sdumbbell		connector = radeon_get_connector_for_encoder_init(encoder);
974254885Sdumbbell		/* just needed to avoid bailing in the encoder check.  the encoder
975254885Sdumbbell		 * isn't used for init
976254885Sdumbbell		 */
977254885Sdumbbell		dig_encoder = 0;
978254885Sdumbbell	} else
979254885Sdumbbell		connector = radeon_get_connector_for_encoder(encoder);
980254885Sdumbbell
981254885Sdumbbell	if (connector) {
982254885Sdumbbell		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
983254885Sdumbbell		struct radeon_connector_atom_dig *dig_connector =
984254885Sdumbbell			radeon_connector->con_priv;
985254885Sdumbbell
986254885Sdumbbell		hpd_id = radeon_connector->hpd.hpd;
987254885Sdumbbell		dp_clock = dig_connector->dp_clock;
988254885Sdumbbell		dp_lane_count = dig_connector->dp_lane_count;
989254885Sdumbbell		connector_object_id =
990254885Sdumbbell			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
991254885Sdumbbell		igp_lane_info = dig_connector->igp_lane_info;
992254885Sdumbbell	}
993254885Sdumbbell
994254885Sdumbbell	if (encoder->crtc) {
995254885Sdumbbell		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
996254885Sdumbbell		pll_id = radeon_crtc->pll_id;
997254885Sdumbbell	}
998254885Sdumbbell
999254885Sdumbbell	/* no dig encoder assigned */
1000254885Sdumbbell	if (dig_encoder == -1)
1001254885Sdumbbell		return;
1002254885Sdumbbell
1003254885Sdumbbell	if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
1004254885Sdumbbell		is_dp = true;
1005254885Sdumbbell
1006254885Sdumbbell	memset(&args, 0, sizeof(args));
1007254885Sdumbbell
1008254885Sdumbbell	switch (radeon_encoder->encoder_id) {
1009254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1010254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1011254885Sdumbbell		break;
1012254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1013254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1014254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1015254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1016254885Sdumbbell		break;
1017254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1018254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
1019254885Sdumbbell		break;
1020254885Sdumbbell	}
1021254885Sdumbbell
1022254885Sdumbbell	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1023254885Sdumbbell		return;
1024254885Sdumbbell
1025254885Sdumbbell	switch (frev) {
1026254885Sdumbbell	case 1:
1027254885Sdumbbell		switch (crev) {
1028254885Sdumbbell		case 1:
1029254885Sdumbbell			args.v1.ucAction = action;
1030254885Sdumbbell			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1031254885Sdumbbell				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
1032254885Sdumbbell			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1033254885Sdumbbell				args.v1.asMode.ucLaneSel = lane_num;
1034254885Sdumbbell				args.v1.asMode.ucLaneSet = lane_set;
1035254885Sdumbbell			} else {
1036254885Sdumbbell				if (is_dp)
1037254885Sdumbbell					args.v1.usPixelClock = cpu_to_le16(dp_clock / 10);
1038254885Sdumbbell				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1039254885Sdumbbell					args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1040254885Sdumbbell				else
1041254885Sdumbbell					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1042254885Sdumbbell			}
1043254885Sdumbbell
1044254885Sdumbbell			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1045254885Sdumbbell
1046254885Sdumbbell			if (dig_encoder)
1047254885Sdumbbell				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
1048254885Sdumbbell			else
1049254885Sdumbbell				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1050254885Sdumbbell
1051254885Sdumbbell			if ((rdev->flags & RADEON_IS_IGP) &&
1052254885Sdumbbell			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1053254885Sdumbbell				if (is_dp ||
1054254885Sdumbbell				    !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
1055254885Sdumbbell					if (igp_lane_info & 0x1)
1056254885Sdumbbell						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
1057254885Sdumbbell					else if (igp_lane_info & 0x2)
1058254885Sdumbbell						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
1059254885Sdumbbell					else if (igp_lane_info & 0x4)
1060254885Sdumbbell						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
1061254885Sdumbbell					else if (igp_lane_info & 0x8)
1062254885Sdumbbell						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1063254885Sdumbbell				} else {
1064254885Sdumbbell					if (igp_lane_info & 0x3)
1065254885Sdumbbell						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
1066254885Sdumbbell					else if (igp_lane_info & 0xc)
1067254885Sdumbbell						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1068254885Sdumbbell				}
1069254885Sdumbbell			}
1070254885Sdumbbell
1071254885Sdumbbell			if (dig->linkb)
1072254885Sdumbbell				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
1073254885Sdumbbell			else
1074254885Sdumbbell				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
1075254885Sdumbbell
1076254885Sdumbbell			if (is_dp)
1077254885Sdumbbell				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1078254885Sdumbbell			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1079254885Sdumbbell				if (dig->coherent_mode)
1080254885Sdumbbell					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1081254885Sdumbbell				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1082254885Sdumbbell					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1083254885Sdumbbell			}
1084254885Sdumbbell			break;
1085254885Sdumbbell		case 2:
1086254885Sdumbbell			args.v2.ucAction = action;
1087254885Sdumbbell			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1088254885Sdumbbell				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
1089254885Sdumbbell			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1090254885Sdumbbell				args.v2.asMode.ucLaneSel = lane_num;
1091254885Sdumbbell				args.v2.asMode.ucLaneSet = lane_set;
1092254885Sdumbbell			} else {
1093254885Sdumbbell				if (is_dp)
1094254885Sdumbbell					args.v2.usPixelClock = cpu_to_le16(dp_clock / 10);
1095254885Sdumbbell				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1096254885Sdumbbell					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1097254885Sdumbbell				else
1098254885Sdumbbell					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1099254885Sdumbbell			}
1100254885Sdumbbell
1101254885Sdumbbell			args.v2.acConfig.ucEncoderSel = dig_encoder;
1102254885Sdumbbell			if (dig->linkb)
1103254885Sdumbbell				args.v2.acConfig.ucLinkSel = 1;
1104254885Sdumbbell
1105254885Sdumbbell			switch (radeon_encoder->encoder_id) {
1106254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1107254885Sdumbbell				args.v2.acConfig.ucTransmitterSel = 0;
1108254885Sdumbbell				break;
1109254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1110254885Sdumbbell				args.v2.acConfig.ucTransmitterSel = 1;
1111254885Sdumbbell				break;
1112254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1113254885Sdumbbell				args.v2.acConfig.ucTransmitterSel = 2;
1114254885Sdumbbell				break;
1115254885Sdumbbell			}
1116254885Sdumbbell
1117254885Sdumbbell			if (is_dp) {
1118254885Sdumbbell				args.v2.acConfig.fCoherentMode = 1;
1119254885Sdumbbell				args.v2.acConfig.fDPConnector = 1;
1120254885Sdumbbell			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1121254885Sdumbbell				if (dig->coherent_mode)
1122254885Sdumbbell					args.v2.acConfig.fCoherentMode = 1;
1123254885Sdumbbell				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1124254885Sdumbbell					args.v2.acConfig.fDualLinkConnector = 1;
1125254885Sdumbbell			}
1126254885Sdumbbell			break;
1127254885Sdumbbell		case 3:
1128254885Sdumbbell			args.v3.ucAction = action;
1129254885Sdumbbell			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1130254885Sdumbbell				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
1131254885Sdumbbell			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1132254885Sdumbbell				args.v3.asMode.ucLaneSel = lane_num;
1133254885Sdumbbell				args.v3.asMode.ucLaneSet = lane_set;
1134254885Sdumbbell			} else {
1135254885Sdumbbell				if (is_dp)
1136254885Sdumbbell					args.v3.usPixelClock = cpu_to_le16(dp_clock / 10);
1137254885Sdumbbell				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1138254885Sdumbbell					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1139254885Sdumbbell				else
1140254885Sdumbbell					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1141254885Sdumbbell			}
1142254885Sdumbbell
1143254885Sdumbbell			if (is_dp)
1144254885Sdumbbell				args.v3.ucLaneNum = dp_lane_count;
1145254885Sdumbbell			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1146254885Sdumbbell				args.v3.ucLaneNum = 8;
1147254885Sdumbbell			else
1148254885Sdumbbell				args.v3.ucLaneNum = 4;
1149254885Sdumbbell
1150254885Sdumbbell			if (dig->linkb)
1151254885Sdumbbell				args.v3.acConfig.ucLinkSel = 1;
1152254885Sdumbbell			if (dig_encoder & 1)
1153254885Sdumbbell				args.v3.acConfig.ucEncoderSel = 1;
1154254885Sdumbbell
1155254885Sdumbbell			/* Select the PLL for the PHY
1156254885Sdumbbell			 * DP PHY should be clocked from external src if there is
1157254885Sdumbbell			 * one.
1158254885Sdumbbell			 */
1159254885Sdumbbell			/* On DCE4, if there is an external clock, it generates the DP ref clock */
1160254885Sdumbbell			if (is_dp && rdev->clock.dp_extclk)
1161254885Sdumbbell				args.v3.acConfig.ucRefClkSource = 2; /* external src */
1162254885Sdumbbell			else
1163254885Sdumbbell				args.v3.acConfig.ucRefClkSource = pll_id;
1164254885Sdumbbell
1165254885Sdumbbell			switch (radeon_encoder->encoder_id) {
1166254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1167254885Sdumbbell				args.v3.acConfig.ucTransmitterSel = 0;
1168254885Sdumbbell				break;
1169254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1170254885Sdumbbell				args.v3.acConfig.ucTransmitterSel = 1;
1171254885Sdumbbell				break;
1172254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1173254885Sdumbbell				args.v3.acConfig.ucTransmitterSel = 2;
1174254885Sdumbbell				break;
1175254885Sdumbbell			}
1176254885Sdumbbell
1177254885Sdumbbell			if (is_dp)
1178254885Sdumbbell				args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
1179254885Sdumbbell			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1180254885Sdumbbell				if (dig->coherent_mode)
1181254885Sdumbbell					args.v3.acConfig.fCoherentMode = 1;
1182254885Sdumbbell				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1183254885Sdumbbell					args.v3.acConfig.fDualLinkConnector = 1;
1184254885Sdumbbell			}
1185254885Sdumbbell			break;
1186254885Sdumbbell		case 4:
1187254885Sdumbbell			args.v4.ucAction = action;
1188254885Sdumbbell			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
1189254885Sdumbbell				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
1190254885Sdumbbell			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1191254885Sdumbbell				args.v4.asMode.ucLaneSel = lane_num;
1192254885Sdumbbell				args.v4.asMode.ucLaneSet = lane_set;
1193254885Sdumbbell			} else {
1194254885Sdumbbell				if (is_dp)
1195254885Sdumbbell					args.v4.usPixelClock = cpu_to_le16(dp_clock / 10);
1196254885Sdumbbell				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1197254885Sdumbbell					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
1198254885Sdumbbell				else
1199254885Sdumbbell					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1200254885Sdumbbell			}
1201254885Sdumbbell
1202254885Sdumbbell			if (is_dp)
1203254885Sdumbbell				args.v4.ucLaneNum = dp_lane_count;
1204254885Sdumbbell			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1205254885Sdumbbell				args.v4.ucLaneNum = 8;
1206254885Sdumbbell			else
1207254885Sdumbbell				args.v4.ucLaneNum = 4;
1208254885Sdumbbell
1209254885Sdumbbell			if (dig->linkb)
1210254885Sdumbbell				args.v4.acConfig.ucLinkSel = 1;
1211254885Sdumbbell			if (dig_encoder & 1)
1212254885Sdumbbell				args.v4.acConfig.ucEncoderSel = 1;
1213254885Sdumbbell
1214254885Sdumbbell			/* Select the PLL for the PHY
1215254885Sdumbbell			 * DP PHY should be clocked from external src if there is
1216254885Sdumbbell			 * one.
1217254885Sdumbbell			 */
1218254885Sdumbbell			/* On DCE5 DCPLL usually generates the DP ref clock */
1219254885Sdumbbell			if (is_dp) {
1220254885Sdumbbell				if (rdev->clock.dp_extclk)
1221254885Sdumbbell					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
1222254885Sdumbbell				else
1223254885Sdumbbell					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
1224254885Sdumbbell			} else
1225254885Sdumbbell				args.v4.acConfig.ucRefClkSource = pll_id;
1226254885Sdumbbell
1227254885Sdumbbell			switch (radeon_encoder->encoder_id) {
1228254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1229254885Sdumbbell				args.v4.acConfig.ucTransmitterSel = 0;
1230254885Sdumbbell				break;
1231254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1232254885Sdumbbell				args.v4.acConfig.ucTransmitterSel = 1;
1233254885Sdumbbell				break;
1234254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1235254885Sdumbbell				args.v4.acConfig.ucTransmitterSel = 2;
1236254885Sdumbbell				break;
1237254885Sdumbbell			}
1238254885Sdumbbell
1239254885Sdumbbell			if (is_dp)
1240254885Sdumbbell				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
1241254885Sdumbbell			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1242254885Sdumbbell				if (dig->coherent_mode)
1243254885Sdumbbell					args.v4.acConfig.fCoherentMode = 1;
1244254885Sdumbbell				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1245254885Sdumbbell					args.v4.acConfig.fDualLinkConnector = 1;
1246254885Sdumbbell			}
1247254885Sdumbbell			break;
1248254885Sdumbbell		case 5:
1249254885Sdumbbell			args.v5.ucAction = action;
1250254885Sdumbbell			if (is_dp)
1251254885Sdumbbell				args.v5.usSymClock = cpu_to_le16(dp_clock / 10);
1252254885Sdumbbell			else
1253254885Sdumbbell				args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1254254885Sdumbbell
1255254885Sdumbbell			switch (radeon_encoder->encoder_id) {
1256254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1257254885Sdumbbell				if (dig->linkb)
1258254885Sdumbbell					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1259254885Sdumbbell				else
1260254885Sdumbbell					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1261254885Sdumbbell				break;
1262254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1263254885Sdumbbell				if (dig->linkb)
1264254885Sdumbbell					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1265254885Sdumbbell				else
1266254885Sdumbbell					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1267254885Sdumbbell				break;
1268254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1269254885Sdumbbell				if (dig->linkb)
1270254885Sdumbbell					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1271254885Sdumbbell				else
1272254885Sdumbbell					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1273254885Sdumbbell				break;
1274254885Sdumbbell			}
1275254885Sdumbbell			if (is_dp)
1276254885Sdumbbell				args.v5.ucLaneNum = dp_lane_count;
1277254885Sdumbbell			else if (radeon_encoder->pixel_clock > 165000)
1278254885Sdumbbell				args.v5.ucLaneNum = 8;
1279254885Sdumbbell			else
1280254885Sdumbbell				args.v5.ucLaneNum = 4;
1281254885Sdumbbell			args.v5.ucConnObjId = connector_object_id;
1282254885Sdumbbell			args.v5.ucDigMode = atombios_get_encoder_mode(encoder);
1283254885Sdumbbell
1284254885Sdumbbell			if (is_dp && rdev->clock.dp_extclk)
1285254885Sdumbbell				args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK;
1286254885Sdumbbell			else
1287254885Sdumbbell				args.v5.asConfig.ucPhyClkSrcId = pll_id;
1288254885Sdumbbell
1289254885Sdumbbell			if (is_dp)
1290254885Sdumbbell				args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */
1291254885Sdumbbell			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1292254885Sdumbbell				if (dig->coherent_mode)
1293254885Sdumbbell					args.v5.asConfig.ucCoherentMode = 1;
1294254885Sdumbbell			}
1295254885Sdumbbell			if (hpd_id == RADEON_HPD_NONE)
1296254885Sdumbbell				args.v5.asConfig.ucHPDSel = 0;
1297254885Sdumbbell			else
1298254885Sdumbbell				args.v5.asConfig.ucHPDSel = hpd_id + 1;
1299254885Sdumbbell			args.v5.ucDigEncoderSel = 1 << dig_encoder;
1300254885Sdumbbell			args.v5.ucDPLaneSet = lane_set;
1301254885Sdumbbell			break;
1302254885Sdumbbell		default:
1303254885Sdumbbell			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1304254885Sdumbbell			break;
1305254885Sdumbbell		}
1306254885Sdumbbell		break;
1307254885Sdumbbell	default:
1308254885Sdumbbell		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
1309254885Sdumbbell		break;
1310254885Sdumbbell	}
1311254885Sdumbbell
1312254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1313254885Sdumbbell}
1314254885Sdumbbell
1315254885Sdumbbellbool
1316254885Sdumbbellatombios_set_edp_panel_power(struct drm_connector *connector, int action)
1317254885Sdumbbell{
1318254885Sdumbbell	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1319254885Sdumbbell	struct drm_device *dev = radeon_connector->base.dev;
1320254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1321254885Sdumbbell	union dig_transmitter_control args;
1322254885Sdumbbell	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1323254885Sdumbbell	uint8_t frev, crev;
1324254885Sdumbbell
1325254885Sdumbbell	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
1326254885Sdumbbell		goto done;
1327254885Sdumbbell
1328254885Sdumbbell	if (!ASIC_IS_DCE4(rdev))
1329254885Sdumbbell		goto done;
1330254885Sdumbbell
1331254885Sdumbbell	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
1332254885Sdumbbell	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
1333254885Sdumbbell		goto done;
1334254885Sdumbbell
1335254885Sdumbbell	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1336254885Sdumbbell		goto done;
1337254885Sdumbbell
1338254885Sdumbbell	memset(&args, 0, sizeof(args));
1339254885Sdumbbell
1340254885Sdumbbell	args.v1.ucAction = action;
1341254885Sdumbbell
1342254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1343254885Sdumbbell
1344254885Sdumbbell	/* wait for the panel to power up */
1345254885Sdumbbell	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
1346254885Sdumbbell		int i;
1347254885Sdumbbell
1348254885Sdumbbell		for (i = 0; i < 300; i++) {
1349254885Sdumbbell			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
1350254885Sdumbbell				return true;
1351280183Sdumbbell			mdelay(1);
1352254885Sdumbbell		}
1353254885Sdumbbell		return false;
1354254885Sdumbbell	}
1355254885Sdumbbelldone:
1356254885Sdumbbell	return true;
1357254885Sdumbbell}
1358254885Sdumbbell
1359254885Sdumbbellunion external_encoder_control {
1360254885Sdumbbell	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
1361254885Sdumbbell	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
1362254885Sdumbbell};
1363254885Sdumbbell
1364254885Sdumbbellstatic void
1365254885Sdumbbellatombios_external_encoder_setup(struct drm_encoder *encoder,
1366254885Sdumbbell				struct drm_encoder *ext_encoder,
1367254885Sdumbbell				int action)
1368254885Sdumbbell{
1369254885Sdumbbell	struct drm_device *dev = encoder->dev;
1370254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1371254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1372254885Sdumbbell	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
1373254885Sdumbbell	union external_encoder_control args;
1374254885Sdumbbell	struct drm_connector *connector;
1375254885Sdumbbell	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
1376254885Sdumbbell	u8 frev, crev;
1377254885Sdumbbell	int dp_clock = 0;
1378254885Sdumbbell	int dp_lane_count = 0;
1379254885Sdumbbell	int connector_object_id = 0;
1380254885Sdumbbell	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
1381254885Sdumbbell
1382254885Sdumbbell	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1383254885Sdumbbell		connector = radeon_get_connector_for_encoder_init(encoder);
1384254885Sdumbbell	else
1385254885Sdumbbell		connector = radeon_get_connector_for_encoder(encoder);
1386254885Sdumbbell
1387254885Sdumbbell	if (connector) {
1388254885Sdumbbell		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1389254885Sdumbbell		struct radeon_connector_atom_dig *dig_connector =
1390254885Sdumbbell			radeon_connector->con_priv;
1391254885Sdumbbell
1392254885Sdumbbell		dp_clock = dig_connector->dp_clock;
1393254885Sdumbbell		dp_lane_count = dig_connector->dp_lane_count;
1394254885Sdumbbell		connector_object_id =
1395254885Sdumbbell			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1396254885Sdumbbell	}
1397254885Sdumbbell
1398254885Sdumbbell	memset(&args, 0, sizeof(args));
1399254885Sdumbbell
1400254885Sdumbbell	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1401254885Sdumbbell		return;
1402254885Sdumbbell
1403254885Sdumbbell	switch (frev) {
1404254885Sdumbbell	case 1:
1405254885Sdumbbell		/* no params on frev 1 */
1406254885Sdumbbell		break;
1407254885Sdumbbell	case 2:
1408254885Sdumbbell		switch (crev) {
1409254885Sdumbbell		case 1:
1410254885Sdumbbell		case 2:
1411254885Sdumbbell			args.v1.sDigEncoder.ucAction = action;
1412254885Sdumbbell			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1413254885Sdumbbell			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1414254885Sdumbbell
1415254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
1416254885Sdumbbell				if (dp_clock == 270000)
1417254885Sdumbbell					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
1418254885Sdumbbell				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
1419254885Sdumbbell			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1420254885Sdumbbell				args.v1.sDigEncoder.ucLaneNum = 8;
1421254885Sdumbbell			else
1422254885Sdumbbell				args.v1.sDigEncoder.ucLaneNum = 4;
1423254885Sdumbbell			break;
1424254885Sdumbbell		case 3:
1425254885Sdumbbell			args.v3.sExtEncoder.ucAction = action;
1426254885Sdumbbell			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
1427254885Sdumbbell				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
1428254885Sdumbbell			else
1429254885Sdumbbell				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
1430254885Sdumbbell			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
1431254885Sdumbbell
1432254885Sdumbbell			if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
1433254885Sdumbbell				if (dp_clock == 270000)
1434254885Sdumbbell					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1435254885Sdumbbell				else if (dp_clock == 540000)
1436254885Sdumbbell					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1437254885Sdumbbell				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
1438254885Sdumbbell			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
1439254885Sdumbbell				args.v3.sExtEncoder.ucLaneNum = 8;
1440254885Sdumbbell			else
1441254885Sdumbbell				args.v3.sExtEncoder.ucLaneNum = 4;
1442254885Sdumbbell			switch (ext_enum) {
1443254885Sdumbbell			case GRAPH_OBJECT_ENUM_ID1:
1444254885Sdumbbell				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1445254885Sdumbbell				break;
1446254885Sdumbbell			case GRAPH_OBJECT_ENUM_ID2:
1447254885Sdumbbell				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1448254885Sdumbbell				break;
1449254885Sdumbbell			case GRAPH_OBJECT_ENUM_ID3:
1450254885Sdumbbell				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1451254885Sdumbbell				break;
1452254885Sdumbbell			}
1453254885Sdumbbell			args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder);
1454254885Sdumbbell			break;
1455254885Sdumbbell		default:
1456254885Sdumbbell			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1457254885Sdumbbell			return;
1458254885Sdumbbell		}
1459254885Sdumbbell		break;
1460254885Sdumbbell	default:
1461254885Sdumbbell		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1462254885Sdumbbell		return;
1463254885Sdumbbell	}
1464254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1465254885Sdumbbell}
1466254885Sdumbbell
1467254885Sdumbbellstatic void
1468254885Sdumbbellatombios_yuv_setup(struct drm_encoder *encoder, bool enable)
1469254885Sdumbbell{
1470254885Sdumbbell	struct drm_device *dev = encoder->dev;
1471254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1472254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1473254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1474254885Sdumbbell	ENABLE_YUV_PS_ALLOCATION args;
1475254885Sdumbbell	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
1476254885Sdumbbell	uint32_t temp, reg;
1477254885Sdumbbell
1478254885Sdumbbell	memset(&args, 0, sizeof(args));
1479254885Sdumbbell
1480254885Sdumbbell	if (rdev->family >= CHIP_R600)
1481254885Sdumbbell		reg = R600_BIOS_3_SCRATCH;
1482254885Sdumbbell	else
1483254885Sdumbbell		reg = RADEON_BIOS_3_SCRATCH;
1484254885Sdumbbell
1485254885Sdumbbell	/* XXX: fix up scratch reg handling */
1486254885Sdumbbell	temp = RREG32(reg);
1487254885Sdumbbell	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1488254885Sdumbbell		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
1489254885Sdumbbell			     (radeon_crtc->crtc_id << 18)));
1490254885Sdumbbell	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1491254885Sdumbbell		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
1492254885Sdumbbell	else
1493254885Sdumbbell		WREG32(reg, 0);
1494254885Sdumbbell
1495254885Sdumbbell	if (enable)
1496254885Sdumbbell		args.ucEnable = ATOM_ENABLE;
1497254885Sdumbbell	args.ucCRTC = radeon_crtc->crtc_id;
1498254885Sdumbbell
1499254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1500254885Sdumbbell
1501254885Sdumbbell	WREG32(reg, temp);
1502254885Sdumbbell}
1503254885Sdumbbell
1504254885Sdumbbellstatic void
1505254885Sdumbbellradeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
1506254885Sdumbbell{
1507254885Sdumbbell	struct drm_device *dev = encoder->dev;
1508254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1509254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1510254885Sdumbbell	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1511254885Sdumbbell	int index = 0;
1512254885Sdumbbell
1513254885Sdumbbell	memset(&args, 0, sizeof(args));
1514254885Sdumbbell
1515254885Sdumbbell	switch (radeon_encoder->encoder_id) {
1516254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1517254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1518254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1519254885Sdumbbell		break;
1520254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1521254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1522254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1523254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1524254885Sdumbbell		break;
1525254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1526254885Sdumbbell		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1527254885Sdumbbell		break;
1528254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1529254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1530254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1531254885Sdumbbell		else
1532254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1533254885Sdumbbell		break;
1534254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1535254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1536254885Sdumbbell		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1537254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1538254885Sdumbbell		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1539254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1540254885Sdumbbell		else
1541254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1542254885Sdumbbell		break;
1543254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1544254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1545254885Sdumbbell		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1546254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1547254885Sdumbbell		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1548254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1549254885Sdumbbell		else
1550254885Sdumbbell			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1551254885Sdumbbell		break;
1552254885Sdumbbell	default:
1553254885Sdumbbell		return;
1554254885Sdumbbell	}
1555254885Sdumbbell
1556254885Sdumbbell	switch (mode) {
1557254885Sdumbbell	case DRM_MODE_DPMS_ON:
1558254885Sdumbbell		args.ucAction = ATOM_ENABLE;
1559254885Sdumbbell		/* workaround for DVOOutputControl on some RS690 systems */
1560254885Sdumbbell		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
1561254885Sdumbbell			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
1562254885Sdumbbell			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
1563254885Sdumbbell			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1564254885Sdumbbell			WREG32(RADEON_BIOS_3_SCRATCH, reg);
1565254885Sdumbbell		} else
1566254885Sdumbbell			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1567254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1568254885Sdumbbell			args.ucAction = ATOM_LCD_BLON;
1569254885Sdumbbell			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1570254885Sdumbbell		}
1571254885Sdumbbell		break;
1572254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
1573254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
1574254885Sdumbbell	case DRM_MODE_DPMS_OFF:
1575254885Sdumbbell		args.ucAction = ATOM_DISABLE;
1576254885Sdumbbell		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1577254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1578254885Sdumbbell			args.ucAction = ATOM_LCD_BLOFF;
1579254885Sdumbbell			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1580254885Sdumbbell		}
1581254885Sdumbbell		break;
1582254885Sdumbbell	}
1583254885Sdumbbell}
1584254885Sdumbbell
1585254885Sdumbbellstatic void
1586254885Sdumbbellradeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
1587254885Sdumbbell{
1588254885Sdumbbell	struct drm_device *dev = encoder->dev;
1589254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1590254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1591254885Sdumbbell	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
1592254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1593254885Sdumbbell	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1594254885Sdumbbell	struct radeon_connector *radeon_connector = NULL;
1595254885Sdumbbell	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
1596254885Sdumbbell
1597254885Sdumbbell	if (connector) {
1598254885Sdumbbell		radeon_connector = to_radeon_connector(connector);
1599254885Sdumbbell		radeon_dig_connector = radeon_connector->con_priv;
1600254885Sdumbbell	}
1601254885Sdumbbell
1602254885Sdumbbell	switch (mode) {
1603254885Sdumbbell	case DRM_MODE_DPMS_ON:
1604254885Sdumbbell		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
1605254885Sdumbbell			if (!connector)
1606254885Sdumbbell				dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
1607254885Sdumbbell			else
1608254885Sdumbbell				dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
1609254885Sdumbbell
1610254885Sdumbbell			/* setup and enable the encoder */
1611254885Sdumbbell			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1612254885Sdumbbell			atombios_dig_encoder_setup(encoder,
1613254885Sdumbbell						   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
1614254885Sdumbbell						   dig->panel_mode);
1615254885Sdumbbell			if (ext_encoder) {
1616254885Sdumbbell				if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
1617254885Sdumbbell					atombios_external_encoder_setup(encoder, ext_encoder,
1618254885Sdumbbell									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
1619254885Sdumbbell			}
1620254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1621254885Sdumbbell		} else if (ASIC_IS_DCE4(rdev)) {
1622254885Sdumbbell			/* setup and enable the encoder */
1623254885Sdumbbell			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
1624254885Sdumbbell			/* enable the transmitter */
1625254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1626254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
1627254885Sdumbbell		} else {
1628254885Sdumbbell			/* setup and enable the encoder and transmitter */
1629254885Sdumbbell			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
1630254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
1631254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
1632254885Sdumbbell			/* some early dce3.2 boards have a bug in their transmitter control table */
1633254885Sdumbbell			if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
1634254885Sdumbbell				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
1635254885Sdumbbell		}
1636254885Sdumbbell		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1637254885Sdumbbell			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1638254885Sdumbbell				atombios_set_edp_panel_power(connector,
1639254885Sdumbbell							     ATOM_TRANSMITTER_ACTION_POWER_ON);
1640254885Sdumbbell				radeon_dig_connector->edp_on = true;
1641254885Sdumbbell			}
1642254885Sdumbbell			radeon_dp_link_train(encoder, connector);
1643254885Sdumbbell			if (ASIC_IS_DCE4(rdev))
1644254885Sdumbbell				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
1645254885Sdumbbell		}
1646254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1647254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
1648254885Sdumbbell		break;
1649254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
1650254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
1651254885Sdumbbell	case DRM_MODE_DPMS_OFF:
1652254885Sdumbbell		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
1653254885Sdumbbell			/* disable the transmitter */
1654254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1655254885Sdumbbell		} else if (ASIC_IS_DCE4(rdev)) {
1656254885Sdumbbell			/* disable the transmitter */
1657254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
1658254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1659254885Sdumbbell		} else {
1660254885Sdumbbell			/* disable the encoder and transmitter */
1661254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
1662254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
1663254885Sdumbbell			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
1664254885Sdumbbell		}
1665254885Sdumbbell		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
1666254885Sdumbbell			if (ASIC_IS_DCE4(rdev))
1667254885Sdumbbell				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
1668254885Sdumbbell			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1669254885Sdumbbell				atombios_set_edp_panel_power(connector,
1670254885Sdumbbell							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
1671254885Sdumbbell				radeon_dig_connector->edp_on = false;
1672254885Sdumbbell			}
1673254885Sdumbbell		}
1674254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
1675254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1676254885Sdumbbell		break;
1677254885Sdumbbell	}
1678254885Sdumbbell}
1679254885Sdumbbell
1680254885Sdumbbellstatic void
1681254885Sdumbbellradeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
1682254885Sdumbbell			     struct drm_encoder *ext_encoder,
1683254885Sdumbbell			     int mode)
1684254885Sdumbbell{
1685254885Sdumbbell	struct drm_device *dev = encoder->dev;
1686254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1687254885Sdumbbell
1688254885Sdumbbell	switch (mode) {
1689254885Sdumbbell	case DRM_MODE_DPMS_ON:
1690254885Sdumbbell	default:
1691254885Sdumbbell		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
1692254885Sdumbbell			atombios_external_encoder_setup(encoder, ext_encoder,
1693254885Sdumbbell							EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
1694254885Sdumbbell			atombios_external_encoder_setup(encoder, ext_encoder,
1695254885Sdumbbell							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
1696254885Sdumbbell		} else
1697254885Sdumbbell			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
1698254885Sdumbbell		break;
1699254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
1700254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
1701254885Sdumbbell	case DRM_MODE_DPMS_OFF:
1702254885Sdumbbell		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
1703254885Sdumbbell			atombios_external_encoder_setup(encoder, ext_encoder,
1704254885Sdumbbell							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
1705254885Sdumbbell			atombios_external_encoder_setup(encoder, ext_encoder,
1706254885Sdumbbell							EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
1707254885Sdumbbell		} else
1708254885Sdumbbell			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
1709254885Sdumbbell		break;
1710254885Sdumbbell	}
1711254885Sdumbbell}
1712254885Sdumbbell
1713254885Sdumbbellstatic void
1714254885Sdumbbellradeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
1715254885Sdumbbell{
1716254885Sdumbbell	struct drm_device *dev = encoder->dev;
1717254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1718254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1719254885Sdumbbell	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
1720254885Sdumbbell
1721254885Sdumbbell	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
1722254885Sdumbbell		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
1723254885Sdumbbell		  radeon_encoder->active_device);
1724254885Sdumbbell	switch (radeon_encoder->encoder_id) {
1725254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1726254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1727254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1728254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1729254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1730254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DDI:
1731254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1732254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1733254885Sdumbbell		radeon_atom_encoder_dpms_avivo(encoder, mode);
1734254885Sdumbbell		break;
1735254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1736254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1737254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1738254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1739254885Sdumbbell		radeon_atom_encoder_dpms_dig(encoder, mode);
1740254885Sdumbbell		break;
1741254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1742254885Sdumbbell		if (ASIC_IS_DCE5(rdev)) {
1743254885Sdumbbell			switch (mode) {
1744254885Sdumbbell			case DRM_MODE_DPMS_ON:
1745254885Sdumbbell				atombios_dvo_setup(encoder, ATOM_ENABLE);
1746254885Sdumbbell				break;
1747254885Sdumbbell			case DRM_MODE_DPMS_STANDBY:
1748254885Sdumbbell			case DRM_MODE_DPMS_SUSPEND:
1749254885Sdumbbell			case DRM_MODE_DPMS_OFF:
1750254885Sdumbbell				atombios_dvo_setup(encoder, ATOM_DISABLE);
1751254885Sdumbbell				break;
1752254885Sdumbbell			}
1753254885Sdumbbell		} else if (ASIC_IS_DCE3(rdev))
1754254885Sdumbbell			radeon_atom_encoder_dpms_dig(encoder, mode);
1755254885Sdumbbell		else
1756254885Sdumbbell			radeon_atom_encoder_dpms_avivo(encoder, mode);
1757254885Sdumbbell		break;
1758254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1759254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1760254885Sdumbbell		if (ASIC_IS_DCE5(rdev)) {
1761254885Sdumbbell			switch (mode) {
1762254885Sdumbbell			case DRM_MODE_DPMS_ON:
1763254885Sdumbbell				atombios_dac_setup(encoder, ATOM_ENABLE);
1764254885Sdumbbell				break;
1765254885Sdumbbell			case DRM_MODE_DPMS_STANDBY:
1766254885Sdumbbell			case DRM_MODE_DPMS_SUSPEND:
1767254885Sdumbbell			case DRM_MODE_DPMS_OFF:
1768254885Sdumbbell				atombios_dac_setup(encoder, ATOM_DISABLE);
1769254885Sdumbbell				break;
1770254885Sdumbbell			}
1771254885Sdumbbell		} else
1772254885Sdumbbell			radeon_atom_encoder_dpms_avivo(encoder, mode);
1773254885Sdumbbell		break;
1774254885Sdumbbell	default:
1775254885Sdumbbell		return;
1776254885Sdumbbell	}
1777254885Sdumbbell
1778254885Sdumbbell	if (ext_encoder)
1779254885Sdumbbell		radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
1780254885Sdumbbell
1781254885Sdumbbell	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1782254885Sdumbbell
1783254885Sdumbbell}
1784254885Sdumbbell
1785254885Sdumbbellunion crtc_source_param {
1786254885Sdumbbell	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
1787254885Sdumbbell	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
1788254885Sdumbbell};
1789254885Sdumbbell
1790254885Sdumbbellstatic void
1791254885Sdumbbellatombios_set_encoder_crtc_source(struct drm_encoder *encoder)
1792254885Sdumbbell{
1793254885Sdumbbell	struct drm_device *dev = encoder->dev;
1794254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1795254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1796254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1797254885Sdumbbell	union crtc_source_param args;
1798254885Sdumbbell	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1799254885Sdumbbell	uint8_t frev, crev;
1800254885Sdumbbell	struct radeon_encoder_atom_dig *dig;
1801254885Sdumbbell
1802254885Sdumbbell	memset(&args, 0, sizeof(args));
1803254885Sdumbbell
1804254885Sdumbbell	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
1805254885Sdumbbell		return;
1806254885Sdumbbell
1807254885Sdumbbell	switch (frev) {
1808254885Sdumbbell	case 1:
1809254885Sdumbbell		switch (crev) {
1810254885Sdumbbell		case 1:
1811254885Sdumbbell		default:
1812254885Sdumbbell			if (ASIC_IS_AVIVO(rdev))
1813254885Sdumbbell				args.v1.ucCRTC = radeon_crtc->crtc_id;
1814254885Sdumbbell			else {
1815254885Sdumbbell				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
1816254885Sdumbbell					args.v1.ucCRTC = radeon_crtc->crtc_id;
1817254885Sdumbbell				} else {
1818254885Sdumbbell					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
1819254885Sdumbbell				}
1820254885Sdumbbell			}
1821254885Sdumbbell			switch (radeon_encoder->encoder_id) {
1822254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1823254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1824254885Sdumbbell				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1825254885Sdumbbell				break;
1826254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1827254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1828254885Sdumbbell				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
1829254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1830254885Sdumbbell				else
1831254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1832254885Sdumbbell				break;
1833254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1834254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_DDI:
1835254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1836254885Sdumbbell				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1837254885Sdumbbell				break;
1838254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1839254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1840254885Sdumbbell				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1841254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
1842254885Sdumbbell				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1843254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1844254885Sdumbbell				else
1845254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1846254885Sdumbbell				break;
1847254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1848254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1849254885Sdumbbell				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1850254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
1851254885Sdumbbell				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1852254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
1853254885Sdumbbell				else
1854254885Sdumbbell					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1855254885Sdumbbell				break;
1856254885Sdumbbell			}
1857254885Sdumbbell			break;
1858254885Sdumbbell		case 2:
1859254885Sdumbbell			args.v2.ucCRTC = radeon_crtc->crtc_id;
1860254885Sdumbbell			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
1861254885Sdumbbell				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
1862254885Sdumbbell
1863254885Sdumbbell				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
1864254885Sdumbbell					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
1865254885Sdumbbell				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
1866254885Sdumbbell					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
1867254885Sdumbbell				else
1868254885Sdumbbell					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1869254885Sdumbbell			} else
1870254885Sdumbbell				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1871254885Sdumbbell			switch (radeon_encoder->encoder_id) {
1872254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1873254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1874254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1875254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1876254885Sdumbbell				dig = radeon_encoder->enc_priv;
1877254885Sdumbbell				switch (dig->dig_encoder) {
1878254885Sdumbbell				case 0:
1879254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1880254885Sdumbbell					break;
1881254885Sdumbbell				case 1:
1882254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1883254885Sdumbbell					break;
1884254885Sdumbbell				case 2:
1885254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
1886254885Sdumbbell					break;
1887254885Sdumbbell				case 3:
1888254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
1889254885Sdumbbell					break;
1890254885Sdumbbell				case 4:
1891254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
1892254885Sdumbbell					break;
1893254885Sdumbbell				case 5:
1894254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
1895254885Sdumbbell					break;
1896254885Sdumbbell				}
1897254885Sdumbbell				break;
1898254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1899254885Sdumbbell				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
1900254885Sdumbbell				break;
1901254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1902254885Sdumbbell				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1903254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1904254885Sdumbbell				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1905254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1906254885Sdumbbell				else
1907254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1908254885Sdumbbell				break;
1909254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1910254885Sdumbbell				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1911254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1912254885Sdumbbell				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1913254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1914254885Sdumbbell				else
1915254885Sdumbbell					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1916254885Sdumbbell				break;
1917254885Sdumbbell			}
1918254885Sdumbbell			break;
1919254885Sdumbbell		}
1920254885Sdumbbell		break;
1921254885Sdumbbell	default:
1922254885Sdumbbell		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1923254885Sdumbbell		return;
1924254885Sdumbbell	}
1925254885Sdumbbell
1926254885Sdumbbell	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1927254885Sdumbbell
1928254885Sdumbbell	/* update scratch regs with new routing */
1929254885Sdumbbell	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1930254885Sdumbbell}
1931254885Sdumbbell
1932254885Sdumbbellstatic void
1933254885Sdumbbellatombios_apply_encoder_quirks(struct drm_encoder *encoder,
1934254885Sdumbbell			      struct drm_display_mode *mode)
1935254885Sdumbbell{
1936254885Sdumbbell	struct drm_device *dev = encoder->dev;
1937254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1938254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1939254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1940254885Sdumbbell
1941254885Sdumbbell	/* Funky macbooks */
1942254885Sdumbbell	if ((dev->pci_device == 0x71C5) &&
1943254885Sdumbbell	    (dev->pci_subvendor == 0x106b) &&
1944254885Sdumbbell	    (dev->pci_subdevice == 0x0080)) {
1945254885Sdumbbell		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1946254885Sdumbbell			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1947254885Sdumbbell
1948254885Sdumbbell			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1949254885Sdumbbell			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1950254885Sdumbbell
1951254885Sdumbbell			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1952254885Sdumbbell		}
1953254885Sdumbbell	}
1954254885Sdumbbell
1955254885Sdumbbell	/* set scaler clears this on some chips */
1956254885Sdumbbell	if (ASIC_IS_AVIVO(rdev) &&
1957254885Sdumbbell	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
1958254885Sdumbbell		if (ASIC_IS_DCE4(rdev)) {
1959254885Sdumbbell			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1960254885Sdumbbell				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
1961254885Sdumbbell				       EVERGREEN_INTERLEAVE_EN);
1962254885Sdumbbell			else
1963254885Sdumbbell				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1964254885Sdumbbell		} else {
1965254885Sdumbbell			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1966254885Sdumbbell				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
1967254885Sdumbbell				       AVIVO_D1MODE_INTERLEAVE_EN);
1968254885Sdumbbell			else
1969254885Sdumbbell				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
1970254885Sdumbbell		}
1971254885Sdumbbell	}
1972254885Sdumbbell}
1973254885Sdumbbell
1974254885Sdumbbellstatic int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
1975254885Sdumbbell{
1976254885Sdumbbell	struct drm_device *dev = encoder->dev;
1977254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1978254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1979254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1980254885Sdumbbell	struct drm_encoder *test_encoder;
1981254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1982254885Sdumbbell	uint32_t dig_enc_in_use = 0;
1983254885Sdumbbell
1984254885Sdumbbell	if (ASIC_IS_DCE6(rdev)) {
1985254885Sdumbbell		/* DCE6 */
1986254885Sdumbbell		switch (radeon_encoder->encoder_id) {
1987254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1988254885Sdumbbell			if (dig->linkb)
1989254885Sdumbbell				return 1;
1990254885Sdumbbell			else
1991254885Sdumbbell				return 0;
1992254885Sdumbbell			break;
1993254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1994254885Sdumbbell			if (dig->linkb)
1995254885Sdumbbell				return 3;
1996254885Sdumbbell			else
1997254885Sdumbbell				return 2;
1998254885Sdumbbell			break;
1999254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2000254885Sdumbbell			if (dig->linkb)
2001254885Sdumbbell				return 5;
2002254885Sdumbbell			else
2003254885Sdumbbell				return 4;
2004254885Sdumbbell			break;
2005254885Sdumbbell		}
2006254885Sdumbbell	} else if (ASIC_IS_DCE4(rdev)) {
2007254885Sdumbbell		/* DCE4/5 */
2008254885Sdumbbell		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
2009254885Sdumbbell			/* ontario follows DCE4 */
2010254885Sdumbbell			if (rdev->family == CHIP_PALM) {
2011254885Sdumbbell				if (dig->linkb)
2012254885Sdumbbell					return 1;
2013254885Sdumbbell				else
2014254885Sdumbbell					return 0;
2015254885Sdumbbell			} else
2016254885Sdumbbell				/* llano follows DCE3.2 */
2017254885Sdumbbell				return radeon_crtc->crtc_id;
2018254885Sdumbbell		} else {
2019254885Sdumbbell			switch (radeon_encoder->encoder_id) {
2020254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2021254885Sdumbbell				if (dig->linkb)
2022254885Sdumbbell					return 1;
2023254885Sdumbbell				else
2024254885Sdumbbell					return 0;
2025254885Sdumbbell				break;
2026254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2027254885Sdumbbell				if (dig->linkb)
2028254885Sdumbbell					return 3;
2029254885Sdumbbell				else
2030254885Sdumbbell					return 2;
2031254885Sdumbbell				break;
2032254885Sdumbbell			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2033254885Sdumbbell				if (dig->linkb)
2034254885Sdumbbell					return 5;
2035254885Sdumbbell				else
2036254885Sdumbbell					return 4;
2037254885Sdumbbell				break;
2038254885Sdumbbell			}
2039254885Sdumbbell		}
2040254885Sdumbbell	}
2041254885Sdumbbell
2042254885Sdumbbell	/* on DCE32 and encoder can driver any block so just crtc id */
2043254885Sdumbbell	if (ASIC_IS_DCE32(rdev)) {
2044254885Sdumbbell		return radeon_crtc->crtc_id;
2045254885Sdumbbell	}
2046254885Sdumbbell
2047254885Sdumbbell	/* on DCE3 - LVTMA can only be driven by DIGB */
2048254885Sdumbbell	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
2049254885Sdumbbell		struct radeon_encoder *radeon_test_encoder;
2050254885Sdumbbell
2051254885Sdumbbell		if (encoder == test_encoder)
2052254885Sdumbbell			continue;
2053254885Sdumbbell
2054254885Sdumbbell		if (!radeon_encoder_is_digital(test_encoder))
2055254885Sdumbbell			continue;
2056254885Sdumbbell
2057254885Sdumbbell		radeon_test_encoder = to_radeon_encoder(test_encoder);
2058254885Sdumbbell		dig = radeon_test_encoder->enc_priv;
2059254885Sdumbbell
2060254885Sdumbbell		if (dig->dig_encoder >= 0)
2061254885Sdumbbell			dig_enc_in_use |= (1 << dig->dig_encoder);
2062254885Sdumbbell	}
2063254885Sdumbbell
2064254885Sdumbbell	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
2065254885Sdumbbell		if (dig_enc_in_use & 0x2)
2066254885Sdumbbell			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
2067254885Sdumbbell		return 1;
2068254885Sdumbbell	}
2069254885Sdumbbell	if (!(dig_enc_in_use & 1))
2070254885Sdumbbell		return 0;
2071254885Sdumbbell	return 1;
2072254885Sdumbbell}
2073254885Sdumbbell
2074254885Sdumbbell/* This only needs to be called once at startup */
2075254885Sdumbbellvoid
2076254885Sdumbbellradeon_atom_encoder_init(struct radeon_device *rdev)
2077254885Sdumbbell{
2078254885Sdumbbell	struct drm_device *dev = rdev->ddev;
2079254885Sdumbbell	struct drm_encoder *encoder;
2080254885Sdumbbell
2081254885Sdumbbell	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2082254885Sdumbbell		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2083254885Sdumbbell		struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2084254885Sdumbbell
2085254885Sdumbbell		switch (radeon_encoder->encoder_id) {
2086254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2087254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2088254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2089254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2090254885Sdumbbell			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
2091254885Sdumbbell			break;
2092254885Sdumbbell		default:
2093254885Sdumbbell			break;
2094254885Sdumbbell		}
2095254885Sdumbbell
2096254885Sdumbbell		if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)))
2097254885Sdumbbell			atombios_external_encoder_setup(encoder, ext_encoder,
2098254885Sdumbbell							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
2099254885Sdumbbell	}
2100254885Sdumbbell}
2101254885Sdumbbell
2102254885Sdumbbellstatic void
2103254885Sdumbbellradeon_atom_encoder_mode_set(struct drm_encoder *encoder,
2104254885Sdumbbell			     struct drm_display_mode *mode,
2105254885Sdumbbell			     struct drm_display_mode *adjusted_mode)
2106254885Sdumbbell{
2107254885Sdumbbell	struct drm_device *dev = encoder->dev;
2108254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
2109254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2110254885Sdumbbell
2111254885Sdumbbell	radeon_encoder->pixel_clock = adjusted_mode->clock;
2112254885Sdumbbell
2113254885Sdumbbell	/* need to call this here rather than in prepare() since we need some crtc info */
2114254885Sdumbbell	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2115254885Sdumbbell
2116254885Sdumbbell	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
2117254885Sdumbbell		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
2118254885Sdumbbell			atombios_yuv_setup(encoder, true);
2119254885Sdumbbell		else
2120254885Sdumbbell			atombios_yuv_setup(encoder, false);
2121254885Sdumbbell	}
2122254885Sdumbbell
2123254885Sdumbbell	switch (radeon_encoder->encoder_id) {
2124254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2125254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2126254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2127254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2128254885Sdumbbell		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
2129254885Sdumbbell		break;
2130254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2131254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2132254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2133254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2134254885Sdumbbell		/* handled in dpms */
2135254885Sdumbbell		break;
2136254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2137254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2138254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2139254885Sdumbbell		atombios_dvo_setup(encoder, ATOM_ENABLE);
2140254885Sdumbbell		break;
2141254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2142254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2143254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2144254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2145254885Sdumbbell		atombios_dac_setup(encoder, ATOM_ENABLE);
2146254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
2147254885Sdumbbell			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2148254885Sdumbbell				atombios_tv_setup(encoder, ATOM_ENABLE);
2149254885Sdumbbell			else
2150254885Sdumbbell				atombios_tv_setup(encoder, ATOM_DISABLE);
2151254885Sdumbbell		}
2152254885Sdumbbell		break;
2153254885Sdumbbell	}
2154254885Sdumbbell
2155254885Sdumbbell	atombios_apply_encoder_quirks(encoder, adjusted_mode);
2156254885Sdumbbell
2157254885Sdumbbell	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
2158254885Sdumbbell		r600_hdmi_enable(encoder);
2159254885Sdumbbell		if (ASIC_IS_DCE6(rdev))
2160254885Sdumbbell			; /* TODO (use pointers instead of if-s?) */
2161254885Sdumbbell		else if (ASIC_IS_DCE4(rdev))
2162254885Sdumbbell			evergreen_hdmi_setmode(encoder, adjusted_mode);
2163254885Sdumbbell		else
2164254885Sdumbbell			r600_hdmi_setmode(encoder, adjusted_mode);
2165254885Sdumbbell	}
2166254885Sdumbbell}
2167254885Sdumbbell
2168254885Sdumbbellstatic bool
2169254885Sdumbbellatombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2170254885Sdumbbell{
2171254885Sdumbbell	struct drm_device *dev = encoder->dev;
2172254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
2173254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2174254885Sdumbbell	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2175254885Sdumbbell
2176254885Sdumbbell	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
2177254885Sdumbbell				       ATOM_DEVICE_CV_SUPPORT |
2178254885Sdumbbell				       ATOM_DEVICE_CRT_SUPPORT)) {
2179254885Sdumbbell		DAC_LOAD_DETECTION_PS_ALLOCATION args;
2180254885Sdumbbell		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
2181254885Sdumbbell		uint8_t frev, crev;
2182254885Sdumbbell
2183254885Sdumbbell		memset(&args, 0, sizeof(args));
2184254885Sdumbbell
2185254885Sdumbbell		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2186254885Sdumbbell			return false;
2187254885Sdumbbell
2188254885Sdumbbell		args.sDacload.ucMisc = 0;
2189254885Sdumbbell
2190254885Sdumbbell		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
2191254885Sdumbbell		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
2192254885Sdumbbell			args.sDacload.ucDacType = ATOM_DAC_A;
2193254885Sdumbbell		else
2194254885Sdumbbell			args.sDacload.ucDacType = ATOM_DAC_B;
2195254885Sdumbbell
2196254885Sdumbbell		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
2197254885Sdumbbell			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
2198254885Sdumbbell		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
2199254885Sdumbbell			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
2200254885Sdumbbell		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2201254885Sdumbbell			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
2202254885Sdumbbell			if (crev >= 3)
2203254885Sdumbbell				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
2204254885Sdumbbell		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2205254885Sdumbbell			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
2206254885Sdumbbell			if (crev >= 3)
2207254885Sdumbbell				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
2208254885Sdumbbell		}
2209254885Sdumbbell
2210254885Sdumbbell		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2211254885Sdumbbell
2212254885Sdumbbell		return true;
2213254885Sdumbbell	} else
2214254885Sdumbbell		return false;
2215254885Sdumbbell}
2216254885Sdumbbell
2217254885Sdumbbellstatic enum drm_connector_status
2218254885Sdumbbellradeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2219254885Sdumbbell{
2220254885Sdumbbell	struct drm_device *dev = encoder->dev;
2221254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
2222254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2223254885Sdumbbell	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2224254885Sdumbbell	uint32_t bios_0_scratch;
2225254885Sdumbbell
2226254885Sdumbbell	if (!atombios_dac_load_detect(encoder, connector)) {
2227254885Sdumbbell		DRM_DEBUG_KMS("detect returned false \n");
2228254885Sdumbbell		return connector_status_unknown;
2229254885Sdumbbell	}
2230254885Sdumbbell
2231254885Sdumbbell	if (rdev->family >= CHIP_R600)
2232254885Sdumbbell		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2233254885Sdumbbell	else
2234254885Sdumbbell		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
2235254885Sdumbbell
2236254885Sdumbbell	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
2237254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2238254885Sdumbbell		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2239254885Sdumbbell			return connector_status_connected;
2240254885Sdumbbell	}
2241254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2242254885Sdumbbell		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2243254885Sdumbbell			return connector_status_connected;
2244254885Sdumbbell	}
2245254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2246254885Sdumbbell		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2247254885Sdumbbell			return connector_status_connected;
2248254885Sdumbbell	}
2249254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2250254885Sdumbbell		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2251254885Sdumbbell			return connector_status_connected; /* CTV */
2252254885Sdumbbell		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2253254885Sdumbbell			return connector_status_connected; /* STV */
2254254885Sdumbbell	}
2255254885Sdumbbell	return connector_status_disconnected;
2256254885Sdumbbell}
2257254885Sdumbbell
2258254885Sdumbbellstatic enum drm_connector_status
2259254885Sdumbbellradeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2260254885Sdumbbell{
2261254885Sdumbbell	struct drm_device *dev = encoder->dev;
2262254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
2263254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2264254885Sdumbbell	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2265254885Sdumbbell	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2266254885Sdumbbell	u32 bios_0_scratch;
2267254885Sdumbbell
2268254885Sdumbbell	if (!ASIC_IS_DCE4(rdev))
2269254885Sdumbbell		return connector_status_unknown;
2270254885Sdumbbell
2271254885Sdumbbell	if (!ext_encoder)
2272254885Sdumbbell		return connector_status_unknown;
2273254885Sdumbbell
2274254885Sdumbbell	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
2275254885Sdumbbell		return connector_status_unknown;
2276254885Sdumbbell
2277254885Sdumbbell	/* load detect on the dp bridge */
2278254885Sdumbbell	atombios_external_encoder_setup(encoder, ext_encoder,
2279254885Sdumbbell					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
2280254885Sdumbbell
2281254885Sdumbbell	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2282254885Sdumbbell
2283254885Sdumbbell	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
2284254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2285254885Sdumbbell		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
2286254885Sdumbbell			return connector_status_connected;
2287254885Sdumbbell	}
2288254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2289254885Sdumbbell		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
2290254885Sdumbbell			return connector_status_connected;
2291254885Sdumbbell	}
2292254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
2293254885Sdumbbell		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
2294254885Sdumbbell			return connector_status_connected;
2295254885Sdumbbell	}
2296254885Sdumbbell	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
2297254885Sdumbbell		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
2298254885Sdumbbell			return connector_status_connected; /* CTV */
2299254885Sdumbbell		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
2300254885Sdumbbell			return connector_status_connected; /* STV */
2301254885Sdumbbell	}
2302254885Sdumbbell	return connector_status_disconnected;
2303254885Sdumbbell}
2304254885Sdumbbell
2305254885Sdumbbellvoid
2306254885Sdumbbellradeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
2307254885Sdumbbell{
2308254885Sdumbbell	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
2309254885Sdumbbell
2310254885Sdumbbell	if (ext_encoder)
2311254885Sdumbbell		/* ddc_setup on the dp bridge */
2312254885Sdumbbell		atombios_external_encoder_setup(encoder, ext_encoder,
2313254885Sdumbbell						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
2314254885Sdumbbell
2315254885Sdumbbell}
2316254885Sdumbbell
2317254885Sdumbbellstatic void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
2318254885Sdumbbell{
2319254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
2320254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2321254885Sdumbbell	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
2322254885Sdumbbell
2323254885Sdumbbell	if ((radeon_encoder->active_device &
2324254885Sdumbbell	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
2325254885Sdumbbell	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
2326254885Sdumbbell	     ENCODER_OBJECT_ID_NONE)) {
2327254885Sdumbbell		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
2328254885Sdumbbell		if (dig) {
2329254885Sdumbbell			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
2330254885Sdumbbell			if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
2331254885Sdumbbell				if (rdev->family >= CHIP_R600)
2332254885Sdumbbell					dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
2333254885Sdumbbell				else
2334254885Sdumbbell					/* RS600/690/740 have only 1 afmt block */
2335254885Sdumbbell					dig->afmt = rdev->mode_info.afmt[0];
2336254885Sdumbbell			}
2337254885Sdumbbell		}
2338254885Sdumbbell	}
2339254885Sdumbbell
2340254885Sdumbbell	radeon_atom_output_lock(encoder, true);
2341254885Sdumbbell
2342254885Sdumbbell	if (connector) {
2343254885Sdumbbell		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
2344254885Sdumbbell
2345254885Sdumbbell		/* select the clock/data port if it uses a router */
2346254885Sdumbbell		if (radeon_connector->router.cd_valid)
2347254885Sdumbbell			radeon_router_select_cd_port(radeon_connector);
2348254885Sdumbbell
2349254885Sdumbbell		/* turn eDP panel on for mode set */
2350254885Sdumbbell		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
2351254885Sdumbbell			atombios_set_edp_panel_power(connector,
2352254885Sdumbbell						     ATOM_TRANSMITTER_ACTION_POWER_ON);
2353254885Sdumbbell	}
2354254885Sdumbbell
2355254885Sdumbbell	/* this is needed for the pll/ss setup to work correctly in some cases */
2356254885Sdumbbell	atombios_set_encoder_crtc_source(encoder);
2357254885Sdumbbell}
2358254885Sdumbbell
2359254885Sdumbbellstatic void radeon_atom_encoder_commit(struct drm_encoder *encoder)
2360254885Sdumbbell{
2361254885Sdumbbell	/* need to call this here as we need the crtc set up */
2362254885Sdumbbell	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
2363254885Sdumbbell	radeon_atom_output_lock(encoder, false);
2364254885Sdumbbell}
2365254885Sdumbbell
2366254885Sdumbbellstatic void radeon_atom_encoder_disable(struct drm_encoder *encoder)
2367254885Sdumbbell{
2368254885Sdumbbell	struct drm_device *dev = encoder->dev;
2369254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
2370254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2371254885Sdumbbell	struct radeon_encoder_atom_dig *dig;
2372254885Sdumbbell
2373254885Sdumbbell	/* check for pre-DCE3 cards with shared encoders;
2374254885Sdumbbell	 * can't really use the links individually, so don't disable
2375254885Sdumbbell	 * the encoder if it's in use by another connector
2376254885Sdumbbell	 */
2377254885Sdumbbell	if (!ASIC_IS_DCE3(rdev)) {
2378254885Sdumbbell		struct drm_encoder *other_encoder;
2379254885Sdumbbell		struct radeon_encoder *other_radeon_encoder;
2380254885Sdumbbell
2381254885Sdumbbell		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
2382254885Sdumbbell			other_radeon_encoder = to_radeon_encoder(other_encoder);
2383254885Sdumbbell			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
2384254885Sdumbbell			    drm_helper_encoder_in_use(other_encoder))
2385254885Sdumbbell				goto disable_done;
2386254885Sdumbbell		}
2387254885Sdumbbell	}
2388254885Sdumbbell
2389254885Sdumbbell	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
2390254885Sdumbbell
2391254885Sdumbbell	switch (radeon_encoder->encoder_id) {
2392254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2393254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2394254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2395254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2396254885Sdumbbell		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
2397254885Sdumbbell		break;
2398254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2399254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2400254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2401254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2402254885Sdumbbell		/* handled in dpms */
2403254885Sdumbbell		break;
2404254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2405254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2406254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2407254885Sdumbbell		atombios_dvo_setup(encoder, ATOM_DISABLE);
2408254885Sdumbbell		break;
2409254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2410254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2411254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2412254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2413254885Sdumbbell		atombios_dac_setup(encoder, ATOM_DISABLE);
2414254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
2415254885Sdumbbell			atombios_tv_setup(encoder, ATOM_DISABLE);
2416254885Sdumbbell		break;
2417254885Sdumbbell	}
2418254885Sdumbbell
2419254885Sdumbbelldisable_done:
2420254885Sdumbbell	if (radeon_encoder_is_digital(encoder)) {
2421254885Sdumbbell		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
2422254885Sdumbbell			r600_hdmi_disable(encoder);
2423254885Sdumbbell		dig = radeon_encoder->enc_priv;
2424254885Sdumbbell		dig->dig_encoder = -1;
2425254885Sdumbbell	}
2426254885Sdumbbell	radeon_encoder->active_device = 0;
2427254885Sdumbbell}
2428254885Sdumbbell
2429254885Sdumbbell/* these are handled by the primary encoders */
2430254885Sdumbbellstatic void radeon_atom_ext_prepare(struct drm_encoder *encoder)
2431254885Sdumbbell{
2432254885Sdumbbell
2433254885Sdumbbell}
2434254885Sdumbbell
2435254885Sdumbbellstatic void radeon_atom_ext_commit(struct drm_encoder *encoder)
2436254885Sdumbbell{
2437254885Sdumbbell
2438254885Sdumbbell}
2439254885Sdumbbell
2440254885Sdumbbellstatic void
2441254885Sdumbbellradeon_atom_ext_mode_set(struct drm_encoder *encoder,
2442254885Sdumbbell			 struct drm_display_mode *mode,
2443254885Sdumbbell			 struct drm_display_mode *adjusted_mode)
2444254885Sdumbbell{
2445254885Sdumbbell
2446254885Sdumbbell}
2447254885Sdumbbell
2448254885Sdumbbellstatic void radeon_atom_ext_disable(struct drm_encoder *encoder)
2449254885Sdumbbell{
2450254885Sdumbbell
2451254885Sdumbbell}
2452254885Sdumbbell
2453254885Sdumbbellstatic void
2454254885Sdumbbellradeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
2455254885Sdumbbell{
2456254885Sdumbbell
2457254885Sdumbbell}
2458254885Sdumbbell
2459254885Sdumbbellstatic bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
2460280183Sdumbbell				       const struct drm_display_mode *mode,
2461254885Sdumbbell				       struct drm_display_mode *adjusted_mode)
2462254885Sdumbbell{
2463254885Sdumbbell	return true;
2464254885Sdumbbell}
2465254885Sdumbbell
2466254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
2467254885Sdumbbell	.dpms = radeon_atom_ext_dpms,
2468254885Sdumbbell	.mode_fixup = radeon_atom_ext_mode_fixup,
2469254885Sdumbbell	.prepare = radeon_atom_ext_prepare,
2470254885Sdumbbell	.mode_set = radeon_atom_ext_mode_set,
2471254885Sdumbbell	.commit = radeon_atom_ext_commit,
2472254885Sdumbbell	.disable = radeon_atom_ext_disable,
2473254885Sdumbbell	/* no detect for TMDS/LVDS yet */
2474254885Sdumbbell};
2475254885Sdumbbell
2476254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
2477254885Sdumbbell	.dpms = radeon_atom_encoder_dpms,
2478254885Sdumbbell	.mode_fixup = radeon_atom_mode_fixup,
2479254885Sdumbbell	.prepare = radeon_atom_encoder_prepare,
2480254885Sdumbbell	.mode_set = radeon_atom_encoder_mode_set,
2481254885Sdumbbell	.commit = radeon_atom_encoder_commit,
2482254885Sdumbbell	.disable = radeon_atom_encoder_disable,
2483254885Sdumbbell	.detect = radeon_atom_dig_detect,
2484254885Sdumbbell};
2485254885Sdumbbell
2486254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
2487254885Sdumbbell	.dpms = radeon_atom_encoder_dpms,
2488254885Sdumbbell	.mode_fixup = radeon_atom_mode_fixup,
2489254885Sdumbbell	.prepare = radeon_atom_encoder_prepare,
2490254885Sdumbbell	.mode_set = radeon_atom_encoder_mode_set,
2491254885Sdumbbell	.commit = radeon_atom_encoder_commit,
2492254885Sdumbbell	.detect = radeon_atom_dac_detect,
2493254885Sdumbbell};
2494254885Sdumbbell
2495254885Sdumbbellvoid radeon_enc_destroy(struct drm_encoder *encoder)
2496254885Sdumbbell{
2497254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2498254885Sdumbbell	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
2499254885Sdumbbell		radeon_atom_backlight_exit(radeon_encoder);
2500254885Sdumbbell	free(radeon_encoder->enc_priv, DRM_MEM_DRIVER);
2501254885Sdumbbell	drm_encoder_cleanup(encoder);
2502254885Sdumbbell	free(radeon_encoder, DRM_MEM_DRIVER);
2503254885Sdumbbell}
2504254885Sdumbbell
2505254885Sdumbbellstatic const struct drm_encoder_funcs radeon_atom_enc_funcs = {
2506254885Sdumbbell	.destroy = radeon_enc_destroy,
2507254885Sdumbbell};
2508254885Sdumbbell
2509254885Sdumbbellstatic struct radeon_encoder_atom_dac *
2510254885Sdumbbellradeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
2511254885Sdumbbell{
2512254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
2513254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
2514254885Sdumbbell	struct radeon_encoder_atom_dac *dac = malloc(sizeof(struct radeon_encoder_atom_dac),
2515280183Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
2516254885Sdumbbell
2517254885Sdumbbell	if (!dac)
2518254885Sdumbbell		return NULL;
2519254885Sdumbbell
2520254885Sdumbbell	dac->tv_std = radeon_atombios_get_tv_info(rdev);
2521254885Sdumbbell	return dac;
2522254885Sdumbbell}
2523254885Sdumbbell
2524254885Sdumbbellstatic struct radeon_encoder_atom_dig *
2525254885Sdumbbellradeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
2526254885Sdumbbell{
2527254885Sdumbbell	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
2528254885Sdumbbell	struct radeon_encoder_atom_dig *dig = malloc(sizeof(struct radeon_encoder_atom_dig),
2529280183Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
2530254885Sdumbbell
2531254885Sdumbbell	if (!dig)
2532254885Sdumbbell		return NULL;
2533254885Sdumbbell
2534254885Sdumbbell	/* coherent mode by default */
2535254885Sdumbbell	dig->coherent_mode = true;
2536254885Sdumbbell	dig->dig_encoder = -1;
2537254885Sdumbbell
2538254885Sdumbbell	if (encoder_enum == 2)
2539254885Sdumbbell		dig->linkb = true;
2540254885Sdumbbell	else
2541254885Sdumbbell		dig->linkb = false;
2542254885Sdumbbell
2543254885Sdumbbell	return dig;
2544254885Sdumbbell}
2545254885Sdumbbell
2546254885Sdumbbellvoid
2547254885Sdumbbellradeon_add_atom_encoder(struct drm_device *dev,
2548254885Sdumbbell			uint32_t encoder_enum,
2549254885Sdumbbell			uint32_t supported_device,
2550254885Sdumbbell			u16 caps)
2551254885Sdumbbell{
2552254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
2553254885Sdumbbell	struct drm_encoder *encoder;
2554254885Sdumbbell	struct radeon_encoder *radeon_encoder;
2555254885Sdumbbell
2556254885Sdumbbell	/* see if we already added it */
2557254885Sdumbbell	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
2558254885Sdumbbell		radeon_encoder = to_radeon_encoder(encoder);
2559254885Sdumbbell		if (radeon_encoder->encoder_enum == encoder_enum) {
2560254885Sdumbbell			radeon_encoder->devices |= supported_device;
2561254885Sdumbbell			return;
2562254885Sdumbbell		}
2563254885Sdumbbell
2564254885Sdumbbell	}
2565254885Sdumbbell
2566254885Sdumbbell	/* add a new one */
2567254885Sdumbbell	radeon_encoder = malloc(sizeof(struct radeon_encoder),
2568280183Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
2569254885Sdumbbell	if (!radeon_encoder)
2570254885Sdumbbell		return;
2571254885Sdumbbell
2572254885Sdumbbell	encoder = &radeon_encoder->base;
2573254885Sdumbbell	switch (rdev->num_crtc) {
2574254885Sdumbbell	case 1:
2575254885Sdumbbell		encoder->possible_crtcs = 0x1;
2576254885Sdumbbell		break;
2577254885Sdumbbell	case 2:
2578254885Sdumbbell	default:
2579254885Sdumbbell		encoder->possible_crtcs = 0x3;
2580254885Sdumbbell		break;
2581254885Sdumbbell	case 4:
2582254885Sdumbbell		encoder->possible_crtcs = 0xf;
2583254885Sdumbbell		break;
2584254885Sdumbbell	case 6:
2585254885Sdumbbell		encoder->possible_crtcs = 0x3f;
2586254885Sdumbbell		break;
2587254885Sdumbbell	}
2588254885Sdumbbell
2589254885Sdumbbell	radeon_encoder->enc_priv = NULL;
2590254885Sdumbbell
2591254885Sdumbbell	radeon_encoder->encoder_enum = encoder_enum;
2592254885Sdumbbell	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
2593254885Sdumbbell	radeon_encoder->devices = supported_device;
2594254885Sdumbbell	radeon_encoder->rmx_type = RMX_OFF;
2595254885Sdumbbell	radeon_encoder->underscan_type = UNDERSCAN_OFF;
2596254885Sdumbbell	radeon_encoder->is_ext_encoder = false;
2597254885Sdumbbell	radeon_encoder->caps = caps;
2598254885Sdumbbell
2599254885Sdumbbell	switch (radeon_encoder->encoder_id) {
2600254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2601254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2602254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2603254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2604254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2605254885Sdumbbell			radeon_encoder->rmx_type = RMX_FULL;
2606254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
2607254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2608254885Sdumbbell		} else {
2609254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
2610254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2611254885Sdumbbell		}
2612254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2613254885Sdumbbell		break;
2614254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2615254885Sdumbbell		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
2616254885Sdumbbell		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2617254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2618254885Sdumbbell		break;
2619254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2620254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2621254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2622254885Sdumbbell		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
2623254885Sdumbbell		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
2624254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
2625254885Sdumbbell		break;
2626254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2627254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2628254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DDI:
2629254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2630254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2631254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2632254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2633254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
2634254885Sdumbbell			radeon_encoder->rmx_type = RMX_FULL;
2635254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
2636254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
2637254885Sdumbbell		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
2638254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
2639254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2640254885Sdumbbell		} else {
2641254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
2642254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
2643254885Sdumbbell		}
2644254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
2645254885Sdumbbell		break;
2646254885Sdumbbell	case ENCODER_OBJECT_ID_SI170B:
2647254885Sdumbbell	case ENCODER_OBJECT_ID_CH7303:
2648254885Sdumbbell	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2649254885Sdumbbell	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2650254885Sdumbbell	case ENCODER_OBJECT_ID_TITFP513:
2651254885Sdumbbell	case ENCODER_OBJECT_ID_VT1623:
2652254885Sdumbbell	case ENCODER_OBJECT_ID_HDMI_SI1930:
2653254885Sdumbbell	case ENCODER_OBJECT_ID_TRAVIS:
2654254885Sdumbbell	case ENCODER_OBJECT_ID_NUTMEG:
2655254885Sdumbbell		/* these are handled by the primary encoders */
2656254885Sdumbbell		radeon_encoder->is_ext_encoder = true;
2657254885Sdumbbell		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
2658254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
2659254885Sdumbbell		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
2660254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
2661254885Sdumbbell		else
2662254885Sdumbbell			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
2663254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
2664254885Sdumbbell		break;
2665254885Sdumbbell	}
2666254885Sdumbbell}
2667