162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2007-8 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
662306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
762306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
862306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
962306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
1062306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1362306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1862306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1962306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2062306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2162306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Authors: Dave Airlie
2462306a36Sopenharmony_ci *          Alex Deucher
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <linux/backlight.h>
2862306a36Sopenharmony_ci#include <linux/pci.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <drm/drm_device.h>
3162306a36Sopenharmony_ci#include <drm/drm_file.h>
3262306a36Sopenharmony_ci#include <drm/drm_modeset_helper_vtables.h>
3362306a36Sopenharmony_ci#include <drm/drm_util.h>
3462306a36Sopenharmony_ci#include <drm/radeon_drm.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include <acpi/video.h>
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#include "radeon.h"
3962306a36Sopenharmony_ci#include "radeon_asic.h"
4062306a36Sopenharmony_ci#include "radeon_legacy_encoders.h"
4162306a36Sopenharmony_ci#include "atom.h"
4262306a36Sopenharmony_ci#ifdef CONFIG_PMAC_BACKLIGHT
4362306a36Sopenharmony_ci#include <asm/backlight.h>
4462306a36Sopenharmony_ci#endif
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
4962306a36Sopenharmony_ci	const struct drm_encoder_helper_funcs *encoder_funcs;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	encoder_funcs = encoder->helper_private;
5262306a36Sopenharmony_ci	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
5362306a36Sopenharmony_ci	radeon_encoder->active_device = 0;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
5962306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
6062306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
6162306a36Sopenharmony_ci	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
6262306a36Sopenharmony_ci	int panel_pwr_delay = 2000;
6362306a36Sopenharmony_ci	bool is_mac = false;
6462306a36Sopenharmony_ci	uint8_t backlight_level;
6562306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
6862306a36Sopenharmony_ci	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	if (radeon_encoder->enc_priv) {
7162306a36Sopenharmony_ci		if (rdev->is_atom_bios) {
7262306a36Sopenharmony_ci			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
7362306a36Sopenharmony_ci			panel_pwr_delay = lvds->panel_pwr_delay;
7462306a36Sopenharmony_ci			if (lvds->bl_dev)
7562306a36Sopenharmony_ci				backlight_level = lvds->backlight_level;
7662306a36Sopenharmony_ci		} else {
7762306a36Sopenharmony_ci			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
7862306a36Sopenharmony_ci			panel_pwr_delay = lvds->panel_pwr_delay;
7962306a36Sopenharmony_ci			if (lvds->bl_dev)
8062306a36Sopenharmony_ci				backlight_level = lvds->backlight_level;
8162306a36Sopenharmony_ci		}
8262306a36Sopenharmony_ci	}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	/* macs (and possibly some x86 oem systems?) wire up LVDS strangely
8562306a36Sopenharmony_ci	 * Taken from radeonfb.
8662306a36Sopenharmony_ci	 */
8762306a36Sopenharmony_ci	if ((rdev->mode_info.connector_table == CT_IBOOK) ||
8862306a36Sopenharmony_ci	    (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) ||
8962306a36Sopenharmony_ci	    (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) ||
9062306a36Sopenharmony_ci	    (rdev->mode_info.connector_table == CT_POWERBOOK_VGA))
9162306a36Sopenharmony_ci		is_mac = true;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	switch (mode) {
9462306a36Sopenharmony_ci	case DRM_MODE_DPMS_ON:
9562306a36Sopenharmony_ci		disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
9662306a36Sopenharmony_ci		disp_pwr_man |= RADEON_AUTO_PWRUP_EN;
9762306a36Sopenharmony_ci		WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man);
9862306a36Sopenharmony_ci		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
9962306a36Sopenharmony_ci		lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
10062306a36Sopenharmony_ci		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
10162306a36Sopenharmony_ci		mdelay(1);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
10462306a36Sopenharmony_ci		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
10562306a36Sopenharmony_ci		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
10862306a36Sopenharmony_ci				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
10962306a36Sopenharmony_ci		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
11062306a36Sopenharmony_ci				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
11162306a36Sopenharmony_ci				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
11262306a36Sopenharmony_ci		if (is_mac)
11362306a36Sopenharmony_ci			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
11462306a36Sopenharmony_ci		mdelay(panel_pwr_delay);
11562306a36Sopenharmony_ci		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
11662306a36Sopenharmony_ci		break;
11762306a36Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
11862306a36Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
11962306a36Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
12062306a36Sopenharmony_ci		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
12162306a36Sopenharmony_ci		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
12262306a36Sopenharmony_ci		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
12362306a36Sopenharmony_ci		if (is_mac) {
12462306a36Sopenharmony_ci			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
12562306a36Sopenharmony_ci			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
12662306a36Sopenharmony_ci			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN);
12762306a36Sopenharmony_ci		} else {
12862306a36Sopenharmony_ci			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
12962306a36Sopenharmony_ci			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
13062306a36Sopenharmony_ci		}
13162306a36Sopenharmony_ci		mdelay(panel_pwr_delay);
13262306a36Sopenharmony_ci		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
13362306a36Sopenharmony_ci		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
13462306a36Sopenharmony_ci		mdelay(panel_pwr_delay);
13562306a36Sopenharmony_ci		break;
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	if (rdev->is_atom_bios)
13962306a36Sopenharmony_ci		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
14062306a36Sopenharmony_ci	else
14162306a36Sopenharmony_ci		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
14862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
14962306a36Sopenharmony_ci	DRM_DEBUG("\n");
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	if (radeon_encoder->enc_priv) {
15262306a36Sopenharmony_ci		if (rdev->is_atom_bios) {
15362306a36Sopenharmony_ci			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
15462306a36Sopenharmony_ci			lvds->dpms_mode = mode;
15562306a36Sopenharmony_ci		} else {
15662306a36Sopenharmony_ci			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
15762306a36Sopenharmony_ci			lvds->dpms_mode = mode;
15862306a36Sopenharmony_ci		}
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	radeon_legacy_lvds_update(encoder, mode);
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (rdev->is_atom_bios)
16962306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, true);
17062306a36Sopenharmony_ci	else
17162306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, true);
17262306a36Sopenharmony_ci	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
17362306a36Sopenharmony_ci}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistatic void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON);
18062306a36Sopenharmony_ci	if (rdev->is_atom_bios)
18162306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, false);
18262306a36Sopenharmony_ci	else
18362306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, false);
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
18762306a36Sopenharmony_ci					struct drm_display_mode *mode,
18862306a36Sopenharmony_ci					struct drm_display_mode *adjusted_mode)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
19162306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
19262306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
19362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
19462306a36Sopenharmony_ci	uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
19962306a36Sopenharmony_ci	lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
20262306a36Sopenharmony_ci	if (rdev->is_atom_bios) {
20362306a36Sopenharmony_ci		/* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
20462306a36Sopenharmony_ci		 * need to call that on resume to set up the reg properly.
20562306a36Sopenharmony_ci		 */
20662306a36Sopenharmony_ci		radeon_encoder->pixel_clock = adjusted_mode->clock;
20762306a36Sopenharmony_ci		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
20862306a36Sopenharmony_ci		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
20962306a36Sopenharmony_ci	} else {
21062306a36Sopenharmony_ci		struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
21162306a36Sopenharmony_ci		if (lvds) {
21262306a36Sopenharmony_ci			DRM_DEBUG_KMS("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
21362306a36Sopenharmony_ci			lvds_gen_cntl = lvds->lvds_gen_cntl;
21462306a36Sopenharmony_ci			lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
21562306a36Sopenharmony_ci					      (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
21662306a36Sopenharmony_ci			lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
21762306a36Sopenharmony_ci					     (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
21862306a36Sopenharmony_ci		} else
21962306a36Sopenharmony_ci			lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
22062306a36Sopenharmony_ci	}
22162306a36Sopenharmony_ci	lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
22262306a36Sopenharmony_ci	lvds_gen_cntl &= ~(RADEON_LVDS_ON |
22362306a36Sopenharmony_ci			   RADEON_LVDS_BLON |
22462306a36Sopenharmony_ci			   RADEON_LVDS_EN |
22562306a36Sopenharmony_ci			   RADEON_LVDS_RST_FM);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev))
22862306a36Sopenharmony_ci		lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	if (radeon_crtc->crtc_id == 0) {
23162306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev)) {
23262306a36Sopenharmony_ci			if (radeon_encoder->rmx_type != RMX_OFF)
23362306a36Sopenharmony_ci				lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
23462306a36Sopenharmony_ci		} else
23562306a36Sopenharmony_ci			lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
23662306a36Sopenharmony_ci	} else {
23762306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev))
23862306a36Sopenharmony_ci			lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
23962306a36Sopenharmony_ci		else
24062306a36Sopenharmony_ci			lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
24462306a36Sopenharmony_ci	WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
24562306a36Sopenharmony_ci	WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	if (rdev->family == CHIP_RV410)
24862306a36Sopenharmony_ci		WREG32(RADEON_CLOCK_CNTL_INDEX, 0);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	if (rdev->is_atom_bios)
25162306a36Sopenharmony_ci		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
25262306a36Sopenharmony_ci	else
25362306a36Sopenharmony_ci		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
25762306a36Sopenharmony_ci				     const struct drm_display_mode *mode,
25862306a36Sopenharmony_ci				     struct drm_display_mode *adjusted_mode)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	/* set the active encoder to connector routing */
26362306a36Sopenharmony_ci	radeon_encoder_set_active_device(encoder);
26462306a36Sopenharmony_ci	drm_mode_set_crtcinfo(adjusted_mode, 0);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	/* get the native mode for LVDS */
26762306a36Sopenharmony_ci	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
26862306a36Sopenharmony_ci		radeon_panel_mode_fixup(encoder, adjusted_mode);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	return true;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
27462306a36Sopenharmony_ci	.dpms = radeon_legacy_lvds_dpms,
27562306a36Sopenharmony_ci	.mode_fixup = radeon_legacy_mode_fixup,
27662306a36Sopenharmony_ci	.prepare = radeon_legacy_lvds_prepare,
27762306a36Sopenharmony_ci	.mode_set = radeon_legacy_lvds_mode_set,
27862306a36Sopenharmony_ci	.commit = radeon_legacy_lvds_commit,
27962306a36Sopenharmony_ci	.disable = radeon_legacy_encoder_disable,
28062306a36Sopenharmony_ci};
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ciu8
28362306a36Sopenharmony_ciradeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
28662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
28762306a36Sopenharmony_ci	u8 backlight_level;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
29062306a36Sopenharmony_ci			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	return backlight_level;
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_civoid
29662306a36Sopenharmony_ciradeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
29962306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
30062306a36Sopenharmony_ci	int dpms_mode = DRM_MODE_DPMS_ON;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	if (radeon_encoder->enc_priv) {
30362306a36Sopenharmony_ci		if (rdev->is_atom_bios) {
30462306a36Sopenharmony_ci			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
30562306a36Sopenharmony_ci			if (lvds->backlight_level > 0)
30662306a36Sopenharmony_ci				dpms_mode = lvds->dpms_mode;
30762306a36Sopenharmony_ci			else
30862306a36Sopenharmony_ci				dpms_mode = DRM_MODE_DPMS_OFF;
30962306a36Sopenharmony_ci			lvds->backlight_level = level;
31062306a36Sopenharmony_ci		} else {
31162306a36Sopenharmony_ci			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
31262306a36Sopenharmony_ci			if (lvds->backlight_level > 0)
31362306a36Sopenharmony_ci				dpms_mode = lvds->dpms_mode;
31462306a36Sopenharmony_ci			else
31562306a36Sopenharmony_ci				dpms_mode = DRM_MODE_DPMS_OFF;
31662306a36Sopenharmony_ci			lvds->backlight_level = level;
31762306a36Sopenharmony_ci		}
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_cistatic uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
32662306a36Sopenharmony_ci	uint8_t level;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	/* Convert brightness to hardware level */
32962306a36Sopenharmony_ci	if (bd->props.brightness < 0)
33062306a36Sopenharmony_ci		level = 0;
33162306a36Sopenharmony_ci	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
33262306a36Sopenharmony_ci		level = RADEON_MAX_BL_LEVEL;
33362306a36Sopenharmony_ci	else
33462306a36Sopenharmony_ci		level = bd->props.brightness;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (pdata->negative)
33762306a36Sopenharmony_ci		level = RADEON_MAX_BL_LEVEL - level;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	return level;
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cistatic int radeon_legacy_backlight_update_status(struct backlight_device *bd)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
34562306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = pdata->encoder;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	radeon_legacy_set_backlight_level(radeon_encoder,
34862306a36Sopenharmony_ci					  radeon_legacy_lvds_level(bd));
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return 0;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_cistatic int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
35462306a36Sopenharmony_ci{
35562306a36Sopenharmony_ci	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
35662306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = pdata->encoder;
35762306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
35862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
35962306a36Sopenharmony_ci	uint8_t backlight_level;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
36262306a36Sopenharmony_ci			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	return pdata->negative ? RADEON_MAX_BL_LEVEL - backlight_level : backlight_level;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic const struct backlight_ops radeon_backlight_ops = {
36862306a36Sopenharmony_ci	.get_brightness = radeon_legacy_backlight_get_brightness,
36962306a36Sopenharmony_ci	.update_status	= radeon_legacy_backlight_update_status,
37062306a36Sopenharmony_ci};
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_civoid radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
37362306a36Sopenharmony_ci				  struct drm_connector *drm_connector)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
37662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
37762306a36Sopenharmony_ci	struct backlight_device *bd;
37862306a36Sopenharmony_ci	struct backlight_properties props;
37962306a36Sopenharmony_ci	struct radeon_backlight_privdata *pdata;
38062306a36Sopenharmony_ci	uint8_t backlight_level;
38162306a36Sopenharmony_ci	char bl_name[16];
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	if (!radeon_encoder->enc_priv)
38462306a36Sopenharmony_ci		return;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci#ifdef CONFIG_PMAC_BACKLIGHT
38762306a36Sopenharmony_ci	if (!pmac_has_backlight_type("ati") &&
38862306a36Sopenharmony_ci	    !pmac_has_backlight_type("mnca"))
38962306a36Sopenharmony_ci		return;
39062306a36Sopenharmony_ci#endif
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	if (!acpi_video_backlight_use_native()) {
39362306a36Sopenharmony_ci		drm_info(dev, "Skipping radeon legacy LVDS backlight registration\n");
39462306a36Sopenharmony_ci		return;
39562306a36Sopenharmony_ci	}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
39862306a36Sopenharmony_ci	if (!pdata) {
39962306a36Sopenharmony_ci		DRM_ERROR("Memory allocation failed\n");
40062306a36Sopenharmony_ci		goto error;
40162306a36Sopenharmony_ci	}
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	memset(&props, 0, sizeof(props));
40462306a36Sopenharmony_ci	props.max_brightness = RADEON_MAX_BL_LEVEL;
40562306a36Sopenharmony_ci	props.type = BACKLIGHT_RAW;
40662306a36Sopenharmony_ci	snprintf(bl_name, sizeof(bl_name),
40762306a36Sopenharmony_ci		 "radeon_bl%d", dev->primary->index);
40862306a36Sopenharmony_ci	bd = backlight_device_register(bl_name, drm_connector->kdev,
40962306a36Sopenharmony_ci				       pdata, &radeon_backlight_ops, &props);
41062306a36Sopenharmony_ci	if (IS_ERR(bd)) {
41162306a36Sopenharmony_ci		DRM_ERROR("Backlight registration failed\n");
41262306a36Sopenharmony_ci		goto error;
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	pdata->encoder = radeon_encoder;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
41862306a36Sopenharmony_ci			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	/* First, try to detect backlight level sense based on the assumption
42162306a36Sopenharmony_ci	 * that firmware set it up at full brightness
42262306a36Sopenharmony_ci	 */
42362306a36Sopenharmony_ci	if (backlight_level == 0)
42462306a36Sopenharmony_ci		pdata->negative = true;
42562306a36Sopenharmony_ci	else if (backlight_level == 0xff)
42662306a36Sopenharmony_ci		pdata->negative = false;
42762306a36Sopenharmony_ci	else {
42862306a36Sopenharmony_ci		/* XXX hack... maybe some day we can figure out in what direction
42962306a36Sopenharmony_ci		 * backlight should work on a given panel?
43062306a36Sopenharmony_ci		 */
43162306a36Sopenharmony_ci		pdata->negative = (rdev->family != CHIP_RV200 &&
43262306a36Sopenharmony_ci				   rdev->family != CHIP_RV250 &&
43362306a36Sopenharmony_ci				   rdev->family != CHIP_RV280 &&
43462306a36Sopenharmony_ci				   rdev->family != CHIP_RV350);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci#ifdef CONFIG_PMAC_BACKLIGHT
43762306a36Sopenharmony_ci		pdata->negative = (pdata->negative ||
43862306a36Sopenharmony_ci				   of_machine_is_compatible("PowerBook4,3") ||
43962306a36Sopenharmony_ci				   of_machine_is_compatible("PowerBook6,3") ||
44062306a36Sopenharmony_ci				   of_machine_is_compatible("PowerBook6,5"));
44162306a36Sopenharmony_ci#endif
44262306a36Sopenharmony_ci	}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (rdev->is_atom_bios) {
44562306a36Sopenharmony_ci		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
44662306a36Sopenharmony_ci		lvds->bl_dev = bd;
44762306a36Sopenharmony_ci	} else {
44862306a36Sopenharmony_ci		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
44962306a36Sopenharmony_ci		lvds->bl_dev = bd;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
45362306a36Sopenharmony_ci	bd->props.power = FB_BLANK_UNBLANK;
45462306a36Sopenharmony_ci	backlight_update_status(bd);
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	DRM_INFO("radeon legacy LVDS backlight initialized\n");
45762306a36Sopenharmony_ci	rdev->mode_info.bl_encoder = radeon_encoder;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cierror:
46262306a36Sopenharmony_ci	kfree(pdata);
46362306a36Sopenharmony_ci	return;
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistatic void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
46762306a36Sopenharmony_ci{
46862306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
46962306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
47062306a36Sopenharmony_ci	struct backlight_device *bd = NULL;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (!radeon_encoder->enc_priv)
47362306a36Sopenharmony_ci		return;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	if (rdev->is_atom_bios) {
47662306a36Sopenharmony_ci		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
47762306a36Sopenharmony_ci		bd = lvds->bl_dev;
47862306a36Sopenharmony_ci		lvds->bl_dev = NULL;
47962306a36Sopenharmony_ci	} else {
48062306a36Sopenharmony_ci		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
48162306a36Sopenharmony_ci		bd = lvds->bl_dev;
48262306a36Sopenharmony_ci		lvds->bl_dev = NULL;
48362306a36Sopenharmony_ci	}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	if (bd) {
48662306a36Sopenharmony_ci		struct radeon_backlight_privdata *pdata;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci		pdata = bl_get_data(bd);
48962306a36Sopenharmony_ci		backlight_device_unregister(bd);
49062306a36Sopenharmony_ci		kfree(pdata);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
49362306a36Sopenharmony_ci	}
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_cistatic void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	if (radeon_encoder->enc_priv) {
50162306a36Sopenharmony_ci		radeon_legacy_backlight_exit(radeon_encoder);
50262306a36Sopenharmony_ci		kfree(radeon_encoder->enc_priv);
50362306a36Sopenharmony_ci	}
50462306a36Sopenharmony_ci	drm_encoder_cleanup(encoder);
50562306a36Sopenharmony_ci	kfree(radeon_encoder);
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_cistatic const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
50962306a36Sopenharmony_ci	.destroy = radeon_lvds_enc_destroy,
51062306a36Sopenharmony_ci};
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cistatic void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
51362306a36Sopenharmony_ci{
51462306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
51562306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
51662306a36Sopenharmony_ci	uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
51762306a36Sopenharmony_ci	uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL);
51862306a36Sopenharmony_ci	uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	switch (mode) {
52362306a36Sopenharmony_ci	case DRM_MODE_DPMS_ON:
52462306a36Sopenharmony_ci		crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
52562306a36Sopenharmony_ci		dac_cntl &= ~RADEON_DAC_PDWN;
52662306a36Sopenharmony_ci		dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
52762306a36Sopenharmony_ci				    RADEON_DAC_PDWN_G |
52862306a36Sopenharmony_ci				    RADEON_DAC_PDWN_B);
52962306a36Sopenharmony_ci		break;
53062306a36Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
53162306a36Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
53262306a36Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
53362306a36Sopenharmony_ci		crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
53462306a36Sopenharmony_ci		dac_cntl |= RADEON_DAC_PDWN;
53562306a36Sopenharmony_ci		dac_macro_cntl |= (RADEON_DAC_PDWN_R |
53662306a36Sopenharmony_ci				   RADEON_DAC_PDWN_G |
53762306a36Sopenharmony_ci				   RADEON_DAC_PDWN_B);
53862306a36Sopenharmony_ci		break;
53962306a36Sopenharmony_ci	}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	/* handled in radeon_crtc_dpms() */
54262306a36Sopenharmony_ci	if (!(rdev->flags & RADEON_SINGLE_CRTC))
54362306a36Sopenharmony_ci		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
54462306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL, dac_cntl);
54562306a36Sopenharmony_ci	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	if (rdev->is_atom_bios)
54862306a36Sopenharmony_ci		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
54962306a36Sopenharmony_ci	else
55062306a36Sopenharmony_ci		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_cistatic void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	if (rdev->is_atom_bios)
55962306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, true);
56062306a36Sopenharmony_ci	else
56162306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, true);
56262306a36Sopenharmony_ci	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	if (rdev->is_atom_bios)
57262306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, false);
57362306a36Sopenharmony_ci	else
57462306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, false);
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cistatic void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
57862306a36Sopenharmony_ci					       struct drm_display_mode *mode,
57962306a36Sopenharmony_ci					       struct drm_display_mode *adjusted_mode)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
58262306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
58362306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
58462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
58562306a36Sopenharmony_ci	uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	if (radeon_crtc->crtc_id == 0) {
59062306a36Sopenharmony_ci		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
59162306a36Sopenharmony_ci			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
59262306a36Sopenharmony_ci				~(RADEON_DISP_DAC_SOURCE_MASK);
59362306a36Sopenharmony_ci			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
59462306a36Sopenharmony_ci		} else {
59562306a36Sopenharmony_ci			dac2_cntl = RREG32(RADEON_DAC_CNTL2)  & ~(RADEON_DAC2_DAC_CLK_SEL);
59662306a36Sopenharmony_ci			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
59762306a36Sopenharmony_ci		}
59862306a36Sopenharmony_ci	} else {
59962306a36Sopenharmony_ci		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
60062306a36Sopenharmony_ci			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
60162306a36Sopenharmony_ci				~(RADEON_DISP_DAC_SOURCE_MASK);
60262306a36Sopenharmony_ci			disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
60362306a36Sopenharmony_ci			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
60462306a36Sopenharmony_ci		} else {
60562306a36Sopenharmony_ci			dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL;
60662306a36Sopenharmony_ci			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
60762306a36Sopenharmony_ci		}
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	dac_cntl = (RADEON_DAC_MASK_ALL |
61162306a36Sopenharmony_ci		    RADEON_DAC_VGA_ADR_EN |
61262306a36Sopenharmony_ci		    /* TODO 6-bits */
61362306a36Sopenharmony_ci		    RADEON_DAC_8BIT_EN);
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	WREG32_P(RADEON_DAC_CNTL,
61662306a36Sopenharmony_ci		       dac_cntl,
61762306a36Sopenharmony_ci		       RADEON_DAC_RANGE_CNTL |
61862306a36Sopenharmony_ci		       RADEON_DAC_BLANKING);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	if (radeon_encoder->enc_priv) {
62162306a36Sopenharmony_ci		struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv;
62262306a36Sopenharmony_ci		dac_macro_cntl = p_dac->ps2_pdac_adj;
62362306a36Sopenharmony_ci	} else
62462306a36Sopenharmony_ci		dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
62562306a36Sopenharmony_ci	dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B;
62662306a36Sopenharmony_ci	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	if (rdev->is_atom_bios)
62962306a36Sopenharmony_ci		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
63062306a36Sopenharmony_ci	else
63162306a36Sopenharmony_ci		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
63262306a36Sopenharmony_ci}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_cistatic enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder,
63562306a36Sopenharmony_ci								  struct drm_connector *connector)
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
63862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
63962306a36Sopenharmony_ci	uint32_t vclk_ecp_cntl, crtc_ext_cntl;
64062306a36Sopenharmony_ci	uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
64162306a36Sopenharmony_ci	enum drm_connector_status found = connector_status_disconnected;
64262306a36Sopenharmony_ci	bool color = true;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	/* just don't bother on RN50 those chip are often connected to remoting
64562306a36Sopenharmony_ci	 * console hw and often we get failure to load detect those. So to make
64662306a36Sopenharmony_ci	 * everyone happy report the encoder as always connected.
64762306a36Sopenharmony_ci	 */
64862306a36Sopenharmony_ci	if (ASIC_IS_RN50(rdev)) {
64962306a36Sopenharmony_ci		return connector_status_connected;
65062306a36Sopenharmony_ci	}
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	/* save the regs we need */
65362306a36Sopenharmony_ci	vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
65462306a36Sopenharmony_ci	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
65562306a36Sopenharmony_ci	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
65662306a36Sopenharmony_ci	dac_cntl = RREG32(RADEON_DAC_CNTL);
65762306a36Sopenharmony_ci	dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	tmp = vclk_ecp_cntl &
66062306a36Sopenharmony_ci		~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
66162306a36Sopenharmony_ci	WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
66462306a36Sopenharmony_ci	WREG32(RADEON_CRTC_EXT_CNTL, tmp);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
66762306a36Sopenharmony_ci		RADEON_DAC_FORCE_DATA_EN;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	if (color)
67062306a36Sopenharmony_ci		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
67162306a36Sopenharmony_ci	else
67262306a36Sopenharmony_ci		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev))
67562306a36Sopenharmony_ci		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
67662306a36Sopenharmony_ci	else if (ASIC_IS_RV100(rdev))
67762306a36Sopenharmony_ci		tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
67862306a36Sopenharmony_ci	else
67962306a36Sopenharmony_ci		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	WREG32(RADEON_DAC_EXT_CNTL, tmp);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
68462306a36Sopenharmony_ci	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
68562306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL, tmp);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	tmp = dac_macro_cntl;
68862306a36Sopenharmony_ci	tmp &= ~(RADEON_DAC_PDWN_R |
68962306a36Sopenharmony_ci		 RADEON_DAC_PDWN_G |
69062306a36Sopenharmony_ci		 RADEON_DAC_PDWN_B);
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	WREG32(RADEON_DAC_MACRO_CNTL, tmp);
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	mdelay(2);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
69762306a36Sopenharmony_ci		found = connector_status_connected;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	/* restore the regs we used */
70062306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL, dac_cntl);
70162306a36Sopenharmony_ci	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
70262306a36Sopenharmony_ci	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
70362306a36Sopenharmony_ci	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
70462306a36Sopenharmony_ci	WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	return found;
70762306a36Sopenharmony_ci}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
71062306a36Sopenharmony_ci	.dpms = radeon_legacy_primary_dac_dpms,
71162306a36Sopenharmony_ci	.mode_fixup = radeon_legacy_mode_fixup,
71262306a36Sopenharmony_ci	.prepare = radeon_legacy_primary_dac_prepare,
71362306a36Sopenharmony_ci	.mode_set = radeon_legacy_primary_dac_mode_set,
71462306a36Sopenharmony_ci	.commit = radeon_legacy_primary_dac_commit,
71562306a36Sopenharmony_ci	.detect = radeon_legacy_primary_dac_detect,
71662306a36Sopenharmony_ci	.disable = radeon_legacy_encoder_disable,
71762306a36Sopenharmony_ci};
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistatic const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = {
72162306a36Sopenharmony_ci	.destroy = radeon_enc_destroy,
72262306a36Sopenharmony_ci};
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cistatic void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
72562306a36Sopenharmony_ci{
72662306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
72762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
72862306a36Sopenharmony_ci	uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL);
72962306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	switch (mode) {
73262306a36Sopenharmony_ci	case DRM_MODE_DPMS_ON:
73362306a36Sopenharmony_ci		fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
73462306a36Sopenharmony_ci		break;
73562306a36Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
73662306a36Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
73762306a36Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
73862306a36Sopenharmony_ci		fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
73962306a36Sopenharmony_ci		break;
74062306a36Sopenharmony_ci	}
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	if (rdev->is_atom_bios)
74562306a36Sopenharmony_ci		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
74662306a36Sopenharmony_ci	else
74762306a36Sopenharmony_ci		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_cistatic void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
75262306a36Sopenharmony_ci{
75362306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	if (rdev->is_atom_bios)
75662306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, true);
75762306a36Sopenharmony_ci	else
75862306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, true);
75962306a36Sopenharmony_ci	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
76062306a36Sopenharmony_ci}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_cistatic void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON);
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	if (rdev->is_atom_bios)
76962306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, true);
77062306a36Sopenharmony_ci	else
77162306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, true);
77262306a36Sopenharmony_ci}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_cistatic void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
77562306a36Sopenharmony_ci					    struct drm_display_mode *mode,
77662306a36Sopenharmony_ci					    struct drm_display_mode *adjusted_mode)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
77962306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
78062306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
78162306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
78262306a36Sopenharmony_ci	uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl;
78362306a36Sopenharmony_ci	int i;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
78862306a36Sopenharmony_ci	tmp &= 0xfffff;
78962306a36Sopenharmony_ci	if (rdev->family == CHIP_RV280) {
79062306a36Sopenharmony_ci		/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
79162306a36Sopenharmony_ci		tmp ^= (1 << 22);
79262306a36Sopenharmony_ci		tmds_pll_cntl ^= (1 << 22);
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if (radeon_encoder->enc_priv) {
79662306a36Sopenharmony_ci		struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci		for (i = 0; i < 4; i++) {
79962306a36Sopenharmony_ci			if (tmds->tmds_pll[i].freq == 0)
80062306a36Sopenharmony_ci				break;
80162306a36Sopenharmony_ci			if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) {
80262306a36Sopenharmony_ci				tmp = tmds->tmds_pll[i].value ;
80362306a36Sopenharmony_ci				break;
80462306a36Sopenharmony_ci			}
80562306a36Sopenharmony_ci		}
80662306a36Sopenharmony_ci	}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) {
80962306a36Sopenharmony_ci		if (tmp & 0xfff00000)
81062306a36Sopenharmony_ci			tmds_pll_cntl = tmp;
81162306a36Sopenharmony_ci		else {
81262306a36Sopenharmony_ci			tmds_pll_cntl &= 0xfff00000;
81362306a36Sopenharmony_ci			tmds_pll_cntl |= tmp;
81462306a36Sopenharmony_ci		}
81562306a36Sopenharmony_ci	} else
81662306a36Sopenharmony_ci		tmds_pll_cntl = tmp;
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) &
81962306a36Sopenharmony_ci		~(RADEON_TMDS_TRANSMITTER_PLLRST);
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	if (rdev->family == CHIP_R200 ||
82262306a36Sopenharmony_ci	    rdev->family == CHIP_R100 ||
82362306a36Sopenharmony_ci	    ASIC_IS_R300(rdev))
82462306a36Sopenharmony_ci		tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
82562306a36Sopenharmony_ci	else /* RV chips got this bit reversed */
82662306a36Sopenharmony_ci		tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN;
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) |
82962306a36Sopenharmony_ci		      (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
83062306a36Sopenharmony_ci		       RADEON_FP_CRTC_DONT_SHADOW_HEND));
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
83562306a36Sopenharmony_ci			 RADEON_FP_DFP_SYNC_SEL |
83662306a36Sopenharmony_ci			 RADEON_FP_CRT_SYNC_SEL |
83762306a36Sopenharmony_ci			 RADEON_FP_CRTC_LOCK_8DOT |
83862306a36Sopenharmony_ci			 RADEON_FP_USE_SHADOW_EN |
83962306a36Sopenharmony_ci			 RADEON_FP_CRTC_USE_SHADOW_VEND |
84062306a36Sopenharmony_ci			 RADEON_FP_CRT_SYNC_ALT);
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	if (1) /*  FIXME rgbBits == 8 */
84362306a36Sopenharmony_ci		fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
84462306a36Sopenharmony_ci	else
84562306a36Sopenharmony_ci		fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	if (radeon_crtc->crtc_id == 0) {
84862306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
84962306a36Sopenharmony_ci			fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
85062306a36Sopenharmony_ci			if (radeon_encoder->rmx_type != RMX_OFF)
85162306a36Sopenharmony_ci				fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
85262306a36Sopenharmony_ci			else
85362306a36Sopenharmony_ci				fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
85462306a36Sopenharmony_ci		} else
85562306a36Sopenharmony_ci			fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
85662306a36Sopenharmony_ci	} else {
85762306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
85862306a36Sopenharmony_ci			fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
85962306a36Sopenharmony_ci			fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
86062306a36Sopenharmony_ci		} else
86162306a36Sopenharmony_ci			fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
86262306a36Sopenharmony_ci	}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl);
86562306a36Sopenharmony_ci	WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl);
86662306a36Sopenharmony_ci	WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	if (rdev->is_atom_bios)
86962306a36Sopenharmony_ci		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
87062306a36Sopenharmony_ci	else
87162306a36Sopenharmony_ci		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
87562306a36Sopenharmony_ci	.dpms = radeon_legacy_tmds_int_dpms,
87662306a36Sopenharmony_ci	.mode_fixup = radeon_legacy_mode_fixup,
87762306a36Sopenharmony_ci	.prepare = radeon_legacy_tmds_int_prepare,
87862306a36Sopenharmony_ci	.mode_set = radeon_legacy_tmds_int_mode_set,
87962306a36Sopenharmony_ci	.commit = radeon_legacy_tmds_int_commit,
88062306a36Sopenharmony_ci	.disable = radeon_legacy_encoder_disable,
88162306a36Sopenharmony_ci};
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_cistatic const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = {
88562306a36Sopenharmony_ci	.destroy = radeon_enc_destroy,
88662306a36Sopenharmony_ci};
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_cistatic void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
88962306a36Sopenharmony_ci{
89062306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
89162306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
89262306a36Sopenharmony_ci	uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
89362306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	switch (mode) {
89662306a36Sopenharmony_ci	case DRM_MODE_DPMS_ON:
89762306a36Sopenharmony_ci		fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
89862306a36Sopenharmony_ci		fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
89962306a36Sopenharmony_ci		break;
90062306a36Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
90162306a36Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
90262306a36Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
90362306a36Sopenharmony_ci		fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
90462306a36Sopenharmony_ci		fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
90562306a36Sopenharmony_ci		break;
90662306a36Sopenharmony_ci	}
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	if (rdev->is_atom_bios)
91162306a36Sopenharmony_ci		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
91262306a36Sopenharmony_ci	else
91362306a36Sopenharmony_ci		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_cistatic void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
91862306a36Sopenharmony_ci{
91962306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	if (rdev->is_atom_bios)
92262306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, true);
92362306a36Sopenharmony_ci	else
92462306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, true);
92562306a36Sopenharmony_ci	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
92662306a36Sopenharmony_ci}
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_cistatic void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
93162306a36Sopenharmony_ci	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON);
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	if (rdev->is_atom_bios)
93462306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, false);
93562306a36Sopenharmony_ci	else
93662306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, false);
93762306a36Sopenharmony_ci}
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_cistatic void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
94062306a36Sopenharmony_ci					    struct drm_display_mode *mode,
94162306a36Sopenharmony_ci					    struct drm_display_mode *adjusted_mode)
94262306a36Sopenharmony_ci{
94362306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
94462306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
94562306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
94662306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
94762306a36Sopenharmony_ci	uint32_t fp2_gen_cntl;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	if (rdev->is_atom_bios) {
95262306a36Sopenharmony_ci		radeon_encoder->pixel_clock = adjusted_mode->clock;
95362306a36Sopenharmony_ci		atombios_dvo_setup(encoder, ATOM_ENABLE);
95462306a36Sopenharmony_ci		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
95562306a36Sopenharmony_ci	} else {
95662306a36Sopenharmony_ci		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci		if (1) /*  FIXME rgbBits == 8 */
95962306a36Sopenharmony_ci			fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
96062306a36Sopenharmony_ci		else
96162306a36Sopenharmony_ci			fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci		fp2_gen_cntl &= ~(RADEON_FP2_ON |
96462306a36Sopenharmony_ci				  RADEON_FP2_DVO_EN |
96562306a36Sopenharmony_ci				  RADEON_FP2_DVO_RATE_SEL_SDR);
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci		/* XXX: these are oem specific */
96862306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev)) {
96962306a36Sopenharmony_ci			if ((rdev->pdev->device == 0x4850) &&
97062306a36Sopenharmony_ci			    (rdev->pdev->subsystem_vendor == 0x1028) &&
97162306a36Sopenharmony_ci			    (rdev->pdev->subsystem_device == 0x2001)) /* Dell Inspiron 8600 */
97262306a36Sopenharmony_ci				fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE;
97362306a36Sopenharmony_ci			else
97462306a36Sopenharmony_ci				fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci			/*if (mode->clock > 165000)
97762306a36Sopenharmony_ci			  fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
97862306a36Sopenharmony_ci		}
97962306a36Sopenharmony_ci		if (!radeon_combios_external_tmds_setup(encoder))
98062306a36Sopenharmony_ci			radeon_external_tmds_setup(encoder);
98162306a36Sopenharmony_ci	}
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	if (radeon_crtc->crtc_id == 0) {
98462306a36Sopenharmony_ci		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
98562306a36Sopenharmony_ci			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
98662306a36Sopenharmony_ci			if (radeon_encoder->rmx_type != RMX_OFF)
98762306a36Sopenharmony_ci				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
98862306a36Sopenharmony_ci			else
98962306a36Sopenharmony_ci				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
99062306a36Sopenharmony_ci		} else
99162306a36Sopenharmony_ci			fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
99262306a36Sopenharmony_ci	} else {
99362306a36Sopenharmony_ci		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
99462306a36Sopenharmony_ci			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
99562306a36Sopenharmony_ci			fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
99662306a36Sopenharmony_ci		} else
99762306a36Sopenharmony_ci			fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
99862306a36Sopenharmony_ci	}
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	if (rdev->is_atom_bios)
100362306a36Sopenharmony_ci		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
100462306a36Sopenharmony_ci	else
100562306a36Sopenharmony_ci		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
100662306a36Sopenharmony_ci}
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_cistatic void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
100962306a36Sopenharmony_ci{
101062306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
101162306a36Sopenharmony_ci	/* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */
101262306a36Sopenharmony_ci	kfree(radeon_encoder->enc_priv);
101362306a36Sopenharmony_ci	drm_encoder_cleanup(encoder);
101462306a36Sopenharmony_ci	kfree(radeon_encoder);
101562306a36Sopenharmony_ci}
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
101862306a36Sopenharmony_ci	.dpms = radeon_legacy_tmds_ext_dpms,
101962306a36Sopenharmony_ci	.mode_fixup = radeon_legacy_mode_fixup,
102062306a36Sopenharmony_ci	.prepare = radeon_legacy_tmds_ext_prepare,
102162306a36Sopenharmony_ci	.mode_set = radeon_legacy_tmds_ext_mode_set,
102262306a36Sopenharmony_ci	.commit = radeon_legacy_tmds_ext_commit,
102362306a36Sopenharmony_ci	.disable = radeon_legacy_encoder_disable,
102462306a36Sopenharmony_ci};
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_cistatic const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
102862306a36Sopenharmony_ci	.destroy = radeon_ext_tmds_enc_destroy,
102962306a36Sopenharmony_ci};
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_cistatic void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
103262306a36Sopenharmony_ci{
103362306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
103462306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
103562306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
103662306a36Sopenharmony_ci	uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
103762306a36Sopenharmony_ci	uint32_t tv_master_cntl = 0;
103862306a36Sopenharmony_ci	bool is_tv;
103962306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	if (rdev->family == CHIP_R200)
104462306a36Sopenharmony_ci		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
104562306a36Sopenharmony_ci	else {
104662306a36Sopenharmony_ci		if (is_tv)
104762306a36Sopenharmony_ci			tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
104862306a36Sopenharmony_ci		else
104962306a36Sopenharmony_ci			crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
105062306a36Sopenharmony_ci		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
105162306a36Sopenharmony_ci	}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	switch (mode) {
105462306a36Sopenharmony_ci	case DRM_MODE_DPMS_ON:
105562306a36Sopenharmony_ci		if (rdev->family == CHIP_R200) {
105662306a36Sopenharmony_ci			fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
105762306a36Sopenharmony_ci		} else {
105862306a36Sopenharmony_ci			if (is_tv)
105962306a36Sopenharmony_ci				tv_master_cntl |= RADEON_TV_ON;
106062306a36Sopenharmony_ci			else
106162306a36Sopenharmony_ci				crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci			if (rdev->family == CHIP_R420 ||
106462306a36Sopenharmony_ci			    rdev->family == CHIP_R423 ||
106562306a36Sopenharmony_ci			    rdev->family == CHIP_RV410)
106662306a36Sopenharmony_ci				tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
106762306a36Sopenharmony_ci						 R420_TV_DAC_GDACPD |
106862306a36Sopenharmony_ci						 R420_TV_DAC_BDACPD |
106962306a36Sopenharmony_ci						 RADEON_TV_DAC_BGSLEEP);
107062306a36Sopenharmony_ci			else
107162306a36Sopenharmony_ci				tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
107262306a36Sopenharmony_ci						 RADEON_TV_DAC_GDACPD |
107362306a36Sopenharmony_ci						 RADEON_TV_DAC_BDACPD |
107462306a36Sopenharmony_ci						 RADEON_TV_DAC_BGSLEEP);
107562306a36Sopenharmony_ci		}
107662306a36Sopenharmony_ci		break;
107762306a36Sopenharmony_ci	case DRM_MODE_DPMS_STANDBY:
107862306a36Sopenharmony_ci	case DRM_MODE_DPMS_SUSPEND:
107962306a36Sopenharmony_ci	case DRM_MODE_DPMS_OFF:
108062306a36Sopenharmony_ci		if (rdev->family == CHIP_R200)
108162306a36Sopenharmony_ci			fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
108262306a36Sopenharmony_ci		else {
108362306a36Sopenharmony_ci			if (is_tv)
108462306a36Sopenharmony_ci				tv_master_cntl &= ~RADEON_TV_ON;
108562306a36Sopenharmony_ci			else
108662306a36Sopenharmony_ci				crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci			if (rdev->family == CHIP_R420 ||
108962306a36Sopenharmony_ci			    rdev->family == CHIP_R423 ||
109062306a36Sopenharmony_ci			    rdev->family == CHIP_RV410)
109162306a36Sopenharmony_ci				tv_dac_cntl |= (R420_TV_DAC_RDACPD |
109262306a36Sopenharmony_ci						R420_TV_DAC_GDACPD |
109362306a36Sopenharmony_ci						R420_TV_DAC_BDACPD |
109462306a36Sopenharmony_ci						RADEON_TV_DAC_BGSLEEP);
109562306a36Sopenharmony_ci			else
109662306a36Sopenharmony_ci				tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
109762306a36Sopenharmony_ci						RADEON_TV_DAC_GDACPD |
109862306a36Sopenharmony_ci						RADEON_TV_DAC_BDACPD |
109962306a36Sopenharmony_ci						RADEON_TV_DAC_BGSLEEP);
110062306a36Sopenharmony_ci		}
110162306a36Sopenharmony_ci		break;
110262306a36Sopenharmony_ci	}
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	if (rdev->family == CHIP_R200) {
110562306a36Sopenharmony_ci		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
110662306a36Sopenharmony_ci	} else {
110762306a36Sopenharmony_ci		if (is_tv)
110862306a36Sopenharmony_ci			WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
110962306a36Sopenharmony_ci		/* handled in radeon_crtc_dpms() */
111062306a36Sopenharmony_ci		else if (!(rdev->flags & RADEON_SINGLE_CRTC))
111162306a36Sopenharmony_ci			WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
111262306a36Sopenharmony_ci		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
111362306a36Sopenharmony_ci	}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	if (rdev->is_atom_bios)
111662306a36Sopenharmony_ci		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
111762306a36Sopenharmony_ci	else
111862306a36Sopenharmony_ci		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_cistatic void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
112362306a36Sopenharmony_ci{
112462306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	if (rdev->is_atom_bios)
112762306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, true);
112862306a36Sopenharmony_ci	else
112962306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, true);
113062306a36Sopenharmony_ci	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
113162306a36Sopenharmony_ci}
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_cistatic void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
113462306a36Sopenharmony_ci{
113562306a36Sopenharmony_ci	struct radeon_device *rdev = encoder->dev->dev_private;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	if (rdev->is_atom_bios)
114062306a36Sopenharmony_ci		radeon_atom_output_lock(encoder, true);
114162306a36Sopenharmony_ci	else
114262306a36Sopenharmony_ci		radeon_combios_output_lock(encoder, true);
114362306a36Sopenharmony_ci}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_cistatic void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
114662306a36Sopenharmony_ci		struct drm_display_mode *mode,
114762306a36Sopenharmony_ci		struct drm_display_mode *adjusted_mode)
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
115062306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
115162306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
115262306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
115362306a36Sopenharmony_ci	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
115462306a36Sopenharmony_ci	uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
115562306a36Sopenharmony_ci	uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0;
115662306a36Sopenharmony_ci	bool is_tv = false;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	if (rdev->family != CHIP_R200) {
116362306a36Sopenharmony_ci		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
116462306a36Sopenharmony_ci		if (rdev->family == CHIP_R420 ||
116562306a36Sopenharmony_ci		    rdev->family == CHIP_R423 ||
116662306a36Sopenharmony_ci		    rdev->family == CHIP_RV410) {
116762306a36Sopenharmony_ci			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
116862306a36Sopenharmony_ci					 RADEON_TV_DAC_BGADJ_MASK |
116962306a36Sopenharmony_ci					 R420_TV_DAC_DACADJ_MASK |
117062306a36Sopenharmony_ci					 R420_TV_DAC_RDACPD |
117162306a36Sopenharmony_ci					 R420_TV_DAC_GDACPD |
117262306a36Sopenharmony_ci					 R420_TV_DAC_BDACPD |
117362306a36Sopenharmony_ci					 R420_TV_DAC_TVENABLE);
117462306a36Sopenharmony_ci		} else {
117562306a36Sopenharmony_ci			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
117662306a36Sopenharmony_ci					 RADEON_TV_DAC_BGADJ_MASK |
117762306a36Sopenharmony_ci					 RADEON_TV_DAC_DACADJ_MASK |
117862306a36Sopenharmony_ci					 RADEON_TV_DAC_RDACPD |
117962306a36Sopenharmony_ci					 RADEON_TV_DAC_GDACPD |
118062306a36Sopenharmony_ci					 RADEON_TV_DAC_BDACPD);
118162306a36Sopenharmony_ci		}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci		tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci		if (is_tv) {
118662306a36Sopenharmony_ci			if (tv_dac->tv_std == TV_STD_NTSC ||
118762306a36Sopenharmony_ci			    tv_dac->tv_std == TV_STD_NTSC_J ||
118862306a36Sopenharmony_ci			    tv_dac->tv_std == TV_STD_PAL_M ||
118962306a36Sopenharmony_ci			    tv_dac->tv_std == TV_STD_PAL_60)
119062306a36Sopenharmony_ci				tv_dac_cntl |= tv_dac->ntsc_tvdac_adj;
119162306a36Sopenharmony_ci			else
119262306a36Sopenharmony_ci				tv_dac_cntl |= tv_dac->pal_tvdac_adj;
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci			if (tv_dac->tv_std == TV_STD_NTSC ||
119562306a36Sopenharmony_ci			    tv_dac->tv_std == TV_STD_NTSC_J)
119662306a36Sopenharmony_ci				tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
119762306a36Sopenharmony_ci			else
119862306a36Sopenharmony_ci				tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
119962306a36Sopenharmony_ci		} else
120062306a36Sopenharmony_ci			tv_dac_cntl |= (RADEON_TV_DAC_STD_PS2 |
120162306a36Sopenharmony_ci					tv_dac->ps2_tvdac_adj);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
120462306a36Sopenharmony_ci	}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev)) {
120762306a36Sopenharmony_ci		gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
120862306a36Sopenharmony_ci		disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
120962306a36Sopenharmony_ci	} else if (rdev->family != CHIP_R200)
121062306a36Sopenharmony_ci		disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
121162306a36Sopenharmony_ci	else if (rdev->family == CHIP_R200)
121262306a36Sopenharmony_ci		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	if (rdev->family >= CHIP_R200)
121562306a36Sopenharmony_ci		disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	if (is_tv) {
121862306a36Sopenharmony_ci		uint32_t dac_cntl;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci		dac_cntl = RREG32(RADEON_DAC_CNTL);
122162306a36Sopenharmony_ci		dac_cntl &= ~RADEON_DAC_TVO_EN;
122262306a36Sopenharmony_ci		WREG32(RADEON_DAC_CNTL, dac_cntl);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev))
122562306a36Sopenharmony_ci			gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci		dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL;
122862306a36Sopenharmony_ci		if (radeon_crtc->crtc_id == 0) {
122962306a36Sopenharmony_ci			if (ASIC_IS_R300(rdev)) {
123062306a36Sopenharmony_ci				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
123162306a36Sopenharmony_ci				disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC |
123262306a36Sopenharmony_ci						     RADEON_DISP_TV_SOURCE_CRTC);
123362306a36Sopenharmony_ci			}
123462306a36Sopenharmony_ci			if (rdev->family >= CHIP_R200) {
123562306a36Sopenharmony_ci				disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
123662306a36Sopenharmony_ci			} else {
123762306a36Sopenharmony_ci				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
123862306a36Sopenharmony_ci			}
123962306a36Sopenharmony_ci		} else {
124062306a36Sopenharmony_ci			if (ASIC_IS_R300(rdev)) {
124162306a36Sopenharmony_ci				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
124262306a36Sopenharmony_ci				disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
124362306a36Sopenharmony_ci			}
124462306a36Sopenharmony_ci			if (rdev->family >= CHIP_R200) {
124562306a36Sopenharmony_ci				disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
124662306a36Sopenharmony_ci			} else {
124762306a36Sopenharmony_ci				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
124862306a36Sopenharmony_ci			}
124962306a36Sopenharmony_ci		}
125062306a36Sopenharmony_ci		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
125162306a36Sopenharmony_ci	} else {
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci		dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci		if (radeon_crtc->crtc_id == 0) {
125662306a36Sopenharmony_ci			if (ASIC_IS_R300(rdev)) {
125762306a36Sopenharmony_ci				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
125862306a36Sopenharmony_ci				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
125962306a36Sopenharmony_ci			} else if (rdev->family == CHIP_R200) {
126062306a36Sopenharmony_ci				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
126162306a36Sopenharmony_ci						  RADEON_FP2_DVO_RATE_SEL_SDR);
126262306a36Sopenharmony_ci			} else
126362306a36Sopenharmony_ci				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
126462306a36Sopenharmony_ci		} else {
126562306a36Sopenharmony_ci			if (ASIC_IS_R300(rdev)) {
126662306a36Sopenharmony_ci				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
126762306a36Sopenharmony_ci				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
126862306a36Sopenharmony_ci			} else if (rdev->family == CHIP_R200) {
126962306a36Sopenharmony_ci				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
127062306a36Sopenharmony_ci						  RADEON_FP2_DVO_RATE_SEL_SDR);
127162306a36Sopenharmony_ci				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
127262306a36Sopenharmony_ci			} else
127362306a36Sopenharmony_ci				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
127462306a36Sopenharmony_ci		}
127562306a36Sopenharmony_ci		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
127662306a36Sopenharmony_ci	}
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev)) {
127962306a36Sopenharmony_ci		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
128062306a36Sopenharmony_ci		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
128162306a36Sopenharmony_ci	} else if (rdev->family != CHIP_R200)
128262306a36Sopenharmony_ci		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
128362306a36Sopenharmony_ci	else if (rdev->family == CHIP_R200)
128462306a36Sopenharmony_ci		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	if (rdev->family >= CHIP_R200)
128762306a36Sopenharmony_ci		WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	if (is_tv)
129062306a36Sopenharmony_ci		radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	if (rdev->is_atom_bios)
129362306a36Sopenharmony_ci		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
129462306a36Sopenharmony_ci	else
129562306a36Sopenharmony_ci		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci}
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_cistatic bool r300_legacy_tv_detect(struct drm_encoder *encoder,
130062306a36Sopenharmony_ci				  struct drm_connector *connector)
130162306a36Sopenharmony_ci{
130262306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
130362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
130462306a36Sopenharmony_ci	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
130562306a36Sopenharmony_ci	uint32_t disp_output_cntl, gpiopad_a, tmp;
130662306a36Sopenharmony_ci	bool found = false;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	/* save regs needed */
130962306a36Sopenharmony_ci	gpiopad_a = RREG32(RADEON_GPIOPAD_A);
131062306a36Sopenharmony_ci	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
131162306a36Sopenharmony_ci	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
131262306a36Sopenharmony_ci	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
131362306a36Sopenharmony_ci	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
131462306a36Sopenharmony_ci	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	WREG32_P(RADEON_GPIOPAD_A, 0, ~1);
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL);
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_GEN_CNTL,
132162306a36Sopenharmony_ci	       RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
132462306a36Sopenharmony_ci	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
132562306a36Sopenharmony_ci	WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	WREG32(RADEON_DAC_EXT_CNTL,
132862306a36Sopenharmony_ci	       RADEON_DAC2_FORCE_BLANK_OFF_EN |
132962306a36Sopenharmony_ci	       RADEON_DAC2_FORCE_DATA_EN |
133062306a36Sopenharmony_ci	       RADEON_DAC_FORCE_DATA_SEL_RGB |
133162306a36Sopenharmony_ci	       (0xec << RADEON_DAC_FORCE_DATA_SHIFT));
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	WREG32(RADEON_TV_DAC_CNTL,
133462306a36Sopenharmony_ci	       RADEON_TV_DAC_STD_NTSC |
133562306a36Sopenharmony_ci	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
133662306a36Sopenharmony_ci	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	RREG32(RADEON_TV_DAC_CNTL);
133962306a36Sopenharmony_ci	mdelay(4);
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	WREG32(RADEON_TV_DAC_CNTL,
134262306a36Sopenharmony_ci	       RADEON_TV_DAC_NBLANK |
134362306a36Sopenharmony_ci	       RADEON_TV_DAC_NHOLD |
134462306a36Sopenharmony_ci	       RADEON_TV_MONITOR_DETECT_EN |
134562306a36Sopenharmony_ci	       RADEON_TV_DAC_STD_NTSC |
134662306a36Sopenharmony_ci	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
134762306a36Sopenharmony_ci	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	RREG32(RADEON_TV_DAC_CNTL);
135062306a36Sopenharmony_ci	mdelay(6);
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci	tmp = RREG32(RADEON_TV_DAC_CNTL);
135362306a36Sopenharmony_ci	if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
135462306a36Sopenharmony_ci		found = true;
135562306a36Sopenharmony_ci		DRM_DEBUG_KMS("S-video TV connection detected\n");
135662306a36Sopenharmony_ci	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
135762306a36Sopenharmony_ci		found = true;
135862306a36Sopenharmony_ci		DRM_DEBUG_KMS("Composite TV connection detected\n");
135962306a36Sopenharmony_ci	}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
136262306a36Sopenharmony_ci	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
136362306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
136462306a36Sopenharmony_ci	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
136562306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
136662306a36Sopenharmony_ci	WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
136762306a36Sopenharmony_ci	return found;
136862306a36Sopenharmony_ci}
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_cistatic bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
137162306a36Sopenharmony_ci				    struct drm_connector *connector)
137262306a36Sopenharmony_ci{
137362306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
137462306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
137562306a36Sopenharmony_ci	uint32_t tv_dac_cntl, dac_cntl2;
137662306a36Sopenharmony_ci	uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp;
137762306a36Sopenharmony_ci	bool found = false;
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev))
138062306a36Sopenharmony_ci		return r300_legacy_tv_detect(encoder, connector);
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
138362306a36Sopenharmony_ci	tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
138462306a36Sopenharmony_ci	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
138562306a36Sopenharmony_ci	config_cntl = RREG32(RADEON_CONFIG_CNTL);
138662306a36Sopenharmony_ci	tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL);
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
138962306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL2, tmp);
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	tmp = tv_master_cntl | RADEON_TV_ON;
139262306a36Sopenharmony_ci	tmp &= ~(RADEON_TV_ASYNC_RST |
139362306a36Sopenharmony_ci		 RADEON_RESTART_PHASE_FIX |
139462306a36Sopenharmony_ci		 RADEON_CRT_FIFO_CE_EN |
139562306a36Sopenharmony_ci		 RADEON_TV_FIFO_CE_EN |
139662306a36Sopenharmony_ci		 RADEON_RE_SYNC_NOW_SEL_MASK);
139762306a36Sopenharmony_ci	tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
139862306a36Sopenharmony_ci	WREG32(RADEON_TV_MASTER_CNTL, tmp);
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
140162306a36Sopenharmony_ci		RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
140262306a36Sopenharmony_ci		(8 << RADEON_TV_DAC_BGADJ_SHIFT);
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
140562306a36Sopenharmony_ci		tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
140662306a36Sopenharmony_ci	else
140762306a36Sopenharmony_ci		tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
140862306a36Sopenharmony_ci	WREG32(RADEON_TV_DAC_CNTL, tmp);
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
141162306a36Sopenharmony_ci		RADEON_RED_MX_FORCE_DAC_DATA |
141262306a36Sopenharmony_ci		RADEON_GRN_MX_FORCE_DAC_DATA |
141362306a36Sopenharmony_ci		RADEON_BLU_MX_FORCE_DAC_DATA |
141462306a36Sopenharmony_ci		(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
141562306a36Sopenharmony_ci	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	mdelay(3);
141862306a36Sopenharmony_ci	tmp = RREG32(RADEON_TV_DAC_CNTL);
141962306a36Sopenharmony_ci	if (tmp & RADEON_TV_DAC_GDACDET) {
142062306a36Sopenharmony_ci		found = true;
142162306a36Sopenharmony_ci		DRM_DEBUG_KMS("S-video TV connection detected\n");
142262306a36Sopenharmony_ci	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
142362306a36Sopenharmony_ci		found = true;
142462306a36Sopenharmony_ci		DRM_DEBUG_KMS("Composite TV connection detected\n");
142562306a36Sopenharmony_ci	}
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
142862306a36Sopenharmony_ci	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
142962306a36Sopenharmony_ci	WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
143062306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
143162306a36Sopenharmony_ci	return found;
143262306a36Sopenharmony_ci}
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_cistatic bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
143562306a36Sopenharmony_ci					 struct drm_connector *connector)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
143862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
143962306a36Sopenharmony_ci	uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
144062306a36Sopenharmony_ci	uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
144162306a36Sopenharmony_ci	uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
144262306a36Sopenharmony_ci	uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
144362306a36Sopenharmony_ci	uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
144462306a36Sopenharmony_ci	bool found = false;
144562306a36Sopenharmony_ci	int i;
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	/* save the regs we need */
144862306a36Sopenharmony_ci	gpio_monid = RREG32(RADEON_GPIO_MONID);
144962306a36Sopenharmony_ci	fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
145062306a36Sopenharmony_ci	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
145162306a36Sopenharmony_ci	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
145262306a36Sopenharmony_ci	disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
145362306a36Sopenharmony_ci	disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
145462306a36Sopenharmony_ci	disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
145562306a36Sopenharmony_ci	disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
145662306a36Sopenharmony_ci	disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
145762306a36Sopenharmony_ci	disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
145862306a36Sopenharmony_ci	crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
145962306a36Sopenharmony_ci	crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
146062306a36Sopenharmony_ci	crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
146162306a36Sopenharmony_ci	crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	tmp = RREG32(RADEON_GPIO_MONID);
146462306a36Sopenharmony_ci	tmp &= ~RADEON_GPIO_A_0;
146562306a36Sopenharmony_ci	WREG32(RADEON_GPIO_MONID, tmp);
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
146862306a36Sopenharmony_ci				     RADEON_FP2_PANEL_FORMAT |
146962306a36Sopenharmony_ci				     R200_FP2_SOURCE_SEL_TRANS_UNIT |
147062306a36Sopenharmony_ci				     RADEON_FP2_DVO_EN |
147162306a36Sopenharmony_ci				     R200_FP2_DVO_RATE_SEL_SDR));
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
147462306a36Sopenharmony_ci					 RADEON_DISP_TRANS_MATRIX_GRAPHICS));
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
147762306a36Sopenharmony_ci				       RADEON_CRTC2_DISP_REQ_EN_B));
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
148062306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
148162306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
148262306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
148362306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
148462306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
148762306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
148862306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
148962306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	for (i = 0; i < 200; i++) {
149262306a36Sopenharmony_ci		tmp = RREG32(RADEON_GPIO_MONID);
149362306a36Sopenharmony_ci		if (tmp & RADEON_GPIO_Y_0)
149462306a36Sopenharmony_ci			found = true;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci		if (found)
149762306a36Sopenharmony_ci			break;
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci		if (!drm_can_sleep())
150062306a36Sopenharmony_ci			mdelay(1);
150162306a36Sopenharmony_ci		else
150262306a36Sopenharmony_ci			msleep(1);
150362306a36Sopenharmony_ci	}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	/* restore the regs we used */
150662306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
150762306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
150862306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
150962306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
151062306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
151162306a36Sopenharmony_ci	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
151262306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
151362306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
151462306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
151562306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
151662306a36Sopenharmony_ci	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
151762306a36Sopenharmony_ci	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
151862306a36Sopenharmony_ci	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
151962306a36Sopenharmony_ci	WREG32(RADEON_GPIO_MONID, gpio_monid);
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	return found;
152262306a36Sopenharmony_ci}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_cistatic enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
152562306a36Sopenharmony_ci							     struct drm_connector *connector)
152662306a36Sopenharmony_ci{
152762306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
152862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
152962306a36Sopenharmony_ci	uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
153062306a36Sopenharmony_ci	uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
153162306a36Sopenharmony_ci	uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
153262306a36Sopenharmony_ci	enum drm_connector_status found = connector_status_disconnected;
153362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
153462306a36Sopenharmony_ci	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
153562306a36Sopenharmony_ci	bool color = true;
153662306a36Sopenharmony_ci	struct drm_crtc *crtc;
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	/* find out if crtc2 is in use or if this encoder is using it */
153962306a36Sopenharmony_ci	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
154062306a36Sopenharmony_ci		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
154162306a36Sopenharmony_ci		if ((radeon_crtc->crtc_id == 1) && crtc->enabled) {
154262306a36Sopenharmony_ci			if (encoder->crtc != crtc) {
154362306a36Sopenharmony_ci				return connector_status_disconnected;
154462306a36Sopenharmony_ci			}
154562306a36Sopenharmony_ci		}
154662306a36Sopenharmony_ci	}
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
154962306a36Sopenharmony_ci	    connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
155062306a36Sopenharmony_ci	    connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) {
155162306a36Sopenharmony_ci		bool tv_detect;
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci		if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT))
155462306a36Sopenharmony_ci			return connector_status_disconnected;
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci		tv_detect = radeon_legacy_tv_detect(encoder, connector);
155762306a36Sopenharmony_ci		if (tv_detect && tv_dac)
155862306a36Sopenharmony_ci			found = connector_status_connected;
155962306a36Sopenharmony_ci		return found;
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	/* don't probe if the encoder is being used for something else not CRT related */
156362306a36Sopenharmony_ci	if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) {
156462306a36Sopenharmony_ci		DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device);
156562306a36Sopenharmony_ci		return connector_status_disconnected;
156662306a36Sopenharmony_ci	}
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	/* R200 uses an external DAC for secondary DAC */
156962306a36Sopenharmony_ci	if (rdev->family == CHIP_R200) {
157062306a36Sopenharmony_ci		if (radeon_legacy_ext_dac_detect(encoder, connector))
157162306a36Sopenharmony_ci			found = connector_status_connected;
157262306a36Sopenharmony_ci		return found;
157362306a36Sopenharmony_ci	}
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci	/* save the regs we need */
157662306a36Sopenharmony_ci	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
157762306a36Sopenharmony_ci
157862306a36Sopenharmony_ci	if (rdev->flags & RADEON_SINGLE_CRTC) {
157962306a36Sopenharmony_ci		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
158062306a36Sopenharmony_ci	} else {
158162306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev)) {
158262306a36Sopenharmony_ci			gpiopad_a = RREG32(RADEON_GPIOPAD_A);
158362306a36Sopenharmony_ci			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
158462306a36Sopenharmony_ci		} else {
158562306a36Sopenharmony_ci			disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
158662306a36Sopenharmony_ci		}
158762306a36Sopenharmony_ci		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
158862306a36Sopenharmony_ci	}
158962306a36Sopenharmony_ci	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
159062306a36Sopenharmony_ci	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
159162306a36Sopenharmony_ci	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
159462306a36Sopenharmony_ci			       | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
159562306a36Sopenharmony_ci	WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	if (rdev->flags & RADEON_SINGLE_CRTC) {
159862306a36Sopenharmony_ci		tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
159962306a36Sopenharmony_ci		WREG32(RADEON_CRTC_EXT_CNTL, tmp);
160062306a36Sopenharmony_ci	} else {
160162306a36Sopenharmony_ci		tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
160262306a36Sopenharmony_ci		tmp |= RADEON_CRTC2_CRT2_ON |
160362306a36Sopenharmony_ci			(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
160462306a36Sopenharmony_ci		WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev)) {
160762306a36Sopenharmony_ci			WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
160862306a36Sopenharmony_ci			tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
160962306a36Sopenharmony_ci			tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
161062306a36Sopenharmony_ci			WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
161162306a36Sopenharmony_ci		} else {
161262306a36Sopenharmony_ci			tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
161362306a36Sopenharmony_ci			WREG32(RADEON_DISP_HW_DEBUG, tmp);
161462306a36Sopenharmony_ci		}
161562306a36Sopenharmony_ci	}
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	tmp = RADEON_TV_DAC_NBLANK |
161862306a36Sopenharmony_ci		RADEON_TV_DAC_NHOLD |
161962306a36Sopenharmony_ci		RADEON_TV_MONITOR_DETECT_EN |
162062306a36Sopenharmony_ci		RADEON_TV_DAC_STD_PS2;
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	WREG32(RADEON_TV_DAC_CNTL, tmp);
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
162562306a36Sopenharmony_ci		RADEON_DAC2_FORCE_DATA_EN;
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	if (color)
162862306a36Sopenharmony_ci		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
162962306a36Sopenharmony_ci	else
163062306a36Sopenharmony_ci		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev))
163362306a36Sopenharmony_ci		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
163462306a36Sopenharmony_ci	else
163562306a36Sopenharmony_ci		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	WREG32(RADEON_DAC_EXT_CNTL, tmp);
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
164062306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL2, tmp);
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	mdelay(10);
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	if (ASIC_IS_R300(rdev)) {
164562306a36Sopenharmony_ci		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
164662306a36Sopenharmony_ci			found = connector_status_connected;
164762306a36Sopenharmony_ci	} else {
164862306a36Sopenharmony_ci		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT)
164962306a36Sopenharmony_ci			found = connector_status_connected;
165062306a36Sopenharmony_ci	}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	/* restore regs we used */
165362306a36Sopenharmony_ci	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
165462306a36Sopenharmony_ci	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
165562306a36Sopenharmony_ci	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	if (rdev->flags & RADEON_SINGLE_CRTC) {
165862306a36Sopenharmony_ci		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
165962306a36Sopenharmony_ci	} else {
166062306a36Sopenharmony_ci		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
166162306a36Sopenharmony_ci		if (ASIC_IS_R300(rdev)) {
166262306a36Sopenharmony_ci			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
166362306a36Sopenharmony_ci			WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
166462306a36Sopenharmony_ci		} else {
166562306a36Sopenharmony_ci			WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
166662306a36Sopenharmony_ci		}
166762306a36Sopenharmony_ci	}
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	return found;
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci}
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
167662306a36Sopenharmony_ci	.dpms = radeon_legacy_tv_dac_dpms,
167762306a36Sopenharmony_ci	.mode_fixup = radeon_legacy_mode_fixup,
167862306a36Sopenharmony_ci	.prepare = radeon_legacy_tv_dac_prepare,
167962306a36Sopenharmony_ci	.mode_set = radeon_legacy_tv_dac_mode_set,
168062306a36Sopenharmony_ci	.commit = radeon_legacy_tv_dac_commit,
168162306a36Sopenharmony_ci	.detect = radeon_legacy_tv_dac_detect,
168262306a36Sopenharmony_ci	.disable = radeon_legacy_encoder_disable,
168362306a36Sopenharmony_ci};
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_cistatic const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = {
168762306a36Sopenharmony_ci	.destroy = radeon_enc_destroy,
168862306a36Sopenharmony_ci};
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_cistatic struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder)
169262306a36Sopenharmony_ci{
169362306a36Sopenharmony_ci	struct drm_device *dev = encoder->base.dev;
169462306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
169562306a36Sopenharmony_ci	struct radeon_encoder_int_tmds *tmds;
169662306a36Sopenharmony_ci	bool ret;
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	if (!tmds)
170162306a36Sopenharmony_ci		return NULL;
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	if (rdev->is_atom_bios)
170462306a36Sopenharmony_ci		ret = radeon_atombios_get_tmds_info(encoder, tmds);
170562306a36Sopenharmony_ci	else
170662306a36Sopenharmony_ci		ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	if (!ret)
170962306a36Sopenharmony_ci		radeon_legacy_get_tmds_info_from_table(encoder, tmds);
171062306a36Sopenharmony_ci
171162306a36Sopenharmony_ci	return tmds;
171262306a36Sopenharmony_ci}
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_cistatic struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
171562306a36Sopenharmony_ci{
171662306a36Sopenharmony_ci	struct drm_device *dev = encoder->base.dev;
171762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
171862306a36Sopenharmony_ci	struct radeon_encoder_ext_tmds *tmds;
171962306a36Sopenharmony_ci	bool ret;
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	if (rdev->is_atom_bios)
172262306a36Sopenharmony_ci		return NULL;
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	tmds = kzalloc(sizeof(struct radeon_encoder_ext_tmds), GFP_KERNEL);
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	if (!tmds)
172762306a36Sopenharmony_ci		return NULL;
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	if (!ret)
173262306a36Sopenharmony_ci		radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci	return tmds;
173562306a36Sopenharmony_ci}
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_civoid
173862306a36Sopenharmony_ciradeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device)
173962306a36Sopenharmony_ci{
174062306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
174162306a36Sopenharmony_ci	struct drm_encoder *encoder;
174262306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	/* see if we already added it */
174562306a36Sopenharmony_ci	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
174662306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
174762306a36Sopenharmony_ci		if (radeon_encoder->encoder_enum == encoder_enum) {
174862306a36Sopenharmony_ci			radeon_encoder->devices |= supported_device;
174962306a36Sopenharmony_ci			return;
175062306a36Sopenharmony_ci		}
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci	}
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	/* add a new one */
175562306a36Sopenharmony_ci	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
175662306a36Sopenharmony_ci	if (!radeon_encoder)
175762306a36Sopenharmony_ci		return;
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	encoder = &radeon_encoder->base;
176062306a36Sopenharmony_ci	if (rdev->flags & RADEON_SINGLE_CRTC)
176162306a36Sopenharmony_ci		encoder->possible_crtcs = 0x1;
176262306a36Sopenharmony_ci	else
176362306a36Sopenharmony_ci		encoder->possible_crtcs = 0x3;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	radeon_encoder->enc_priv = NULL;
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	radeon_encoder->encoder_enum = encoder_enum;
176862306a36Sopenharmony_ci	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
176962306a36Sopenharmony_ci	radeon_encoder->devices = supported_device;
177062306a36Sopenharmony_ci	radeon_encoder->rmx_type = RMX_OFF;
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
177362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
177462306a36Sopenharmony_ci		encoder->possible_crtcs = 0x1;
177562306a36Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs,
177662306a36Sopenharmony_ci				 DRM_MODE_ENCODER_LVDS, NULL);
177762306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
177862306a36Sopenharmony_ci		if (rdev->is_atom_bios)
177962306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
178062306a36Sopenharmony_ci		else
178162306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder);
178262306a36Sopenharmony_ci		radeon_encoder->rmx_type = RMX_FULL;
178362306a36Sopenharmony_ci		break;
178462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
178562306a36Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs,
178662306a36Sopenharmony_ci				 DRM_MODE_ENCODER_TMDS, NULL);
178762306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
178862306a36Sopenharmony_ci		radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder);
178962306a36Sopenharmony_ci		break;
179062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
179162306a36Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs,
179262306a36Sopenharmony_ci				 DRM_MODE_ENCODER_DAC, NULL);
179362306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs);
179462306a36Sopenharmony_ci		if (rdev->is_atom_bios)
179562306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder);
179662306a36Sopenharmony_ci		else
179762306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder);
179862306a36Sopenharmony_ci		break;
179962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
180062306a36Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs,
180162306a36Sopenharmony_ci				 DRM_MODE_ENCODER_TVDAC, NULL);
180262306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs);
180362306a36Sopenharmony_ci		if (rdev->is_atom_bios)
180462306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder);
180562306a36Sopenharmony_ci		else
180662306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder);
180762306a36Sopenharmony_ci		break;
180862306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
180962306a36Sopenharmony_ci		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs,
181062306a36Sopenharmony_ci				 DRM_MODE_ENCODER_TMDS, NULL);
181162306a36Sopenharmony_ci		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
181262306a36Sopenharmony_ci		if (!rdev->is_atom_bios)
181362306a36Sopenharmony_ci			radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
181462306a36Sopenharmony_ci		break;
181562306a36Sopenharmony_ci	}
181662306a36Sopenharmony_ci}
1817