18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2007-11 Advanced Micro Devices, Inc.
38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
68c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
78c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
88c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
98c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
108c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
138c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
188c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
198c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
208c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
218c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Authors: Dave Airlie
248c2ecf20Sopenharmony_ci *          Alex Deucher
258c2ecf20Sopenharmony_ci */
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#include <linux/backlight.h>
288c2ecf20Sopenharmony_ci#include <linux/dmi.h>
298c2ecf20Sopenharmony_ci#include <linux/pci.h>
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include <drm/drm_crtc_helper.h>
328c2ecf20Sopenharmony_ci#include <drm/drm_file.h>
338c2ecf20Sopenharmony_ci#include <drm/radeon_drm.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include "atom.h"
368c2ecf20Sopenharmony_ci#include "radeon.h"
378c2ecf20Sopenharmony_ci#include "radeon_asic.h"
388c2ecf20Sopenharmony_ci#include "radeon_audio.h"
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ciextern int atom_debug;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic u8
438c2ecf20Sopenharmony_ciradeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	u8 backlight_level;
468c2ecf20Sopenharmony_ci	u32 bios_2_scratch;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (rdev->family >= CHIP_R600)
498c2ecf20Sopenharmony_ci		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
508c2ecf20Sopenharmony_ci	else
518c2ecf20Sopenharmony_ci		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >>
548c2ecf20Sopenharmony_ci			   ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	return backlight_level;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic void
608c2ecf20Sopenharmony_ciradeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev,
618c2ecf20Sopenharmony_ci				       u8 backlight_level)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	u32 bios_2_scratch;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	if (rdev->family >= CHIP_R600)
668c2ecf20Sopenharmony_ci		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
678c2ecf20Sopenharmony_ci	else
688c2ecf20Sopenharmony_ci		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
718c2ecf20Sopenharmony_ci	bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
728c2ecf20Sopenharmony_ci			   ATOM_S2_CURRENT_BL_LEVEL_MASK);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	if (rdev->family >= CHIP_R600)
758c2ecf20Sopenharmony_ci		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
768c2ecf20Sopenharmony_ci	else
778c2ecf20Sopenharmony_ci		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ciu8
818c2ecf20Sopenharmony_ciatombios_get_backlight_level(struct radeon_encoder *radeon_encoder)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
848c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
878c2ecf20Sopenharmony_ci		return 0;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	return radeon_atom_get_backlight_level_from_reg(rdev);
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_civoid
938c2ecf20Sopenharmony_ciatombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	struct drm_encoder *encoder = &radeon_encoder->base;
968c2ecf20Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
978c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
988c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
998c2ecf20Sopenharmony_ci	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1008c2ecf20Sopenharmony_ci	int index;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
1038c2ecf20Sopenharmony_ci		return;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
1068c2ecf20Sopenharmony_ci	    radeon_encoder->enc_priv) {
1078c2ecf20Sopenharmony_ci		dig = radeon_encoder->enc_priv;
1088c2ecf20Sopenharmony_ci		dig->backlight_level = level;
1098c2ecf20Sopenharmony_ci		radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
1128c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1138c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1148c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1158c2ecf20Sopenharmony_ci			if (dig->backlight_level == 0) {
1168c2ecf20Sopenharmony_ci				args.ucAction = ATOM_LCD_BLOFF;
1178c2ecf20Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1188c2ecf20Sopenharmony_ci			} else {
1198c2ecf20Sopenharmony_ci				args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
1208c2ecf20Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1218c2ecf20Sopenharmony_ci				args.ucAction = ATOM_LCD_BLON;
1228c2ecf20Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1238c2ecf20Sopenharmony_ci			}
1248c2ecf20Sopenharmony_ci			break;
1258c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1268c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1278c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1288c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1298c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1308c2ecf20Sopenharmony_ci			if (dig->backlight_level == 0)
1318c2ecf20Sopenharmony_ci				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
1328c2ecf20Sopenharmony_ci			else {
1338c2ecf20Sopenharmony_ci				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0);
1348c2ecf20Sopenharmony_ci				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
1358c2ecf20Sopenharmony_ci			}
1368c2ecf20Sopenharmony_ci			break;
1378c2ecf20Sopenharmony_ci		default:
1388c2ecf20Sopenharmony_ci			break;
1398c2ecf20Sopenharmony_ci		}
1408c2ecf20Sopenharmony_ci	}
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic u8 radeon_atom_bl_level(struct backlight_device *bd)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	u8 level;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	/* Convert brightness to hardware level */
1508c2ecf20Sopenharmony_ci	if (bd->props.brightness < 0)
1518c2ecf20Sopenharmony_ci		level = 0;
1528c2ecf20Sopenharmony_ci	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
1538c2ecf20Sopenharmony_ci		level = RADEON_MAX_BL_LEVEL;
1548c2ecf20Sopenharmony_ci	else
1558c2ecf20Sopenharmony_ci		level = bd->props.brightness;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	return level;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic int radeon_atom_backlight_update_status(struct backlight_device *bd)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
1638c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = pdata->encoder;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd));
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	return 0;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic int radeon_atom_backlight_get_brightness(struct backlight_device *bd)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
1738c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = pdata->encoder;
1748c2ecf20Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
1758c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	return radeon_atom_get_backlight_level_from_reg(rdev);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic const struct backlight_ops radeon_atom_backlight_ops = {
1818c2ecf20Sopenharmony_ci	.get_brightness = radeon_atom_backlight_get_brightness,
1828c2ecf20Sopenharmony_ci	.update_status	= radeon_atom_backlight_update_status,
1838c2ecf20Sopenharmony_ci};
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_civoid radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
1868c2ecf20Sopenharmony_ci				struct drm_connector *drm_connector)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
1898c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
1908c2ecf20Sopenharmony_ci	struct backlight_device *bd;
1918c2ecf20Sopenharmony_ci	struct backlight_properties props;
1928c2ecf20Sopenharmony_ci	struct radeon_backlight_privdata *pdata;
1938c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
1948c2ecf20Sopenharmony_ci	char bl_name[16];
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	/* Mac laptops with multiple GPUs use the gmux driver for backlight
1978c2ecf20Sopenharmony_ci	 * so don't register a backlight device
1988c2ecf20Sopenharmony_ci	 */
1998c2ecf20Sopenharmony_ci	if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
2008c2ecf20Sopenharmony_ci	    (rdev->pdev->device == 0x6741) &&
2018c2ecf20Sopenharmony_ci	    !dmi_match(DMI_PRODUCT_NAME, "iMac12,1"))
2028c2ecf20Sopenharmony_ci		return;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	if (!radeon_encoder->enc_priv)
2058c2ecf20Sopenharmony_ci		return;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	if (!rdev->is_atom_bios)
2088c2ecf20Sopenharmony_ci		return;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
2118c2ecf20Sopenharmony_ci		return;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
2148c2ecf20Sopenharmony_ci	if (!pdata) {
2158c2ecf20Sopenharmony_ci		DRM_ERROR("Memory allocation failed\n");
2168c2ecf20Sopenharmony_ci		goto error;
2178c2ecf20Sopenharmony_ci	}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	memset(&props, 0, sizeof(props));
2208c2ecf20Sopenharmony_ci	props.max_brightness = RADEON_MAX_BL_LEVEL;
2218c2ecf20Sopenharmony_ci	props.type = BACKLIGHT_RAW;
2228c2ecf20Sopenharmony_ci	snprintf(bl_name, sizeof(bl_name),
2238c2ecf20Sopenharmony_ci		 "radeon_bl%d", dev->primary->index);
2248c2ecf20Sopenharmony_ci	bd = backlight_device_register(bl_name, drm_connector->kdev,
2258c2ecf20Sopenharmony_ci				       pdata, &radeon_atom_backlight_ops, &props);
2268c2ecf20Sopenharmony_ci	if (IS_ERR(bd)) {
2278c2ecf20Sopenharmony_ci		DRM_ERROR("Backlight registration failed\n");
2288c2ecf20Sopenharmony_ci		goto error;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	pdata->encoder = radeon_encoder;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	dig = radeon_encoder->enc_priv;
2348c2ecf20Sopenharmony_ci	dig->bl_dev = bd;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	bd->props.brightness = radeon_atom_backlight_get_brightness(bd);
2378c2ecf20Sopenharmony_ci	/* Set a reasonable default here if the level is 0 otherwise
2388c2ecf20Sopenharmony_ci	 * fbdev will attempt to turn the backlight on after console
2398c2ecf20Sopenharmony_ci	 * unblanking and it will try and restore 0 which turns the backlight
2408c2ecf20Sopenharmony_ci	 * off again.
2418c2ecf20Sopenharmony_ci	 */
2428c2ecf20Sopenharmony_ci	if (bd->props.brightness == 0)
2438c2ecf20Sopenharmony_ci		bd->props.brightness = RADEON_MAX_BL_LEVEL;
2448c2ecf20Sopenharmony_ci	bd->props.power = FB_BLANK_UNBLANK;
2458c2ecf20Sopenharmony_ci	backlight_update_status(bd);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	DRM_INFO("radeon atom DIG backlight initialized\n");
2488c2ecf20Sopenharmony_ci	rdev->mode_info.bl_encoder = radeon_encoder;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	return;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cierror:
2538c2ecf20Sopenharmony_ci	kfree(pdata);
2548c2ecf20Sopenharmony_ci	return;
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
2608c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
2618c2ecf20Sopenharmony_ci	struct backlight_device *bd = NULL;
2628c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (!radeon_encoder->enc_priv)
2658c2ecf20Sopenharmony_ci		return;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (!rdev->is_atom_bios)
2688c2ecf20Sopenharmony_ci		return;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
2718c2ecf20Sopenharmony_ci		return;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	dig = radeon_encoder->enc_priv;
2748c2ecf20Sopenharmony_ci	bd = dig->bl_dev;
2758c2ecf20Sopenharmony_ci	dig->bl_dev = NULL;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	if (bd) {
2788c2ecf20Sopenharmony_ci		struct radeon_legacy_backlight_privdata *pdata;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci		pdata = bl_get_data(bd);
2818c2ecf20Sopenharmony_ci		backlight_device_unregister(bd);
2828c2ecf20Sopenharmony_ci		kfree(pdata);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci		DRM_INFO("radeon atom LVDS backlight unloaded\n");
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_civoid radeon_atom_backlight_init(struct radeon_encoder *encoder)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic void radeon_atom_backlight_exit(struct radeon_encoder *encoder)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci#endif
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci/* evil but including atombios.h is much worse */
3018c2ecf20Sopenharmony_cibool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
3028c2ecf20Sopenharmony_ci				struct drm_display_mode *mode);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
3058c2ecf20Sopenharmony_ci				   const struct drm_display_mode *mode,
3068c2ecf20Sopenharmony_ci				   struct drm_display_mode *adjusted_mode)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3098c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
3108c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* set the active encoder to connector routing */
3138c2ecf20Sopenharmony_ci	radeon_encoder_set_active_device(encoder);
3148c2ecf20Sopenharmony_ci	drm_mode_set_crtcinfo(adjusted_mode, 0);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	/* hw bug */
3178c2ecf20Sopenharmony_ci	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
3188c2ecf20Sopenharmony_ci	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
3198c2ecf20Sopenharmony_ci		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	/* vertical FP must be at least 1 */
3228c2ecf20Sopenharmony_ci	if (mode->crtc_vsync_start == mode->crtc_vdisplay)
3238c2ecf20Sopenharmony_ci		adjusted_mode->crtc_vsync_start++;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/* get the native mode for scaling */
3268c2ecf20Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
3278c2ecf20Sopenharmony_ci		radeon_panel_mode_fixup(encoder, adjusted_mode);
3288c2ecf20Sopenharmony_ci	} else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
3298c2ecf20Sopenharmony_ci		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
3308c2ecf20Sopenharmony_ci		if (tv_dac) {
3318c2ecf20Sopenharmony_ci			if (tv_dac->tv_std == TV_STD_NTSC ||
3328c2ecf20Sopenharmony_ci			    tv_dac->tv_std == TV_STD_NTSC_J ||
3338c2ecf20Sopenharmony_ci			    tv_dac->tv_std == TV_STD_PAL_M)
3348c2ecf20Sopenharmony_ci				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
3358c2ecf20Sopenharmony_ci			else
3368c2ecf20Sopenharmony_ci				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
3378c2ecf20Sopenharmony_ci		}
3388c2ecf20Sopenharmony_ci	} else if (radeon_encoder->rmx_type != RMX_OFF) {
3398c2ecf20Sopenharmony_ci		radeon_panel_mode_fixup(encoder, adjusted_mode);
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (ASIC_IS_DCE3(rdev) &&
3438c2ecf20Sopenharmony_ci	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
3448c2ecf20Sopenharmony_ci	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
3458c2ecf20Sopenharmony_ci		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
3468c2ecf20Sopenharmony_ci		radeon_dp_set_link_config(connector, adjusted_mode);
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	return true;
3508c2ecf20Sopenharmony_ci}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_cistatic void
3538c2ecf20Sopenharmony_ciatombios_dac_setup(struct drm_encoder *encoder, int action)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
3568c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
3578c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3588c2ecf20Sopenharmony_ci	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
3598c2ecf20Sopenharmony_ci	int index = 0;
3608c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
3658c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
3668c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
3678c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
3688c2ecf20Sopenharmony_ci		break;
3698c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
3708c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
3718c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
3728c2ecf20Sopenharmony_ci		break;
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	args.ucAction = action;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
3788c2ecf20Sopenharmony_ci		args.ucDacStandard = ATOM_DAC1_PS2;
3798c2ecf20Sopenharmony_ci	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
3808c2ecf20Sopenharmony_ci		args.ucDacStandard = ATOM_DAC1_CV;
3818c2ecf20Sopenharmony_ci	else {
3828c2ecf20Sopenharmony_ci		switch (dac_info->tv_std) {
3838c2ecf20Sopenharmony_ci		case TV_STD_PAL:
3848c2ecf20Sopenharmony_ci		case TV_STD_PAL_M:
3858c2ecf20Sopenharmony_ci		case TV_STD_SCART_PAL:
3868c2ecf20Sopenharmony_ci		case TV_STD_SECAM:
3878c2ecf20Sopenharmony_ci		case TV_STD_PAL_CN:
3888c2ecf20Sopenharmony_ci			args.ucDacStandard = ATOM_DAC1_PAL;
3898c2ecf20Sopenharmony_ci			break;
3908c2ecf20Sopenharmony_ci		case TV_STD_NTSC:
3918c2ecf20Sopenharmony_ci		case TV_STD_NTSC_J:
3928c2ecf20Sopenharmony_ci		case TV_STD_PAL_60:
3938c2ecf20Sopenharmony_ci		default:
3948c2ecf20Sopenharmony_ci			args.ucDacStandard = ATOM_DAC1_NTSC;
3958c2ecf20Sopenharmony_ci			break;
3968c2ecf20Sopenharmony_ci		}
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic void
4058c2ecf20Sopenharmony_ciatombios_tv_setup(struct drm_encoder *encoder, int action)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
4088c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
4098c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
4108c2ecf20Sopenharmony_ci	TV_ENCODER_CONTROL_PS_ALLOCATION args;
4118c2ecf20Sopenharmony_ci	int index = 0;
4128c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	args.sTVEncoder.ucAction = action;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
4218c2ecf20Sopenharmony_ci		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
4228c2ecf20Sopenharmony_ci	else {
4238c2ecf20Sopenharmony_ci		switch (dac_info->tv_std) {
4248c2ecf20Sopenharmony_ci		case TV_STD_NTSC:
4258c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
4268c2ecf20Sopenharmony_ci			break;
4278c2ecf20Sopenharmony_ci		case TV_STD_PAL:
4288c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
4298c2ecf20Sopenharmony_ci			break;
4308c2ecf20Sopenharmony_ci		case TV_STD_PAL_M:
4318c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
4328c2ecf20Sopenharmony_ci			break;
4338c2ecf20Sopenharmony_ci		case TV_STD_PAL_60:
4348c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
4358c2ecf20Sopenharmony_ci			break;
4368c2ecf20Sopenharmony_ci		case TV_STD_NTSC_J:
4378c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
4388c2ecf20Sopenharmony_ci			break;
4398c2ecf20Sopenharmony_ci		case TV_STD_SCART_PAL:
4408c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
4418c2ecf20Sopenharmony_ci			break;
4428c2ecf20Sopenharmony_ci		case TV_STD_SECAM:
4438c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
4448c2ecf20Sopenharmony_ci			break;
4458c2ecf20Sopenharmony_ci		case TV_STD_PAL_CN:
4468c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
4478c2ecf20Sopenharmony_ci			break;
4488c2ecf20Sopenharmony_ci		default:
4498c2ecf20Sopenharmony_ci			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
4508c2ecf20Sopenharmony_ci			break;
4518c2ecf20Sopenharmony_ci		}
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci}
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_cistatic u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	int bpc = 8;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (encoder->crtc) {
4658c2ecf20Sopenharmony_ci		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
4668c2ecf20Sopenharmony_ci		bpc = radeon_crtc->bpc;
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	switch (bpc) {
4708c2ecf20Sopenharmony_ci	case 0:
4718c2ecf20Sopenharmony_ci		return PANEL_BPC_UNDEFINE;
4728c2ecf20Sopenharmony_ci	case 6:
4738c2ecf20Sopenharmony_ci		return PANEL_6BIT_PER_COLOR;
4748c2ecf20Sopenharmony_ci	case 8:
4758c2ecf20Sopenharmony_ci	default:
4768c2ecf20Sopenharmony_ci		return PANEL_8BIT_PER_COLOR;
4778c2ecf20Sopenharmony_ci	case 10:
4788c2ecf20Sopenharmony_ci		return PANEL_10BIT_PER_COLOR;
4798c2ecf20Sopenharmony_ci	case 12:
4808c2ecf20Sopenharmony_ci		return PANEL_12BIT_PER_COLOR;
4818c2ecf20Sopenharmony_ci	case 16:
4828c2ecf20Sopenharmony_ci		return PANEL_16BIT_PER_COLOR;
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ciunion dvo_encoder_control {
4878c2ecf20Sopenharmony_ci	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
4888c2ecf20Sopenharmony_ci	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
4898c2ecf20Sopenharmony_ci	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
4908c2ecf20Sopenharmony_ci	DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 dvo_v4;
4918c2ecf20Sopenharmony_ci};
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_civoid
4948c2ecf20Sopenharmony_ciatombios_dvo_setup(struct drm_encoder *encoder, int action)
4958c2ecf20Sopenharmony_ci{
4968c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
4978c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
4988c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
4998c2ecf20Sopenharmony_ci	union dvo_encoder_control args;
5008c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
5018c2ecf20Sopenharmony_ci	uint8_t frev, crev;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
5068c2ecf20Sopenharmony_ci		return;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* some R4xx chips have the wrong frev */
5098c2ecf20Sopenharmony_ci	if (rdev->family <= CHIP_RV410)
5108c2ecf20Sopenharmony_ci		frev = 1;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	switch (frev) {
5138c2ecf20Sopenharmony_ci	case 1:
5148c2ecf20Sopenharmony_ci		switch (crev) {
5158c2ecf20Sopenharmony_ci		case 1:
5168c2ecf20Sopenharmony_ci			/* R4xx, R5xx */
5178c2ecf20Sopenharmony_ci			args.ext_tmds.sXTmdsEncoder.ucEnable = action;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
5208c2ecf20Sopenharmony_ci				args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci			args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
5238c2ecf20Sopenharmony_ci			break;
5248c2ecf20Sopenharmony_ci		case 2:
5258c2ecf20Sopenharmony_ci			/* RS600/690/740 */
5268c2ecf20Sopenharmony_ci			args.dvo.sDVOEncoder.ucAction = action;
5278c2ecf20Sopenharmony_ci			args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
5288c2ecf20Sopenharmony_ci			/* DFP1, CRT1, TV1 depending on the type of port */
5298c2ecf20Sopenharmony_ci			args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci			if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
5328c2ecf20Sopenharmony_ci				args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
5338c2ecf20Sopenharmony_ci			break;
5348c2ecf20Sopenharmony_ci		case 3:
5358c2ecf20Sopenharmony_ci			/* R6xx */
5368c2ecf20Sopenharmony_ci			args.dvo_v3.ucAction = action;
5378c2ecf20Sopenharmony_ci			args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
5388c2ecf20Sopenharmony_ci			args.dvo_v3.ucDVOConfig = 0; /* XXX */
5398c2ecf20Sopenharmony_ci			break;
5408c2ecf20Sopenharmony_ci		case 4:
5418c2ecf20Sopenharmony_ci			/* DCE8 */
5428c2ecf20Sopenharmony_ci			args.dvo_v4.ucAction = action;
5438c2ecf20Sopenharmony_ci			args.dvo_v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
5448c2ecf20Sopenharmony_ci			args.dvo_v4.ucDVOConfig = 0; /* XXX */
5458c2ecf20Sopenharmony_ci			args.dvo_v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
5468c2ecf20Sopenharmony_ci			break;
5478c2ecf20Sopenharmony_ci		default:
5488c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
5498c2ecf20Sopenharmony_ci			break;
5508c2ecf20Sopenharmony_ci		}
5518c2ecf20Sopenharmony_ci		break;
5528c2ecf20Sopenharmony_ci	default:
5538c2ecf20Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
5548c2ecf20Sopenharmony_ci		break;
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ciunion lvds_encoder_control {
5618c2ecf20Sopenharmony_ci	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
5628c2ecf20Sopenharmony_ci	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
5638c2ecf20Sopenharmony_ci};
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_civoid
5668c2ecf20Sopenharmony_ciatombios_digital_setup(struct drm_encoder *encoder, int action)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
5698c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
5708c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
5718c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
5728c2ecf20Sopenharmony_ci	union lvds_encoder_control args;
5738c2ecf20Sopenharmony_ci	int index = 0;
5748c2ecf20Sopenharmony_ci	int hdmi_detected = 0;
5758c2ecf20Sopenharmony_ci	uint8_t frev, crev;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	if (!dig)
5788c2ecf20Sopenharmony_ci		return;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
5818c2ecf20Sopenharmony_ci		hdmi_detected = 1;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
5868c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
5878c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
5888c2ecf20Sopenharmony_ci		break;
5898c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
5908c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
5918c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
5928c2ecf20Sopenharmony_ci		break;
5938c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
5948c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
5958c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
5968c2ecf20Sopenharmony_ci		else
5978c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
5988c2ecf20Sopenharmony_ci		break;
5998c2ecf20Sopenharmony_ci	}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
6028c2ecf20Sopenharmony_ci		return;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	switch (frev) {
6058c2ecf20Sopenharmony_ci	case 1:
6068c2ecf20Sopenharmony_ci	case 2:
6078c2ecf20Sopenharmony_ci		switch (crev) {
6088c2ecf20Sopenharmony_ci		case 1:
6098c2ecf20Sopenharmony_ci			args.v1.ucMisc = 0;
6108c2ecf20Sopenharmony_ci			args.v1.ucAction = action;
6118c2ecf20Sopenharmony_ci			if (hdmi_detected)
6128c2ecf20Sopenharmony_ci				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
6138c2ecf20Sopenharmony_ci			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
6148c2ecf20Sopenharmony_ci			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
6158c2ecf20Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
6168c2ecf20Sopenharmony_ci					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
6178c2ecf20Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
6188c2ecf20Sopenharmony_ci					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
6198c2ecf20Sopenharmony_ci			} else {
6208c2ecf20Sopenharmony_ci				if (dig->linkb)
6218c2ecf20Sopenharmony_ci					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
6228c2ecf20Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
6238c2ecf20Sopenharmony_ci					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
6248c2ecf20Sopenharmony_ci				/*if (pScrn->rgbBits == 8) */
6258c2ecf20Sopenharmony_ci				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
6268c2ecf20Sopenharmony_ci			}
6278c2ecf20Sopenharmony_ci			break;
6288c2ecf20Sopenharmony_ci		case 2:
6298c2ecf20Sopenharmony_ci		case 3:
6308c2ecf20Sopenharmony_ci			args.v2.ucMisc = 0;
6318c2ecf20Sopenharmony_ci			args.v2.ucAction = action;
6328c2ecf20Sopenharmony_ci			if (crev == 3) {
6338c2ecf20Sopenharmony_ci				if (dig->coherent_mode)
6348c2ecf20Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
6358c2ecf20Sopenharmony_ci			}
6368c2ecf20Sopenharmony_ci			if (hdmi_detected)
6378c2ecf20Sopenharmony_ci				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
6388c2ecf20Sopenharmony_ci			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
6398c2ecf20Sopenharmony_ci			args.v2.ucTruncate = 0;
6408c2ecf20Sopenharmony_ci			args.v2.ucSpatial = 0;
6418c2ecf20Sopenharmony_ci			args.v2.ucTemporal = 0;
6428c2ecf20Sopenharmony_ci			args.v2.ucFRC = 0;
6438c2ecf20Sopenharmony_ci			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
6448c2ecf20Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
6458c2ecf20Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
6468c2ecf20Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
6478c2ecf20Sopenharmony_ci					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
6488c2ecf20Sopenharmony_ci					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
6498c2ecf20Sopenharmony_ci						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
6508c2ecf20Sopenharmony_ci				}
6518c2ecf20Sopenharmony_ci				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
6528c2ecf20Sopenharmony_ci					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
6538c2ecf20Sopenharmony_ci					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
6548c2ecf20Sopenharmony_ci						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
6558c2ecf20Sopenharmony_ci					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
6568c2ecf20Sopenharmony_ci						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
6578c2ecf20Sopenharmony_ci				}
6588c2ecf20Sopenharmony_ci			} else {
6598c2ecf20Sopenharmony_ci				if (dig->linkb)
6608c2ecf20Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
6618c2ecf20Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
6628c2ecf20Sopenharmony_ci					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
6638c2ecf20Sopenharmony_ci			}
6648c2ecf20Sopenharmony_ci			break;
6658c2ecf20Sopenharmony_ci		default:
6668c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
6678c2ecf20Sopenharmony_ci			break;
6688c2ecf20Sopenharmony_ci		}
6698c2ecf20Sopenharmony_ci		break;
6708c2ecf20Sopenharmony_ci	default:
6718c2ecf20Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
6728c2ecf20Sopenharmony_ci		break;
6738c2ecf20Sopenharmony_ci	}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
6768c2ecf20Sopenharmony_ci}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ciint
6798c2ecf20Sopenharmony_ciatombios_get_encoder_mode(struct drm_encoder *encoder)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
6828c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
6838c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
6848c2ecf20Sopenharmony_ci	struct drm_connector *connector;
6858c2ecf20Sopenharmony_ci	struct radeon_connector *radeon_connector;
6868c2ecf20Sopenharmony_ci	struct radeon_connector_atom_dig *dig_connector;
6878c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig_enc;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	if (radeon_encoder_is_digital(encoder)) {
6908c2ecf20Sopenharmony_ci		dig_enc = radeon_encoder->enc_priv;
6918c2ecf20Sopenharmony_ci		if (dig_enc->active_mst_links)
6928c2ecf20Sopenharmony_ci			return ATOM_ENCODER_MODE_DP_MST;
6938c2ecf20Sopenharmony_ci	}
6948c2ecf20Sopenharmony_ci	if (radeon_encoder->is_mst_encoder || radeon_encoder->offset)
6958c2ecf20Sopenharmony_ci		return ATOM_ENCODER_MODE_DP_MST;
6968c2ecf20Sopenharmony_ci	/* dp bridges are always DP */
6978c2ecf20Sopenharmony_ci	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
6988c2ecf20Sopenharmony_ci		return ATOM_ENCODER_MODE_DP;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	/* DVO is always DVO */
7018c2ecf20Sopenharmony_ci	if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) ||
7028c2ecf20Sopenharmony_ci	    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
7038c2ecf20Sopenharmony_ci		return ATOM_ENCODER_MODE_DVO;
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	connector = radeon_get_connector_for_encoder(encoder);
7068c2ecf20Sopenharmony_ci	/* if we don't have an active device yet, just use one of
7078c2ecf20Sopenharmony_ci	 * the connectors tied to the encoder.
7088c2ecf20Sopenharmony_ci	 */
7098c2ecf20Sopenharmony_ci	if (!connector)
7108c2ecf20Sopenharmony_ci		connector = radeon_get_connector_for_encoder_init(encoder);
7118c2ecf20Sopenharmony_ci	radeon_connector = to_radeon_connector(connector);
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	switch (connector->connector_type) {
7148c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVII:
7158c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
7168c2ecf20Sopenharmony_ci		if (radeon_audio != 0) {
7178c2ecf20Sopenharmony_ci			if (radeon_connector->use_digital &&
7188c2ecf20Sopenharmony_ci			    (radeon_connector->audio == RADEON_AUDIO_ENABLE))
7198c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
7208c2ecf20Sopenharmony_ci			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7218c2ecf20Sopenharmony_ci				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
7228c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
7238c2ecf20Sopenharmony_ci			else if (radeon_connector->use_digital)
7248c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_DVI;
7258c2ecf20Sopenharmony_ci			else
7268c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_CRT;
7278c2ecf20Sopenharmony_ci		} else if (radeon_connector->use_digital) {
7288c2ecf20Sopenharmony_ci			return ATOM_ENCODER_MODE_DVI;
7298c2ecf20Sopenharmony_ci		} else {
7308c2ecf20Sopenharmony_ci			return ATOM_ENCODER_MODE_CRT;
7318c2ecf20Sopenharmony_ci		}
7328c2ecf20Sopenharmony_ci		break;
7338c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVID:
7348c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIA:
7358c2ecf20Sopenharmony_ci	default:
7368c2ecf20Sopenharmony_ci		if (radeon_audio != 0) {
7378c2ecf20Sopenharmony_ci			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
7388c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
7398c2ecf20Sopenharmony_ci			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7408c2ecf20Sopenharmony_ci				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
7418c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
7428c2ecf20Sopenharmony_ci			else
7438c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_DVI;
7448c2ecf20Sopenharmony_ci		} else {
7458c2ecf20Sopenharmony_ci			return ATOM_ENCODER_MODE_DVI;
7468c2ecf20Sopenharmony_ci		}
7478c2ecf20Sopenharmony_ci		break;
7488c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_LVDS:
7498c2ecf20Sopenharmony_ci		return ATOM_ENCODER_MODE_LVDS;
7508c2ecf20Sopenharmony_ci		break;
7518c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_DisplayPort:
7528c2ecf20Sopenharmony_ci		dig_connector = radeon_connector->con_priv;
7538c2ecf20Sopenharmony_ci		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
7548c2ecf20Sopenharmony_ci		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
7558c2ecf20Sopenharmony_ci			if (radeon_audio != 0 &&
7568c2ecf20Sopenharmony_ci			    drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
7578c2ecf20Sopenharmony_ci			    ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
7588c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_DP_AUDIO;
7598c2ecf20Sopenharmony_ci			return ATOM_ENCODER_MODE_DP;
7608c2ecf20Sopenharmony_ci		} else if (radeon_audio != 0) {
7618c2ecf20Sopenharmony_ci			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
7628c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
7638c2ecf20Sopenharmony_ci			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
7648c2ecf20Sopenharmony_ci				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
7658c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_HDMI;
7668c2ecf20Sopenharmony_ci			else
7678c2ecf20Sopenharmony_ci				return ATOM_ENCODER_MODE_DVI;
7688c2ecf20Sopenharmony_ci		} else {
7698c2ecf20Sopenharmony_ci			return ATOM_ENCODER_MODE_DVI;
7708c2ecf20Sopenharmony_ci		}
7718c2ecf20Sopenharmony_ci		break;
7728c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_eDP:
7738c2ecf20Sopenharmony_ci		if (radeon_audio != 0 &&
7748c2ecf20Sopenharmony_ci		    drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
7758c2ecf20Sopenharmony_ci		    ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
7768c2ecf20Sopenharmony_ci			return ATOM_ENCODER_MODE_DP_AUDIO;
7778c2ecf20Sopenharmony_ci		return ATOM_ENCODER_MODE_DP;
7788c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVIA:
7798c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_VGA:
7808c2ecf20Sopenharmony_ci		return ATOM_ENCODER_MODE_CRT;
7818c2ecf20Sopenharmony_ci		break;
7828c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_Composite:
7838c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_SVIDEO:
7848c2ecf20Sopenharmony_ci	case DRM_MODE_CONNECTOR_9PinDIN:
7858c2ecf20Sopenharmony_ci		/* fix me */
7868c2ecf20Sopenharmony_ci		return ATOM_ENCODER_MODE_TV;
7878c2ecf20Sopenharmony_ci		/*return ATOM_ENCODER_MODE_CV;*/
7888c2ecf20Sopenharmony_ci		break;
7898c2ecf20Sopenharmony_ci	}
7908c2ecf20Sopenharmony_ci}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci/*
7938c2ecf20Sopenharmony_ci * DIG Encoder/Transmitter Setup
7948c2ecf20Sopenharmony_ci *
7958c2ecf20Sopenharmony_ci * DCE 3.0/3.1
7968c2ecf20Sopenharmony_ci * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
7978c2ecf20Sopenharmony_ci * Supports up to 3 digital outputs
7988c2ecf20Sopenharmony_ci * - 2 DIG encoder blocks.
7998c2ecf20Sopenharmony_ci * DIG1 can drive UNIPHY link A or link B
8008c2ecf20Sopenharmony_ci * DIG2 can drive UNIPHY link B or LVTMA
8018c2ecf20Sopenharmony_ci *
8028c2ecf20Sopenharmony_ci * DCE 3.2
8038c2ecf20Sopenharmony_ci * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
8048c2ecf20Sopenharmony_ci * Supports up to 5 digital outputs
8058c2ecf20Sopenharmony_ci * - 2 DIG encoder blocks.
8068c2ecf20Sopenharmony_ci * DIG1/2 can drive UNIPHY0/1/2 link A or link B
8078c2ecf20Sopenharmony_ci *
8088c2ecf20Sopenharmony_ci * DCE 4.0/5.0/6.0
8098c2ecf20Sopenharmony_ci * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
8108c2ecf20Sopenharmony_ci * Supports up to 6 digital outputs
8118c2ecf20Sopenharmony_ci * - 6 DIG encoder blocks.
8128c2ecf20Sopenharmony_ci * - DIG to PHY mapping is hardcoded
8138c2ecf20Sopenharmony_ci * DIG1 drives UNIPHY0 link A, A+B
8148c2ecf20Sopenharmony_ci * DIG2 drives UNIPHY0 link B
8158c2ecf20Sopenharmony_ci * DIG3 drives UNIPHY1 link A, A+B
8168c2ecf20Sopenharmony_ci * DIG4 drives UNIPHY1 link B
8178c2ecf20Sopenharmony_ci * DIG5 drives UNIPHY2 link A, A+B
8188c2ecf20Sopenharmony_ci * DIG6 drives UNIPHY2 link B
8198c2ecf20Sopenharmony_ci *
8208c2ecf20Sopenharmony_ci * DCE 4.1
8218c2ecf20Sopenharmony_ci * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
8228c2ecf20Sopenharmony_ci * Supports up to 6 digital outputs
8238c2ecf20Sopenharmony_ci * - 2 DIG encoder blocks.
8248c2ecf20Sopenharmony_ci * llano
8258c2ecf20Sopenharmony_ci * DIG1/2 can drive UNIPHY0/1/2 link A or link B
8268c2ecf20Sopenharmony_ci * ontario
8278c2ecf20Sopenharmony_ci * DIG1 drives UNIPHY0/1/2 link A
8288c2ecf20Sopenharmony_ci * DIG2 drives UNIPHY0/1/2 link B
8298c2ecf20Sopenharmony_ci *
8308c2ecf20Sopenharmony_ci * Routing
8318c2ecf20Sopenharmony_ci * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
8328c2ecf20Sopenharmony_ci * Examples:
8338c2ecf20Sopenharmony_ci * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
8348c2ecf20Sopenharmony_ci * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
8358c2ecf20Sopenharmony_ci * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
8368c2ecf20Sopenharmony_ci * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
8378c2ecf20Sopenharmony_ci */
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ciunion dig_encoder_control {
8408c2ecf20Sopenharmony_ci	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
8418c2ecf20Sopenharmony_ci	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
8428c2ecf20Sopenharmony_ci	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
8438c2ecf20Sopenharmony_ci	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
8448c2ecf20Sopenharmony_ci};
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_civoid
8478c2ecf20Sopenharmony_ciatombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override)
8488c2ecf20Sopenharmony_ci{
8498c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
8508c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
8518c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
8528c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
8538c2ecf20Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
8548c2ecf20Sopenharmony_ci	union dig_encoder_control args;
8558c2ecf20Sopenharmony_ci	int index = 0;
8568c2ecf20Sopenharmony_ci	uint8_t frev, crev;
8578c2ecf20Sopenharmony_ci	int dp_clock = 0;
8588c2ecf20Sopenharmony_ci	int dp_lane_count = 0;
8598c2ecf20Sopenharmony_ci	int hpd_id = RADEON_HPD_NONE;
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	if (connector) {
8628c2ecf20Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
8638c2ecf20Sopenharmony_ci		struct radeon_connector_atom_dig *dig_connector =
8648c2ecf20Sopenharmony_ci			radeon_connector->con_priv;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci		dp_clock = dig_connector->dp_clock;
8678c2ecf20Sopenharmony_ci		dp_lane_count = dig_connector->dp_lane_count;
8688c2ecf20Sopenharmony_ci		hpd_id = radeon_connector->hpd.hpd;
8698c2ecf20Sopenharmony_ci	}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	/* no dig encoder assigned */
8728c2ecf20Sopenharmony_ci	if (dig->dig_encoder == -1)
8738c2ecf20Sopenharmony_ci		return;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	if (ASIC_IS_DCE4(rdev))
8788c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
8798c2ecf20Sopenharmony_ci	else {
8808c2ecf20Sopenharmony_ci		if (dig->dig_encoder)
8818c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
8828c2ecf20Sopenharmony_ci		else
8838c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
8848c2ecf20Sopenharmony_ci	}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
8878c2ecf20Sopenharmony_ci		return;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	switch (frev) {
8908c2ecf20Sopenharmony_ci	case 1:
8918c2ecf20Sopenharmony_ci		switch (crev) {
8928c2ecf20Sopenharmony_ci		case 1:
8938c2ecf20Sopenharmony_ci			args.v1.ucAction = action;
8948c2ecf20Sopenharmony_ci			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
8958c2ecf20Sopenharmony_ci			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
8968c2ecf20Sopenharmony_ci				args.v3.ucPanelMode = panel_mode;
8978c2ecf20Sopenharmony_ci			else
8988c2ecf20Sopenharmony_ci				args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
9018c2ecf20Sopenharmony_ci				args.v1.ucLaneNum = dp_lane_count;
9028c2ecf20Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
9038c2ecf20Sopenharmony_ci				args.v1.ucLaneNum = 8;
9048c2ecf20Sopenharmony_ci			else
9058c2ecf20Sopenharmony_ci				args.v1.ucLaneNum = 4;
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
9088c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
9098c2ecf20Sopenharmony_ci				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
9108c2ecf20Sopenharmony_ci				break;
9118c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
9128c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
9138c2ecf20Sopenharmony_ci				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
9148c2ecf20Sopenharmony_ci				break;
9158c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
9168c2ecf20Sopenharmony_ci				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
9178c2ecf20Sopenharmony_ci				break;
9188c2ecf20Sopenharmony_ci			}
9198c2ecf20Sopenharmony_ci			if (dig->linkb)
9208c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
9218c2ecf20Sopenharmony_ci			else
9228c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
9258c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci			break;
9288c2ecf20Sopenharmony_ci		case 2:
9298c2ecf20Sopenharmony_ci		case 3:
9308c2ecf20Sopenharmony_ci			args.v3.ucAction = action;
9318c2ecf20Sopenharmony_ci			args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
9328c2ecf20Sopenharmony_ci			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
9338c2ecf20Sopenharmony_ci				args.v3.ucPanelMode = panel_mode;
9348c2ecf20Sopenharmony_ci			else
9358c2ecf20Sopenharmony_ci				args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode))
9388c2ecf20Sopenharmony_ci				args.v3.ucLaneNum = dp_lane_count;
9398c2ecf20Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
9408c2ecf20Sopenharmony_ci				args.v3.ucLaneNum = 8;
9418c2ecf20Sopenharmony_ci			else
9428c2ecf20Sopenharmony_ci				args.v3.ucLaneNum = 4;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
9458c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
9468c2ecf20Sopenharmony_ci			if (enc_override != -1)
9478c2ecf20Sopenharmony_ci				args.v3.acConfig.ucDigSel = enc_override;
9488c2ecf20Sopenharmony_ci			else
9498c2ecf20Sopenharmony_ci				args.v3.acConfig.ucDigSel = dig->dig_encoder;
9508c2ecf20Sopenharmony_ci			args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
9518c2ecf20Sopenharmony_ci			break;
9528c2ecf20Sopenharmony_ci		case 4:
9538c2ecf20Sopenharmony_ci			args.v4.ucAction = action;
9548c2ecf20Sopenharmony_ci			args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
9558c2ecf20Sopenharmony_ci			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
9568c2ecf20Sopenharmony_ci				args.v4.ucPanelMode = panel_mode;
9578c2ecf20Sopenharmony_ci			else
9588c2ecf20Sopenharmony_ci				args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode))
9618c2ecf20Sopenharmony_ci				args.v4.ucLaneNum = dp_lane_count;
9628c2ecf20Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
9638c2ecf20Sopenharmony_ci				args.v4.ucLaneNum = 8;
9648c2ecf20Sopenharmony_ci			else
9658c2ecf20Sopenharmony_ci				args.v4.ucLaneNum = 4;
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) {
9688c2ecf20Sopenharmony_ci				if (dp_clock == 540000)
9698c2ecf20Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
9708c2ecf20Sopenharmony_ci				else if (dp_clock == 324000)
9718c2ecf20Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ;
9728c2ecf20Sopenharmony_ci				else if (dp_clock == 270000)
9738c2ecf20Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
9748c2ecf20Sopenharmony_ci				else
9758c2ecf20Sopenharmony_ci					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
9768c2ecf20Sopenharmony_ci			}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci			if (enc_override != -1)
9798c2ecf20Sopenharmony_ci				args.v4.acConfig.ucDigSel = enc_override;
9808c2ecf20Sopenharmony_ci			else
9818c2ecf20Sopenharmony_ci				args.v4.acConfig.ucDigSel = dig->dig_encoder;
9828c2ecf20Sopenharmony_ci			args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
9838c2ecf20Sopenharmony_ci			if (hpd_id == RADEON_HPD_NONE)
9848c2ecf20Sopenharmony_ci				args.v4.ucHPD_ID = 0;
9858c2ecf20Sopenharmony_ci			else
9868c2ecf20Sopenharmony_ci				args.v4.ucHPD_ID = hpd_id + 1;
9878c2ecf20Sopenharmony_ci			break;
9888c2ecf20Sopenharmony_ci		default:
9898c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
9908c2ecf20Sopenharmony_ci			break;
9918c2ecf20Sopenharmony_ci		}
9928c2ecf20Sopenharmony_ci		break;
9938c2ecf20Sopenharmony_ci	default:
9948c2ecf20Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
9958c2ecf20Sopenharmony_ci		break;
9968c2ecf20Sopenharmony_ci	}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci}
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_civoid
10038c2ecf20Sopenharmony_ciatombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
10048c2ecf20Sopenharmony_ci{
10058c2ecf20Sopenharmony_ci	atombios_dig_encoder_setup2(encoder, action, panel_mode, -1);
10068c2ecf20Sopenharmony_ci}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ciunion dig_transmitter_control {
10098c2ecf20Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
10108c2ecf20Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
10118c2ecf20Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
10128c2ecf20Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
10138c2ecf20Sopenharmony_ci	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
10148c2ecf20Sopenharmony_ci};
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_civoid
10178c2ecf20Sopenharmony_ciatombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe)
10188c2ecf20Sopenharmony_ci{
10198c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
10208c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
10218c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
10228c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
10238c2ecf20Sopenharmony_ci	struct drm_connector *connector;
10248c2ecf20Sopenharmony_ci	union dig_transmitter_control args;
10258c2ecf20Sopenharmony_ci	int index = 0;
10268c2ecf20Sopenharmony_ci	uint8_t frev, crev;
10278c2ecf20Sopenharmony_ci	bool is_dp = false;
10288c2ecf20Sopenharmony_ci	int pll_id = 0;
10298c2ecf20Sopenharmony_ci	int dp_clock = 0;
10308c2ecf20Sopenharmony_ci	int dp_lane_count = 0;
10318c2ecf20Sopenharmony_ci	int connector_object_id = 0;
10328c2ecf20Sopenharmony_ci	int igp_lane_info = 0;
10338c2ecf20Sopenharmony_ci	int dig_encoder = dig->dig_encoder;
10348c2ecf20Sopenharmony_ci	int hpd_id = RADEON_HPD_NONE;
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
10378c2ecf20Sopenharmony_ci		connector = radeon_get_connector_for_encoder_init(encoder);
10388c2ecf20Sopenharmony_ci		/* just needed to avoid bailing in the encoder check.  the encoder
10398c2ecf20Sopenharmony_ci		 * isn't used for init
10408c2ecf20Sopenharmony_ci		 */
10418c2ecf20Sopenharmony_ci		dig_encoder = 0;
10428c2ecf20Sopenharmony_ci	} else
10438c2ecf20Sopenharmony_ci		connector = radeon_get_connector_for_encoder(encoder);
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	if (connector) {
10468c2ecf20Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
10478c2ecf20Sopenharmony_ci		struct radeon_connector_atom_dig *dig_connector =
10488c2ecf20Sopenharmony_ci			radeon_connector->con_priv;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		hpd_id = radeon_connector->hpd.hpd;
10518c2ecf20Sopenharmony_ci		dp_clock = dig_connector->dp_clock;
10528c2ecf20Sopenharmony_ci		dp_lane_count = dig_connector->dp_lane_count;
10538c2ecf20Sopenharmony_ci		connector_object_id =
10548c2ecf20Sopenharmony_ci			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
10558c2ecf20Sopenharmony_ci		igp_lane_info = dig_connector->igp_lane_info;
10568c2ecf20Sopenharmony_ci	}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	if (encoder->crtc) {
10598c2ecf20Sopenharmony_ci		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
10608c2ecf20Sopenharmony_ci		pll_id = radeon_crtc->pll_id;
10618c2ecf20Sopenharmony_ci	}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	/* no dig encoder assigned */
10648c2ecf20Sopenharmony_ci	if (dig_encoder == -1)
10658c2ecf20Sopenharmony_ci		return;
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
10688c2ecf20Sopenharmony_ci		is_dp = true;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
10738c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
10748c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
10758c2ecf20Sopenharmony_ci		break;
10768c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
10778c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
10788c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
10798c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
10808c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
10818c2ecf20Sopenharmony_ci		break;
10828c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
10838c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
10848c2ecf20Sopenharmony_ci		break;
10858c2ecf20Sopenharmony_ci	}
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
10888c2ecf20Sopenharmony_ci		return;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	switch (frev) {
10918c2ecf20Sopenharmony_ci	case 1:
10928c2ecf20Sopenharmony_ci		switch (crev) {
10938c2ecf20Sopenharmony_ci		case 1:
10948c2ecf20Sopenharmony_ci			args.v1.ucAction = action;
10958c2ecf20Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
10968c2ecf20Sopenharmony_ci				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
10978c2ecf20Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
10988c2ecf20Sopenharmony_ci				args.v1.asMode.ucLaneSel = lane_num;
10998c2ecf20Sopenharmony_ci				args.v1.asMode.ucLaneSet = lane_set;
11008c2ecf20Sopenharmony_ci			} else {
11018c2ecf20Sopenharmony_ci				if (is_dp)
11028c2ecf20Sopenharmony_ci					args.v1.usPixelClock = cpu_to_le16(dp_clock / 10);
11038c2ecf20Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
11048c2ecf20Sopenharmony_ci					args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
11058c2ecf20Sopenharmony_ci				else
11068c2ecf20Sopenharmony_ci					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
11078c2ecf20Sopenharmony_ci			}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci			if (dig_encoder)
11128c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
11138c2ecf20Sopenharmony_ci			else
11148c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci			if ((rdev->flags & RADEON_IS_IGP) &&
11178c2ecf20Sopenharmony_ci			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
11188c2ecf20Sopenharmony_ci				if (is_dp ||
11198c2ecf20Sopenharmony_ci				    !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
11208c2ecf20Sopenharmony_ci					if (igp_lane_info & 0x1)
11218c2ecf20Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
11228c2ecf20Sopenharmony_ci					else if (igp_lane_info & 0x2)
11238c2ecf20Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
11248c2ecf20Sopenharmony_ci					else if (igp_lane_info & 0x4)
11258c2ecf20Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
11268c2ecf20Sopenharmony_ci					else if (igp_lane_info & 0x8)
11278c2ecf20Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
11288c2ecf20Sopenharmony_ci				} else {
11298c2ecf20Sopenharmony_ci					if (igp_lane_info & 0x3)
11308c2ecf20Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
11318c2ecf20Sopenharmony_ci					else if (igp_lane_info & 0xc)
11328c2ecf20Sopenharmony_ci						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
11338c2ecf20Sopenharmony_ci				}
11348c2ecf20Sopenharmony_ci			}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci			if (dig->linkb)
11378c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
11388c2ecf20Sopenharmony_ci			else
11398c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci			if (is_dp)
11428c2ecf20Sopenharmony_ci				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
11438c2ecf20Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
11448c2ecf20Sopenharmony_ci				if (dig->coherent_mode)
11458c2ecf20Sopenharmony_ci					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
11468c2ecf20Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
11478c2ecf20Sopenharmony_ci					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
11488c2ecf20Sopenharmony_ci			}
11498c2ecf20Sopenharmony_ci			break;
11508c2ecf20Sopenharmony_ci		case 2:
11518c2ecf20Sopenharmony_ci			args.v2.ucAction = action;
11528c2ecf20Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
11538c2ecf20Sopenharmony_ci				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
11548c2ecf20Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
11558c2ecf20Sopenharmony_ci				args.v2.asMode.ucLaneSel = lane_num;
11568c2ecf20Sopenharmony_ci				args.v2.asMode.ucLaneSet = lane_set;
11578c2ecf20Sopenharmony_ci			} else {
11588c2ecf20Sopenharmony_ci				if (is_dp)
11598c2ecf20Sopenharmony_ci					args.v2.usPixelClock = cpu_to_le16(dp_clock / 10);
11608c2ecf20Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
11618c2ecf20Sopenharmony_ci					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
11628c2ecf20Sopenharmony_ci				else
11638c2ecf20Sopenharmony_ci					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
11648c2ecf20Sopenharmony_ci			}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci			args.v2.acConfig.ucEncoderSel = dig_encoder;
11678c2ecf20Sopenharmony_ci			if (dig->linkb)
11688c2ecf20Sopenharmony_ci				args.v2.acConfig.ucLinkSel = 1;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
11718c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
11728c2ecf20Sopenharmony_ci				args.v2.acConfig.ucTransmitterSel = 0;
11738c2ecf20Sopenharmony_ci				break;
11748c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
11758c2ecf20Sopenharmony_ci				args.v2.acConfig.ucTransmitterSel = 1;
11768c2ecf20Sopenharmony_ci				break;
11778c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
11788c2ecf20Sopenharmony_ci				args.v2.acConfig.ucTransmitterSel = 2;
11798c2ecf20Sopenharmony_ci				break;
11808c2ecf20Sopenharmony_ci			}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci			if (is_dp) {
11838c2ecf20Sopenharmony_ci				args.v2.acConfig.fCoherentMode = 1;
11848c2ecf20Sopenharmony_ci				args.v2.acConfig.fDPConnector = 1;
11858c2ecf20Sopenharmony_ci			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
11868c2ecf20Sopenharmony_ci				if (dig->coherent_mode)
11878c2ecf20Sopenharmony_ci					args.v2.acConfig.fCoherentMode = 1;
11888c2ecf20Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
11898c2ecf20Sopenharmony_ci					args.v2.acConfig.fDualLinkConnector = 1;
11908c2ecf20Sopenharmony_ci			}
11918c2ecf20Sopenharmony_ci			break;
11928c2ecf20Sopenharmony_ci		case 3:
11938c2ecf20Sopenharmony_ci			args.v3.ucAction = action;
11948c2ecf20Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
11958c2ecf20Sopenharmony_ci				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
11968c2ecf20Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
11978c2ecf20Sopenharmony_ci				args.v3.asMode.ucLaneSel = lane_num;
11988c2ecf20Sopenharmony_ci				args.v3.asMode.ucLaneSet = lane_set;
11998c2ecf20Sopenharmony_ci			} else {
12008c2ecf20Sopenharmony_ci				if (is_dp)
12018c2ecf20Sopenharmony_ci					args.v3.usPixelClock = cpu_to_le16(dp_clock / 10);
12028c2ecf20Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
12038c2ecf20Sopenharmony_ci					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
12048c2ecf20Sopenharmony_ci				else
12058c2ecf20Sopenharmony_ci					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
12068c2ecf20Sopenharmony_ci			}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci			if (is_dp)
12098c2ecf20Sopenharmony_ci				args.v3.ucLaneNum = dp_lane_count;
12108c2ecf20Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
12118c2ecf20Sopenharmony_ci				args.v3.ucLaneNum = 8;
12128c2ecf20Sopenharmony_ci			else
12138c2ecf20Sopenharmony_ci				args.v3.ucLaneNum = 4;
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci			if (dig->linkb)
12168c2ecf20Sopenharmony_ci				args.v3.acConfig.ucLinkSel = 1;
12178c2ecf20Sopenharmony_ci			if (dig_encoder & 1)
12188c2ecf20Sopenharmony_ci				args.v3.acConfig.ucEncoderSel = 1;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci			/* Select the PLL for the PHY
12218c2ecf20Sopenharmony_ci			 * DP PHY should be clocked from external src if there is
12228c2ecf20Sopenharmony_ci			 * one.
12238c2ecf20Sopenharmony_ci			 */
12248c2ecf20Sopenharmony_ci			/* On DCE4, if there is an external clock, it generates the DP ref clock */
12258c2ecf20Sopenharmony_ci			if (is_dp && rdev->clock.dp_extclk)
12268c2ecf20Sopenharmony_ci				args.v3.acConfig.ucRefClkSource = 2; /* external src */
12278c2ecf20Sopenharmony_ci			else
12288c2ecf20Sopenharmony_ci				args.v3.acConfig.ucRefClkSource = pll_id;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
12318c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
12328c2ecf20Sopenharmony_ci				args.v3.acConfig.ucTransmitterSel = 0;
12338c2ecf20Sopenharmony_ci				break;
12348c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
12358c2ecf20Sopenharmony_ci				args.v3.acConfig.ucTransmitterSel = 1;
12368c2ecf20Sopenharmony_ci				break;
12378c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
12388c2ecf20Sopenharmony_ci				args.v3.acConfig.ucTransmitterSel = 2;
12398c2ecf20Sopenharmony_ci				break;
12408c2ecf20Sopenharmony_ci			}
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci			if (is_dp)
12438c2ecf20Sopenharmony_ci				args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
12448c2ecf20Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
12458c2ecf20Sopenharmony_ci				if (dig->coherent_mode)
12468c2ecf20Sopenharmony_ci					args.v3.acConfig.fCoherentMode = 1;
12478c2ecf20Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
12488c2ecf20Sopenharmony_ci					args.v3.acConfig.fDualLinkConnector = 1;
12498c2ecf20Sopenharmony_ci			}
12508c2ecf20Sopenharmony_ci			break;
12518c2ecf20Sopenharmony_ci		case 4:
12528c2ecf20Sopenharmony_ci			args.v4.ucAction = action;
12538c2ecf20Sopenharmony_ci			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
12548c2ecf20Sopenharmony_ci				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
12558c2ecf20Sopenharmony_ci			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
12568c2ecf20Sopenharmony_ci				args.v4.asMode.ucLaneSel = lane_num;
12578c2ecf20Sopenharmony_ci				args.v4.asMode.ucLaneSet = lane_set;
12588c2ecf20Sopenharmony_ci			} else {
12598c2ecf20Sopenharmony_ci				if (is_dp)
12608c2ecf20Sopenharmony_ci					args.v4.usPixelClock = cpu_to_le16(dp_clock / 10);
12618c2ecf20Sopenharmony_ci				else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
12628c2ecf20Sopenharmony_ci					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
12638c2ecf20Sopenharmony_ci				else
12648c2ecf20Sopenharmony_ci					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
12658c2ecf20Sopenharmony_ci			}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci			if (is_dp)
12688c2ecf20Sopenharmony_ci				args.v4.ucLaneNum = dp_lane_count;
12698c2ecf20Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
12708c2ecf20Sopenharmony_ci				args.v4.ucLaneNum = 8;
12718c2ecf20Sopenharmony_ci			else
12728c2ecf20Sopenharmony_ci				args.v4.ucLaneNum = 4;
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci			if (dig->linkb)
12758c2ecf20Sopenharmony_ci				args.v4.acConfig.ucLinkSel = 1;
12768c2ecf20Sopenharmony_ci			if (dig_encoder & 1)
12778c2ecf20Sopenharmony_ci				args.v4.acConfig.ucEncoderSel = 1;
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci			/* Select the PLL for the PHY
12808c2ecf20Sopenharmony_ci			 * DP PHY should be clocked from external src if there is
12818c2ecf20Sopenharmony_ci			 * one.
12828c2ecf20Sopenharmony_ci			 */
12838c2ecf20Sopenharmony_ci			/* On DCE5 DCPLL usually generates the DP ref clock */
12848c2ecf20Sopenharmony_ci			if (is_dp) {
12858c2ecf20Sopenharmony_ci				if (rdev->clock.dp_extclk)
12868c2ecf20Sopenharmony_ci					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
12878c2ecf20Sopenharmony_ci				else
12888c2ecf20Sopenharmony_ci					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
12898c2ecf20Sopenharmony_ci			} else
12908c2ecf20Sopenharmony_ci				args.v4.acConfig.ucRefClkSource = pll_id;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
12938c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
12948c2ecf20Sopenharmony_ci				args.v4.acConfig.ucTransmitterSel = 0;
12958c2ecf20Sopenharmony_ci				break;
12968c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
12978c2ecf20Sopenharmony_ci				args.v4.acConfig.ucTransmitterSel = 1;
12988c2ecf20Sopenharmony_ci				break;
12998c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
13008c2ecf20Sopenharmony_ci				args.v4.acConfig.ucTransmitterSel = 2;
13018c2ecf20Sopenharmony_ci				break;
13028c2ecf20Sopenharmony_ci			}
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci			if (is_dp)
13058c2ecf20Sopenharmony_ci				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
13068c2ecf20Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
13078c2ecf20Sopenharmony_ci				if (dig->coherent_mode)
13088c2ecf20Sopenharmony_ci					args.v4.acConfig.fCoherentMode = 1;
13098c2ecf20Sopenharmony_ci				if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
13108c2ecf20Sopenharmony_ci					args.v4.acConfig.fDualLinkConnector = 1;
13118c2ecf20Sopenharmony_ci			}
13128c2ecf20Sopenharmony_ci			break;
13138c2ecf20Sopenharmony_ci		case 5:
13148c2ecf20Sopenharmony_ci			args.v5.ucAction = action;
13158c2ecf20Sopenharmony_ci			if (is_dp)
13168c2ecf20Sopenharmony_ci				args.v5.usSymClock = cpu_to_le16(dp_clock / 10);
13178c2ecf20Sopenharmony_ci			else
13188c2ecf20Sopenharmony_ci				args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
13218c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
13228c2ecf20Sopenharmony_ci				if (dig->linkb)
13238c2ecf20Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
13248c2ecf20Sopenharmony_ci				else
13258c2ecf20Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
13268c2ecf20Sopenharmony_ci				break;
13278c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
13288c2ecf20Sopenharmony_ci				if (dig->linkb)
13298c2ecf20Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
13308c2ecf20Sopenharmony_ci				else
13318c2ecf20Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
13328c2ecf20Sopenharmony_ci				break;
13338c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
13348c2ecf20Sopenharmony_ci				if (dig->linkb)
13358c2ecf20Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
13368c2ecf20Sopenharmony_ci				else
13378c2ecf20Sopenharmony_ci					args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
13388c2ecf20Sopenharmony_ci				break;
13398c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
13408c2ecf20Sopenharmony_ci				args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG;
13418c2ecf20Sopenharmony_ci				break;
13428c2ecf20Sopenharmony_ci			}
13438c2ecf20Sopenharmony_ci			if (is_dp)
13448c2ecf20Sopenharmony_ci				args.v5.ucLaneNum = dp_lane_count;
13458c2ecf20Sopenharmony_ci			else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
13468c2ecf20Sopenharmony_ci				args.v5.ucLaneNum = 8;
13478c2ecf20Sopenharmony_ci			else
13488c2ecf20Sopenharmony_ci				args.v5.ucLaneNum = 4;
13498c2ecf20Sopenharmony_ci			args.v5.ucConnObjId = connector_object_id;
13508c2ecf20Sopenharmony_ci			args.v5.ucDigMode = atombios_get_encoder_mode(encoder);
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci			if (is_dp && rdev->clock.dp_extclk)
13538c2ecf20Sopenharmony_ci				args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK;
13548c2ecf20Sopenharmony_ci			else
13558c2ecf20Sopenharmony_ci				args.v5.asConfig.ucPhyClkSrcId = pll_id;
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_ci			if (is_dp)
13588c2ecf20Sopenharmony_ci				args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */
13598c2ecf20Sopenharmony_ci			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
13608c2ecf20Sopenharmony_ci				if (dig->coherent_mode)
13618c2ecf20Sopenharmony_ci					args.v5.asConfig.ucCoherentMode = 1;
13628c2ecf20Sopenharmony_ci			}
13638c2ecf20Sopenharmony_ci			if (hpd_id == RADEON_HPD_NONE)
13648c2ecf20Sopenharmony_ci				args.v5.asConfig.ucHPDSel = 0;
13658c2ecf20Sopenharmony_ci			else
13668c2ecf20Sopenharmony_ci				args.v5.asConfig.ucHPDSel = hpd_id + 1;
13678c2ecf20Sopenharmony_ci			args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder);
13688c2ecf20Sopenharmony_ci			args.v5.ucDPLaneSet = lane_set;
13698c2ecf20Sopenharmony_ci			break;
13708c2ecf20Sopenharmony_ci		default:
13718c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
13728c2ecf20Sopenharmony_ci			break;
13738c2ecf20Sopenharmony_ci		}
13748c2ecf20Sopenharmony_ci		break;
13758c2ecf20Sopenharmony_ci	default:
13768c2ecf20Sopenharmony_ci		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
13778c2ecf20Sopenharmony_ci		break;
13788c2ecf20Sopenharmony_ci	}
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
13818c2ecf20Sopenharmony_ci}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_civoid
13848c2ecf20Sopenharmony_ciatombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
13858c2ecf20Sopenharmony_ci{
13868c2ecf20Sopenharmony_ci	atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1);
13878c2ecf20Sopenharmony_ci}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_cibool
13908c2ecf20Sopenharmony_ciatombios_set_edp_panel_power(struct drm_connector *connector, int action)
13918c2ecf20Sopenharmony_ci{
13928c2ecf20Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
13938c2ecf20Sopenharmony_ci	struct drm_device *dev = radeon_connector->base.dev;
13948c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
13958c2ecf20Sopenharmony_ci	union dig_transmitter_control args;
13968c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
13978c2ecf20Sopenharmony_ci	uint8_t frev, crev;
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
14008c2ecf20Sopenharmony_ci		goto done;
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	if (!ASIC_IS_DCE4(rdev))
14038c2ecf20Sopenharmony_ci		goto done;
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
14068c2ecf20Sopenharmony_ci	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
14078c2ecf20Sopenharmony_ci		goto done;
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
14108c2ecf20Sopenharmony_ci		goto done;
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	args.v1.ucAction = action;
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	/* wait for the panel to power up */
14198c2ecf20Sopenharmony_ci	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
14208c2ecf20Sopenharmony_ci		int i;
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci		for (i = 0; i < 300; i++) {
14238c2ecf20Sopenharmony_ci			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
14248c2ecf20Sopenharmony_ci				return true;
14258c2ecf20Sopenharmony_ci			mdelay(1);
14268c2ecf20Sopenharmony_ci		}
14278c2ecf20Sopenharmony_ci		return false;
14288c2ecf20Sopenharmony_ci	}
14298c2ecf20Sopenharmony_cidone:
14308c2ecf20Sopenharmony_ci	return true;
14318c2ecf20Sopenharmony_ci}
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ciunion external_encoder_control {
14348c2ecf20Sopenharmony_ci	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
14358c2ecf20Sopenharmony_ci	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
14368c2ecf20Sopenharmony_ci};
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_cistatic void
14398c2ecf20Sopenharmony_ciatombios_external_encoder_setup(struct drm_encoder *encoder,
14408c2ecf20Sopenharmony_ci				struct drm_encoder *ext_encoder,
14418c2ecf20Sopenharmony_ci				int action)
14428c2ecf20Sopenharmony_ci{
14438c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
14448c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
14458c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
14468c2ecf20Sopenharmony_ci	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
14478c2ecf20Sopenharmony_ci	union external_encoder_control args;
14488c2ecf20Sopenharmony_ci	struct drm_connector *connector;
14498c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
14508c2ecf20Sopenharmony_ci	u8 frev, crev;
14518c2ecf20Sopenharmony_ci	int dp_clock = 0;
14528c2ecf20Sopenharmony_ci	int dp_lane_count = 0;
14538c2ecf20Sopenharmony_ci	int connector_object_id = 0;
14548c2ecf20Sopenharmony_ci	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
14578c2ecf20Sopenharmony_ci		connector = radeon_get_connector_for_encoder_init(encoder);
14588c2ecf20Sopenharmony_ci	else
14598c2ecf20Sopenharmony_ci		connector = radeon_get_connector_for_encoder(encoder);
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	if (connector) {
14628c2ecf20Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
14638c2ecf20Sopenharmony_ci		struct radeon_connector_atom_dig *dig_connector =
14648c2ecf20Sopenharmony_ci			radeon_connector->con_priv;
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci		dp_clock = dig_connector->dp_clock;
14678c2ecf20Sopenharmony_ci		dp_lane_count = dig_connector->dp_lane_count;
14688c2ecf20Sopenharmony_ci		connector_object_id =
14698c2ecf20Sopenharmony_ci			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
14708c2ecf20Sopenharmony_ci	}
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
14758c2ecf20Sopenharmony_ci		return;
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	switch (frev) {
14788c2ecf20Sopenharmony_ci	case 1:
14798c2ecf20Sopenharmony_ci		/* no params on frev 1 */
14808c2ecf20Sopenharmony_ci		break;
14818c2ecf20Sopenharmony_ci	case 2:
14828c2ecf20Sopenharmony_ci		switch (crev) {
14838c2ecf20Sopenharmony_ci		case 1:
14848c2ecf20Sopenharmony_ci		case 2:
14858c2ecf20Sopenharmony_ci			args.v1.sDigEncoder.ucAction = action;
14868c2ecf20Sopenharmony_ci			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
14878c2ecf20Sopenharmony_ci			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
14908c2ecf20Sopenharmony_ci				if (dp_clock == 270000)
14918c2ecf20Sopenharmony_ci					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
14928c2ecf20Sopenharmony_ci				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
14938c2ecf20Sopenharmony_ci			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
14948c2ecf20Sopenharmony_ci				args.v1.sDigEncoder.ucLaneNum = 8;
14958c2ecf20Sopenharmony_ci			else
14968c2ecf20Sopenharmony_ci				args.v1.sDigEncoder.ucLaneNum = 4;
14978c2ecf20Sopenharmony_ci			break;
14988c2ecf20Sopenharmony_ci		case 3:
14998c2ecf20Sopenharmony_ci			args.v3.sExtEncoder.ucAction = action;
15008c2ecf20Sopenharmony_ci			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
15018c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
15028c2ecf20Sopenharmony_ci			else
15038c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
15048c2ecf20Sopenharmony_ci			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
15078c2ecf20Sopenharmony_ci				if (dp_clock == 270000)
15088c2ecf20Sopenharmony_ci					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
15098c2ecf20Sopenharmony_ci				else if (dp_clock == 540000)
15108c2ecf20Sopenharmony_ci					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
15118c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
15128c2ecf20Sopenharmony_ci			} else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
15138c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.ucLaneNum = 8;
15148c2ecf20Sopenharmony_ci			else
15158c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.ucLaneNum = 4;
15168c2ecf20Sopenharmony_ci			switch (ext_enum) {
15178c2ecf20Sopenharmony_ci			case GRAPH_OBJECT_ENUM_ID1:
15188c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
15198c2ecf20Sopenharmony_ci				break;
15208c2ecf20Sopenharmony_ci			case GRAPH_OBJECT_ENUM_ID2:
15218c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
15228c2ecf20Sopenharmony_ci				break;
15238c2ecf20Sopenharmony_ci			case GRAPH_OBJECT_ENUM_ID3:
15248c2ecf20Sopenharmony_ci				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
15258c2ecf20Sopenharmony_ci				break;
15268c2ecf20Sopenharmony_ci			}
15278c2ecf20Sopenharmony_ci			args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder);
15288c2ecf20Sopenharmony_ci			break;
15298c2ecf20Sopenharmony_ci		default:
15308c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
15318c2ecf20Sopenharmony_ci			return;
15328c2ecf20Sopenharmony_ci		}
15338c2ecf20Sopenharmony_ci		break;
15348c2ecf20Sopenharmony_ci	default:
15358c2ecf20Sopenharmony_ci		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
15368c2ecf20Sopenharmony_ci		return;
15378c2ecf20Sopenharmony_ci	}
15388c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
15398c2ecf20Sopenharmony_ci}
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_cistatic void
15428c2ecf20Sopenharmony_ciatombios_yuv_setup(struct drm_encoder *encoder, bool enable)
15438c2ecf20Sopenharmony_ci{
15448c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
15458c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
15468c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
15478c2ecf20Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
15488c2ecf20Sopenharmony_ci	ENABLE_YUV_PS_ALLOCATION args;
15498c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
15508c2ecf20Sopenharmony_ci	uint32_t temp, reg;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	if (rdev->family >= CHIP_R600)
15558c2ecf20Sopenharmony_ci		reg = R600_BIOS_3_SCRATCH;
15568c2ecf20Sopenharmony_ci	else
15578c2ecf20Sopenharmony_ci		reg = RADEON_BIOS_3_SCRATCH;
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	/* XXX: fix up scratch reg handling */
15608c2ecf20Sopenharmony_ci	temp = RREG32(reg);
15618c2ecf20Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
15628c2ecf20Sopenharmony_ci		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
15638c2ecf20Sopenharmony_ci			     (radeon_crtc->crtc_id << 18)));
15648c2ecf20Sopenharmony_ci	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
15658c2ecf20Sopenharmony_ci		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
15668c2ecf20Sopenharmony_ci	else
15678c2ecf20Sopenharmony_ci		WREG32(reg, 0);
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci	if (enable)
15708c2ecf20Sopenharmony_ci		args.ucEnable = ATOM_ENABLE;
15718c2ecf20Sopenharmony_ci	args.ucCRTC = radeon_crtc->crtc_id;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	WREG32(reg, temp);
15768c2ecf20Sopenharmony_ci}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_cistatic void
15798c2ecf20Sopenharmony_ciradeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
15808c2ecf20Sopenharmony_ci{
15818c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
15828c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
15838c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
15848c2ecf20Sopenharmony_ci	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
15858c2ecf20Sopenharmony_ci	int index = 0;
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
15908c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
15918c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
15928c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
15938c2ecf20Sopenharmony_ci		break;
15948c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
15958c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
15968c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
15978c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
15988c2ecf20Sopenharmony_ci		break;
15998c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
16008c2ecf20Sopenharmony_ci		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
16018c2ecf20Sopenharmony_ci		break;
16028c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
16038c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
16048c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
16058c2ecf20Sopenharmony_ci		else
16068c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
16078c2ecf20Sopenharmony_ci		break;
16088c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
16098c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
16108c2ecf20Sopenharmony_ci		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
16118c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
16128c2ecf20Sopenharmony_ci		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
16138c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
16148c2ecf20Sopenharmony_ci		else
16158c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
16168c2ecf20Sopenharmony_ci		break;
16178c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
16188c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
16198c2ecf20Sopenharmony_ci		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
16208c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
16218c2ecf20Sopenharmony_ci		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
16228c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
16238c2ecf20Sopenharmony_ci		else
16248c2ecf20Sopenharmony_ci			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
16258c2ecf20Sopenharmony_ci		break;
16268c2ecf20Sopenharmony_ci	default:
16278c2ecf20Sopenharmony_ci		return;
16288c2ecf20Sopenharmony_ci	}
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	switch (mode) {
16318c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_ON:
16328c2ecf20Sopenharmony_ci		args.ucAction = ATOM_ENABLE;
16338c2ecf20Sopenharmony_ci		/* workaround for DVOOutputControl on some RS690 systems */
16348c2ecf20Sopenharmony_ci		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
16358c2ecf20Sopenharmony_ci			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
16368c2ecf20Sopenharmony_ci			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
16378c2ecf20Sopenharmony_ci			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
16388c2ecf20Sopenharmony_ci			WREG32(RADEON_BIOS_3_SCRATCH, reg);
16398c2ecf20Sopenharmony_ci		} else
16408c2ecf20Sopenharmony_ci			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
16418c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
16428c2ecf20Sopenharmony_ci			if (rdev->mode_info.bl_encoder) {
16438c2ecf20Sopenharmony_ci				struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci				atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
16468c2ecf20Sopenharmony_ci			} else {
16478c2ecf20Sopenharmony_ci				args.ucAction = ATOM_LCD_BLON;
16488c2ecf20Sopenharmony_ci				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
16498c2ecf20Sopenharmony_ci			}
16508c2ecf20Sopenharmony_ci		}
16518c2ecf20Sopenharmony_ci		break;
16528c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
16538c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
16548c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
16558c2ecf20Sopenharmony_ci		args.ucAction = ATOM_DISABLE;
16568c2ecf20Sopenharmony_ci		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
16578c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
16588c2ecf20Sopenharmony_ci			args.ucAction = ATOM_LCD_BLOFF;
16598c2ecf20Sopenharmony_ci			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
16608c2ecf20Sopenharmony_ci		}
16618c2ecf20Sopenharmony_ci		break;
16628c2ecf20Sopenharmony_ci	}
16638c2ecf20Sopenharmony_ci}
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_cistatic void
16668c2ecf20Sopenharmony_ciradeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
16678c2ecf20Sopenharmony_ci{
16688c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
16698c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
16708c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
16718c2ecf20Sopenharmony_ci	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
16728c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
16738c2ecf20Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
16748c2ecf20Sopenharmony_ci	struct radeon_connector *radeon_connector = NULL;
16758c2ecf20Sopenharmony_ci	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
16768c2ecf20Sopenharmony_ci	bool travis_quirk = false;
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci	if (connector) {
16798c2ecf20Sopenharmony_ci		radeon_connector = to_radeon_connector(connector);
16808c2ecf20Sopenharmony_ci		radeon_dig_connector = radeon_connector->con_priv;
16818c2ecf20Sopenharmony_ci		if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
16828c2ecf20Sopenharmony_ci		     ENCODER_OBJECT_ID_TRAVIS) &&
16838c2ecf20Sopenharmony_ci		    (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
16848c2ecf20Sopenharmony_ci		    !ASIC_IS_DCE5(rdev))
16858c2ecf20Sopenharmony_ci			travis_quirk = true;
16868c2ecf20Sopenharmony_ci	}
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	switch (mode) {
16898c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_ON:
16908c2ecf20Sopenharmony_ci		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
16918c2ecf20Sopenharmony_ci			if (!connector)
16928c2ecf20Sopenharmony_ci				dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
16938c2ecf20Sopenharmony_ci			else
16948c2ecf20Sopenharmony_ci				dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
16958c2ecf20Sopenharmony_ci
16968c2ecf20Sopenharmony_ci			/* setup and enable the encoder */
16978c2ecf20Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
16988c2ecf20Sopenharmony_ci			atombios_dig_encoder_setup(encoder,
16998c2ecf20Sopenharmony_ci						   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
17008c2ecf20Sopenharmony_ci						   dig->panel_mode);
17018c2ecf20Sopenharmony_ci			if (ext_encoder) {
17028c2ecf20Sopenharmony_ci				if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
17038c2ecf20Sopenharmony_ci					atombios_external_encoder_setup(encoder, ext_encoder,
17048c2ecf20Sopenharmony_ci									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
17058c2ecf20Sopenharmony_ci			}
17068c2ecf20Sopenharmony_ci		} else if (ASIC_IS_DCE4(rdev)) {
17078c2ecf20Sopenharmony_ci			/* setup and enable the encoder */
17088c2ecf20Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
17098c2ecf20Sopenharmony_ci		} else {
17108c2ecf20Sopenharmony_ci			/* setup and enable the encoder and transmitter */
17118c2ecf20Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
17128c2ecf20Sopenharmony_ci			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
17138c2ecf20Sopenharmony_ci		}
17148c2ecf20Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
17158c2ecf20Sopenharmony_ci			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
17168c2ecf20Sopenharmony_ci				atombios_set_edp_panel_power(connector,
17178c2ecf20Sopenharmony_ci							     ATOM_TRANSMITTER_ACTION_POWER_ON);
17188c2ecf20Sopenharmony_ci				radeon_dig_connector->edp_on = true;
17198c2ecf20Sopenharmony_ci			}
17208c2ecf20Sopenharmony_ci		}
17218c2ecf20Sopenharmony_ci		/* enable the transmitter */
17228c2ecf20Sopenharmony_ci		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
17238c2ecf20Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
17248c2ecf20Sopenharmony_ci			/* DP_SET_POWER_D0 is set in radeon_dp_link_train */
17258c2ecf20Sopenharmony_ci			radeon_dp_link_train(encoder, connector);
17268c2ecf20Sopenharmony_ci			if (ASIC_IS_DCE4(rdev))
17278c2ecf20Sopenharmony_ci				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
17288c2ecf20Sopenharmony_ci		}
17298c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
17308c2ecf20Sopenharmony_ci			if (rdev->mode_info.bl_encoder)
17318c2ecf20Sopenharmony_ci				atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
17328c2ecf20Sopenharmony_ci			else
17338c2ecf20Sopenharmony_ci				atombios_dig_transmitter_setup(encoder,
17348c2ecf20Sopenharmony_ci							       ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
17358c2ecf20Sopenharmony_ci		}
17368c2ecf20Sopenharmony_ci		if (ext_encoder)
17378c2ecf20Sopenharmony_ci			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
17388c2ecf20Sopenharmony_ci		break;
17398c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
17408c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
17418c2ecf20Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci		/* don't power off encoders with active MST links */
17448c2ecf20Sopenharmony_ci		if (dig->active_mst_links)
17458c2ecf20Sopenharmony_ci			return;
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci		if (ASIC_IS_DCE4(rdev)) {
17488c2ecf20Sopenharmony_ci			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
17498c2ecf20Sopenharmony_ci				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
17508c2ecf20Sopenharmony_ci		}
17518c2ecf20Sopenharmony_ci		if (ext_encoder)
17528c2ecf20Sopenharmony_ci			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
17538c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
17548c2ecf20Sopenharmony_ci			atombios_dig_transmitter_setup(encoder,
17558c2ecf20Sopenharmony_ci						       ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
17588c2ecf20Sopenharmony_ci		    connector && !travis_quirk)
17598c2ecf20Sopenharmony_ci			radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
17608c2ecf20Sopenharmony_ci		if (ASIC_IS_DCE4(rdev)) {
17618c2ecf20Sopenharmony_ci			/* disable the transmitter */
17628c2ecf20Sopenharmony_ci			atombios_dig_transmitter_setup(encoder,
17638c2ecf20Sopenharmony_ci						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
17648c2ecf20Sopenharmony_ci		} else {
17658c2ecf20Sopenharmony_ci			/* disable the encoder and transmitter */
17668c2ecf20Sopenharmony_ci			atombios_dig_transmitter_setup(encoder,
17678c2ecf20Sopenharmony_ci						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
17688c2ecf20Sopenharmony_ci			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
17698c2ecf20Sopenharmony_ci		}
17708c2ecf20Sopenharmony_ci		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
17718c2ecf20Sopenharmony_ci			if (travis_quirk)
17728c2ecf20Sopenharmony_ci				radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
17738c2ecf20Sopenharmony_ci			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
17748c2ecf20Sopenharmony_ci				atombios_set_edp_panel_power(connector,
17758c2ecf20Sopenharmony_ci							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
17768c2ecf20Sopenharmony_ci				radeon_dig_connector->edp_on = false;
17778c2ecf20Sopenharmony_ci			}
17788c2ecf20Sopenharmony_ci		}
17798c2ecf20Sopenharmony_ci		break;
17808c2ecf20Sopenharmony_ci	}
17818c2ecf20Sopenharmony_ci}
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_cistatic void
17848c2ecf20Sopenharmony_ciradeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
17858c2ecf20Sopenharmony_ci{
17868c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
17878c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
17888c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
17898c2ecf20Sopenharmony_ci	int encoder_mode = atombios_get_encoder_mode(encoder);
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
17928c2ecf20Sopenharmony_ci		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
17938c2ecf20Sopenharmony_ci		  radeon_encoder->active_device);
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	if ((radeon_audio != 0) &&
17968c2ecf20Sopenharmony_ci	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
17978c2ecf20Sopenharmony_ci	     ENCODER_MODE_IS_DP(encoder_mode)))
17988c2ecf20Sopenharmony_ci		radeon_audio_dpms(encoder, mode);
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
18018c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
18028c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
18038c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
18048c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
18058c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
18068c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
18078c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
18088c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
18098c2ecf20Sopenharmony_ci		radeon_atom_encoder_dpms_avivo(encoder, mode);
18108c2ecf20Sopenharmony_ci		break;
18118c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
18128c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
18138c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
18148c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
18158c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
18168c2ecf20Sopenharmony_ci		radeon_atom_encoder_dpms_dig(encoder, mode);
18178c2ecf20Sopenharmony_ci		break;
18188c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
18198c2ecf20Sopenharmony_ci		if (ASIC_IS_DCE5(rdev)) {
18208c2ecf20Sopenharmony_ci			switch (mode) {
18218c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_ON:
18228c2ecf20Sopenharmony_ci				atombios_dvo_setup(encoder, ATOM_ENABLE);
18238c2ecf20Sopenharmony_ci				break;
18248c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_STANDBY:
18258c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_SUSPEND:
18268c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_OFF:
18278c2ecf20Sopenharmony_ci				atombios_dvo_setup(encoder, ATOM_DISABLE);
18288c2ecf20Sopenharmony_ci				break;
18298c2ecf20Sopenharmony_ci			}
18308c2ecf20Sopenharmony_ci		} else if (ASIC_IS_DCE3(rdev))
18318c2ecf20Sopenharmony_ci			radeon_atom_encoder_dpms_dig(encoder, mode);
18328c2ecf20Sopenharmony_ci		else
18338c2ecf20Sopenharmony_ci			radeon_atom_encoder_dpms_avivo(encoder, mode);
18348c2ecf20Sopenharmony_ci		break;
18358c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
18368c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
18378c2ecf20Sopenharmony_ci		if (ASIC_IS_DCE5(rdev)) {
18388c2ecf20Sopenharmony_ci			switch (mode) {
18398c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_ON:
18408c2ecf20Sopenharmony_ci				atombios_dac_setup(encoder, ATOM_ENABLE);
18418c2ecf20Sopenharmony_ci				break;
18428c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_STANDBY:
18438c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_SUSPEND:
18448c2ecf20Sopenharmony_ci			case DRM_MODE_DPMS_OFF:
18458c2ecf20Sopenharmony_ci				atombios_dac_setup(encoder, ATOM_DISABLE);
18468c2ecf20Sopenharmony_ci				break;
18478c2ecf20Sopenharmony_ci			}
18488c2ecf20Sopenharmony_ci		} else
18498c2ecf20Sopenharmony_ci			radeon_atom_encoder_dpms_avivo(encoder, mode);
18508c2ecf20Sopenharmony_ci		break;
18518c2ecf20Sopenharmony_ci	default:
18528c2ecf20Sopenharmony_ci		return;
18538c2ecf20Sopenharmony_ci	}
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci}
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ciunion crtc_source_param {
18608c2ecf20Sopenharmony_ci	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
18618c2ecf20Sopenharmony_ci	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
18628c2ecf20Sopenharmony_ci};
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_cistatic void
18658c2ecf20Sopenharmony_ciatombios_set_encoder_crtc_source(struct drm_encoder *encoder)
18668c2ecf20Sopenharmony_ci{
18678c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
18688c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
18698c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
18708c2ecf20Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
18718c2ecf20Sopenharmony_ci	union crtc_source_param args;
18728c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
18738c2ecf20Sopenharmony_ci	uint8_t frev, crev;
18748c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
18758c2ecf20Sopenharmony_ci
18768c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
18798c2ecf20Sopenharmony_ci		return;
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci	switch (frev) {
18828c2ecf20Sopenharmony_ci	case 1:
18838c2ecf20Sopenharmony_ci		switch (crev) {
18848c2ecf20Sopenharmony_ci		case 1:
18858c2ecf20Sopenharmony_ci		default:
18868c2ecf20Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev))
18878c2ecf20Sopenharmony_ci				args.v1.ucCRTC = radeon_crtc->crtc_id;
18888c2ecf20Sopenharmony_ci			else {
18898c2ecf20Sopenharmony_ci				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)
18908c2ecf20Sopenharmony_ci					args.v1.ucCRTC = radeon_crtc->crtc_id;
18918c2ecf20Sopenharmony_ci				else
18928c2ecf20Sopenharmony_ci					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
18938c2ecf20Sopenharmony_ci			}
18948c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
18958c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
18968c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
18978c2ecf20Sopenharmony_ci				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
18988c2ecf20Sopenharmony_ci				break;
18998c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
19008c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
19018c2ecf20Sopenharmony_ci				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
19028c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
19038c2ecf20Sopenharmony_ci				else
19048c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
19058c2ecf20Sopenharmony_ci				break;
19068c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
19078c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DDI:
19088c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
19098c2ecf20Sopenharmony_ci				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
19108c2ecf20Sopenharmony_ci				break;
19118c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
19128c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
19138c2ecf20Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
19148c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
19158c2ecf20Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
19168c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
19178c2ecf20Sopenharmony_ci				else
19188c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
19198c2ecf20Sopenharmony_ci				break;
19208c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
19218c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
19228c2ecf20Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
19238c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
19248c2ecf20Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
19258c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
19268c2ecf20Sopenharmony_ci				else
19278c2ecf20Sopenharmony_ci					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
19288c2ecf20Sopenharmony_ci				break;
19298c2ecf20Sopenharmony_ci			}
19308c2ecf20Sopenharmony_ci			break;
19318c2ecf20Sopenharmony_ci		case 2:
19328c2ecf20Sopenharmony_ci			args.v2.ucCRTC = radeon_crtc->crtc_id;
19338c2ecf20Sopenharmony_ci			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
19348c2ecf20Sopenharmony_ci				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
19378c2ecf20Sopenharmony_ci					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
19388c2ecf20Sopenharmony_ci				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
19398c2ecf20Sopenharmony_ci					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
19408c2ecf20Sopenharmony_ci				else
19418c2ecf20Sopenharmony_ci					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
19428c2ecf20Sopenharmony_ci			} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
19438c2ecf20Sopenharmony_ci				args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
19448c2ecf20Sopenharmony_ci			} else {
19458c2ecf20Sopenharmony_ci				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
19468c2ecf20Sopenharmony_ci			}
19478c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
19488c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
19498c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
19508c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
19518c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
19528c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
19538c2ecf20Sopenharmony_ci				dig = radeon_encoder->enc_priv;
19548c2ecf20Sopenharmony_ci				switch (dig->dig_encoder) {
19558c2ecf20Sopenharmony_ci				case 0:
19568c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
19578c2ecf20Sopenharmony_ci					break;
19588c2ecf20Sopenharmony_ci				case 1:
19598c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
19608c2ecf20Sopenharmony_ci					break;
19618c2ecf20Sopenharmony_ci				case 2:
19628c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
19638c2ecf20Sopenharmony_ci					break;
19648c2ecf20Sopenharmony_ci				case 3:
19658c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
19668c2ecf20Sopenharmony_ci					break;
19678c2ecf20Sopenharmony_ci				case 4:
19688c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
19698c2ecf20Sopenharmony_ci					break;
19708c2ecf20Sopenharmony_ci				case 5:
19718c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
19728c2ecf20Sopenharmony_ci					break;
19738c2ecf20Sopenharmony_ci				case 6:
19748c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
19758c2ecf20Sopenharmony_ci					break;
19768c2ecf20Sopenharmony_ci				}
19778c2ecf20Sopenharmony_ci				break;
19788c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
19798c2ecf20Sopenharmony_ci				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
19808c2ecf20Sopenharmony_ci				break;
19818c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
19828c2ecf20Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
19838c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
19848c2ecf20Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
19858c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
19868c2ecf20Sopenharmony_ci				else
19878c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
19888c2ecf20Sopenharmony_ci				break;
19898c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
19908c2ecf20Sopenharmony_ci				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
19918c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
19928c2ecf20Sopenharmony_ci				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
19938c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
19948c2ecf20Sopenharmony_ci				else
19958c2ecf20Sopenharmony_ci					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
19968c2ecf20Sopenharmony_ci				break;
19978c2ecf20Sopenharmony_ci			}
19988c2ecf20Sopenharmony_ci			break;
19998c2ecf20Sopenharmony_ci		}
20008c2ecf20Sopenharmony_ci		break;
20018c2ecf20Sopenharmony_ci	default:
20028c2ecf20Sopenharmony_ci		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
20038c2ecf20Sopenharmony_ci		return;
20048c2ecf20Sopenharmony_ci	}
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
20078c2ecf20Sopenharmony_ci
20088c2ecf20Sopenharmony_ci	/* update scratch regs with new routing */
20098c2ecf20Sopenharmony_ci	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
20108c2ecf20Sopenharmony_ci}
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_civoid
20138c2ecf20Sopenharmony_ciatombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe)
20148c2ecf20Sopenharmony_ci{
20158c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
20168c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
20178c2ecf20Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
20188c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
20198c2ecf20Sopenharmony_ci	uint8_t frev, crev;
20208c2ecf20Sopenharmony_ci	union crtc_source_param args;
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	memset(&args, 0, sizeof(args));
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ci	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
20258c2ecf20Sopenharmony_ci		return;
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	if (frev != 1 && crev != 2)
20288c2ecf20Sopenharmony_ci		DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev);
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci	args.v2.ucCRTC = radeon_crtc->crtc_id;
20318c2ecf20Sopenharmony_ci	args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST;
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_ci	switch (fe) {
20348c2ecf20Sopenharmony_ci	case 0:
20358c2ecf20Sopenharmony_ci		args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
20368c2ecf20Sopenharmony_ci		break;
20378c2ecf20Sopenharmony_ci	case 1:
20388c2ecf20Sopenharmony_ci		args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
20398c2ecf20Sopenharmony_ci		break;
20408c2ecf20Sopenharmony_ci	case 2:
20418c2ecf20Sopenharmony_ci		args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
20428c2ecf20Sopenharmony_ci		break;
20438c2ecf20Sopenharmony_ci	case 3:
20448c2ecf20Sopenharmony_ci		args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
20458c2ecf20Sopenharmony_ci		break;
20468c2ecf20Sopenharmony_ci	case 4:
20478c2ecf20Sopenharmony_ci		args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
20488c2ecf20Sopenharmony_ci		break;
20498c2ecf20Sopenharmony_ci	case 5:
20508c2ecf20Sopenharmony_ci		args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
20518c2ecf20Sopenharmony_ci		break;
20528c2ecf20Sopenharmony_ci	case 6:
20538c2ecf20Sopenharmony_ci		args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
20548c2ecf20Sopenharmony_ci		break;
20558c2ecf20Sopenharmony_ci	}
20568c2ecf20Sopenharmony_ci	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
20578c2ecf20Sopenharmony_ci}
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_cistatic void
20608c2ecf20Sopenharmony_ciatombios_apply_encoder_quirks(struct drm_encoder *encoder,
20618c2ecf20Sopenharmony_ci			      struct drm_display_mode *mode)
20628c2ecf20Sopenharmony_ci{
20638c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
20648c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
20658c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
20668c2ecf20Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci	/* Funky macbooks */
20698c2ecf20Sopenharmony_ci	if ((dev->pdev->device == 0x71C5) &&
20708c2ecf20Sopenharmony_ci	    (dev->pdev->subsystem_vendor == 0x106b) &&
20718c2ecf20Sopenharmony_ci	    (dev->pdev->subsystem_device == 0x0080)) {
20728c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
20738c2ecf20Sopenharmony_ci			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
20748c2ecf20Sopenharmony_ci
20758c2ecf20Sopenharmony_ci			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
20768c2ecf20Sopenharmony_ci			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
20798c2ecf20Sopenharmony_ci		}
20808c2ecf20Sopenharmony_ci	}
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	/* set scaler clears this on some chips */
20838c2ecf20Sopenharmony_ci	if (ASIC_IS_AVIVO(rdev) &&
20848c2ecf20Sopenharmony_ci	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
20858c2ecf20Sopenharmony_ci		if (ASIC_IS_DCE8(rdev)) {
20868c2ecf20Sopenharmony_ci			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
20878c2ecf20Sopenharmony_ci				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset,
20888c2ecf20Sopenharmony_ci				       CIK_INTERLEAVE_EN);
20898c2ecf20Sopenharmony_ci			else
20908c2ecf20Sopenharmony_ci				WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
20918c2ecf20Sopenharmony_ci		} else if (ASIC_IS_DCE4(rdev)) {
20928c2ecf20Sopenharmony_ci			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
20938c2ecf20Sopenharmony_ci				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
20948c2ecf20Sopenharmony_ci				       EVERGREEN_INTERLEAVE_EN);
20958c2ecf20Sopenharmony_ci			else
20968c2ecf20Sopenharmony_ci				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
20978c2ecf20Sopenharmony_ci		} else {
20988c2ecf20Sopenharmony_ci			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
20998c2ecf20Sopenharmony_ci				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
21008c2ecf20Sopenharmony_ci				       AVIVO_D1MODE_INTERLEAVE_EN);
21018c2ecf20Sopenharmony_ci			else
21028c2ecf20Sopenharmony_ci				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
21038c2ecf20Sopenharmony_ci		}
21048c2ecf20Sopenharmony_ci	}
21058c2ecf20Sopenharmony_ci}
21068c2ecf20Sopenharmony_ci
21078c2ecf20Sopenharmony_civoid radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx)
21088c2ecf20Sopenharmony_ci{
21098c2ecf20Sopenharmony_ci	if (enc_idx < 0)
21108c2ecf20Sopenharmony_ci		return;
21118c2ecf20Sopenharmony_ci	rdev->mode_info.active_encoders &= ~(1 << enc_idx);
21128c2ecf20Sopenharmony_ci}
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ciint radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
21158c2ecf20Sopenharmony_ci{
21168c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
21178c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
21188c2ecf20Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
21198c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
21208c2ecf20Sopenharmony_ci	struct drm_encoder *test_encoder;
21218c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
21228c2ecf20Sopenharmony_ci	uint32_t dig_enc_in_use = 0;
21238c2ecf20Sopenharmony_ci	int enc_idx = -1;
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci	if (fe_idx >= 0) {
21268c2ecf20Sopenharmony_ci		enc_idx = fe_idx;
21278c2ecf20Sopenharmony_ci		goto assigned;
21288c2ecf20Sopenharmony_ci	}
21298c2ecf20Sopenharmony_ci	if (ASIC_IS_DCE6(rdev)) {
21308c2ecf20Sopenharmony_ci		/* DCE6 */
21318c2ecf20Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
21328c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
21338c2ecf20Sopenharmony_ci			if (dig->linkb)
21348c2ecf20Sopenharmony_ci				enc_idx = 1;
21358c2ecf20Sopenharmony_ci			else
21368c2ecf20Sopenharmony_ci				enc_idx = 0;
21378c2ecf20Sopenharmony_ci			break;
21388c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
21398c2ecf20Sopenharmony_ci			if (dig->linkb)
21408c2ecf20Sopenharmony_ci				enc_idx = 3;
21418c2ecf20Sopenharmony_ci			else
21428c2ecf20Sopenharmony_ci				enc_idx = 2;
21438c2ecf20Sopenharmony_ci			break;
21448c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
21458c2ecf20Sopenharmony_ci			if (dig->linkb)
21468c2ecf20Sopenharmony_ci				enc_idx = 5;
21478c2ecf20Sopenharmony_ci			else
21488c2ecf20Sopenharmony_ci				enc_idx = 4;
21498c2ecf20Sopenharmony_ci			break;
21508c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
21518c2ecf20Sopenharmony_ci			enc_idx = 6;
21528c2ecf20Sopenharmony_ci			break;
21538c2ecf20Sopenharmony_ci		}
21548c2ecf20Sopenharmony_ci		goto assigned;
21558c2ecf20Sopenharmony_ci	} else if (ASIC_IS_DCE4(rdev)) {
21568c2ecf20Sopenharmony_ci		/* DCE4/5 */
21578c2ecf20Sopenharmony_ci		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
21588c2ecf20Sopenharmony_ci			/* ontario follows DCE4 */
21598c2ecf20Sopenharmony_ci			if (rdev->family == CHIP_PALM) {
21608c2ecf20Sopenharmony_ci				if (dig->linkb)
21618c2ecf20Sopenharmony_ci					enc_idx = 1;
21628c2ecf20Sopenharmony_ci				else
21638c2ecf20Sopenharmony_ci					enc_idx = 0;
21648c2ecf20Sopenharmony_ci			} else
21658c2ecf20Sopenharmony_ci				/* llano follows DCE3.2 */
21668c2ecf20Sopenharmony_ci				enc_idx = radeon_crtc->crtc_id;
21678c2ecf20Sopenharmony_ci		} else {
21688c2ecf20Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
21698c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
21708c2ecf20Sopenharmony_ci				if (dig->linkb)
21718c2ecf20Sopenharmony_ci					enc_idx = 1;
21728c2ecf20Sopenharmony_ci				else
21738c2ecf20Sopenharmony_ci					enc_idx = 0;
21748c2ecf20Sopenharmony_ci				break;
21758c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
21768c2ecf20Sopenharmony_ci				if (dig->linkb)
21778c2ecf20Sopenharmony_ci					enc_idx = 3;
21788c2ecf20Sopenharmony_ci				else
21798c2ecf20Sopenharmony_ci					enc_idx = 2;
21808c2ecf20Sopenharmony_ci				break;
21818c2ecf20Sopenharmony_ci			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
21828c2ecf20Sopenharmony_ci				if (dig->linkb)
21838c2ecf20Sopenharmony_ci					enc_idx = 5;
21848c2ecf20Sopenharmony_ci				else
21858c2ecf20Sopenharmony_ci					enc_idx = 4;
21868c2ecf20Sopenharmony_ci				break;
21878c2ecf20Sopenharmony_ci			}
21888c2ecf20Sopenharmony_ci		}
21898c2ecf20Sopenharmony_ci		goto assigned;
21908c2ecf20Sopenharmony_ci	}
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	/*
21938c2ecf20Sopenharmony_ci	 * On DCE32 any encoder can drive any block so usually just use crtc id,
21948c2ecf20Sopenharmony_ci	 * but Apple thinks different at least on iMac10,1 and iMac11,2, so there use linkb,
21958c2ecf20Sopenharmony_ci	 * otherwise the internal eDP panel will stay dark.
21968c2ecf20Sopenharmony_ci	 */
21978c2ecf20Sopenharmony_ci	if (ASIC_IS_DCE32(rdev)) {
21988c2ecf20Sopenharmony_ci		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
21998c2ecf20Sopenharmony_ci		    dmi_match(DMI_PRODUCT_NAME, "iMac11,2"))
22008c2ecf20Sopenharmony_ci			enc_idx = (dig->linkb) ? 1 : 0;
22018c2ecf20Sopenharmony_ci		else
22028c2ecf20Sopenharmony_ci			enc_idx = radeon_crtc->crtc_id;
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci		goto assigned;
22058c2ecf20Sopenharmony_ci	}
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	/* on DCE3 - LVTMA can only be driven by DIGB */
22088c2ecf20Sopenharmony_ci	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
22098c2ecf20Sopenharmony_ci		struct radeon_encoder *radeon_test_encoder;
22108c2ecf20Sopenharmony_ci
22118c2ecf20Sopenharmony_ci		if (encoder == test_encoder)
22128c2ecf20Sopenharmony_ci			continue;
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci		if (!radeon_encoder_is_digital(test_encoder))
22158c2ecf20Sopenharmony_ci			continue;
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci		radeon_test_encoder = to_radeon_encoder(test_encoder);
22188c2ecf20Sopenharmony_ci		dig = radeon_test_encoder->enc_priv;
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_ci		if (dig->dig_encoder >= 0)
22218c2ecf20Sopenharmony_ci			dig_enc_in_use |= (1 << dig->dig_encoder);
22228c2ecf20Sopenharmony_ci	}
22238c2ecf20Sopenharmony_ci
22248c2ecf20Sopenharmony_ci	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
22258c2ecf20Sopenharmony_ci		if (dig_enc_in_use & 0x2)
22268c2ecf20Sopenharmony_ci			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
22278c2ecf20Sopenharmony_ci		return 1;
22288c2ecf20Sopenharmony_ci	}
22298c2ecf20Sopenharmony_ci	if (!(dig_enc_in_use & 1))
22308c2ecf20Sopenharmony_ci		return 0;
22318c2ecf20Sopenharmony_ci	return 1;
22328c2ecf20Sopenharmony_ci
22338c2ecf20Sopenharmony_ciassigned:
22348c2ecf20Sopenharmony_ci	if (enc_idx == -1) {
22358c2ecf20Sopenharmony_ci		DRM_ERROR("Got encoder index incorrect - returning 0\n");
22368c2ecf20Sopenharmony_ci		return 0;
22378c2ecf20Sopenharmony_ci	}
22388c2ecf20Sopenharmony_ci	if (rdev->mode_info.active_encoders & (1 << enc_idx))
22398c2ecf20Sopenharmony_ci		DRM_ERROR("chosen encoder in use %d\n", enc_idx);
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	rdev->mode_info.active_encoders |= (1 << enc_idx);
22428c2ecf20Sopenharmony_ci	return enc_idx;
22438c2ecf20Sopenharmony_ci}
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci/* This only needs to be called once at startup */
22468c2ecf20Sopenharmony_civoid
22478c2ecf20Sopenharmony_ciradeon_atom_encoder_init(struct radeon_device *rdev)
22488c2ecf20Sopenharmony_ci{
22498c2ecf20Sopenharmony_ci	struct drm_device *dev = rdev->ddev;
22508c2ecf20Sopenharmony_ci	struct drm_encoder *encoder;
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ci	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
22538c2ecf20Sopenharmony_ci		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
22548c2ecf20Sopenharmony_ci		struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
22558c2ecf20Sopenharmony_ci
22568c2ecf20Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
22578c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
22588c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
22598c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
22608c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
22618c2ecf20Sopenharmony_ci		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
22628c2ecf20Sopenharmony_ci			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
22638c2ecf20Sopenharmony_ci			break;
22648c2ecf20Sopenharmony_ci		default:
22658c2ecf20Sopenharmony_ci			break;
22668c2ecf20Sopenharmony_ci		}
22678c2ecf20Sopenharmony_ci
22688c2ecf20Sopenharmony_ci		if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)))
22698c2ecf20Sopenharmony_ci			atombios_external_encoder_setup(encoder, ext_encoder,
22708c2ecf20Sopenharmony_ci							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
22718c2ecf20Sopenharmony_ci	}
22728c2ecf20Sopenharmony_ci}
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_cistatic void
22758c2ecf20Sopenharmony_ciradeon_atom_encoder_mode_set(struct drm_encoder *encoder,
22768c2ecf20Sopenharmony_ci			     struct drm_display_mode *mode,
22778c2ecf20Sopenharmony_ci			     struct drm_display_mode *adjusted_mode)
22788c2ecf20Sopenharmony_ci{
22798c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
22808c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
22818c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
22828c2ecf20Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
22838c2ecf20Sopenharmony_ci	int encoder_mode;
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci	radeon_encoder->pixel_clock = adjusted_mode->clock;
22868c2ecf20Sopenharmony_ci
22878c2ecf20Sopenharmony_ci	/* need to call this here rather than in prepare() since we need some crtc info */
22888c2ecf20Sopenharmony_ci	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
22918c2ecf20Sopenharmony_ci		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
22928c2ecf20Sopenharmony_ci			atombios_yuv_setup(encoder, true);
22938c2ecf20Sopenharmony_ci		else
22948c2ecf20Sopenharmony_ci			atombios_yuv_setup(encoder, false);
22958c2ecf20Sopenharmony_ci	}
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
22988c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
22998c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
23008c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
23018c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
23028c2ecf20Sopenharmony_ci		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
23038c2ecf20Sopenharmony_ci		break;
23048c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
23058c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
23068c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
23078c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
23088c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
23098c2ecf20Sopenharmony_ci		/* handled in dpms */
23108c2ecf20Sopenharmony_ci		break;
23118c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
23128c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
23138c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
23148c2ecf20Sopenharmony_ci		atombios_dvo_setup(encoder, ATOM_ENABLE);
23158c2ecf20Sopenharmony_ci		break;
23168c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
23178c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
23188c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
23198c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
23208c2ecf20Sopenharmony_ci		atombios_dac_setup(encoder, ATOM_ENABLE);
23218c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
23228c2ecf20Sopenharmony_ci			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
23238c2ecf20Sopenharmony_ci				atombios_tv_setup(encoder, ATOM_ENABLE);
23248c2ecf20Sopenharmony_ci			else
23258c2ecf20Sopenharmony_ci				atombios_tv_setup(encoder, ATOM_DISABLE);
23268c2ecf20Sopenharmony_ci		}
23278c2ecf20Sopenharmony_ci		break;
23288c2ecf20Sopenharmony_ci	}
23298c2ecf20Sopenharmony_ci
23308c2ecf20Sopenharmony_ci	atombios_apply_encoder_quirks(encoder, adjusted_mode);
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	encoder_mode = atombios_get_encoder_mode(encoder);
23338c2ecf20Sopenharmony_ci	if (connector && (radeon_audio != 0) &&
23348c2ecf20Sopenharmony_ci	    ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
23358c2ecf20Sopenharmony_ci	     ENCODER_MODE_IS_DP(encoder_mode)))
23368c2ecf20Sopenharmony_ci		radeon_audio_mode_set(encoder, adjusted_mode);
23378c2ecf20Sopenharmony_ci}
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_cistatic bool
23408c2ecf20Sopenharmony_ciatombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
23418c2ecf20Sopenharmony_ci{
23428c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
23438c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
23448c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
23458c2ecf20Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
23468c2ecf20Sopenharmony_ci
23478c2ecf20Sopenharmony_ci	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
23488c2ecf20Sopenharmony_ci				       ATOM_DEVICE_CV_SUPPORT |
23498c2ecf20Sopenharmony_ci				       ATOM_DEVICE_CRT_SUPPORT)) {
23508c2ecf20Sopenharmony_ci		DAC_LOAD_DETECTION_PS_ALLOCATION args;
23518c2ecf20Sopenharmony_ci		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
23528c2ecf20Sopenharmony_ci		uint8_t frev, crev;
23538c2ecf20Sopenharmony_ci
23548c2ecf20Sopenharmony_ci		memset(&args, 0, sizeof(args));
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
23578c2ecf20Sopenharmony_ci			return false;
23588c2ecf20Sopenharmony_ci
23598c2ecf20Sopenharmony_ci		args.sDacload.ucMisc = 0;
23608c2ecf20Sopenharmony_ci
23618c2ecf20Sopenharmony_ci		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
23628c2ecf20Sopenharmony_ci		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
23638c2ecf20Sopenharmony_ci			args.sDacload.ucDacType = ATOM_DAC_A;
23648c2ecf20Sopenharmony_ci		else
23658c2ecf20Sopenharmony_ci			args.sDacload.ucDacType = ATOM_DAC_B;
23668c2ecf20Sopenharmony_ci
23678c2ecf20Sopenharmony_ci		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
23688c2ecf20Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
23698c2ecf20Sopenharmony_ci		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
23708c2ecf20Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
23718c2ecf20Sopenharmony_ci		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
23728c2ecf20Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
23738c2ecf20Sopenharmony_ci			if (crev >= 3)
23748c2ecf20Sopenharmony_ci				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
23758c2ecf20Sopenharmony_ci		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
23768c2ecf20Sopenharmony_ci			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
23778c2ecf20Sopenharmony_ci			if (crev >= 3)
23788c2ecf20Sopenharmony_ci				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
23798c2ecf20Sopenharmony_ci		}
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
23828c2ecf20Sopenharmony_ci
23838c2ecf20Sopenharmony_ci		return true;
23848c2ecf20Sopenharmony_ci	} else
23858c2ecf20Sopenharmony_ci		return false;
23868c2ecf20Sopenharmony_ci}
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_cistatic enum drm_connector_status
23898c2ecf20Sopenharmony_ciradeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
23908c2ecf20Sopenharmony_ci{
23918c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
23928c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
23938c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
23948c2ecf20Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
23958c2ecf20Sopenharmony_ci	uint32_t bios_0_scratch;
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_ci	if (!atombios_dac_load_detect(encoder, connector)) {
23988c2ecf20Sopenharmony_ci		DRM_DEBUG_KMS("detect returned false \n");
23998c2ecf20Sopenharmony_ci		return connector_status_unknown;
24008c2ecf20Sopenharmony_ci	}
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci	if (rdev->family >= CHIP_R600)
24038c2ecf20Sopenharmony_ci		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
24048c2ecf20Sopenharmony_ci	else
24058c2ecf20Sopenharmony_ci		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
24068c2ecf20Sopenharmony_ci
24078c2ecf20Sopenharmony_ci	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
24088c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
24098c2ecf20Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
24108c2ecf20Sopenharmony_ci			return connector_status_connected;
24118c2ecf20Sopenharmony_ci	}
24128c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
24138c2ecf20Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
24148c2ecf20Sopenharmony_ci			return connector_status_connected;
24158c2ecf20Sopenharmony_ci	}
24168c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
24178c2ecf20Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
24188c2ecf20Sopenharmony_ci			return connector_status_connected;
24198c2ecf20Sopenharmony_ci	}
24208c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
24218c2ecf20Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
24228c2ecf20Sopenharmony_ci			return connector_status_connected; /* CTV */
24238c2ecf20Sopenharmony_ci		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
24248c2ecf20Sopenharmony_ci			return connector_status_connected; /* STV */
24258c2ecf20Sopenharmony_ci	}
24268c2ecf20Sopenharmony_ci	return connector_status_disconnected;
24278c2ecf20Sopenharmony_ci}
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_cistatic enum drm_connector_status
24308c2ecf20Sopenharmony_ciradeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
24318c2ecf20Sopenharmony_ci{
24328c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
24338c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
24348c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
24358c2ecf20Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
24368c2ecf20Sopenharmony_ci	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
24378c2ecf20Sopenharmony_ci	u32 bios_0_scratch;
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci	if (!ASIC_IS_DCE4(rdev))
24408c2ecf20Sopenharmony_ci		return connector_status_unknown;
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci	if (!ext_encoder)
24438c2ecf20Sopenharmony_ci		return connector_status_unknown;
24448c2ecf20Sopenharmony_ci
24458c2ecf20Sopenharmony_ci	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
24468c2ecf20Sopenharmony_ci		return connector_status_unknown;
24478c2ecf20Sopenharmony_ci
24488c2ecf20Sopenharmony_ci	/* load detect on the dp bridge */
24498c2ecf20Sopenharmony_ci	atombios_external_encoder_setup(encoder, ext_encoder,
24508c2ecf20Sopenharmony_ci					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_ci	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
24558c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
24568c2ecf20Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
24578c2ecf20Sopenharmony_ci			return connector_status_connected;
24588c2ecf20Sopenharmony_ci	}
24598c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
24608c2ecf20Sopenharmony_ci		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
24618c2ecf20Sopenharmony_ci			return connector_status_connected;
24628c2ecf20Sopenharmony_ci	}
24638c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
24648c2ecf20Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
24658c2ecf20Sopenharmony_ci			return connector_status_connected;
24668c2ecf20Sopenharmony_ci	}
24678c2ecf20Sopenharmony_ci	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
24688c2ecf20Sopenharmony_ci		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
24698c2ecf20Sopenharmony_ci			return connector_status_connected; /* CTV */
24708c2ecf20Sopenharmony_ci		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
24718c2ecf20Sopenharmony_ci			return connector_status_connected; /* STV */
24728c2ecf20Sopenharmony_ci	}
24738c2ecf20Sopenharmony_ci	return connector_status_disconnected;
24748c2ecf20Sopenharmony_ci}
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_civoid
24778c2ecf20Sopenharmony_ciradeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
24788c2ecf20Sopenharmony_ci{
24798c2ecf20Sopenharmony_ci	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
24808c2ecf20Sopenharmony_ci
24818c2ecf20Sopenharmony_ci	if (ext_encoder)
24828c2ecf20Sopenharmony_ci		/* ddc_setup on the dp bridge */
24838c2ecf20Sopenharmony_ci		atombios_external_encoder_setup(encoder, ext_encoder,
24848c2ecf20Sopenharmony_ci						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
24858c2ecf20Sopenharmony_ci
24868c2ecf20Sopenharmony_ci}
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_cistatic void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
24898c2ecf20Sopenharmony_ci{
24908c2ecf20Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
24918c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
24928c2ecf20Sopenharmony_ci	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	if ((radeon_encoder->active_device &
24958c2ecf20Sopenharmony_ci	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
24968c2ecf20Sopenharmony_ci	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
24978c2ecf20Sopenharmony_ci	     ENCODER_OBJECT_ID_NONE)) {
24988c2ecf20Sopenharmony_ci		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
24998c2ecf20Sopenharmony_ci		if (dig) {
25008c2ecf20Sopenharmony_ci			if (dig->dig_encoder >= 0)
25018c2ecf20Sopenharmony_ci				radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
25028c2ecf20Sopenharmony_ci			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1);
25038c2ecf20Sopenharmony_ci			if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
25048c2ecf20Sopenharmony_ci				if (rdev->family >= CHIP_R600)
25058c2ecf20Sopenharmony_ci					dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
25068c2ecf20Sopenharmony_ci				else
25078c2ecf20Sopenharmony_ci					/* RS600/690/740 have only 1 afmt block */
25088c2ecf20Sopenharmony_ci					dig->afmt = rdev->mode_info.afmt[0];
25098c2ecf20Sopenharmony_ci			}
25108c2ecf20Sopenharmony_ci		}
25118c2ecf20Sopenharmony_ci	}
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci	radeon_atom_output_lock(encoder, true);
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci	if (connector) {
25168c2ecf20Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_ci		/* select the clock/data port if it uses a router */
25198c2ecf20Sopenharmony_ci		if (radeon_connector->router.cd_valid)
25208c2ecf20Sopenharmony_ci			radeon_router_select_cd_port(radeon_connector);
25218c2ecf20Sopenharmony_ci
25228c2ecf20Sopenharmony_ci		/* turn eDP panel on for mode set */
25238c2ecf20Sopenharmony_ci		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
25248c2ecf20Sopenharmony_ci			atombios_set_edp_panel_power(connector,
25258c2ecf20Sopenharmony_ci						     ATOM_TRANSMITTER_ACTION_POWER_ON);
25268c2ecf20Sopenharmony_ci	}
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci	/* this is needed for the pll/ss setup to work correctly in some cases */
25298c2ecf20Sopenharmony_ci	atombios_set_encoder_crtc_source(encoder);
25308c2ecf20Sopenharmony_ci	/* set up the FMT blocks */
25318c2ecf20Sopenharmony_ci	if (ASIC_IS_DCE8(rdev))
25328c2ecf20Sopenharmony_ci		dce8_program_fmt(encoder);
25338c2ecf20Sopenharmony_ci	else if (ASIC_IS_DCE4(rdev))
25348c2ecf20Sopenharmony_ci		dce4_program_fmt(encoder);
25358c2ecf20Sopenharmony_ci	else if (ASIC_IS_DCE3(rdev))
25368c2ecf20Sopenharmony_ci		dce3_program_fmt(encoder);
25378c2ecf20Sopenharmony_ci	else if (ASIC_IS_AVIVO(rdev))
25388c2ecf20Sopenharmony_ci		avivo_program_fmt(encoder);
25398c2ecf20Sopenharmony_ci}
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_cistatic void radeon_atom_encoder_commit(struct drm_encoder *encoder)
25428c2ecf20Sopenharmony_ci{
25438c2ecf20Sopenharmony_ci	/* need to call this here as we need the crtc set up */
25448c2ecf20Sopenharmony_ci	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
25458c2ecf20Sopenharmony_ci	radeon_atom_output_lock(encoder, false);
25468c2ecf20Sopenharmony_ci}
25478c2ecf20Sopenharmony_ci
25488c2ecf20Sopenharmony_cistatic void radeon_atom_encoder_disable(struct drm_encoder *encoder)
25498c2ecf20Sopenharmony_ci{
25508c2ecf20Sopenharmony_ci	struct drm_device *dev = encoder->dev;
25518c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
25528c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
25538c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig;
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci	/* check for pre-DCE3 cards with shared encoders;
25568c2ecf20Sopenharmony_ci	 * can't really use the links individually, so don't disable
25578c2ecf20Sopenharmony_ci	 * the encoder if it's in use by another connector
25588c2ecf20Sopenharmony_ci	 */
25598c2ecf20Sopenharmony_ci	if (!ASIC_IS_DCE3(rdev)) {
25608c2ecf20Sopenharmony_ci		struct drm_encoder *other_encoder;
25618c2ecf20Sopenharmony_ci		struct radeon_encoder *other_radeon_encoder;
25628c2ecf20Sopenharmony_ci
25638c2ecf20Sopenharmony_ci		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
25648c2ecf20Sopenharmony_ci			other_radeon_encoder = to_radeon_encoder(other_encoder);
25658c2ecf20Sopenharmony_ci			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
25668c2ecf20Sopenharmony_ci			    drm_helper_encoder_in_use(other_encoder))
25678c2ecf20Sopenharmony_ci				goto disable_done;
25688c2ecf20Sopenharmony_ci		}
25698c2ecf20Sopenharmony_ci	}
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
25728c2ecf20Sopenharmony_ci
25738c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
25748c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
25758c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
25768c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
25778c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
25788c2ecf20Sopenharmony_ci		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
25798c2ecf20Sopenharmony_ci		break;
25808c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
25818c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
25828c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
25838c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
25848c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
25858c2ecf20Sopenharmony_ci		/* handled in dpms */
25868c2ecf20Sopenharmony_ci		break;
25878c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
25888c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
25898c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
25908c2ecf20Sopenharmony_ci		atombios_dvo_setup(encoder, ATOM_DISABLE);
25918c2ecf20Sopenharmony_ci		break;
25928c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
25938c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
25948c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
25958c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
25968c2ecf20Sopenharmony_ci		atombios_dac_setup(encoder, ATOM_DISABLE);
25978c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
25988c2ecf20Sopenharmony_ci			atombios_tv_setup(encoder, ATOM_DISABLE);
25998c2ecf20Sopenharmony_ci		break;
26008c2ecf20Sopenharmony_ci	}
26018c2ecf20Sopenharmony_ci
26028c2ecf20Sopenharmony_cidisable_done:
26038c2ecf20Sopenharmony_ci	if (radeon_encoder_is_digital(encoder)) {
26048c2ecf20Sopenharmony_ci		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
26058c2ecf20Sopenharmony_ci			if (rdev->asic->display.hdmi_enable)
26068c2ecf20Sopenharmony_ci				radeon_hdmi_enable(rdev, encoder, false);
26078c2ecf20Sopenharmony_ci		}
26088c2ecf20Sopenharmony_ci		if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST) {
26098c2ecf20Sopenharmony_ci			dig = radeon_encoder->enc_priv;
26108c2ecf20Sopenharmony_ci			radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
26118c2ecf20Sopenharmony_ci			dig->dig_encoder = -1;
26128c2ecf20Sopenharmony_ci			radeon_encoder->active_device = 0;
26138c2ecf20Sopenharmony_ci		}
26148c2ecf20Sopenharmony_ci	} else
26158c2ecf20Sopenharmony_ci		radeon_encoder->active_device = 0;
26168c2ecf20Sopenharmony_ci}
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci/* these are handled by the primary encoders */
26198c2ecf20Sopenharmony_cistatic void radeon_atom_ext_prepare(struct drm_encoder *encoder)
26208c2ecf20Sopenharmony_ci{
26218c2ecf20Sopenharmony_ci
26228c2ecf20Sopenharmony_ci}
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_cistatic void radeon_atom_ext_commit(struct drm_encoder *encoder)
26258c2ecf20Sopenharmony_ci{
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_ci}
26288c2ecf20Sopenharmony_ci
26298c2ecf20Sopenharmony_cistatic void
26308c2ecf20Sopenharmony_ciradeon_atom_ext_mode_set(struct drm_encoder *encoder,
26318c2ecf20Sopenharmony_ci			 struct drm_display_mode *mode,
26328c2ecf20Sopenharmony_ci			 struct drm_display_mode *adjusted_mode)
26338c2ecf20Sopenharmony_ci{
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci}
26368c2ecf20Sopenharmony_ci
26378c2ecf20Sopenharmony_cistatic void radeon_atom_ext_disable(struct drm_encoder *encoder)
26388c2ecf20Sopenharmony_ci{
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci}
26418c2ecf20Sopenharmony_ci
26428c2ecf20Sopenharmony_cistatic void
26438c2ecf20Sopenharmony_ciradeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
26448c2ecf20Sopenharmony_ci{
26458c2ecf20Sopenharmony_ci
26468c2ecf20Sopenharmony_ci}
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
26498c2ecf20Sopenharmony_ci	.dpms = radeon_atom_ext_dpms,
26508c2ecf20Sopenharmony_ci	.prepare = radeon_atom_ext_prepare,
26518c2ecf20Sopenharmony_ci	.mode_set = radeon_atom_ext_mode_set,
26528c2ecf20Sopenharmony_ci	.commit = radeon_atom_ext_commit,
26538c2ecf20Sopenharmony_ci	.disable = radeon_atom_ext_disable,
26548c2ecf20Sopenharmony_ci	/* no detect for TMDS/LVDS yet */
26558c2ecf20Sopenharmony_ci};
26568c2ecf20Sopenharmony_ci
26578c2ecf20Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
26588c2ecf20Sopenharmony_ci	.dpms = radeon_atom_encoder_dpms,
26598c2ecf20Sopenharmony_ci	.mode_fixup = radeon_atom_mode_fixup,
26608c2ecf20Sopenharmony_ci	.prepare = radeon_atom_encoder_prepare,
26618c2ecf20Sopenharmony_ci	.mode_set = radeon_atom_encoder_mode_set,
26628c2ecf20Sopenharmony_ci	.commit = radeon_atom_encoder_commit,
26638c2ecf20Sopenharmony_ci	.disable = radeon_atom_encoder_disable,
26648c2ecf20Sopenharmony_ci	.detect = radeon_atom_dig_detect,
26658c2ecf20Sopenharmony_ci};
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
26688c2ecf20Sopenharmony_ci	.dpms = radeon_atom_encoder_dpms,
26698c2ecf20Sopenharmony_ci	.mode_fixup = radeon_atom_mode_fixup,
26708c2ecf20Sopenharmony_ci	.prepare = radeon_atom_encoder_prepare,
26718c2ecf20Sopenharmony_ci	.mode_set = radeon_atom_encoder_mode_set,
26728c2ecf20Sopenharmony_ci	.commit = radeon_atom_encoder_commit,
26738c2ecf20Sopenharmony_ci	.detect = radeon_atom_dac_detect,
26748c2ecf20Sopenharmony_ci};
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_civoid radeon_enc_destroy(struct drm_encoder *encoder)
26778c2ecf20Sopenharmony_ci{
26788c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
26798c2ecf20Sopenharmony_ci	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
26808c2ecf20Sopenharmony_ci		radeon_atom_backlight_exit(radeon_encoder);
26818c2ecf20Sopenharmony_ci	kfree(radeon_encoder->enc_priv);
26828c2ecf20Sopenharmony_ci	drm_encoder_cleanup(encoder);
26838c2ecf20Sopenharmony_ci	kfree(radeon_encoder);
26848c2ecf20Sopenharmony_ci}
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_cistatic const struct drm_encoder_funcs radeon_atom_enc_funcs = {
26878c2ecf20Sopenharmony_ci	.destroy = radeon_enc_destroy,
26888c2ecf20Sopenharmony_ci};
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_cistatic struct radeon_encoder_atom_dac *
26918c2ecf20Sopenharmony_ciradeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
26928c2ecf20Sopenharmony_ci{
26938c2ecf20Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
26948c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
26958c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
26968c2ecf20Sopenharmony_ci
26978c2ecf20Sopenharmony_ci	if (!dac)
26988c2ecf20Sopenharmony_ci		return NULL;
26998c2ecf20Sopenharmony_ci
27008c2ecf20Sopenharmony_ci	dac->tv_std = radeon_atombios_get_tv_info(rdev);
27018c2ecf20Sopenharmony_ci	return dac;
27028c2ecf20Sopenharmony_ci}
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_cistatic struct radeon_encoder_atom_dig *
27058c2ecf20Sopenharmony_ciradeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
27068c2ecf20Sopenharmony_ci{
27078c2ecf20Sopenharmony_ci	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
27088c2ecf20Sopenharmony_ci	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
27098c2ecf20Sopenharmony_ci
27108c2ecf20Sopenharmony_ci	if (!dig)
27118c2ecf20Sopenharmony_ci		return NULL;
27128c2ecf20Sopenharmony_ci
27138c2ecf20Sopenharmony_ci	/* coherent mode by default */
27148c2ecf20Sopenharmony_ci	dig->coherent_mode = true;
27158c2ecf20Sopenharmony_ci	dig->dig_encoder = -1;
27168c2ecf20Sopenharmony_ci
27178c2ecf20Sopenharmony_ci	if (encoder_enum == 2)
27188c2ecf20Sopenharmony_ci		dig->linkb = true;
27198c2ecf20Sopenharmony_ci	else
27208c2ecf20Sopenharmony_ci		dig->linkb = false;
27218c2ecf20Sopenharmony_ci
27228c2ecf20Sopenharmony_ci	return dig;
27238c2ecf20Sopenharmony_ci}
27248c2ecf20Sopenharmony_ci
27258c2ecf20Sopenharmony_civoid
27268c2ecf20Sopenharmony_ciradeon_add_atom_encoder(struct drm_device *dev,
27278c2ecf20Sopenharmony_ci			uint32_t encoder_enum,
27288c2ecf20Sopenharmony_ci			uint32_t supported_device,
27298c2ecf20Sopenharmony_ci			u16 caps)
27308c2ecf20Sopenharmony_ci{
27318c2ecf20Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
27328c2ecf20Sopenharmony_ci	struct drm_encoder *encoder;
27338c2ecf20Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci	/* see if we already added it */
27368c2ecf20Sopenharmony_ci	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
27378c2ecf20Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
27388c2ecf20Sopenharmony_ci		if (radeon_encoder->encoder_enum == encoder_enum) {
27398c2ecf20Sopenharmony_ci			radeon_encoder->devices |= supported_device;
27408c2ecf20Sopenharmony_ci			return;
27418c2ecf20Sopenharmony_ci		}
27428c2ecf20Sopenharmony_ci
27438c2ecf20Sopenharmony_ci	}
27448c2ecf20Sopenharmony_ci
27458c2ecf20Sopenharmony_ci	/* add a new one */
27468c2ecf20Sopenharmony_ci	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
27478c2ecf20Sopenharmony_ci	if (!radeon_encoder)
27488c2ecf20Sopenharmony_ci		return;
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_ci	encoder = &radeon_encoder->base;
27518c2ecf20Sopenharmony_ci	switch (rdev->num_crtc) {
27528c2ecf20Sopenharmony_ci	case 1:
27538c2ecf20Sopenharmony_ci		encoder->possible_crtcs = 0x1;
27548c2ecf20Sopenharmony_ci		break;
27558c2ecf20Sopenharmony_ci	case 2:
27568c2ecf20Sopenharmony_ci	default:
27578c2ecf20Sopenharmony_ci		encoder->possible_crtcs = 0x3;
27588c2ecf20Sopenharmony_ci		break;
27598c2ecf20Sopenharmony_ci	case 4:
27608c2ecf20Sopenharmony_ci		encoder->possible_crtcs = 0xf;
27618c2ecf20Sopenharmony_ci		break;
27628c2ecf20Sopenharmony_ci	case 6:
27638c2ecf20Sopenharmony_ci		encoder->possible_crtcs = 0x3f;
27648c2ecf20Sopenharmony_ci		break;
27658c2ecf20Sopenharmony_ci	}
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci	radeon_encoder->enc_priv = NULL;
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci	radeon_encoder->encoder_enum = encoder_enum;
27708c2ecf20Sopenharmony_ci	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
27718c2ecf20Sopenharmony_ci	radeon_encoder->devices = supported_device;
27728c2ecf20Sopenharmony_ci	radeon_encoder->rmx_type = RMX_OFF;
27738c2ecf20Sopenharmony_ci	radeon_encoder->underscan_type = UNDERSCAN_OFF;
27748c2ecf20Sopenharmony_ci	radeon_encoder->is_ext_encoder = false;
27758c2ecf20Sopenharmony_ci	radeon_encoder->caps = caps;
27768c2ecf20Sopenharmony_ci
27778c2ecf20Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
27788c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
27798c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
27808c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
27818c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
27828c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
27838c2ecf20Sopenharmony_ci			radeon_encoder->rmx_type = RMX_FULL;
27848c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
27858c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_LVDS, NULL);
27868c2ecf20Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
27878c2ecf20Sopenharmony_ci		} else {
27888c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
27898c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_TMDS, NULL);
27908c2ecf20Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
27918c2ecf20Sopenharmony_ci		}
27928c2ecf20Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
27938c2ecf20Sopenharmony_ci		break;
27948c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
27958c2ecf20Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
27968c2ecf20Sopenharmony_ci				 DRM_MODE_ENCODER_DAC, NULL);
27978c2ecf20Sopenharmony_ci		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
27988c2ecf20Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
27998c2ecf20Sopenharmony_ci		break;
28008c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
28018c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
28028c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
28038c2ecf20Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
28048c2ecf20Sopenharmony_ci				 DRM_MODE_ENCODER_TVDAC, NULL);
28058c2ecf20Sopenharmony_ci		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
28068c2ecf20Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
28078c2ecf20Sopenharmony_ci		break;
28088c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
28098c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
28108c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
28118c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
28128c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
28138c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
28148c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
28158c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
28168c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
28178c2ecf20Sopenharmony_ci			radeon_encoder->rmx_type = RMX_FULL;
28188c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
28198c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_LVDS, NULL);
28208c2ecf20Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
28218c2ecf20Sopenharmony_ci		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
28228c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
28238c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_DAC, NULL);
28248c2ecf20Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
28258c2ecf20Sopenharmony_ci		} else {
28268c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
28278c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_TMDS, NULL);
28288c2ecf20Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
28298c2ecf20Sopenharmony_ci		}
28308c2ecf20Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
28318c2ecf20Sopenharmony_ci		break;
28328c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_SI170B:
28338c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_CH7303:
28348c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
28358c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
28368c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_TITFP513:
28378c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_VT1623:
28388c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_HDMI_SI1930:
28398c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_TRAVIS:
28408c2ecf20Sopenharmony_ci	case ENCODER_OBJECT_ID_NUTMEG:
28418c2ecf20Sopenharmony_ci		/* these are handled by the primary encoders */
28428c2ecf20Sopenharmony_ci		radeon_encoder->is_ext_encoder = true;
28438c2ecf20Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
28448c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
28458c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_LVDS, NULL);
28468c2ecf20Sopenharmony_ci		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
28478c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
28488c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_DAC, NULL);
28498c2ecf20Sopenharmony_ci		else
28508c2ecf20Sopenharmony_ci			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
28518c2ecf20Sopenharmony_ci					 DRM_MODE_ENCODER_TMDS, NULL);
28528c2ecf20Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
28538c2ecf20Sopenharmony_ci		break;
28548c2ecf20Sopenharmony_ci	}
28558c2ecf20Sopenharmony_ci}
2856