162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2007-11 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
662306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
762306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
862306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
962306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
1062306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1362306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1862306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1962306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2062306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2162306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Authors: Dave Airlie
2462306a36Sopenharmony_ci *          Alex Deucher
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <linux/backlight.h>
2862306a36Sopenharmony_ci#include <linux/dmi.h>
2962306a36Sopenharmony_ci#include <linux/pci.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <drm/drm_crtc_helper.h>
3262306a36Sopenharmony_ci#include <drm/drm_file.h>
3362306a36Sopenharmony_ci#include <drm/drm_modeset_helper_vtables.h>
3462306a36Sopenharmony_ci#include <drm/radeon_drm.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include <acpi/video.h>
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#include "atom.h"
3962306a36Sopenharmony_ci#include "radeon_atombios.h"
4062306a36Sopenharmony_ci#include "radeon.h"
4162306a36Sopenharmony_ci#include "radeon_asic.h"
4262306a36Sopenharmony_ci#include "radeon_audio.h"
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciextern int atom_debug;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic u8
4762306a36Sopenharmony_ciradeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	u8 backlight_level;
5062306a36Sopenharmony_ci	u32 bios_2_scratch;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	if (rdev->family >= CHIP_R600)
5362306a36Sopenharmony_ci		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
5462306a36Sopenharmony_ci	else
5562306a36Sopenharmony_ci		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >>
5862306a36Sopenharmony_ci			   ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return backlight_level;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic void
6462306a36Sopenharmony_ciradeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev,
6562306a36Sopenharmony_ci				       u8 backlight_level)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	u32 bios_2_scratch;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	if (rdev->family >= CHIP_R600)
7062306a36Sopenharmony_ci		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
7162306a36Sopenharmony_ci	else
7262306a36Sopenharmony_ci		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
7562306a36Sopenharmony_ci	bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
7662306a36Sopenharmony_ci			   ATOM_S2_CURRENT_BL_LEVEL_MASK);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	if (rdev->family >= CHIP_R600)
7962306a36Sopenharmony_ci		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
8062306a36Sopenharmony_ci	else
8162306a36Sopenharmony_ci		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciu8
8562306a36Sopenharmony_ciatombios_get_backlight_level(struct radeon_encoder *radeon_encoder)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
8862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
9162306a36Sopenharmony_ci		return 0;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	return radeon_atom_get_backlight_level_from_reg(rdev);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_civoid
9762306a36Sopenharmony_ciatombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	struct drm_encoder *encoder = &radeon_encoder->base;
10062306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
10162306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
10262306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
10362306a36Sopenharmony_ci	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
10462306a36Sopenharmony_ci	int index;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
10762306a36Sopenharmony_ci		return;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
11062306a36Sopenharmony_ci	    radeon_encoder->enc_priv) {
11162306a36Sopenharmony_ci		dig = radeon_encoder->enc_priv;
11262306a36Sopenharmony_ci		dig->backlight_level = level;
11362306a36Sopenharmony_ci		radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
11662306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
11762306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
11862306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
11962306a36Sopenharmony_ci			if (dig->backlight_level == 0) {
12062306a36Sopenharmony_ci				args.ucAction = ATOM_LCD_BLOFF;
12162306a36Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
12262306a36Sopenharmony_ci			} else {
12362306a36Sopenharmony_ci				args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
12462306a36Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
12562306a36Sopenharmony_ci				args.ucAction = ATOM_LCD_BLON;
12662306a36Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
12762306a36Sopenharmony_ci			}
12862306a36Sopenharmony_ci			break;
12962306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
13062306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
13162306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
13262306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
13362306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
13462306a36Sopenharmony_ci			if (dig->backlight_level == 0)
13562306a36Sopenharmony_ci				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
13662306a36Sopenharmony_ci			else {
13762306a36Sopenharmony_ci				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0);
13862306a36Sopenharmony_ci				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
13962306a36Sopenharmony_ci			}
14062306a36Sopenharmony_ci			break;
14162306a36Sopenharmony_ci		default:
14262306a36Sopenharmony_ci			break;
14362306a36Sopenharmony_ci		}
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic u8 radeon_atom_bl_level(struct backlight_device *bd)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	u8 level;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/* Convert brightness to hardware level */
15262306a36Sopenharmony_ci	if (bd->props.brightness < 0)
15362306a36Sopenharmony_ci		level = 0;
15462306a36Sopenharmony_ci	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
15562306a36Sopenharmony_ci		level = RADEON_MAX_BL_LEVEL;
15662306a36Sopenharmony_ci	else
15762306a36Sopenharmony_ci		level = bd->props.brightness;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	return level;
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic int radeon_atom_backlight_update_status(struct backlight_device *bd)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
16562306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = pdata->encoder;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd));
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	return 0;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic int radeon_atom_backlight_get_brightness(struct backlight_device *bd)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
17562306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = pdata->encoder;
17662306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
17762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	return radeon_atom_get_backlight_level_from_reg(rdev);
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic const struct backlight_ops radeon_atom_backlight_ops = {
18362306a36Sopenharmony_ci	.get_brightness = radeon_atom_backlight_get_brightness,
18462306a36Sopenharmony_ci	.update_status	= radeon_atom_backlight_update_status,
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_civoid radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
18862306a36Sopenharmony_ci				struct drm_connector *drm_connector)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
19162306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
19262306a36Sopenharmony_ci	struct backlight_device *bd;
19362306a36Sopenharmony_ci	struct backlight_properties props;
19462306a36Sopenharmony_ci	struct radeon_backlight_privdata *pdata;
19562306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
19662306a36Sopenharmony_ci	char bl_name[16];
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	/* Mac laptops with multiple GPUs use the gmux driver for backlight
19962306a36Sopenharmony_ci	 * so don't register a backlight device
20062306a36Sopenharmony_ci	 */
20162306a36Sopenharmony_ci	if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
20262306a36Sopenharmony_ci	    (rdev->pdev->device == 0x6741) &&
20362306a36Sopenharmony_ci	    !dmi_match(DMI_PRODUCT_NAME, "iMac12,1"))
20462306a36Sopenharmony_ci		return;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (!radeon_encoder->enc_priv)
20762306a36Sopenharmony_ci		return;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if (!rdev->is_atom_bios)
21062306a36Sopenharmony_ci		return;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
21362306a36Sopenharmony_ci		return;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	if (!acpi_video_backlight_use_native()) {
21662306a36Sopenharmony_ci		drm_info(dev, "Skipping radeon atom DIG backlight registration\n");
21762306a36Sopenharmony_ci		return;
21862306a36Sopenharmony_ci	}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
22162306a36Sopenharmony_ci	if (!pdata) {
22262306a36Sopenharmony_ci		DRM_ERROR("Memory allocation failed\n");
22362306a36Sopenharmony_ci		goto error;
22462306a36Sopenharmony_ci	}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	memset(&props, 0, sizeof(props));
22762306a36Sopenharmony_ci	props.max_brightness = RADEON_MAX_BL_LEVEL;
22862306a36Sopenharmony_ci	props.type = BACKLIGHT_RAW;
22962306a36Sopenharmony_ci	snprintf(bl_name, sizeof(bl_name),
23062306a36Sopenharmony_ci		 "radeon_bl%d", dev->primary->index);
23162306a36Sopenharmony_ci	bd = backlight_device_register(bl_name, drm_connector->kdev,
23262306a36Sopenharmony_ci				       pdata, &radeon_atom_backlight_ops, &props);
23362306a36Sopenharmony_ci	if (IS_ERR(bd)) {
23462306a36Sopenharmony_ci		DRM_ERROR("Backlight registration failed\n");
23562306a36Sopenharmony_ci		goto error;
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	pdata->encoder = radeon_encoder;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	dig = radeon_encoder->enc_priv;
24162306a36Sopenharmony_ci	dig->bl_dev = bd;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	bd->props.brightness = radeon_atom_backlight_get_brightness(bd);
24462306a36Sopenharmony_ci	/* Set a reasonable default here if the level is 0 otherwise
24562306a36Sopenharmony_ci	 * fbdev will attempt to turn the backlight on after console
24662306a36Sopenharmony_ci	 * unblanking and it will try and restore 0 which turns the backlight
24762306a36Sopenharmony_ci	 * off again.
24862306a36Sopenharmony_ci	 */
24962306a36Sopenharmony_ci	if (bd->props.brightness == 0)
25062306a36Sopenharmony_ci		bd->props.brightness = RADEON_MAX_BL_LEVEL;
25162306a36Sopenharmony_ci	bd->props.power = FB_BLANK_UNBLANK;
25262306a36Sopenharmony_ci	backlight_update_status(bd);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	DRM_INFO("radeon atom DIG backlight initialized\n");
25562306a36Sopenharmony_ci	rdev->mode_info.bl_encoder = radeon_encoder;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_cierror:
26062306a36Sopenharmony_ci	kfree(pdata);
26162306a36Sopenharmony_ci	return;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
26762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
26862306a36Sopenharmony_ci	struct backlight_device *bd = NULL;
26962306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (!radeon_encoder->enc_priv)
27262306a36Sopenharmony_ci		return;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	if (!rdev->is_atom_bios)
27562306a36Sopenharmony_ci		return;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
27862306a36Sopenharmony_ci		return;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	dig = radeon_encoder->enc_priv;
28162306a36Sopenharmony_ci	bd = dig->bl_dev;
28262306a36Sopenharmony_ci	dig->bl_dev = NULL;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	if (bd) {
28562306a36Sopenharmony_ci		struct radeon_legacy_backlight_privdata *pdata;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		pdata = bl_get_data(bd);
28862306a36Sopenharmony_ci		backlight_device_unregister(bd);
28962306a36Sopenharmony_ci		kfree(pdata);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci		DRM_INFO("radeon atom LVDS backlight unloaded\n");
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
29662306a36Sopenharmony_ci				   const struct drm_display_mode *mode,
29762306a36Sopenharmony_ci				   struct drm_display_mode *adjusted_mode)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
30062306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
30162306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	/* set the active encoder to connector routing */
30462306a36Sopenharmony_ci	radeon_encoder_set_active_device(encoder);
30562306a36Sopenharmony_ci	drm_mode_set_crtcinfo(adjusted_mode, 0);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	/* hw bug */
30862306a36Sopenharmony_ci	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
30962306a36Sopenharmony_ci	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
31062306a36Sopenharmony_ci		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/* vertical FP must be at least 1 */
31362306a36Sopenharmony_ci	if (mode->crtc_vsync_start == mode->crtc_vdisplay)
31462306a36Sopenharmony_ci		adjusted_mode->crtc_vsync_start++;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	/* get the native mode for scaling */
31762306a36Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
31862306a36Sopenharmony_ci		radeon_panel_mode_fixup(encoder, adjusted_mode);
31962306a36Sopenharmony_ci	} else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
32062306a36Sopenharmony_ci		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
32162306a36Sopenharmony_ci		if (tv_dac) {
32262306a36Sopenharmony_ci			if (tv_dac->tv_std == TV_STD_NTSC ||
32362306a36Sopenharmony_ci			    tv_dac->tv_std == TV_STD_NTSC_J ||
32462306a36Sopenharmony_ci			    tv_dac->tv_std == TV_STD_PAL_M)
32562306a36Sopenharmony_ci				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
32662306a36Sopenharmony_ci			else
32762306a36Sopenharmony_ci				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
32862306a36Sopenharmony_ci		}
32962306a36Sopenharmony_ci	} else if (radeon_encoder->rmx_type != RMX_OFF) {
33062306a36Sopenharmony_ci		radeon_panel_mode_fixup(encoder, adjusted_mode);
33162306a36Sopenharmony_ci	}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	if (ASIC_IS_DCE3(rdev) &&
33462306a36Sopenharmony_ci	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
33562306a36Sopenharmony_ci	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
33662306a36Sopenharmony_ci		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
33762306a36Sopenharmony_ci		radeon_dp_set_link_config(connector, adjusted_mode);
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return true;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic void
34462306a36Sopenharmony_ciatombios_dac_setup(struct drm_encoder *encoder, int action)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
34762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
34862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
34962306a36Sopenharmony_ci	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
35062306a36Sopenharmony_ci	int index = 0;
35162306a36Sopenharmony_ci	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
35662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
35762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
35862306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
36162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
36262306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
36362306a36Sopenharmony_ci		break;
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	args.ucAction = action;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
36962306a36Sopenharmony_ci		args.ucDacStandard = ATOM_DAC1_PS2;
37062306a36Sopenharmony_ci	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
37162306a36Sopenharmony_ci		args.ucDacStandard = ATOM_DAC1_CV;
37262306a36Sopenharmony_ci	else {
37362306a36Sopenharmony_ci		switch (dac_info->tv_std) {
37462306a36Sopenharmony_ci		case TV_STD_PAL:
37562306a36Sopenharmony_ci		case TV_STD_PAL_M:
37662306a36Sopenharmony_ci		case TV_STD_SCART_PAL:
37762306a36Sopenharmony_ci		case TV_STD_SECAM:
37862306a36Sopenharmony_ci		case TV_STD_PAL_CN:
37962306a36Sopenharmony_ci			args.ucDacStandard = ATOM_DAC1_PAL;
38062306a36Sopenharmony_ci			break;
38162306a36Sopenharmony_ci		case TV_STD_NTSC:
38262306a36Sopenharmony_ci		case TV_STD_NTSC_J:
38362306a36Sopenharmony_ci		case TV_STD_PAL_60:
38462306a36Sopenharmony_ci		default:
38562306a36Sopenharmony_ci			args.ucDacStandard = ATOM_DAC1_NTSC;
38662306a36Sopenharmony_ci			break;
38762306a36Sopenharmony_ci		}
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cistatic void
39662306a36Sopenharmony_ciatombios_tv_setup(struct drm_encoder *encoder, int action)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
39962306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
40062306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
40162306a36Sopenharmony_ci	TV_ENCODER_CONTROL_PS_ALLOCATION args;
40262306a36Sopenharmony_ci	int index = 0;
40362306a36Sopenharmony_ci	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	args.sTVEncoder.ucAction = action;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
41262306a36Sopenharmony_ci		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
41362306a36Sopenharmony_ci	else {
41462306a36Sopenharmony_ci		switch (dac_info->tv_std) {
41562306a36Sopenharmony_ci		case TV_STD_NTSC:
41662306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
41762306a36Sopenharmony_ci			break;
41862306a36Sopenharmony_ci		case TV_STD_PAL:
41962306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
42062306a36Sopenharmony_ci			break;
42162306a36Sopenharmony_ci		case TV_STD_PAL_M:
42262306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
42362306a36Sopenharmony_ci			break;
42462306a36Sopenharmony_ci		case TV_STD_PAL_60:
42562306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
42662306a36Sopenharmony_ci			break;
42762306a36Sopenharmony_ci		case TV_STD_NTSC_J:
42862306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
42962306a36Sopenharmony_ci			break;
43062306a36Sopenharmony_ci		case TV_STD_SCART_PAL:
43162306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
43262306a36Sopenharmony_ci			break;
43362306a36Sopenharmony_ci		case TV_STD_SECAM:
43462306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
43562306a36Sopenharmony_ci			break;
43662306a36Sopenharmony_ci		case TV_STD_PAL_CN:
43762306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
43862306a36Sopenharmony_ci			break;
43962306a36Sopenharmony_ci		default:
44062306a36Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
44162306a36Sopenharmony_ci			break;
44262306a36Sopenharmony_ci		}
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_cistatic u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	int bpc = 8;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	if (encoder->crtc) {
45662306a36Sopenharmony_ci		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
45762306a36Sopenharmony_ci		bpc = radeon_crtc->bpc;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	switch (bpc) {
46162306a36Sopenharmony_ci	case 0:
46262306a36Sopenharmony_ci		return PANEL_BPC_UNDEFINE;
46362306a36Sopenharmony_ci	case 6:
46462306a36Sopenharmony_ci		return PANEL_6BIT_PER_COLOR;
46562306a36Sopenharmony_ci	case 8:
46662306a36Sopenharmony_ci	default:
46762306a36Sopenharmony_ci		return PANEL_8BIT_PER_COLOR;
46862306a36Sopenharmony_ci	case 10:
46962306a36Sopenharmony_ci		return PANEL_10BIT_PER_COLOR;
47062306a36Sopenharmony_ci	case 12:
47162306a36Sopenharmony_ci		return PANEL_12BIT_PER_COLOR;
47262306a36Sopenharmony_ci	case 16:
47362306a36Sopenharmony_ci		return PANEL_16BIT_PER_COLOR;
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ciunion dvo_encoder_control {
47862306a36Sopenharmony_ci	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
47962306a36Sopenharmony_ci	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
48062306a36Sopenharmony_ci	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
48162306a36Sopenharmony_ci	DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 dvo_v4;
48262306a36Sopenharmony_ci};
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_civoid
48562306a36Sopenharmony_ciatombios_dvo_setup(struct drm_encoder *encoder, int action)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
48862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
48962306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
49062306a36Sopenharmony_ci	union dvo_encoder_control args;
49162306a36Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
49262306a36Sopenharmony_ci	uint8_t frev, crev;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
49762306a36Sopenharmony_ci		return;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	/* some R4xx chips have the wrong frev */
50062306a36Sopenharmony_ci	if (rdev->family <= CHIP_RV410)
50162306a36Sopenharmony_ci		frev = 1;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	switch (frev) {
50462306a36Sopenharmony_ci	case 1:
50562306a36Sopenharmony_ci		switch (crev) {
50662306a36Sopenharmony_ci		case 1:
50762306a36Sopenharmony_ci			/* R4xx, R5xx */
50862306a36Sopenharmony_ci			args.ext_tmds.sXTmdsEncoder.ucEnable = action;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
51162306a36Sopenharmony_ci				args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci			args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
51462306a36Sopenharmony_ci			break;
51562306a36Sopenharmony_ci		case 2:
51662306a36Sopenharmony_ci			/* RS600/690/740 */
51762306a36Sopenharmony_ci			args.dvo.sDVOEncoder.ucAction = action;
51862306a36Sopenharmony_ci			args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
51962306a36Sopenharmony_ci			/* DFP1, CRT1, TV1 depending on the type of port */
52062306a36Sopenharmony_ci			args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
52362306a36Sopenharmony_ci				args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
52462306a36Sopenharmony_ci			break;
52562306a36Sopenharmony_ci		case 3:
52662306a36Sopenharmony_ci			/* R6xx */
52762306a36Sopenharmony_ci			args.dvo_v3.ucAction = action;
52862306a36Sopenharmony_ci			args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
52962306a36Sopenharmony_ci			args.dvo_v3.ucDVOConfig = 0; /* XXX */
53062306a36Sopenharmony_ci			break;
53162306a36Sopenharmony_ci		case 4:
53262306a36Sopenharmony_ci			/* DCE8 */
53362306a36Sopenharmony_ci			args.dvo_v4.ucAction = action;
53462306a36Sopenharmony_ci			args.dvo_v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
53562306a36Sopenharmony_ci			args.dvo_v4.ucDVOConfig = 0; /* XXX */
53662306a36Sopenharmony_ci			args.dvo_v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
53762306a36Sopenharmony_ci			break;
53862306a36Sopenharmony_ci		default:
53962306a36Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
54062306a36Sopenharmony_ci			break;
54162306a36Sopenharmony_ci		}
54262306a36Sopenharmony_ci		break;
54362306a36Sopenharmony_ci	default:
54462306a36Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
54562306a36Sopenharmony_ci		break;
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ciunion lvds_encoder_control {
55262306a36Sopenharmony_ci	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
55362306a36Sopenharmony_ci	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
55462306a36Sopenharmony_ci};
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_civoid
55762306a36Sopenharmony_ciatombios_digital_setup(struct drm_encoder *encoder, int action)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
56062306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
56162306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
56262306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
56362306a36Sopenharmony_ci	union lvds_encoder_control args;
56462306a36Sopenharmony_ci	int index = 0;
56562306a36Sopenharmony_ci	int hdmi_detected = 0;
56662306a36Sopenharmony_ci	uint8_t frev, crev;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	if (!dig)
56962306a36Sopenharmony_ci		return;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
57262306a36Sopenharmony_ci		hdmi_detected = 1;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
57762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
57862306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
57962306a36Sopenharmony_ci		break;
58062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
58162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
58262306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
58362306a36Sopenharmony_ci		break;
58462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
58562306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
58662306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
58762306a36Sopenharmony_ci		else
58862306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
58962306a36Sopenharmony_ci		break;
59062306a36Sopenharmony_ci	}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
59362306a36Sopenharmony_ci		return;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	switch (frev) {
59662306a36Sopenharmony_ci	case 1:
59762306a36Sopenharmony_ci	case 2:
59862306a36Sopenharmony_ci		switch (crev) {
59962306a36Sopenharmony_ci		case 1:
60062306a36Sopenharmony_ci			args.v1.ucMisc = 0;
60162306a36Sopenharmony_ci			args.v1.ucAction = action;
60262306a36Sopenharmony_ci			if (hdmi_detected)
60362306a36Sopenharmony_ci				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
60462306a36Sopenharmony_ci			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
60562306a36Sopenharmony_ci			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
60662306a36Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
60762306a36Sopenharmony_ci					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
60862306a36Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
60962306a36Sopenharmony_ci					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
61062306a36Sopenharmony_ci			} else {
61162306a36Sopenharmony_ci				if (dig->linkb)
61262306a36Sopenharmony_ci					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
61362306a36Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
61462306a36Sopenharmony_ci					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
61562306a36Sopenharmony_ci				/*if (pScrn->rgbBits == 8) */
61662306a36Sopenharmony_ci				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
61762306a36Sopenharmony_ci			}
61862306a36Sopenharmony_ci			break;
61962306a36Sopenharmony_ci		case 2:
62062306a36Sopenharmony_ci		case 3:
62162306a36Sopenharmony_ci			args.v2.ucMisc = 0;
62262306a36Sopenharmony_ci			args.v2.ucAction = action;
62362306a36Sopenharmony_ci			if (crev == 3) {
62462306a36Sopenharmony_ci				if (dig->coherent_mode)
62562306a36Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
62662306a36Sopenharmony_ci			}
62762306a36Sopenharmony_ci			if (hdmi_detected)
62862306a36Sopenharmony_ci				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
62962306a36Sopenharmony_ci			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
63062306a36Sopenharmony_ci			args.v2.ucTruncate = 0;
63162306a36Sopenharmony_ci			args.v2.ucSpatial = 0;
63262306a36Sopenharmony_ci			args.v2.ucTemporal = 0;
63362306a36Sopenharmony_ci			args.v2.ucFRC = 0;
63462306a36Sopenharmony_ci			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
63562306a36Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
63662306a36Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
63762306a36Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
63862306a36Sopenharmony_ci					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
63962306a36Sopenharmony_ci					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
64062306a36Sopenharmony_ci						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
64162306a36Sopenharmony_ci				}
64262306a36Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
64362306a36Sopenharmony_ci					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
64462306a36Sopenharmony_ci					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
64562306a36Sopenharmony_ci						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
64662306a36Sopenharmony_ci					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
64762306a36Sopenharmony_ci						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
64862306a36Sopenharmony_ci				}
64962306a36Sopenharmony_ci			} else {
65062306a36Sopenharmony_ci				if (dig->linkb)
65162306a36Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
65262306a36Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
65362306a36Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
65462306a36Sopenharmony_ci			}
65562306a36Sopenharmony_ci			break;
65662306a36Sopenharmony_ci		default:
65762306a36Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
65862306a36Sopenharmony_ci			break;
65962306a36Sopenharmony_ci		}
66062306a36Sopenharmony_ci		break;
66162306a36Sopenharmony_ci	default:
66262306a36Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
66362306a36Sopenharmony_ci		break;
66462306a36Sopenharmony_ci	}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
66762306a36Sopenharmony_ci}
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ciint
67062306a36Sopenharmony_ciatombios_get_encoder_mode(struct drm_encoder *encoder)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
67362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
67462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
67562306a36Sopenharmony_ci	struct drm_connector *connector;
67662306a36Sopenharmony_ci	struct radeon_connector *radeon_connector;
67762306a36Sopenharmony_ci	struct radeon_connector_atom_dig *dig_connector;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	/* dp bridges are always DP */
68062306a36Sopenharmony_ci	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
68162306a36Sopenharmony_ci		return ATOM_ENCODER_MODE_DP;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	/* DVO is always DVO */
68462306a36Sopenharmony_ci	if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) ||
68562306a36Sopenharmony_ci	    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
68662306a36Sopenharmony_ci		return ATOM_ENCODER_MODE_DVO;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	connector = radeon_get_connector_for_encoder(encoder);
68962306a36Sopenharmony_ci	/* if we don't have an active device yet, just use one of
69062306a36Sopenharmony_ci	 * the connectors tied to the encoder.
69162306a36Sopenharmony_ci	 */
69262306a36Sopenharmony_ci	if (!connector)
69362306a36Sopenharmony_ci		connector = radeon_get_connector_for_encoder_init(encoder);
69462306a36Sopenharmony_ci	radeon_connector = to_radeon_connector(connector);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	switch (connector->connector_type) {
69762306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVII:
69862306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
69962306a36Sopenharmony_ci		if (radeon_audio != 0) {
70062306a36Sopenharmony_ci			if (radeon_connector->use_digital &&
70162306a36Sopenharmony_ci			    (radeon_connector->audio == RADEON_AUDIO_ENABLE))
70262306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
70362306a36Sopenharmony_ci			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
70462306a36Sopenharmony_ci				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
70562306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
70662306a36Sopenharmony_ci			else if (radeon_connector->use_digital)
70762306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_DVI;
70862306a36Sopenharmony_ci			else
70962306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_CRT;
71062306a36Sopenharmony_ci		} else if (radeon_connector->use_digital) {
71162306a36Sopenharmony_ci			return ATOM_ENCODER_MODE_DVI;
71262306a36Sopenharmony_ci		} else {
71362306a36Sopenharmony_ci			return ATOM_ENCODER_MODE_CRT;
71462306a36Sopenharmony_ci		}
71562306a36Sopenharmony_ci		break;
71662306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVID:
71762306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIA:
71862306a36Sopenharmony_ci	default:
71962306a36Sopenharmony_ci		if (radeon_audio != 0) {
72062306a36Sopenharmony_ci			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
72162306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
72262306a36Sopenharmony_ci			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
72362306a36Sopenharmony_ci				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
72462306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
72562306a36Sopenharmony_ci			else
72662306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_DVI;
72762306a36Sopenharmony_ci		} else {
72862306a36Sopenharmony_ci			return ATOM_ENCODER_MODE_DVI;
72962306a36Sopenharmony_ci		}
73062306a36Sopenharmony_ci		break;
73162306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_LVDS:
73262306a36Sopenharmony_ci		return ATOM_ENCODER_MODE_LVDS;
73362306a36Sopenharmony_ci		break;
73462306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DisplayPort:
73562306a36Sopenharmony_ci		dig_connector = radeon_connector->con_priv;
73662306a36Sopenharmony_ci		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
73762306a36Sopenharmony_ci		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
73862306a36Sopenharmony_ci			if (radeon_audio != 0 &&
73962306a36Sopenharmony_ci			    drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
74062306a36Sopenharmony_ci			    ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
74162306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_DP_AUDIO;
74262306a36Sopenharmony_ci			return ATOM_ENCODER_MODE_DP;
74362306a36Sopenharmony_ci		} else if (radeon_audio != 0) {
74462306a36Sopenharmony_ci			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
74562306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
74662306a36Sopenharmony_ci			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
74762306a36Sopenharmony_ci				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
74862306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
74962306a36Sopenharmony_ci			else
75062306a36Sopenharmony_ci				return ATOM_ENCODER_MODE_DVI;
75162306a36Sopenharmony_ci		} else {
75262306a36Sopenharmony_ci			return ATOM_ENCODER_MODE_DVI;
75362306a36Sopenharmony_ci		}
75462306a36Sopenharmony_ci		break;
75562306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_eDP:
75662306a36Sopenharmony_ci		if (radeon_audio != 0 &&
75762306a36Sopenharmony_ci		    drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
75862306a36Sopenharmony_ci		    ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
75962306a36Sopenharmony_ci			return ATOM_ENCODER_MODE_DP_AUDIO;
76062306a36Sopenharmony_ci		return ATOM_ENCODER_MODE_DP;
76162306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVIA:
76262306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_VGA:
76362306a36Sopenharmony_ci		return ATOM_ENCODER_MODE_CRT;
76462306a36Sopenharmony_ci		break;
76562306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_Composite:
76662306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_SVIDEO:
76762306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_9PinDIN:
76862306a36Sopenharmony_ci		/* fix me */
76962306a36Sopenharmony_ci		return ATOM_ENCODER_MODE_TV;
77062306a36Sopenharmony_ci		/*return ATOM_ENCODER_MODE_CV;*/
77162306a36Sopenharmony_ci		break;
77262306a36Sopenharmony_ci	}
77362306a36Sopenharmony_ci}
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci/*
77662306a36Sopenharmony_ci * DIG Encoder/Transmitter Setup
77762306a36Sopenharmony_ci *
77862306a36Sopenharmony_ci * DCE 3.0/3.1
77962306a36Sopenharmony_ci * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
78062306a36Sopenharmony_ci * Supports up to 3 digital outputs
78162306a36Sopenharmony_ci * - 2 DIG encoder blocks.
78262306a36Sopenharmony_ci * DIG1 can drive UNIPHY link A or link B
78362306a36Sopenharmony_ci * DIG2 can drive UNIPHY link B or LVTMA
78462306a36Sopenharmony_ci *
78562306a36Sopenharmony_ci * DCE 3.2
78662306a36Sopenharmony_ci * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
78762306a36Sopenharmony_ci * Supports up to 5 digital outputs
78862306a36Sopenharmony_ci * - 2 DIG encoder blocks.
78962306a36Sopenharmony_ci * DIG1/2 can drive UNIPHY0/1/2 link A or link B
79062306a36Sopenharmony_ci *
79162306a36Sopenharmony_ci * DCE 4.0/5.0/6.0
79262306a36Sopenharmony_ci * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
79362306a36Sopenharmony_ci * Supports up to 6 digital outputs
79462306a36Sopenharmony_ci * - 6 DIG encoder blocks.
79562306a36Sopenharmony_ci * - DIG to PHY mapping is hardcoded
79662306a36Sopenharmony_ci * DIG1 drives UNIPHY0 link A, A+B
79762306a36Sopenharmony_ci * DIG2 drives UNIPHY0 link B
79862306a36Sopenharmony_ci * DIG3 drives UNIPHY1 link A, A+B
79962306a36Sopenharmony_ci * DIG4 drives UNIPHY1 link B
80062306a36Sopenharmony_ci * DIG5 drives UNIPHY2 link A, A+B
80162306a36Sopenharmony_ci * DIG6 drives UNIPHY2 link B
80262306a36Sopenharmony_ci *
80362306a36Sopenharmony_ci * DCE 4.1
80462306a36Sopenharmony_ci * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
80562306a36Sopenharmony_ci * Supports up to 6 digital outputs
80662306a36Sopenharmony_ci * - 2 DIG encoder blocks.
80762306a36Sopenharmony_ci * llano
80862306a36Sopenharmony_ci * DIG1/2 can drive UNIPHY0/1/2 link A or link B
80962306a36Sopenharmony_ci * ontario
81062306a36Sopenharmony_ci * DIG1 drives UNIPHY0/1/2 link A
81162306a36Sopenharmony_ci * DIG2 drives UNIPHY0/1/2 link B
81262306a36Sopenharmony_ci *
81362306a36Sopenharmony_ci * Routing
81462306a36Sopenharmony_ci * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
81562306a36Sopenharmony_ci * Examples:
81662306a36Sopenharmony_ci * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
81762306a36Sopenharmony_ci * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
81862306a36Sopenharmony_ci * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
81962306a36Sopenharmony_ci * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
82062306a36Sopenharmony_ci */
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ciunion dig_encoder_control {
82362306a36Sopenharmony_ci	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
82462306a36Sopenharmony_ci	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
82562306a36Sopenharmony_ci	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
82662306a36Sopenharmony_ci	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
82762306a36Sopenharmony_ci};
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_civoid
83062306a36Sopenharmony_ciatombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override)
83162306a36Sopenharmony_ci{
83262306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
83362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
83462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
83562306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
83662306a36Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
83762306a36Sopenharmony_ci	union dig_encoder_control args;
83862306a36Sopenharmony_ci	int index = 0;
83962306a36Sopenharmony_ci	uint8_t frev, crev;
84062306a36Sopenharmony_ci	int dp_clock = 0;
84162306a36Sopenharmony_ci	int dp_lane_count = 0;
84262306a36Sopenharmony_ci	int hpd_id = RADEON_HPD_NONE;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	if (connector) {
84562306a36Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
84662306a36Sopenharmony_ci		struct radeon_connector_atom_dig *dig_connector =
84762306a36Sopenharmony_ci			radeon_connector->con_priv;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci		dp_clock = dig_connector->dp_clock;
85062306a36Sopenharmony_ci		dp_lane_count = dig_connector->dp_lane_count;
85162306a36Sopenharmony_ci		hpd_id = radeon_connector->hpd.hpd;
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	/* no dig encoder assigned */
85562306a36Sopenharmony_ci	if (dig->dig_encoder == -1)
85662306a36Sopenharmony_ci		return;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	if (ASIC_IS_DCE4(rdev))
86162306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
86262306a36Sopenharmony_ci	else {
86362306a36Sopenharmony_ci		if (dig->dig_encoder)
86462306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
86562306a36Sopenharmony_ci		else
86662306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
87062306a36Sopenharmony_ci		return;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	switch (frev) {
87362306a36Sopenharmony_ci	case 1:
87462306a36Sopenharmony_ci		switch (crev) {
87562306a36Sopenharmony_ci		case 1:
87662306a36Sopenharmony_ci			args.v1.ucAction = action;
87762306a36Sopenharmony_ci			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
87862306a36Sopenharmony_ci			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
87962306a36Sopenharmony_ci				args.v3.ucPanelMode = panel_mode;
88062306a36Sopenharmony_ci			else
88162306a36Sopenharmony_ci				args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
88462306a36Sopenharmony_ci				args.v1.ucLaneNum = dp_lane_count;
88562306a36Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
88662306a36Sopenharmony_ci				args.v1.ucLaneNum = 8;
88762306a36Sopenharmony_ci			else
88862306a36Sopenharmony_ci				args.v1.ucLaneNum = 4;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
89162306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
89262306a36Sopenharmony_ci				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
89362306a36Sopenharmony_ci				break;
89462306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
89562306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
89662306a36Sopenharmony_ci				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
89762306a36Sopenharmony_ci				break;
89862306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
89962306a36Sopenharmony_ci				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
90062306a36Sopenharmony_ci				break;
90162306a36Sopenharmony_ci			}
90262306a36Sopenharmony_ci			if (dig->linkb)
90362306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
90462306a36Sopenharmony_ci			else
90562306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
90862306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci			break;
91162306a36Sopenharmony_ci		case 2:
91262306a36Sopenharmony_ci		case 3:
91362306a36Sopenharmony_ci			args.v3.ucAction = action;
91462306a36Sopenharmony_ci			args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
91562306a36Sopenharmony_ci			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
91662306a36Sopenharmony_ci				args.v3.ucPanelMode = panel_mode;
91762306a36Sopenharmony_ci			else
91862306a36Sopenharmony_ci				args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode))
92162306a36Sopenharmony_ci				args.v3.ucLaneNum = dp_lane_count;
92262306a36Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
92362306a36Sopenharmony_ci				args.v3.ucLaneNum = 8;
92462306a36Sopenharmony_ci			else
92562306a36Sopenharmony_ci				args.v3.ucLaneNum = 4;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
92862306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
92962306a36Sopenharmony_ci			if (enc_override != -1)
93062306a36Sopenharmony_ci				args.v3.acConfig.ucDigSel = enc_override;
93162306a36Sopenharmony_ci			else
93262306a36Sopenharmony_ci				args.v3.acConfig.ucDigSel = dig->dig_encoder;
93362306a36Sopenharmony_ci			args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
93462306a36Sopenharmony_ci			break;
93562306a36Sopenharmony_ci		case 4:
93662306a36Sopenharmony_ci			args.v4.ucAction = action;
93762306a36Sopenharmony_ci			args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
93862306a36Sopenharmony_ci			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
93962306a36Sopenharmony_ci				args.v4.ucPanelMode = panel_mode;
94062306a36Sopenharmony_ci			else
94162306a36Sopenharmony_ci				args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode))
94462306a36Sopenharmony_ci				args.v4.ucLaneNum = dp_lane_count;
94562306a36Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
94662306a36Sopenharmony_ci				args.v4.ucLaneNum = 8;
94762306a36Sopenharmony_ci			else
94862306a36Sopenharmony_ci				args.v4.ucLaneNum = 4;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) {
95162306a36Sopenharmony_ci				if (dp_clock == 540000)
95262306a36Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
95362306a36Sopenharmony_ci				else if (dp_clock == 324000)
95462306a36Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ;
95562306a36Sopenharmony_ci				else if (dp_clock == 270000)
95662306a36Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
95762306a36Sopenharmony_ci				else
95862306a36Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
95962306a36Sopenharmony_ci			}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci			if (enc_override != -1)
96262306a36Sopenharmony_ci				args.v4.acConfig.ucDigSel = enc_override;
96362306a36Sopenharmony_ci			else
96462306a36Sopenharmony_ci				args.v4.acConfig.ucDigSel = dig->dig_encoder;
96562306a36Sopenharmony_ci			args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
96662306a36Sopenharmony_ci			if (hpd_id == RADEON_HPD_NONE)
96762306a36Sopenharmony_ci				args.v4.ucHPD_ID = 0;
96862306a36Sopenharmony_ci			else
96962306a36Sopenharmony_ci				args.v4.ucHPD_ID = hpd_id + 1;
97062306a36Sopenharmony_ci			break;
97162306a36Sopenharmony_ci		default:
97262306a36Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
97362306a36Sopenharmony_ci			break;
97462306a36Sopenharmony_ci		}
97562306a36Sopenharmony_ci		break;
97662306a36Sopenharmony_ci	default:
97762306a36Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
97862306a36Sopenharmony_ci		break;
97962306a36Sopenharmony_ci	}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_civoid
98662306a36Sopenharmony_ciatombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
98762306a36Sopenharmony_ci{
98862306a36Sopenharmony_ci	atombios_dig_encoder_setup2(encoder, action, panel_mode, -1);
98962306a36Sopenharmony_ci}
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ciunion dig_transmitter_control {
99262306a36Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
99362306a36Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
99462306a36Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
99562306a36Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
99662306a36Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
99762306a36Sopenharmony_ci};
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_civoid
100062306a36Sopenharmony_ciatombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
100362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
100462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
100562306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
100662306a36Sopenharmony_ci	struct drm_connector *connector;
100762306a36Sopenharmony_ci	union dig_transmitter_control args;
100862306a36Sopenharmony_ci	int index = 0;
100962306a36Sopenharmony_ci	uint8_t frev, crev;
101062306a36Sopenharmony_ci	bool is_dp = false;
101162306a36Sopenharmony_ci	int pll_id = 0;
101262306a36Sopenharmony_ci	int dp_clock = 0;
101362306a36Sopenharmony_ci	int dp_lane_count = 0;
101462306a36Sopenharmony_ci	int connector_object_id = 0;
101562306a36Sopenharmony_ci	int igp_lane_info = 0;
101662306a36Sopenharmony_ci	int dig_encoder = dig->dig_encoder;
101762306a36Sopenharmony_ci	int hpd_id = RADEON_HPD_NONE;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
102062306a36Sopenharmony_ci		connector = radeon_get_connector_for_encoder_init(encoder);
102162306a36Sopenharmony_ci		/* just needed to avoid bailing in the encoder check.  the encoder
102262306a36Sopenharmony_ci		 * isn't used for init
102362306a36Sopenharmony_ci		 */
102462306a36Sopenharmony_ci		dig_encoder = 0;
102562306a36Sopenharmony_ci	} else
102662306a36Sopenharmony_ci		connector = radeon_get_connector_for_encoder(encoder);
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	if (connector) {
102962306a36Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
103062306a36Sopenharmony_ci		struct radeon_connector_atom_dig *dig_connector =
103162306a36Sopenharmony_ci			radeon_connector->con_priv;
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci		hpd_id = radeon_connector->hpd.hpd;
103462306a36Sopenharmony_ci		dp_clock = dig_connector->dp_clock;
103562306a36Sopenharmony_ci		dp_lane_count = dig_connector->dp_lane_count;
103662306a36Sopenharmony_ci		connector_object_id =
103762306a36Sopenharmony_ci			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
103862306a36Sopenharmony_ci		igp_lane_info = dig_connector->igp_lane_info;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	if (encoder->crtc) {
104262306a36Sopenharmony_ci		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
104362306a36Sopenharmony_ci		pll_id = radeon_crtc->pll_id;
104462306a36Sopenharmony_ci	}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	/* no dig encoder assigned */
104762306a36Sopenharmony_ci	if (dig_encoder == -1)
104862306a36Sopenharmony_ci		return;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
105162306a36Sopenharmony_ci		is_dp = true;
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
105662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
105762306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
105862306a36Sopenharmony_ci		break;
105962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
106062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
106162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
106262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
106362306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
106462306a36Sopenharmony_ci		break;
106562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
106662306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
106762306a36Sopenharmony_ci		break;
106862306a36Sopenharmony_ci	}
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
107162306a36Sopenharmony_ci		return;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	switch (frev) {
107462306a36Sopenharmony_ci	case 1:
107562306a36Sopenharmony_ci		switch (crev) {
107662306a36Sopenharmony_ci		case 1:
107762306a36Sopenharmony_ci			args.v1.ucAction = action;
107862306a36Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
107962306a36Sopenharmony_ci				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
108062306a36Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
108162306a36Sopenharmony_ci				args.v1.asMode.ucLaneSel = lane_num;
108262306a36Sopenharmony_ci				args.v1.asMode.ucLaneSet = lane_set;
108362306a36Sopenharmony_ci			} else {
108462306a36Sopenharmony_ci				if (is_dp)
108562306a36Sopenharmony_ci					args.v1.usPixelClock = cpu_to_le16(dp_clock / 10);
108662306a36Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
108762306a36Sopenharmony_ci					args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
108862306a36Sopenharmony_ci				else
108962306a36Sopenharmony_ci					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
109062306a36Sopenharmony_ci			}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci			if (dig_encoder)
109562306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
109662306a36Sopenharmony_ci			else
109762306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci			if ((rdev->flags & RADEON_IS_IGP) &&
110062306a36Sopenharmony_ci			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
110162306a36Sopenharmony_ci				if (is_dp ||
110262306a36Sopenharmony_ci				    !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
110362306a36Sopenharmony_ci					if (igp_lane_info & 0x1)
110462306a36Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
110562306a36Sopenharmony_ci					else if (igp_lane_info & 0x2)
110662306a36Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
110762306a36Sopenharmony_ci					else if (igp_lane_info & 0x4)
110862306a36Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
110962306a36Sopenharmony_ci					else if (igp_lane_info & 0x8)
111062306a36Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
111162306a36Sopenharmony_ci				} else {
111262306a36Sopenharmony_ci					if (igp_lane_info & 0x3)
111362306a36Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
111462306a36Sopenharmony_ci					else if (igp_lane_info & 0xc)
111562306a36Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
111662306a36Sopenharmony_ci				}
111762306a36Sopenharmony_ci			}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci			if (dig->linkb)
112062306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
112162306a36Sopenharmony_ci			else
112262306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci			if (is_dp)
112562306a36Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
112662306a36Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
112762306a36Sopenharmony_ci				if (dig->coherent_mode)
112862306a36Sopenharmony_ci					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
112962306a36Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
113062306a36Sopenharmony_ci					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
113162306a36Sopenharmony_ci			}
113262306a36Sopenharmony_ci			break;
113362306a36Sopenharmony_ci		case 2:
113462306a36Sopenharmony_ci			args.v2.ucAction = action;
113562306a36Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
113662306a36Sopenharmony_ci				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
113762306a36Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
113862306a36Sopenharmony_ci				args.v2.asMode.ucLaneSel = lane_num;
113962306a36Sopenharmony_ci				args.v2.asMode.ucLaneSet = lane_set;
114062306a36Sopenharmony_ci			} else {
114162306a36Sopenharmony_ci				if (is_dp)
114262306a36Sopenharmony_ci					args.v2.usPixelClock = cpu_to_le16(dp_clock / 10);
114362306a36Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
114462306a36Sopenharmony_ci					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
114562306a36Sopenharmony_ci				else
114662306a36Sopenharmony_ci					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
114762306a36Sopenharmony_ci			}
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci			args.v2.acConfig.ucEncoderSel = dig_encoder;
115062306a36Sopenharmony_ci			if (dig->linkb)
115162306a36Sopenharmony_ci				args.v2.acConfig.ucLinkSel = 1;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
115462306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
115562306a36Sopenharmony_ci				args.v2.acConfig.ucTransmitterSel = 0;
115662306a36Sopenharmony_ci				break;
115762306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
115862306a36Sopenharmony_ci				args.v2.acConfig.ucTransmitterSel = 1;
115962306a36Sopenharmony_ci				break;
116062306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
116162306a36Sopenharmony_ci				args.v2.acConfig.ucTransmitterSel = 2;
116262306a36Sopenharmony_ci				break;
116362306a36Sopenharmony_ci			}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci			if (is_dp) {
116662306a36Sopenharmony_ci				args.v2.acConfig.fCoherentMode = 1;
116762306a36Sopenharmony_ci				args.v2.acConfig.fDPConnector = 1;
116862306a36Sopenharmony_ci			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
116962306a36Sopenharmony_ci				if (dig->coherent_mode)
117062306a36Sopenharmony_ci					args.v2.acConfig.fCoherentMode = 1;
117162306a36Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
117262306a36Sopenharmony_ci					args.v2.acConfig.fDualLinkConnector = 1;
117362306a36Sopenharmony_ci			}
117462306a36Sopenharmony_ci			break;
117562306a36Sopenharmony_ci		case 3:
117662306a36Sopenharmony_ci			args.v3.ucAction = action;
117762306a36Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
117862306a36Sopenharmony_ci				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
117962306a36Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
118062306a36Sopenharmony_ci				args.v3.asMode.ucLaneSel = lane_num;
118162306a36Sopenharmony_ci				args.v3.asMode.ucLaneSet = lane_set;
118262306a36Sopenharmony_ci			} else {
118362306a36Sopenharmony_ci				if (is_dp)
118462306a36Sopenharmony_ci					args.v3.usPixelClock = cpu_to_le16(dp_clock / 10);
118562306a36Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
118662306a36Sopenharmony_ci					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
118762306a36Sopenharmony_ci				else
118862306a36Sopenharmony_ci					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
118962306a36Sopenharmony_ci			}
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci			if (is_dp)
119262306a36Sopenharmony_ci				args.v3.ucLaneNum = dp_lane_count;
119362306a36Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
119462306a36Sopenharmony_ci				args.v3.ucLaneNum = 8;
119562306a36Sopenharmony_ci			else
119662306a36Sopenharmony_ci				args.v3.ucLaneNum = 4;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci			if (dig->linkb)
119962306a36Sopenharmony_ci				args.v3.acConfig.ucLinkSel = 1;
120062306a36Sopenharmony_ci			if (dig_encoder & 1)
120162306a36Sopenharmony_ci				args.v3.acConfig.ucEncoderSel = 1;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci			/* Select the PLL for the PHY
120462306a36Sopenharmony_ci			 * DP PHY should be clocked from external src if there is
120562306a36Sopenharmony_ci			 * one.
120662306a36Sopenharmony_ci			 */
120762306a36Sopenharmony_ci			/* On DCE4, if there is an external clock, it generates the DP ref clock */
120862306a36Sopenharmony_ci			if (is_dp && rdev->clock.dp_extclk)
120962306a36Sopenharmony_ci				args.v3.acConfig.ucRefClkSource = 2; /* external src */
121062306a36Sopenharmony_ci			else
121162306a36Sopenharmony_ci				args.v3.acConfig.ucRefClkSource = pll_id;
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
121462306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
121562306a36Sopenharmony_ci				args.v3.acConfig.ucTransmitterSel = 0;
121662306a36Sopenharmony_ci				break;
121762306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
121862306a36Sopenharmony_ci				args.v3.acConfig.ucTransmitterSel = 1;
121962306a36Sopenharmony_ci				break;
122062306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
122162306a36Sopenharmony_ci				args.v3.acConfig.ucTransmitterSel = 2;
122262306a36Sopenharmony_ci				break;
122362306a36Sopenharmony_ci			}
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci			if (is_dp)
122662306a36Sopenharmony_ci				args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
122762306a36Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
122862306a36Sopenharmony_ci				if (dig->coherent_mode)
122962306a36Sopenharmony_ci					args.v3.acConfig.fCoherentMode = 1;
123062306a36Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
123162306a36Sopenharmony_ci					args.v3.acConfig.fDualLinkConnector = 1;
123262306a36Sopenharmony_ci			}
123362306a36Sopenharmony_ci			break;
123462306a36Sopenharmony_ci		case 4:
123562306a36Sopenharmony_ci			args.v4.ucAction = action;
123662306a36Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
123762306a36Sopenharmony_ci				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
123862306a36Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
123962306a36Sopenharmony_ci				args.v4.asMode.ucLaneSel = lane_num;
124062306a36Sopenharmony_ci				args.v4.asMode.ucLaneSet = lane_set;
124162306a36Sopenharmony_ci			} else {
124262306a36Sopenharmony_ci				if (is_dp)
124362306a36Sopenharmony_ci					args.v4.usPixelClock = cpu_to_le16(dp_clock / 10);
124462306a36Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
124562306a36Sopenharmony_ci					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
124662306a36Sopenharmony_ci				else
124762306a36Sopenharmony_ci					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
124862306a36Sopenharmony_ci			}
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci			if (is_dp)
125162306a36Sopenharmony_ci				args.v4.ucLaneNum = dp_lane_count;
125262306a36Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
125362306a36Sopenharmony_ci				args.v4.ucLaneNum = 8;
125462306a36Sopenharmony_ci			else
125562306a36Sopenharmony_ci				args.v4.ucLaneNum = 4;
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci			if (dig->linkb)
125862306a36Sopenharmony_ci				args.v4.acConfig.ucLinkSel = 1;
125962306a36Sopenharmony_ci			if (dig_encoder & 1)
126062306a36Sopenharmony_ci				args.v4.acConfig.ucEncoderSel = 1;
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci			/* Select the PLL for the PHY
126362306a36Sopenharmony_ci			 * DP PHY should be clocked from external src if there is
126462306a36Sopenharmony_ci			 * one.
126562306a36Sopenharmony_ci			 */
126662306a36Sopenharmony_ci			/* On DCE5 DCPLL usually generates the DP ref clock */
126762306a36Sopenharmony_ci			if (is_dp) {
126862306a36Sopenharmony_ci				if (rdev->clock.dp_extclk)
126962306a36Sopenharmony_ci					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
127062306a36Sopenharmony_ci				else
127162306a36Sopenharmony_ci					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
127262306a36Sopenharmony_ci			} else
127362306a36Sopenharmony_ci				args.v4.acConfig.ucRefClkSource = pll_id;
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
127662306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
127762306a36Sopenharmony_ci				args.v4.acConfig.ucTransmitterSel = 0;
127862306a36Sopenharmony_ci				break;
127962306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
128062306a36Sopenharmony_ci				args.v4.acConfig.ucTransmitterSel = 1;
128162306a36Sopenharmony_ci				break;
128262306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
128362306a36Sopenharmony_ci				args.v4.acConfig.ucTransmitterSel = 2;
128462306a36Sopenharmony_ci				break;
128562306a36Sopenharmony_ci			}
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci			if (is_dp)
128862306a36Sopenharmony_ci				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
128962306a36Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
129062306a36Sopenharmony_ci				if (dig->coherent_mode)
129162306a36Sopenharmony_ci					args.v4.acConfig.fCoherentMode = 1;
129262306a36Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
129362306a36Sopenharmony_ci					args.v4.acConfig.fDualLinkConnector = 1;
129462306a36Sopenharmony_ci			}
129562306a36Sopenharmony_ci			break;
129662306a36Sopenharmony_ci		case 5:
129762306a36Sopenharmony_ci			args.v5.ucAction = action;
129862306a36Sopenharmony_ci			if (is_dp)
129962306a36Sopenharmony_ci				args.v5.usSymClock = cpu_to_le16(dp_clock / 10);
130062306a36Sopenharmony_ci			else
130162306a36Sopenharmony_ci				args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
130462306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
130562306a36Sopenharmony_ci				if (dig->linkb)
130662306a36Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
130762306a36Sopenharmony_ci				else
130862306a36Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
130962306a36Sopenharmony_ci				break;
131062306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
131162306a36Sopenharmony_ci				if (dig->linkb)
131262306a36Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
131362306a36Sopenharmony_ci				else
131462306a36Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
131562306a36Sopenharmony_ci				break;
131662306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
131762306a36Sopenharmony_ci				if (dig->linkb)
131862306a36Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
131962306a36Sopenharmony_ci				else
132062306a36Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
132162306a36Sopenharmony_ci				break;
132262306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
132362306a36Sopenharmony_ci				args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG;
132462306a36Sopenharmony_ci				break;
132562306a36Sopenharmony_ci			}
132662306a36Sopenharmony_ci			if (is_dp)
132762306a36Sopenharmony_ci				args.v5.ucLaneNum = dp_lane_count;
132862306a36Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
132962306a36Sopenharmony_ci				args.v5.ucLaneNum = 8;
133062306a36Sopenharmony_ci			else
133162306a36Sopenharmony_ci				args.v5.ucLaneNum = 4;
133262306a36Sopenharmony_ci			args.v5.ucConnObjId = connector_object_id;
133362306a36Sopenharmony_ci			args.v5.ucDigMode = atombios_get_encoder_mode(encoder);
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci			if (is_dp && rdev->clock.dp_extclk)
133662306a36Sopenharmony_ci				args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK;
133762306a36Sopenharmony_ci			else
133862306a36Sopenharmony_ci				args.v5.asConfig.ucPhyClkSrcId = pll_id;
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci			if (is_dp)
134162306a36Sopenharmony_ci				args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */
134262306a36Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
134362306a36Sopenharmony_ci				if (dig->coherent_mode)
134462306a36Sopenharmony_ci					args.v5.asConfig.ucCoherentMode = 1;
134562306a36Sopenharmony_ci			}
134662306a36Sopenharmony_ci			if (hpd_id == RADEON_HPD_NONE)
134762306a36Sopenharmony_ci				args.v5.asConfig.ucHPDSel = 0;
134862306a36Sopenharmony_ci			else
134962306a36Sopenharmony_ci				args.v5.asConfig.ucHPDSel = hpd_id + 1;
135062306a36Sopenharmony_ci			args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder);
135162306a36Sopenharmony_ci			args.v5.ucDPLaneSet = lane_set;
135262306a36Sopenharmony_ci			break;
135362306a36Sopenharmony_ci		default:
135462306a36Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
135562306a36Sopenharmony_ci			break;
135662306a36Sopenharmony_ci		}
135762306a36Sopenharmony_ci		break;
135862306a36Sopenharmony_ci	default:
135962306a36Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
136062306a36Sopenharmony_ci		break;
136162306a36Sopenharmony_ci	}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
136462306a36Sopenharmony_ci}
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_civoid
136762306a36Sopenharmony_ciatombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
136862306a36Sopenharmony_ci{
136962306a36Sopenharmony_ci	atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1);
137062306a36Sopenharmony_ci}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_cibool
137362306a36Sopenharmony_ciatombios_set_edp_panel_power(struct drm_connector *connector, int action)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
137662306a36Sopenharmony_ci	struct drm_device *dev = radeon_connector->base.dev;
137762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
137862306a36Sopenharmony_ci	union dig_transmitter_control args;
137962306a36Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
138062306a36Sopenharmony_ci	uint8_t frev, crev;
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
138362306a36Sopenharmony_ci		goto done;
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	if (!ASIC_IS_DCE4(rdev))
138662306a36Sopenharmony_ci		goto done;
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
138962306a36Sopenharmony_ci	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
139062306a36Sopenharmony_ci		goto done;
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
139362306a36Sopenharmony_ci		goto done;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	args.v1.ucAction = action;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci	/* wait for the panel to power up */
140262306a36Sopenharmony_ci	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
140362306a36Sopenharmony_ci		int i;
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci		for (i = 0; i < 300; i++) {
140662306a36Sopenharmony_ci			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
140762306a36Sopenharmony_ci				return true;
140862306a36Sopenharmony_ci			mdelay(1);
140962306a36Sopenharmony_ci		}
141062306a36Sopenharmony_ci		return false;
141162306a36Sopenharmony_ci	}
141262306a36Sopenharmony_cidone:
141362306a36Sopenharmony_ci	return true;
141462306a36Sopenharmony_ci}
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ciunion external_encoder_control {
141762306a36Sopenharmony_ci	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
141862306a36Sopenharmony_ci	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
141962306a36Sopenharmony_ci};
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_cistatic void
142262306a36Sopenharmony_ciatombios_external_encoder_setup(struct drm_encoder *encoder,
142362306a36Sopenharmony_ci				struct drm_encoder *ext_encoder,
142462306a36Sopenharmony_ci				int action)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
142762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
142862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
142962306a36Sopenharmony_ci	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
143062306a36Sopenharmony_ci	union external_encoder_control args;
143162306a36Sopenharmony_ci	struct drm_connector *connector;
143262306a36Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
143362306a36Sopenharmony_ci	u8 frev, crev;
143462306a36Sopenharmony_ci	int dp_clock = 0;
143562306a36Sopenharmony_ci	int dp_lane_count = 0;
143662306a36Sopenharmony_ci	int connector_object_id = 0;
143762306a36Sopenharmony_ci	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
144062306a36Sopenharmony_ci		connector = radeon_get_connector_for_encoder_init(encoder);
144162306a36Sopenharmony_ci	else
144262306a36Sopenharmony_ci		connector = radeon_get_connector_for_encoder(encoder);
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	if (connector) {
144562306a36Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
144662306a36Sopenharmony_ci		struct radeon_connector_atom_dig *dig_connector =
144762306a36Sopenharmony_ci			radeon_connector->con_priv;
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci		dp_clock = dig_connector->dp_clock;
145062306a36Sopenharmony_ci		dp_lane_count = dig_connector->dp_lane_count;
145162306a36Sopenharmony_ci		connector_object_id =
145262306a36Sopenharmony_ci			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
145362306a36Sopenharmony_ci	}
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
145862306a36Sopenharmony_ci		return;
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	switch (frev) {
146162306a36Sopenharmony_ci	case 1:
146262306a36Sopenharmony_ci		/* no params on frev 1 */
146362306a36Sopenharmony_ci		break;
146462306a36Sopenharmony_ci	case 2:
146562306a36Sopenharmony_ci		switch (crev) {
146662306a36Sopenharmony_ci		case 1:
146762306a36Sopenharmony_ci		case 2:
146862306a36Sopenharmony_ci			args.v1.sDigEncoder.ucAction = action;
146962306a36Sopenharmony_ci			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
147062306a36Sopenharmony_ci			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
147362306a36Sopenharmony_ci				if (dp_clock == 270000)
147462306a36Sopenharmony_ci					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
147562306a36Sopenharmony_ci				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
147662306a36Sopenharmony_ci			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
147762306a36Sopenharmony_ci				args.v1.sDigEncoder.ucLaneNum = 8;
147862306a36Sopenharmony_ci			else
147962306a36Sopenharmony_ci				args.v1.sDigEncoder.ucLaneNum = 4;
148062306a36Sopenharmony_ci			break;
148162306a36Sopenharmony_ci		case 3:
148262306a36Sopenharmony_ci			args.v3.sExtEncoder.ucAction = action;
148362306a36Sopenharmony_ci			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
148462306a36Sopenharmony_ci				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
148562306a36Sopenharmony_ci			else
148662306a36Sopenharmony_ci				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
148762306a36Sopenharmony_ci			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
148862306a36Sopenharmony_ci
148962306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
149062306a36Sopenharmony_ci				if (dp_clock == 270000)
149162306a36Sopenharmony_ci					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
149262306a36Sopenharmony_ci				else if (dp_clock == 540000)
149362306a36Sopenharmony_ci					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
149462306a36Sopenharmony_ci				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
149562306a36Sopenharmony_ci			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
149662306a36Sopenharmony_ci				args.v3.sExtEncoder.ucLaneNum = 8;
149762306a36Sopenharmony_ci			else
149862306a36Sopenharmony_ci				args.v3.sExtEncoder.ucLaneNum = 4;
149962306a36Sopenharmony_ci			switch (ext_enum) {
150062306a36Sopenharmony_ci			case GRAPH_OBJECT_ENUM_ID1:
150162306a36Sopenharmony_ci				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
150262306a36Sopenharmony_ci				break;
150362306a36Sopenharmony_ci			case GRAPH_OBJECT_ENUM_ID2:
150462306a36Sopenharmony_ci				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
150562306a36Sopenharmony_ci				break;
150662306a36Sopenharmony_ci			case GRAPH_OBJECT_ENUM_ID3:
150762306a36Sopenharmony_ci				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
150862306a36Sopenharmony_ci				break;
150962306a36Sopenharmony_ci			}
151062306a36Sopenharmony_ci			args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder);
151162306a36Sopenharmony_ci			break;
151262306a36Sopenharmony_ci		default:
151362306a36Sopenharmony_ci			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
151462306a36Sopenharmony_ci			return;
151562306a36Sopenharmony_ci		}
151662306a36Sopenharmony_ci		break;
151762306a36Sopenharmony_ci	default:
151862306a36Sopenharmony_ci		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
151962306a36Sopenharmony_ci		return;
152062306a36Sopenharmony_ci	}
152162306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
152262306a36Sopenharmony_ci}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_cistatic void
152562306a36Sopenharmony_ciatombios_yuv_setup(struct drm_encoder *encoder, bool enable)
152662306a36Sopenharmony_ci{
152762306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
152862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
152962306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
153062306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
153162306a36Sopenharmony_ci	ENABLE_YUV_PS_ALLOCATION args;
153262306a36Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
153362306a36Sopenharmony_ci	uint32_t temp, reg;
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	if (rdev->family >= CHIP_R600)
153862306a36Sopenharmony_ci		reg = R600_BIOS_3_SCRATCH;
153962306a36Sopenharmony_ci	else
154062306a36Sopenharmony_ci		reg = RADEON_BIOS_3_SCRATCH;
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	/* XXX: fix up scratch reg handling */
154362306a36Sopenharmony_ci	temp = RREG32(reg);
154462306a36Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
154562306a36Sopenharmony_ci		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
154662306a36Sopenharmony_ci			     (radeon_crtc->crtc_id << 18)));
154762306a36Sopenharmony_ci	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
154862306a36Sopenharmony_ci		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
154962306a36Sopenharmony_ci	else
155062306a36Sopenharmony_ci		WREG32(reg, 0);
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci	if (enable)
155362306a36Sopenharmony_ci		args.ucEnable = ATOM_ENABLE;
155462306a36Sopenharmony_ci	args.ucCRTC = radeon_crtc->crtc_id;
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	WREG32(reg, temp);
155962306a36Sopenharmony_ci}
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_cistatic void
156262306a36Sopenharmony_ciradeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
156362306a36Sopenharmony_ci{
156462306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
156562306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
156662306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
156762306a36Sopenharmony_ci	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
156862306a36Sopenharmony_ci	int index = 0;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
157362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
157462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
157562306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
157662306a36Sopenharmony_ci		break;
157762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
157862306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
157962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
158062306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
158162306a36Sopenharmony_ci		break;
158262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
158362306a36Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
158462306a36Sopenharmony_ci		break;
158562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
158662306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
158762306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
158862306a36Sopenharmony_ci		else
158962306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
159062306a36Sopenharmony_ci		break;
159162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
159262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
159362306a36Sopenharmony_ci		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
159462306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
159562306a36Sopenharmony_ci		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
159662306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
159762306a36Sopenharmony_ci		else
159862306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
159962306a36Sopenharmony_ci		break;
160062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
160162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
160262306a36Sopenharmony_ci		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
160362306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
160462306a36Sopenharmony_ci		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
160562306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
160662306a36Sopenharmony_ci		else
160762306a36Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
160862306a36Sopenharmony_ci		break;
160962306a36Sopenharmony_ci	default:
161062306a36Sopenharmony_ci		return;
161162306a36Sopenharmony_ci	}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	switch (mode) {
161462306a36Sopenharmony_ci	case DRM_MODE_DPMS_ON:
161562306a36Sopenharmony_ci		args.ucAction = ATOM_ENABLE;
161662306a36Sopenharmony_ci		/* workaround for DVOOutputControl on some RS690 systems */
161762306a36Sopenharmony_ci		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
161862306a36Sopenharmony_ci			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
161962306a36Sopenharmony_ci			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
162062306a36Sopenharmony_ci			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
162162306a36Sopenharmony_ci			WREG32(RADEON_BIOS_3_SCRATCH, reg);
162262306a36Sopenharmony_ci		} else
162362306a36Sopenharmony_ci			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
162462306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
162562306a36Sopenharmony_ci			if (rdev->mode_info.bl_encoder) {
162662306a36Sopenharmony_ci				struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci				atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
162962306a36Sopenharmony_ci			} else {
163062306a36Sopenharmony_ci				args.ucAction = ATOM_LCD_BLON;
163162306a36Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
163262306a36Sopenharmony_ci			}
163362306a36Sopenharmony_ci		}
163462306a36Sopenharmony_ci		break;
163562306a36Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
163662306a36Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
163762306a36Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
163862306a36Sopenharmony_ci		args.ucAction = ATOM_DISABLE;
163962306a36Sopenharmony_ci		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
164062306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
164162306a36Sopenharmony_ci			args.ucAction = ATOM_LCD_BLOFF;
164262306a36Sopenharmony_ci			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
164362306a36Sopenharmony_ci		}
164462306a36Sopenharmony_ci		break;
164562306a36Sopenharmony_ci	}
164662306a36Sopenharmony_ci}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_cistatic void
164962306a36Sopenharmony_ciradeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
165062306a36Sopenharmony_ci{
165162306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
165262306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
165362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
165462306a36Sopenharmony_ci	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
165562306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
165662306a36Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
165762306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = NULL;
165862306a36Sopenharmony_ci	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
165962306a36Sopenharmony_ci	bool travis_quirk = false;
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	if (connector) {
166262306a36Sopenharmony_ci		radeon_connector = to_radeon_connector(connector);
166362306a36Sopenharmony_ci		radeon_dig_connector = radeon_connector->con_priv;
166462306a36Sopenharmony_ci		if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
166562306a36Sopenharmony_ci		     ENCODER_OBJECT_ID_TRAVIS) &&
166662306a36Sopenharmony_ci		    (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
166762306a36Sopenharmony_ci		    !ASIC_IS_DCE5(rdev))
166862306a36Sopenharmony_ci			travis_quirk = true;
166962306a36Sopenharmony_ci	}
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	switch (mode) {
167262306a36Sopenharmony_ci	case DRM_MODE_DPMS_ON:
167362306a36Sopenharmony_ci		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
167462306a36Sopenharmony_ci			if (!connector)
167562306a36Sopenharmony_ci				dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
167662306a36Sopenharmony_ci			else
167762306a36Sopenharmony_ci				dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci			/* setup and enable the encoder */
168062306a36Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
168162306a36Sopenharmony_ci			atombios_dig_encoder_setup(encoder,
168262306a36Sopenharmony_ci						   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
168362306a36Sopenharmony_ci						   dig->panel_mode);
168462306a36Sopenharmony_ci			if (ext_encoder) {
168562306a36Sopenharmony_ci				if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
168662306a36Sopenharmony_ci					atombios_external_encoder_setup(encoder, ext_encoder,
168762306a36Sopenharmony_ci									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
168862306a36Sopenharmony_ci			}
168962306a36Sopenharmony_ci		} else if (ASIC_IS_DCE4(rdev)) {
169062306a36Sopenharmony_ci			/* setup and enable the encoder */
169162306a36Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
169262306a36Sopenharmony_ci		} else {
169362306a36Sopenharmony_ci			/* setup and enable the encoder and transmitter */
169462306a36Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
169562306a36Sopenharmony_ci			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
169662306a36Sopenharmony_ci		}
169762306a36Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
169862306a36Sopenharmony_ci			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
169962306a36Sopenharmony_ci				atombios_set_edp_panel_power(connector,
170062306a36Sopenharmony_ci							     ATOM_TRANSMITTER_ACTION_POWER_ON);
170162306a36Sopenharmony_ci				radeon_dig_connector->edp_on = true;
170262306a36Sopenharmony_ci			}
170362306a36Sopenharmony_ci		}
170462306a36Sopenharmony_ci		/* enable the transmitter */
170562306a36Sopenharmony_ci		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
170662306a36Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
170762306a36Sopenharmony_ci			/* DP_SET_POWER_D0 is set in radeon_dp_link_train */
170862306a36Sopenharmony_ci			radeon_dp_link_train(encoder, connector);
170962306a36Sopenharmony_ci			if (ASIC_IS_DCE4(rdev))
171062306a36Sopenharmony_ci				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
171162306a36Sopenharmony_ci		}
171262306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
171362306a36Sopenharmony_ci			if (rdev->mode_info.bl_encoder)
171462306a36Sopenharmony_ci				atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
171562306a36Sopenharmony_ci			else
171662306a36Sopenharmony_ci				atombios_dig_transmitter_setup(encoder,
171762306a36Sopenharmony_ci							       ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
171862306a36Sopenharmony_ci		}
171962306a36Sopenharmony_ci		if (ext_encoder)
172062306a36Sopenharmony_ci			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
172162306a36Sopenharmony_ci		break;
172262306a36Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
172362306a36Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
172462306a36Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci		if (ASIC_IS_DCE4(rdev)) {
172762306a36Sopenharmony_ci			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
172862306a36Sopenharmony_ci				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
172962306a36Sopenharmony_ci		}
173062306a36Sopenharmony_ci		if (ext_encoder)
173162306a36Sopenharmony_ci			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
173262306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
173362306a36Sopenharmony_ci			atombios_dig_transmitter_setup(encoder,
173462306a36Sopenharmony_ci						       ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
173762306a36Sopenharmony_ci		    connector && !travis_quirk)
173862306a36Sopenharmony_ci			radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
173962306a36Sopenharmony_ci		if (ASIC_IS_DCE4(rdev)) {
174062306a36Sopenharmony_ci			/* disable the transmitter */
174162306a36Sopenharmony_ci			atombios_dig_transmitter_setup(encoder,
174262306a36Sopenharmony_ci						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
174362306a36Sopenharmony_ci		} else {
174462306a36Sopenharmony_ci			/* disable the encoder and transmitter */
174562306a36Sopenharmony_ci			atombios_dig_transmitter_setup(encoder,
174662306a36Sopenharmony_ci						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
174762306a36Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
174862306a36Sopenharmony_ci		}
174962306a36Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
175062306a36Sopenharmony_ci			if (travis_quirk)
175162306a36Sopenharmony_ci				radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
175262306a36Sopenharmony_ci			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
175362306a36Sopenharmony_ci				atombios_set_edp_panel_power(connector,
175462306a36Sopenharmony_ci							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
175562306a36Sopenharmony_ci				radeon_dig_connector->edp_on = false;
175662306a36Sopenharmony_ci			}
175762306a36Sopenharmony_ci		}
175862306a36Sopenharmony_ci		break;
175962306a36Sopenharmony_ci	}
176062306a36Sopenharmony_ci}
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_cistatic void
176362306a36Sopenharmony_ciradeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
176462306a36Sopenharmony_ci{
176562306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
176662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
176762306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
176862306a36Sopenharmony_ci	int encoder_mode = atombios_get_encoder_mode(encoder);
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
177162306a36Sopenharmony_ci		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
177262306a36Sopenharmony_ci		  radeon_encoder->active_device);
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	if ((radeon_audio != 0) &&
177562306a36Sopenharmony_ci	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
177662306a36Sopenharmony_ci	     ENCODER_MODE_IS_DP(encoder_mode)))
177762306a36Sopenharmony_ci		radeon_audio_dpms(encoder, mode);
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
178062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
178162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
178262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
178362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
178462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
178562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
178662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
178762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
178862306a36Sopenharmony_ci		radeon_atom_encoder_dpms_avivo(encoder, mode);
178962306a36Sopenharmony_ci		break;
179062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
179162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
179262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
179362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
179462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
179562306a36Sopenharmony_ci		radeon_atom_encoder_dpms_dig(encoder, mode);
179662306a36Sopenharmony_ci		break;
179762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
179862306a36Sopenharmony_ci		if (ASIC_IS_DCE5(rdev)) {
179962306a36Sopenharmony_ci			switch (mode) {
180062306a36Sopenharmony_ci			case DRM_MODE_DPMS_ON:
180162306a36Sopenharmony_ci				atombios_dvo_setup(encoder, ATOM_ENABLE);
180262306a36Sopenharmony_ci				break;
180362306a36Sopenharmony_ci			case DRM_MODE_DPMS_STANDBY:
180462306a36Sopenharmony_ci			case DRM_MODE_DPMS_SUSPEND:
180562306a36Sopenharmony_ci			case DRM_MODE_DPMS_OFF:
180662306a36Sopenharmony_ci				atombios_dvo_setup(encoder, ATOM_DISABLE);
180762306a36Sopenharmony_ci				break;
180862306a36Sopenharmony_ci			}
180962306a36Sopenharmony_ci		} else if (ASIC_IS_DCE3(rdev))
181062306a36Sopenharmony_ci			radeon_atom_encoder_dpms_dig(encoder, mode);
181162306a36Sopenharmony_ci		else
181262306a36Sopenharmony_ci			radeon_atom_encoder_dpms_avivo(encoder, mode);
181362306a36Sopenharmony_ci		break;
181462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
181562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
181662306a36Sopenharmony_ci		if (ASIC_IS_DCE5(rdev)) {
181762306a36Sopenharmony_ci			switch (mode) {
181862306a36Sopenharmony_ci			case DRM_MODE_DPMS_ON:
181962306a36Sopenharmony_ci				atombios_dac_setup(encoder, ATOM_ENABLE);
182062306a36Sopenharmony_ci				break;
182162306a36Sopenharmony_ci			case DRM_MODE_DPMS_STANDBY:
182262306a36Sopenharmony_ci			case DRM_MODE_DPMS_SUSPEND:
182362306a36Sopenharmony_ci			case DRM_MODE_DPMS_OFF:
182462306a36Sopenharmony_ci				atombios_dac_setup(encoder, ATOM_DISABLE);
182562306a36Sopenharmony_ci				break;
182662306a36Sopenharmony_ci			}
182762306a36Sopenharmony_ci		} else
182862306a36Sopenharmony_ci			radeon_atom_encoder_dpms_avivo(encoder, mode);
182962306a36Sopenharmony_ci		break;
183062306a36Sopenharmony_ci	default:
183162306a36Sopenharmony_ci		return;
183262306a36Sopenharmony_ci	}
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci}
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ciunion crtc_source_param {
183962306a36Sopenharmony_ci	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
184062306a36Sopenharmony_ci	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
184162306a36Sopenharmony_ci};
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_cistatic void
184462306a36Sopenharmony_ciatombios_set_encoder_crtc_source(struct drm_encoder *encoder)
184562306a36Sopenharmony_ci{
184662306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
184762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
184862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
184962306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
185062306a36Sopenharmony_ci	union crtc_source_param args;
185162306a36Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
185262306a36Sopenharmony_ci	uint8_t frev, crev;
185362306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	memset(&args, 0, sizeof(args));
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
185862306a36Sopenharmony_ci		return;
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci	switch (frev) {
186162306a36Sopenharmony_ci	case 1:
186262306a36Sopenharmony_ci		switch (crev) {
186362306a36Sopenharmony_ci		case 1:
186462306a36Sopenharmony_ci		default:
186562306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev))
186662306a36Sopenharmony_ci				args.v1.ucCRTC = radeon_crtc->crtc_id;
186762306a36Sopenharmony_ci			else {
186862306a36Sopenharmony_ci				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)
186962306a36Sopenharmony_ci					args.v1.ucCRTC = radeon_crtc->crtc_id;
187062306a36Sopenharmony_ci				else
187162306a36Sopenharmony_ci					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
187262306a36Sopenharmony_ci			}
187362306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
187462306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
187562306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
187662306a36Sopenharmony_ci				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
187762306a36Sopenharmony_ci				break;
187862306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
187962306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
188062306a36Sopenharmony_ci				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
188162306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
188262306a36Sopenharmony_ci				else
188362306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
188462306a36Sopenharmony_ci				break;
188562306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
188662306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DDI:
188762306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
188862306a36Sopenharmony_ci				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
188962306a36Sopenharmony_ci				break;
189062306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
189162306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
189262306a36Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
189362306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
189462306a36Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
189562306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
189662306a36Sopenharmony_ci				else
189762306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
189862306a36Sopenharmony_ci				break;
189962306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
190062306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
190162306a36Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
190262306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
190362306a36Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
190462306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
190562306a36Sopenharmony_ci				else
190662306a36Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
190762306a36Sopenharmony_ci				break;
190862306a36Sopenharmony_ci			}
190962306a36Sopenharmony_ci			break;
191062306a36Sopenharmony_ci		case 2:
191162306a36Sopenharmony_ci			args.v2.ucCRTC = radeon_crtc->crtc_id;
191262306a36Sopenharmony_ci			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
191362306a36Sopenharmony_ci				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ci				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
191662306a36Sopenharmony_ci					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
191762306a36Sopenharmony_ci				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
191862306a36Sopenharmony_ci					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
191962306a36Sopenharmony_ci				else
192062306a36Sopenharmony_ci					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
192162306a36Sopenharmony_ci			} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
192262306a36Sopenharmony_ci				args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
192362306a36Sopenharmony_ci			} else {
192462306a36Sopenharmony_ci				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
192562306a36Sopenharmony_ci			}
192662306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
192762306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
192862306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
192962306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
193062306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
193162306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
193262306a36Sopenharmony_ci				dig = radeon_encoder->enc_priv;
193362306a36Sopenharmony_ci				switch (dig->dig_encoder) {
193462306a36Sopenharmony_ci				case 0:
193562306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
193662306a36Sopenharmony_ci					break;
193762306a36Sopenharmony_ci				case 1:
193862306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
193962306a36Sopenharmony_ci					break;
194062306a36Sopenharmony_ci				case 2:
194162306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
194262306a36Sopenharmony_ci					break;
194362306a36Sopenharmony_ci				case 3:
194462306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
194562306a36Sopenharmony_ci					break;
194662306a36Sopenharmony_ci				case 4:
194762306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
194862306a36Sopenharmony_ci					break;
194962306a36Sopenharmony_ci				case 5:
195062306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
195162306a36Sopenharmony_ci					break;
195262306a36Sopenharmony_ci				case 6:
195362306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
195462306a36Sopenharmony_ci					break;
195562306a36Sopenharmony_ci				}
195662306a36Sopenharmony_ci				break;
195762306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
195862306a36Sopenharmony_ci				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
195962306a36Sopenharmony_ci				break;
196062306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
196162306a36Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
196262306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
196362306a36Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
196462306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
196562306a36Sopenharmony_ci				else
196662306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
196762306a36Sopenharmony_ci				break;
196862306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
196962306a36Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
197062306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
197162306a36Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
197262306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
197362306a36Sopenharmony_ci				else
197462306a36Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
197562306a36Sopenharmony_ci				break;
197662306a36Sopenharmony_ci			}
197762306a36Sopenharmony_ci			break;
197862306a36Sopenharmony_ci		}
197962306a36Sopenharmony_ci		break;
198062306a36Sopenharmony_ci	default:
198162306a36Sopenharmony_ci		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
198262306a36Sopenharmony_ci		return;
198362306a36Sopenharmony_ci	}
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci	/* update scratch regs with new routing */
198862306a36Sopenharmony_ci	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
198962306a36Sopenharmony_ci}
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_cistatic void
199262306a36Sopenharmony_ciatombios_apply_encoder_quirks(struct drm_encoder *encoder,
199362306a36Sopenharmony_ci			      struct drm_display_mode *mode)
199462306a36Sopenharmony_ci{
199562306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
199662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
199762306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
199862306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci	/* Funky macbooks */
200162306a36Sopenharmony_ci	if ((rdev->pdev->device == 0x71C5) &&
200262306a36Sopenharmony_ci	    (rdev->pdev->subsystem_vendor == 0x106b) &&
200362306a36Sopenharmony_ci	    (rdev->pdev->subsystem_device == 0x0080)) {
200462306a36Sopenharmony_ci		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
200562306a36Sopenharmony_ci			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
200862306a36Sopenharmony_ci			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_ci			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
201162306a36Sopenharmony_ci		}
201262306a36Sopenharmony_ci	}
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci	/* set scaler clears this on some chips */
201562306a36Sopenharmony_ci	if (ASIC_IS_AVIVO(rdev) &&
201662306a36Sopenharmony_ci	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
201762306a36Sopenharmony_ci		if (ASIC_IS_DCE8(rdev)) {
201862306a36Sopenharmony_ci			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
201962306a36Sopenharmony_ci				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset,
202062306a36Sopenharmony_ci				       CIK_INTERLEAVE_EN);
202162306a36Sopenharmony_ci			else
202262306a36Sopenharmony_ci				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
202362306a36Sopenharmony_ci		} else if (ASIC_IS_DCE4(rdev)) {
202462306a36Sopenharmony_ci			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
202562306a36Sopenharmony_ci				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
202662306a36Sopenharmony_ci				       EVERGREEN_INTERLEAVE_EN);
202762306a36Sopenharmony_ci			else
202862306a36Sopenharmony_ci				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
202962306a36Sopenharmony_ci		} else {
203062306a36Sopenharmony_ci			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
203162306a36Sopenharmony_ci				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
203262306a36Sopenharmony_ci				       AVIVO_D1MODE_INTERLEAVE_EN);
203362306a36Sopenharmony_ci			else
203462306a36Sopenharmony_ci				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
203562306a36Sopenharmony_ci		}
203662306a36Sopenharmony_ci	}
203762306a36Sopenharmony_ci}
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_civoid radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx)
204062306a36Sopenharmony_ci{
204162306a36Sopenharmony_ci	if (enc_idx < 0)
204262306a36Sopenharmony_ci		return;
204362306a36Sopenharmony_ci	rdev->mode_info.active_encoders &= ~(1 << enc_idx);
204462306a36Sopenharmony_ci}
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_ciint radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
204762306a36Sopenharmony_ci{
204862306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
204962306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
205062306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
205162306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
205262306a36Sopenharmony_ci	struct drm_encoder *test_encoder;
205362306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
205462306a36Sopenharmony_ci	uint32_t dig_enc_in_use = 0;
205562306a36Sopenharmony_ci	int enc_idx = -1;
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	if (fe_idx >= 0) {
205862306a36Sopenharmony_ci		enc_idx = fe_idx;
205962306a36Sopenharmony_ci		goto assigned;
206062306a36Sopenharmony_ci	}
206162306a36Sopenharmony_ci	if (ASIC_IS_DCE6(rdev)) {
206262306a36Sopenharmony_ci		/* DCE6 */
206362306a36Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
206462306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
206562306a36Sopenharmony_ci			if (dig->linkb)
206662306a36Sopenharmony_ci				enc_idx = 1;
206762306a36Sopenharmony_ci			else
206862306a36Sopenharmony_ci				enc_idx = 0;
206962306a36Sopenharmony_ci			break;
207062306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
207162306a36Sopenharmony_ci			if (dig->linkb)
207262306a36Sopenharmony_ci				enc_idx = 3;
207362306a36Sopenharmony_ci			else
207462306a36Sopenharmony_ci				enc_idx = 2;
207562306a36Sopenharmony_ci			break;
207662306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
207762306a36Sopenharmony_ci			if (dig->linkb)
207862306a36Sopenharmony_ci				enc_idx = 5;
207962306a36Sopenharmony_ci			else
208062306a36Sopenharmony_ci				enc_idx = 4;
208162306a36Sopenharmony_ci			break;
208262306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
208362306a36Sopenharmony_ci			enc_idx = 6;
208462306a36Sopenharmony_ci			break;
208562306a36Sopenharmony_ci		}
208662306a36Sopenharmony_ci		goto assigned;
208762306a36Sopenharmony_ci	} else if (ASIC_IS_DCE4(rdev)) {
208862306a36Sopenharmony_ci		/* DCE4/5 */
208962306a36Sopenharmony_ci		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
209062306a36Sopenharmony_ci			/* ontario follows DCE4 */
209162306a36Sopenharmony_ci			if (rdev->family == CHIP_PALM) {
209262306a36Sopenharmony_ci				if (dig->linkb)
209362306a36Sopenharmony_ci					enc_idx = 1;
209462306a36Sopenharmony_ci				else
209562306a36Sopenharmony_ci					enc_idx = 0;
209662306a36Sopenharmony_ci			} else
209762306a36Sopenharmony_ci				/* llano follows DCE3.2 */
209862306a36Sopenharmony_ci				enc_idx = radeon_crtc->crtc_id;
209962306a36Sopenharmony_ci		} else {
210062306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
210162306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
210262306a36Sopenharmony_ci				if (dig->linkb)
210362306a36Sopenharmony_ci					enc_idx = 1;
210462306a36Sopenharmony_ci				else
210562306a36Sopenharmony_ci					enc_idx = 0;
210662306a36Sopenharmony_ci				break;
210762306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
210862306a36Sopenharmony_ci				if (dig->linkb)
210962306a36Sopenharmony_ci					enc_idx = 3;
211062306a36Sopenharmony_ci				else
211162306a36Sopenharmony_ci					enc_idx = 2;
211262306a36Sopenharmony_ci				break;
211362306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
211462306a36Sopenharmony_ci				if (dig->linkb)
211562306a36Sopenharmony_ci					enc_idx = 5;
211662306a36Sopenharmony_ci				else
211762306a36Sopenharmony_ci					enc_idx = 4;
211862306a36Sopenharmony_ci				break;
211962306a36Sopenharmony_ci			}
212062306a36Sopenharmony_ci		}
212162306a36Sopenharmony_ci		goto assigned;
212262306a36Sopenharmony_ci	}
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ci	/*
212562306a36Sopenharmony_ci	 * On DCE32 any encoder can drive any block so usually just use crtc id,
212662306a36Sopenharmony_ci	 * but Apple thinks different at least on iMac10,1 and iMac11,2, so there use linkb,
212762306a36Sopenharmony_ci	 * otherwise the internal eDP panel will stay dark.
212862306a36Sopenharmony_ci	 */
212962306a36Sopenharmony_ci	if (ASIC_IS_DCE32(rdev)) {
213062306a36Sopenharmony_ci		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
213162306a36Sopenharmony_ci		    dmi_match(DMI_PRODUCT_NAME, "iMac11,2"))
213262306a36Sopenharmony_ci			enc_idx = (dig->linkb) ? 1 : 0;
213362306a36Sopenharmony_ci		else
213462306a36Sopenharmony_ci			enc_idx = radeon_crtc->crtc_id;
213562306a36Sopenharmony_ci
213662306a36Sopenharmony_ci		goto assigned;
213762306a36Sopenharmony_ci	}
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci	/* on DCE3 - LVTMA can only be driven by DIGB */
214062306a36Sopenharmony_ci	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
214162306a36Sopenharmony_ci		struct radeon_encoder *radeon_test_encoder;
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_ci		if (encoder == test_encoder)
214462306a36Sopenharmony_ci			continue;
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci		if (!radeon_encoder_is_digital(test_encoder))
214762306a36Sopenharmony_ci			continue;
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci		radeon_test_encoder = to_radeon_encoder(test_encoder);
215062306a36Sopenharmony_ci		dig = radeon_test_encoder->enc_priv;
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci		if (dig->dig_encoder >= 0)
215362306a36Sopenharmony_ci			dig_enc_in_use |= (1 << dig->dig_encoder);
215462306a36Sopenharmony_ci	}
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
215762306a36Sopenharmony_ci		if (dig_enc_in_use & 0x2)
215862306a36Sopenharmony_ci			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
215962306a36Sopenharmony_ci		return 1;
216062306a36Sopenharmony_ci	}
216162306a36Sopenharmony_ci	if (!(dig_enc_in_use & 1))
216262306a36Sopenharmony_ci		return 0;
216362306a36Sopenharmony_ci	return 1;
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ciassigned:
216662306a36Sopenharmony_ci	if (enc_idx == -1) {
216762306a36Sopenharmony_ci		DRM_ERROR("Got encoder index incorrect - returning 0\n");
216862306a36Sopenharmony_ci		return 0;
216962306a36Sopenharmony_ci	}
217062306a36Sopenharmony_ci	if (rdev->mode_info.active_encoders & (1 << enc_idx))
217162306a36Sopenharmony_ci		DRM_ERROR("chosen encoder in use %d\n", enc_idx);
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci	rdev->mode_info.active_encoders |= (1 << enc_idx);
217462306a36Sopenharmony_ci	return enc_idx;
217562306a36Sopenharmony_ci}
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci/* This only needs to be called once at startup */
217862306a36Sopenharmony_civoid
217962306a36Sopenharmony_ciradeon_atom_encoder_init(struct radeon_device *rdev)
218062306a36Sopenharmony_ci{
218162306a36Sopenharmony_ci	struct drm_device *dev = rdev->ddev;
218262306a36Sopenharmony_ci	struct drm_encoder *encoder;
218362306a36Sopenharmony_ci
218462306a36Sopenharmony_ci	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
218562306a36Sopenharmony_ci		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
218662306a36Sopenharmony_ci		struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
218962306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
219062306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
219162306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
219262306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
219362306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
219462306a36Sopenharmony_ci			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
219562306a36Sopenharmony_ci			break;
219662306a36Sopenharmony_ci		default:
219762306a36Sopenharmony_ci			break;
219862306a36Sopenharmony_ci		}
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci		if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)))
220162306a36Sopenharmony_ci			atombios_external_encoder_setup(encoder, ext_encoder,
220262306a36Sopenharmony_ci							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
220362306a36Sopenharmony_ci	}
220462306a36Sopenharmony_ci}
220562306a36Sopenharmony_ci
220662306a36Sopenharmony_cistatic void
220762306a36Sopenharmony_ciradeon_atom_encoder_mode_set(struct drm_encoder *encoder,
220862306a36Sopenharmony_ci			     struct drm_display_mode *mode,
220962306a36Sopenharmony_ci			     struct drm_display_mode *adjusted_mode)
221062306a36Sopenharmony_ci{
221162306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
221262306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
221362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
221462306a36Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
221562306a36Sopenharmony_ci	int encoder_mode;
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci	radeon_encoder->pixel_clock = adjusted_mode->clock;
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_ci	/* need to call this here rather than in prepare() since we need some crtc info */
222062306a36Sopenharmony_ci	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
222362306a36Sopenharmony_ci		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
222462306a36Sopenharmony_ci			atombios_yuv_setup(encoder, true);
222562306a36Sopenharmony_ci		else
222662306a36Sopenharmony_ci			atombios_yuv_setup(encoder, false);
222762306a36Sopenharmony_ci	}
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
223062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
223162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
223262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
223362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
223462306a36Sopenharmony_ci		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
223562306a36Sopenharmony_ci		break;
223662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
223762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
223862306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
223962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
224062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
224162306a36Sopenharmony_ci		/* handled in dpms */
224262306a36Sopenharmony_ci		break;
224362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
224462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
224562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
224662306a36Sopenharmony_ci		atombios_dvo_setup(encoder, ATOM_ENABLE);
224762306a36Sopenharmony_ci		break;
224862306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
224962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
225062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
225162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
225262306a36Sopenharmony_ci		atombios_dac_setup(encoder, ATOM_ENABLE);
225362306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
225462306a36Sopenharmony_ci			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
225562306a36Sopenharmony_ci				atombios_tv_setup(encoder, ATOM_ENABLE);
225662306a36Sopenharmony_ci			else
225762306a36Sopenharmony_ci				atombios_tv_setup(encoder, ATOM_DISABLE);
225862306a36Sopenharmony_ci		}
225962306a36Sopenharmony_ci		break;
226062306a36Sopenharmony_ci	}
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci	atombios_apply_encoder_quirks(encoder, adjusted_mode);
226362306a36Sopenharmony_ci
226462306a36Sopenharmony_ci	encoder_mode = atombios_get_encoder_mode(encoder);
226562306a36Sopenharmony_ci	if (connector && (radeon_audio != 0) &&
226662306a36Sopenharmony_ci	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
226762306a36Sopenharmony_ci	     ENCODER_MODE_IS_DP(encoder_mode)))
226862306a36Sopenharmony_ci		radeon_audio_mode_set(encoder, adjusted_mode);
226962306a36Sopenharmony_ci}
227062306a36Sopenharmony_ci
227162306a36Sopenharmony_cistatic bool
227262306a36Sopenharmony_ciatombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
227362306a36Sopenharmony_ci{
227462306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
227562306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
227662306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
227762306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_ci	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
228062306a36Sopenharmony_ci				       ATOM_DEVICE_CV_SUPPORT |
228162306a36Sopenharmony_ci				       ATOM_DEVICE_CRT_SUPPORT)) {
228262306a36Sopenharmony_ci		DAC_LOAD_DETECTION_PS_ALLOCATION args;
228362306a36Sopenharmony_ci		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
228462306a36Sopenharmony_ci		uint8_t frev, crev;
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci		memset(&args, 0, sizeof(args));
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
228962306a36Sopenharmony_ci			return false;
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ci		args.sDacload.ucMisc = 0;
229262306a36Sopenharmony_ci
229362306a36Sopenharmony_ci		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
229462306a36Sopenharmony_ci		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
229562306a36Sopenharmony_ci			args.sDacload.ucDacType = ATOM_DAC_A;
229662306a36Sopenharmony_ci		else
229762306a36Sopenharmony_ci			args.sDacload.ucDacType = ATOM_DAC_B;
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ci		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
230062306a36Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
230162306a36Sopenharmony_ci		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
230262306a36Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
230362306a36Sopenharmony_ci		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
230462306a36Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
230562306a36Sopenharmony_ci			if (crev >= 3)
230662306a36Sopenharmony_ci				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
230762306a36Sopenharmony_ci		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
230862306a36Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
230962306a36Sopenharmony_ci			if (crev >= 3)
231062306a36Sopenharmony_ci				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
231162306a36Sopenharmony_ci		}
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_ci		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_ci		return true;
231662306a36Sopenharmony_ci	} else
231762306a36Sopenharmony_ci		return false;
231862306a36Sopenharmony_ci}
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_cistatic enum drm_connector_status
232162306a36Sopenharmony_ciradeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
232262306a36Sopenharmony_ci{
232362306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
232462306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
232562306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
232662306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
232762306a36Sopenharmony_ci	uint32_t bios_0_scratch;
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci	if (!atombios_dac_load_detect(encoder, connector)) {
233062306a36Sopenharmony_ci		DRM_DEBUG_KMS("detect returned false \n");
233162306a36Sopenharmony_ci		return connector_status_unknown;
233262306a36Sopenharmony_ci	}
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	if (rdev->family >= CHIP_R600)
233562306a36Sopenharmony_ci		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
233662306a36Sopenharmony_ci	else
233762306a36Sopenharmony_ci		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
234062306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
234162306a36Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
234262306a36Sopenharmony_ci			return connector_status_connected;
234362306a36Sopenharmony_ci	}
234462306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
234562306a36Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
234662306a36Sopenharmony_ci			return connector_status_connected;
234762306a36Sopenharmony_ci	}
234862306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
234962306a36Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
235062306a36Sopenharmony_ci			return connector_status_connected;
235162306a36Sopenharmony_ci	}
235262306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
235362306a36Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
235462306a36Sopenharmony_ci			return connector_status_connected; /* CTV */
235562306a36Sopenharmony_ci		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
235662306a36Sopenharmony_ci			return connector_status_connected; /* STV */
235762306a36Sopenharmony_ci	}
235862306a36Sopenharmony_ci	return connector_status_disconnected;
235962306a36Sopenharmony_ci}
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_cistatic enum drm_connector_status
236262306a36Sopenharmony_ciradeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
236362306a36Sopenharmony_ci{
236462306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
236562306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
236662306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
236762306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
236862306a36Sopenharmony_ci	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
236962306a36Sopenharmony_ci	u32 bios_0_scratch;
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	if (!ASIC_IS_DCE4(rdev))
237262306a36Sopenharmony_ci		return connector_status_unknown;
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci	if (!ext_encoder)
237562306a36Sopenharmony_ci		return connector_status_unknown;
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
237862306a36Sopenharmony_ci		return connector_status_unknown;
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci	/* load detect on the dp bridge */
238162306a36Sopenharmony_ci	atombios_external_encoder_setup(encoder, ext_encoder,
238262306a36Sopenharmony_ci					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
238762306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
238862306a36Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
238962306a36Sopenharmony_ci			return connector_status_connected;
239062306a36Sopenharmony_ci	}
239162306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
239262306a36Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
239362306a36Sopenharmony_ci			return connector_status_connected;
239462306a36Sopenharmony_ci	}
239562306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
239662306a36Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
239762306a36Sopenharmony_ci			return connector_status_connected;
239862306a36Sopenharmony_ci	}
239962306a36Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
240062306a36Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
240162306a36Sopenharmony_ci			return connector_status_connected; /* CTV */
240262306a36Sopenharmony_ci		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
240362306a36Sopenharmony_ci			return connector_status_connected; /* STV */
240462306a36Sopenharmony_ci	}
240562306a36Sopenharmony_ci	return connector_status_disconnected;
240662306a36Sopenharmony_ci}
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_civoid
240962306a36Sopenharmony_ciradeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
241062306a36Sopenharmony_ci{
241162306a36Sopenharmony_ci	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci	if (ext_encoder)
241462306a36Sopenharmony_ci		/* ddc_setup on the dp bridge */
241562306a36Sopenharmony_ci		atombios_external_encoder_setup(encoder, ext_encoder,
241662306a36Sopenharmony_ci						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_ci}
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_cistatic void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
242162306a36Sopenharmony_ci{
242262306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
242362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
242462306a36Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	if ((radeon_encoder->active_device &
242762306a36Sopenharmony_ci	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
242862306a36Sopenharmony_ci	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
242962306a36Sopenharmony_ci	     ENCODER_OBJECT_ID_NONE)) {
243062306a36Sopenharmony_ci		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
243162306a36Sopenharmony_ci		if (dig) {
243262306a36Sopenharmony_ci			if (dig->dig_encoder >= 0)
243362306a36Sopenharmony_ci				radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
243462306a36Sopenharmony_ci			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1);
243562306a36Sopenharmony_ci			if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
243662306a36Sopenharmony_ci				if (rdev->family >= CHIP_R600)
243762306a36Sopenharmony_ci					dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
243862306a36Sopenharmony_ci				else
243962306a36Sopenharmony_ci					/* RS600/690/740 have only 1 afmt block */
244062306a36Sopenharmony_ci					dig->afmt = rdev->mode_info.afmt[0];
244162306a36Sopenharmony_ci			}
244262306a36Sopenharmony_ci		}
244362306a36Sopenharmony_ci	}
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci	radeon_atom_output_lock(encoder, true);
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	if (connector) {
244862306a36Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci		/* select the clock/data port if it uses a router */
245162306a36Sopenharmony_ci		if (radeon_connector->router.cd_valid)
245262306a36Sopenharmony_ci			radeon_router_select_cd_port(radeon_connector);
245362306a36Sopenharmony_ci
245462306a36Sopenharmony_ci		/* turn eDP panel on for mode set */
245562306a36Sopenharmony_ci		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
245662306a36Sopenharmony_ci			atombios_set_edp_panel_power(connector,
245762306a36Sopenharmony_ci						     ATOM_TRANSMITTER_ACTION_POWER_ON);
245862306a36Sopenharmony_ci	}
245962306a36Sopenharmony_ci
246062306a36Sopenharmony_ci	/* this is needed for the pll/ss setup to work correctly in some cases */
246162306a36Sopenharmony_ci	atombios_set_encoder_crtc_source(encoder);
246262306a36Sopenharmony_ci	/* set up the FMT blocks */
246362306a36Sopenharmony_ci	if (ASIC_IS_DCE8(rdev))
246462306a36Sopenharmony_ci		dce8_program_fmt(encoder);
246562306a36Sopenharmony_ci	else if (ASIC_IS_DCE4(rdev))
246662306a36Sopenharmony_ci		dce4_program_fmt(encoder);
246762306a36Sopenharmony_ci	else if (ASIC_IS_DCE3(rdev))
246862306a36Sopenharmony_ci		dce3_program_fmt(encoder);
246962306a36Sopenharmony_ci	else if (ASIC_IS_AVIVO(rdev))
247062306a36Sopenharmony_ci		avivo_program_fmt(encoder);
247162306a36Sopenharmony_ci}
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_cistatic void radeon_atom_encoder_commit(struct drm_encoder *encoder)
247462306a36Sopenharmony_ci{
247562306a36Sopenharmony_ci	/* need to call this here as we need the crtc set up */
247662306a36Sopenharmony_ci	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
247762306a36Sopenharmony_ci	radeon_atom_output_lock(encoder, false);
247862306a36Sopenharmony_ci}
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_cistatic void radeon_atom_encoder_disable(struct drm_encoder *encoder)
248162306a36Sopenharmony_ci{
248262306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
248362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
248462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
248562306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
248662306a36Sopenharmony_ci
248762306a36Sopenharmony_ci	/* check for pre-DCE3 cards with shared encoders;
248862306a36Sopenharmony_ci	 * can't really use the links individually, so don't disable
248962306a36Sopenharmony_ci	 * the encoder if it's in use by another connector
249062306a36Sopenharmony_ci	 */
249162306a36Sopenharmony_ci	if (!ASIC_IS_DCE3(rdev)) {
249262306a36Sopenharmony_ci		struct drm_encoder *other_encoder;
249362306a36Sopenharmony_ci		struct radeon_encoder *other_radeon_encoder;
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
249662306a36Sopenharmony_ci			other_radeon_encoder = to_radeon_encoder(other_encoder);
249762306a36Sopenharmony_ci			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
249862306a36Sopenharmony_ci			    drm_helper_encoder_in_use(other_encoder))
249962306a36Sopenharmony_ci				goto disable_done;
250062306a36Sopenharmony_ci		}
250162306a36Sopenharmony_ci	}
250262306a36Sopenharmony_ci
250362306a36Sopenharmony_ci	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
250462306a36Sopenharmony_ci
250562306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
250662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
250762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
250862306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
250962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
251062306a36Sopenharmony_ci		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
251162306a36Sopenharmony_ci		break;
251262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
251362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
251462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
251562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
251662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
251762306a36Sopenharmony_ci		/* handled in dpms */
251862306a36Sopenharmony_ci		break;
251962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
252062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
252162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
252262306a36Sopenharmony_ci		atombios_dvo_setup(encoder, ATOM_DISABLE);
252362306a36Sopenharmony_ci		break;
252462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
252562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
252662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
252762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
252862306a36Sopenharmony_ci		atombios_dac_setup(encoder, ATOM_DISABLE);
252962306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
253062306a36Sopenharmony_ci			atombios_tv_setup(encoder, ATOM_DISABLE);
253162306a36Sopenharmony_ci		break;
253262306a36Sopenharmony_ci	}
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_cidisable_done:
253562306a36Sopenharmony_ci	if (radeon_encoder_is_digital(encoder)) {
253662306a36Sopenharmony_ci		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
253762306a36Sopenharmony_ci			if (rdev->asic->display.hdmi_enable)
253862306a36Sopenharmony_ci				radeon_hdmi_enable(rdev, encoder, false);
253962306a36Sopenharmony_ci		}
254062306a36Sopenharmony_ci		if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST) {
254162306a36Sopenharmony_ci			dig = radeon_encoder->enc_priv;
254262306a36Sopenharmony_ci			radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
254362306a36Sopenharmony_ci			dig->dig_encoder = -1;
254462306a36Sopenharmony_ci			radeon_encoder->active_device = 0;
254562306a36Sopenharmony_ci		}
254662306a36Sopenharmony_ci	} else
254762306a36Sopenharmony_ci		radeon_encoder->active_device = 0;
254862306a36Sopenharmony_ci}
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci/* these are handled by the primary encoders */
255162306a36Sopenharmony_cistatic void radeon_atom_ext_prepare(struct drm_encoder *encoder)
255262306a36Sopenharmony_ci{
255362306a36Sopenharmony_ci
255462306a36Sopenharmony_ci}
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_cistatic void radeon_atom_ext_commit(struct drm_encoder *encoder)
255762306a36Sopenharmony_ci{
255862306a36Sopenharmony_ci
255962306a36Sopenharmony_ci}
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_cistatic void
256262306a36Sopenharmony_ciradeon_atom_ext_mode_set(struct drm_encoder *encoder,
256362306a36Sopenharmony_ci			 struct drm_display_mode *mode,
256462306a36Sopenharmony_ci			 struct drm_display_mode *adjusted_mode)
256562306a36Sopenharmony_ci{
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci}
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_cistatic void radeon_atom_ext_disable(struct drm_encoder *encoder)
257062306a36Sopenharmony_ci{
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci}
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_cistatic void
257562306a36Sopenharmony_ciradeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
257662306a36Sopenharmony_ci{
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci}
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
258162306a36Sopenharmony_ci	.dpms = radeon_atom_ext_dpms,
258262306a36Sopenharmony_ci	.prepare = radeon_atom_ext_prepare,
258362306a36Sopenharmony_ci	.mode_set = radeon_atom_ext_mode_set,
258462306a36Sopenharmony_ci	.commit = radeon_atom_ext_commit,
258562306a36Sopenharmony_ci	.disable = radeon_atom_ext_disable,
258662306a36Sopenharmony_ci	/* no detect for TMDS/LVDS yet */
258762306a36Sopenharmony_ci};
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
259062306a36Sopenharmony_ci	.dpms = radeon_atom_encoder_dpms,
259162306a36Sopenharmony_ci	.mode_fixup = radeon_atom_mode_fixup,
259262306a36Sopenharmony_ci	.prepare = radeon_atom_encoder_prepare,
259362306a36Sopenharmony_ci	.mode_set = radeon_atom_encoder_mode_set,
259462306a36Sopenharmony_ci	.commit = radeon_atom_encoder_commit,
259562306a36Sopenharmony_ci	.disable = radeon_atom_encoder_disable,
259662306a36Sopenharmony_ci	.detect = radeon_atom_dig_detect,
259762306a36Sopenharmony_ci};
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
260062306a36Sopenharmony_ci	.dpms = radeon_atom_encoder_dpms,
260162306a36Sopenharmony_ci	.mode_fixup = radeon_atom_mode_fixup,
260262306a36Sopenharmony_ci	.prepare = radeon_atom_encoder_prepare,
260362306a36Sopenharmony_ci	.mode_set = radeon_atom_encoder_mode_set,
260462306a36Sopenharmony_ci	.commit = radeon_atom_encoder_commit,
260562306a36Sopenharmony_ci	.detect = radeon_atom_dac_detect,
260662306a36Sopenharmony_ci};
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_civoid radeon_enc_destroy(struct drm_encoder *encoder)
260962306a36Sopenharmony_ci{
261062306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
261162306a36Sopenharmony_ci	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
261262306a36Sopenharmony_ci		radeon_atom_backlight_exit(radeon_encoder);
261362306a36Sopenharmony_ci	kfree(radeon_encoder->enc_priv);
261462306a36Sopenharmony_ci	drm_encoder_cleanup(encoder);
261562306a36Sopenharmony_ci	kfree(radeon_encoder);
261662306a36Sopenharmony_ci}
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_cistatic const struct drm_encoder_funcs radeon_atom_enc_funcs = {
261962306a36Sopenharmony_ci	.destroy = radeon_enc_destroy,
262062306a36Sopenharmony_ci};
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_cistatic struct radeon_encoder_atom_dac *
262362306a36Sopenharmony_ciradeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
262462306a36Sopenharmony_ci{
262562306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
262662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
262762306a36Sopenharmony_ci	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
262862306a36Sopenharmony_ci
262962306a36Sopenharmony_ci	if (!dac)
263062306a36Sopenharmony_ci		return NULL;
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	dac->tv_std = radeon_atombios_get_tv_info(rdev);
263362306a36Sopenharmony_ci	return dac;
263462306a36Sopenharmony_ci}
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_cistatic struct radeon_encoder_atom_dig *
263762306a36Sopenharmony_ciradeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
263862306a36Sopenharmony_ci{
263962306a36Sopenharmony_ci	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
264062306a36Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
264162306a36Sopenharmony_ci
264262306a36Sopenharmony_ci	if (!dig)
264362306a36Sopenharmony_ci		return NULL;
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci	/* coherent mode by default */
264662306a36Sopenharmony_ci	dig->coherent_mode = true;
264762306a36Sopenharmony_ci	dig->dig_encoder = -1;
264862306a36Sopenharmony_ci
264962306a36Sopenharmony_ci	if (encoder_enum == 2)
265062306a36Sopenharmony_ci		dig->linkb = true;
265162306a36Sopenharmony_ci	else
265262306a36Sopenharmony_ci		dig->linkb = false;
265362306a36Sopenharmony_ci
265462306a36Sopenharmony_ci	return dig;
265562306a36Sopenharmony_ci}
265662306a36Sopenharmony_ci
265762306a36Sopenharmony_civoid
265862306a36Sopenharmony_ciradeon_add_atom_encoder(struct drm_device *dev,
265962306a36Sopenharmony_ci			uint32_t encoder_enum,
266062306a36Sopenharmony_ci			uint32_t supported_device,
266162306a36Sopenharmony_ci			u16 caps)
266262306a36Sopenharmony_ci{
266362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
266462306a36Sopenharmony_ci	struct drm_encoder *encoder;
266562306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_ci	/* see if we already added it */
266862306a36Sopenharmony_ci	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
266962306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
267062306a36Sopenharmony_ci		if (radeon_encoder->encoder_enum == encoder_enum) {
267162306a36Sopenharmony_ci			radeon_encoder->devices |= supported_device;
267262306a36Sopenharmony_ci			return;
267362306a36Sopenharmony_ci		}
267462306a36Sopenharmony_ci
267562306a36Sopenharmony_ci	}
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci	/* add a new one */
267862306a36Sopenharmony_ci	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
267962306a36Sopenharmony_ci	if (!radeon_encoder)
268062306a36Sopenharmony_ci		return;
268162306a36Sopenharmony_ci
268262306a36Sopenharmony_ci	encoder = &radeon_encoder->base;
268362306a36Sopenharmony_ci	switch (rdev->num_crtc) {
268462306a36Sopenharmony_ci	case 1:
268562306a36Sopenharmony_ci		encoder->possible_crtcs = 0x1;
268662306a36Sopenharmony_ci		break;
268762306a36Sopenharmony_ci	case 2:
268862306a36Sopenharmony_ci	default:
268962306a36Sopenharmony_ci		encoder->possible_crtcs = 0x3;
269062306a36Sopenharmony_ci		break;
269162306a36Sopenharmony_ci	case 4:
269262306a36Sopenharmony_ci		encoder->possible_crtcs = 0xf;
269362306a36Sopenharmony_ci		break;
269462306a36Sopenharmony_ci	case 6:
269562306a36Sopenharmony_ci		encoder->possible_crtcs = 0x3f;
269662306a36Sopenharmony_ci		break;
269762306a36Sopenharmony_ci	}
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci	radeon_encoder->enc_priv = NULL;
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	radeon_encoder->encoder_enum = encoder_enum;
270262306a36Sopenharmony_ci	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
270362306a36Sopenharmony_ci	radeon_encoder->devices = supported_device;
270462306a36Sopenharmony_ci	radeon_encoder->rmx_type = RMX_OFF;
270562306a36Sopenharmony_ci	radeon_encoder->underscan_type = UNDERSCAN_OFF;
270662306a36Sopenharmony_ci	radeon_encoder->is_ext_encoder = false;
270762306a36Sopenharmony_ci	radeon_encoder->caps = caps;
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
271062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
271162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
271262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
271362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
271462306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
271562306a36Sopenharmony_ci			radeon_encoder->rmx_type = RMX_FULL;
271662306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
271762306a36Sopenharmony_ci					 DRM_MODE_ENCODER_LVDS, NULL);
271862306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
271962306a36Sopenharmony_ci		} else {
272062306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
272162306a36Sopenharmony_ci					 DRM_MODE_ENCODER_TMDS, NULL);
272262306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
272362306a36Sopenharmony_ci		}
272462306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
272562306a36Sopenharmony_ci		break;
272662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
272762306a36Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
272862306a36Sopenharmony_ci				 DRM_MODE_ENCODER_DAC, NULL);
272962306a36Sopenharmony_ci		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
273062306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
273162306a36Sopenharmony_ci		break;
273262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
273362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
273462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
273562306a36Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
273662306a36Sopenharmony_ci				 DRM_MODE_ENCODER_TVDAC, NULL);
273762306a36Sopenharmony_ci		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
273862306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
273962306a36Sopenharmony_ci		break;
274062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
274162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
274262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
274362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
274462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
274562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
274662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
274762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
274862306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
274962306a36Sopenharmony_ci			radeon_encoder->rmx_type = RMX_FULL;
275062306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
275162306a36Sopenharmony_ci					 DRM_MODE_ENCODER_LVDS, NULL);
275262306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
275362306a36Sopenharmony_ci		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
275462306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
275562306a36Sopenharmony_ci					 DRM_MODE_ENCODER_DAC, NULL);
275662306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
275762306a36Sopenharmony_ci		} else {
275862306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
275962306a36Sopenharmony_ci					 DRM_MODE_ENCODER_TMDS, NULL);
276062306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
276162306a36Sopenharmony_ci		}
276262306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
276362306a36Sopenharmony_ci		break;
276462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_SI170B:
276562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_CH7303:
276662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
276762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
276862306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_TITFP513:
276962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_VT1623:
277062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_HDMI_SI1930:
277162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_TRAVIS:
277262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_NUTMEG:
277362306a36Sopenharmony_ci		/* these are handled by the primary encoders */
277462306a36Sopenharmony_ci		radeon_encoder->is_ext_encoder = true;
277562306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
277662306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
277762306a36Sopenharmony_ci					 DRM_MODE_ENCODER_LVDS, NULL);
277862306a36Sopenharmony_ci		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
277962306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
278062306a36Sopenharmony_ci					 DRM_MODE_ENCODER_DAC, NULL);
278162306a36Sopenharmony_ci		else
278262306a36Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
278362306a36Sopenharmony_ci					 DRM_MODE_ENCODER_TMDS, NULL);
278462306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
278562306a36Sopenharmony_ci		break;
278662306a36Sopenharmony_ci	}
278762306a36Sopenharmony_ci}
2788