1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2007-8 Advanced Micro Devices, Inc.
3254885Sdumbbell * Copyright 2008 Red Hat Inc.
4254885Sdumbbell *
5254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
6254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
7254885Sdumbbell * to deal in the Software without restriction, including without limitation
8254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
10254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
11254885Sdumbbell *
12254885Sdumbbell * The above copyright notice and this permission notice shall be included in
13254885Sdumbbell * all copies or substantial portions of the Software.
14254885Sdumbbell *
15254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
22254885Sdumbbell *
23254885Sdumbbell * Authors: Dave Airlie
24254885Sdumbbell *          Alex Deucher
25254885Sdumbbell */
26254885Sdumbbell
27254885Sdumbbell#include <sys/cdefs.h>
28254885Sdumbbell__FBSDID("$FreeBSD$");
29254885Sdumbbell
30254885Sdumbbell#include <dev/drm2/drmP.h>
31254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h>
32254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
33254885Sdumbbell#include "radeon.h"
34254885Sdumbbell#include "radeon_asic.h"
35254885Sdumbbell#include "atom.h"
36254885Sdumbbell
37254885Sdumbbellstatic void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
38254885Sdumbbell{
39254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
40254885Sdumbbell	struct drm_encoder_helper_funcs *encoder_funcs;
41254885Sdumbbell
42254885Sdumbbell	encoder_funcs = encoder->helper_private;
43254885Sdumbbell	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
44254885Sdumbbell	radeon_encoder->active_device = 0;
45254885Sdumbbell}
46254885Sdumbbell
47254885Sdumbbellstatic void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
48254885Sdumbbell{
49254885Sdumbbell	struct drm_device *dev = encoder->dev;
50254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
51254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
52254885Sdumbbell	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
53254885Sdumbbell	int panel_pwr_delay = 2000;
54254885Sdumbbell	bool is_mac = false;
55254885Sdumbbell	uint8_t backlight_level;
56254885Sdumbbell	DRM_DEBUG_KMS("\n");
57254885Sdumbbell
58254885Sdumbbell	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
59254885Sdumbbell	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
60254885Sdumbbell
61254885Sdumbbell	if (radeon_encoder->enc_priv) {
62254885Sdumbbell		if (rdev->is_atom_bios) {
63254885Sdumbbell			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
64254885Sdumbbell			panel_pwr_delay = lvds->panel_pwr_delay;
65254885Sdumbbell			if (lvds->bl_dev)
66254885Sdumbbell				backlight_level = lvds->backlight_level;
67254885Sdumbbell		} else {
68254885Sdumbbell			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
69254885Sdumbbell			panel_pwr_delay = lvds->panel_pwr_delay;
70254885Sdumbbell			if (lvds->bl_dev)
71254885Sdumbbell				backlight_level = lvds->backlight_level;
72254885Sdumbbell		}
73254885Sdumbbell	}
74254885Sdumbbell
75254885Sdumbbell	/* macs (and possibly some x86 oem systems?) wire up LVDS strangely
76254885Sdumbbell	 * Taken from radeonfb.
77254885Sdumbbell	 */
78254885Sdumbbell	if ((rdev->mode_info.connector_table == CT_IBOOK) ||
79254885Sdumbbell	    (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) ||
80254885Sdumbbell	    (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) ||
81254885Sdumbbell	    (rdev->mode_info.connector_table == CT_POWERBOOK_VGA))
82254885Sdumbbell		is_mac = true;
83254885Sdumbbell
84254885Sdumbbell	switch (mode) {
85254885Sdumbbell	case DRM_MODE_DPMS_ON:
86254885Sdumbbell		disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
87254885Sdumbbell		disp_pwr_man |= RADEON_AUTO_PWRUP_EN;
88254885Sdumbbell		WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man);
89254885Sdumbbell		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
90254885Sdumbbell		lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
91254885Sdumbbell		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
92280183Sdumbbell		mdelay(1);
93254885Sdumbbell
94254885Sdumbbell		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
95254885Sdumbbell		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
96254885Sdumbbell		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
97254885Sdumbbell
98254885Sdumbbell		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
99254885Sdumbbell				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
100254885Sdumbbell		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
101254885Sdumbbell				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
102254885Sdumbbell				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
103254885Sdumbbell		if (is_mac)
104254885Sdumbbell			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
105280183Sdumbbell		mdelay(panel_pwr_delay);
106254885Sdumbbell		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
107254885Sdumbbell		break;
108254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
109254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
110254885Sdumbbell	case DRM_MODE_DPMS_OFF:
111254885Sdumbbell		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
112254885Sdumbbell		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
113254885Sdumbbell		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
114254885Sdumbbell		if (is_mac) {
115254885Sdumbbell			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
116254885Sdumbbell			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
117254885Sdumbbell			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN);
118254885Sdumbbell		} else {
119254885Sdumbbell			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
120254885Sdumbbell			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
121254885Sdumbbell		}
122280183Sdumbbell		mdelay(panel_pwr_delay);
123254885Sdumbbell		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
124254885Sdumbbell		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
125280183Sdumbbell		mdelay(panel_pwr_delay);
126254885Sdumbbell		break;
127254885Sdumbbell	}
128254885Sdumbbell
129254885Sdumbbell	if (rdev->is_atom_bios)
130254885Sdumbbell		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
131254885Sdumbbell	else
132254885Sdumbbell		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
133254885Sdumbbell
134254885Sdumbbell}
135254885Sdumbbell
136254885Sdumbbellstatic void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
137254885Sdumbbell{
138254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
139254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
140254885Sdumbbell	DRM_DEBUG("\n");
141254885Sdumbbell
142254885Sdumbbell	if (radeon_encoder->enc_priv) {
143254885Sdumbbell		if (rdev->is_atom_bios) {
144254885Sdumbbell			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
145254885Sdumbbell			lvds->dpms_mode = mode;
146254885Sdumbbell		} else {
147254885Sdumbbell			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
148254885Sdumbbell			lvds->dpms_mode = mode;
149254885Sdumbbell		}
150254885Sdumbbell	}
151254885Sdumbbell
152254885Sdumbbell	radeon_legacy_lvds_update(encoder, mode);
153254885Sdumbbell}
154254885Sdumbbell
155254885Sdumbbellstatic void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
156254885Sdumbbell{
157254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
158254885Sdumbbell
159254885Sdumbbell	if (rdev->is_atom_bios)
160254885Sdumbbell		radeon_atom_output_lock(encoder, true);
161254885Sdumbbell	else
162254885Sdumbbell		radeon_combios_output_lock(encoder, true);
163254885Sdumbbell	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
164254885Sdumbbell}
165254885Sdumbbell
166254885Sdumbbellstatic void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
167254885Sdumbbell{
168254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
169254885Sdumbbell
170254885Sdumbbell	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON);
171254885Sdumbbell	if (rdev->is_atom_bios)
172254885Sdumbbell		radeon_atom_output_lock(encoder, false);
173254885Sdumbbell	else
174254885Sdumbbell		radeon_combios_output_lock(encoder, false);
175254885Sdumbbell}
176254885Sdumbbell
177254885Sdumbbellstatic void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
178254885Sdumbbell					struct drm_display_mode *mode,
179254885Sdumbbell					struct drm_display_mode *adjusted_mode)
180254885Sdumbbell{
181254885Sdumbbell	struct drm_device *dev = encoder->dev;
182254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
183254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
184254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
185254885Sdumbbell	uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl;
186254885Sdumbbell
187254885Sdumbbell	DRM_DEBUG_KMS("\n");
188254885Sdumbbell
189254885Sdumbbell	lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
190254885Sdumbbell	lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
191254885Sdumbbell
192254885Sdumbbell	lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
193254885Sdumbbell	if (rdev->is_atom_bios) {
194254885Sdumbbell		/* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
195254885Sdumbbell		 * need to call that on resume to set up the reg properly.
196254885Sdumbbell		 */
197254885Sdumbbell		radeon_encoder->pixel_clock = adjusted_mode->clock;
198254885Sdumbbell		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
199254885Sdumbbell		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
200254885Sdumbbell	} else {
201254885Sdumbbell		struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
202254885Sdumbbell		if (lvds) {
203254885Sdumbbell			DRM_DEBUG_KMS("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
204254885Sdumbbell			lvds_gen_cntl = lvds->lvds_gen_cntl;
205254885Sdumbbell			lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
206254885Sdumbbell					      (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
207254885Sdumbbell			lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
208254885Sdumbbell					     (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
209254885Sdumbbell		} else
210254885Sdumbbell			lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
211254885Sdumbbell	}
212254885Sdumbbell	lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
213254885Sdumbbell	lvds_gen_cntl &= ~(RADEON_LVDS_ON |
214254885Sdumbbell			   RADEON_LVDS_BLON |
215254885Sdumbbell			   RADEON_LVDS_EN |
216254885Sdumbbell			   RADEON_LVDS_RST_FM);
217254885Sdumbbell
218254885Sdumbbell	if (ASIC_IS_R300(rdev))
219254885Sdumbbell		lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
220254885Sdumbbell
221254885Sdumbbell	if (radeon_crtc->crtc_id == 0) {
222254885Sdumbbell		if (ASIC_IS_R300(rdev)) {
223254885Sdumbbell			if (radeon_encoder->rmx_type != RMX_OFF)
224254885Sdumbbell				lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
225254885Sdumbbell		} else
226254885Sdumbbell			lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
227254885Sdumbbell	} else {
228254885Sdumbbell		if (ASIC_IS_R300(rdev))
229254885Sdumbbell			lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
230254885Sdumbbell		else
231254885Sdumbbell			lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
232254885Sdumbbell	}
233254885Sdumbbell
234254885Sdumbbell	WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
235254885Sdumbbell	WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
236254885Sdumbbell	WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl);
237254885Sdumbbell
238254885Sdumbbell	if (rdev->family == CHIP_RV410)
239254885Sdumbbell		WREG32(RADEON_CLOCK_CNTL_INDEX, 0);
240254885Sdumbbell
241254885Sdumbbell	if (rdev->is_atom_bios)
242254885Sdumbbell		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
243254885Sdumbbell	else
244254885Sdumbbell		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
245254885Sdumbbell}
246254885Sdumbbell
247254885Sdumbbellstatic bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
248280183Sdumbbell				     const struct drm_display_mode *mode,
249254885Sdumbbell				     struct drm_display_mode *adjusted_mode)
250254885Sdumbbell{
251254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
252254885Sdumbbell
253254885Sdumbbell	/* set the active encoder to connector routing */
254254885Sdumbbell	radeon_encoder_set_active_device(encoder);
255254885Sdumbbell	drm_mode_set_crtcinfo(adjusted_mode, 0);
256254885Sdumbbell
257254885Sdumbbell	/* get the native mode for LVDS */
258254885Sdumbbell	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
259254885Sdumbbell		radeon_panel_mode_fixup(encoder, adjusted_mode);
260254885Sdumbbell
261254885Sdumbbell	return true;
262254885Sdumbbell}
263254885Sdumbbell
264254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
265254885Sdumbbell	.dpms = radeon_legacy_lvds_dpms,
266254885Sdumbbell	.mode_fixup = radeon_legacy_mode_fixup,
267254885Sdumbbell	.prepare = radeon_legacy_lvds_prepare,
268254885Sdumbbell	.mode_set = radeon_legacy_lvds_mode_set,
269254885Sdumbbell	.commit = radeon_legacy_lvds_commit,
270254885Sdumbbell	.disable = radeon_legacy_encoder_disable,
271254885Sdumbbell};
272254885Sdumbbell
273254885Sdumbbellu8
274254885Sdumbbellradeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder)
275254885Sdumbbell{
276254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
277254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
278254885Sdumbbell	u8 backlight_level;
279254885Sdumbbell
280254885Sdumbbell	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
281254885Sdumbbell			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
282254885Sdumbbell
283254885Sdumbbell	return backlight_level;
284254885Sdumbbell}
285254885Sdumbbell
286254885Sdumbbellvoid
287254885Sdumbbellradeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
288254885Sdumbbell{
289254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
290254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
291254885Sdumbbell	int dpms_mode = DRM_MODE_DPMS_ON;
292254885Sdumbbell
293254885Sdumbbell	if (radeon_encoder->enc_priv) {
294254885Sdumbbell		if (rdev->is_atom_bios) {
295254885Sdumbbell			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
296254885Sdumbbell			if (lvds->backlight_level > 0)
297254885Sdumbbell				dpms_mode = lvds->dpms_mode;
298254885Sdumbbell			else
299254885Sdumbbell				dpms_mode = DRM_MODE_DPMS_OFF;
300254885Sdumbbell			lvds->backlight_level = level;
301254885Sdumbbell		} else {
302254885Sdumbbell			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
303254885Sdumbbell			if (lvds->backlight_level > 0)
304254885Sdumbbell				dpms_mode = lvds->dpms_mode;
305254885Sdumbbell			else
306254885Sdumbbell				dpms_mode = DRM_MODE_DPMS_OFF;
307254885Sdumbbell			lvds->backlight_level = level;
308254885Sdumbbell		}
309254885Sdumbbell	}
310254885Sdumbbell
311254885Sdumbbell	radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
312254885Sdumbbell}
313254885Sdumbbell
314254885Sdumbbell#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
315254885Sdumbbell
316254885Sdumbbellstatic uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
317254885Sdumbbell{
318254885Sdumbbell	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
319254885Sdumbbell	uint8_t level;
320254885Sdumbbell
321254885Sdumbbell	/* Convert brightness to hardware level */
322254885Sdumbbell	if (bd->props.brightness < 0)
323254885Sdumbbell		level = 0;
324254885Sdumbbell	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
325254885Sdumbbell		level = RADEON_MAX_BL_LEVEL;
326254885Sdumbbell	else
327254885Sdumbbell		level = bd->props.brightness;
328254885Sdumbbell
329254885Sdumbbell	if (pdata->negative)
330254885Sdumbbell		level = RADEON_MAX_BL_LEVEL - level;
331254885Sdumbbell
332254885Sdumbbell	return level;
333254885Sdumbbell}
334254885Sdumbbell
335254885Sdumbbellstatic int radeon_legacy_backlight_update_status(struct backlight_device *bd)
336254885Sdumbbell{
337254885Sdumbbell	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
338254885Sdumbbell	struct radeon_encoder *radeon_encoder = pdata->encoder;
339254885Sdumbbell
340254885Sdumbbell	radeon_legacy_set_backlight_level(radeon_encoder,
341254885Sdumbbell					  radeon_legacy_lvds_level(bd));
342254885Sdumbbell
343254885Sdumbbell	return 0;
344254885Sdumbbell}
345254885Sdumbbell
346254885Sdumbbellstatic int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
347254885Sdumbbell{
348254885Sdumbbell	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
349254885Sdumbbell	struct radeon_encoder *radeon_encoder = pdata->encoder;
350254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
351254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
352254885Sdumbbell	uint8_t backlight_level;
353254885Sdumbbell
354254885Sdumbbell	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
355254885Sdumbbell			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
356254885Sdumbbell
357254885Sdumbbell	return pdata->negative ? RADEON_MAX_BL_LEVEL - backlight_level : backlight_level;
358254885Sdumbbell}
359254885Sdumbbell
360254885Sdumbbellstatic const struct backlight_ops radeon_backlight_ops = {
361254885Sdumbbell	.get_brightness = radeon_legacy_backlight_get_brightness,
362254885Sdumbbell	.update_status	= radeon_legacy_backlight_update_status,
363254885Sdumbbell};
364254885Sdumbbell
365254885Sdumbbellvoid radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
366254885Sdumbbell				  struct drm_connector *drm_connector)
367254885Sdumbbell{
368254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
369254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
370254885Sdumbbell	struct backlight_device *bd;
371254885Sdumbbell	struct backlight_properties props;
372254885Sdumbbell	struct radeon_backlight_privdata *pdata;
373254885Sdumbbell	uint8_t backlight_level;
374254885Sdumbbell	char bl_name[16];
375254885Sdumbbell
376254885Sdumbbell	if (!radeon_encoder->enc_priv)
377254885Sdumbbell		return;
378254885Sdumbbell
379254885Sdumbbell#ifdef CONFIG_PMAC_BACKLIGHT
380254885Sdumbbell	if (!pmac_has_backlight_type("ati") &&
381254885Sdumbbell	    !pmac_has_backlight_type("mnca"))
382254885Sdumbbell		return;
383254885Sdumbbell#endif
384254885Sdumbbell
385254885Sdumbbell	pdata = malloc(sizeof(struct radeon_backlight_privdata),
386280183Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT);
387254885Sdumbbell	if (!pdata) {
388254885Sdumbbell		DRM_ERROR("Memory allocation failed\n");
389254885Sdumbbell		goto error;
390254885Sdumbbell	}
391254885Sdumbbell
392254885Sdumbbell	memset(&props, 0, sizeof(props));
393254885Sdumbbell	props.max_brightness = RADEON_MAX_BL_LEVEL;
394254885Sdumbbell	props.type = BACKLIGHT_RAW;
395254885Sdumbbell	snprintf(bl_name, sizeof(bl_name),
396254885Sdumbbell		 "radeon_bl%d", dev->primary->index);
397254885Sdumbbell	bd = backlight_device_register(bl_name, &drm_connector->kdev,
398254885Sdumbbell				       pdata, &radeon_backlight_ops, &props);
399254885Sdumbbell	if (IS_ERR(bd)) {
400254885Sdumbbell		DRM_ERROR("Backlight registration failed\n");
401254885Sdumbbell		goto error;
402254885Sdumbbell	}
403254885Sdumbbell
404254885Sdumbbell	pdata->encoder = radeon_encoder;
405254885Sdumbbell
406254885Sdumbbell	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
407254885Sdumbbell			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
408254885Sdumbbell
409254885Sdumbbell	/* First, try to detect backlight level sense based on the assumption
410254885Sdumbbell	 * that firmware set it up at full brightness
411254885Sdumbbell	 */
412254885Sdumbbell	if (backlight_level == 0)
413254885Sdumbbell		pdata->negative = true;
414254885Sdumbbell	else if (backlight_level == 0xff)
415254885Sdumbbell		pdata->negative = false;
416254885Sdumbbell	else {
417254885Sdumbbell		/* XXX hack... maybe some day we can figure out in what direction
418254885Sdumbbell		 * backlight should work on a given panel?
419254885Sdumbbell		 */
420254885Sdumbbell		pdata->negative = (rdev->family != CHIP_RV200 &&
421254885Sdumbbell				   rdev->family != CHIP_RV250 &&
422254885Sdumbbell				   rdev->family != CHIP_RV280 &&
423254885Sdumbbell				   rdev->family != CHIP_RV350);
424254885Sdumbbell
425254885Sdumbbell#ifdef CONFIG_PMAC_BACKLIGHT
426254885Sdumbbell		pdata->negative = (pdata->negative ||
427254885Sdumbbell				   of_machine_is_compatible("PowerBook4,3") ||
428254885Sdumbbell				   of_machine_is_compatible("PowerBook6,3") ||
429254885Sdumbbell				   of_machine_is_compatible("PowerBook6,5"));
430254885Sdumbbell#endif
431254885Sdumbbell	}
432254885Sdumbbell
433254885Sdumbbell	if (rdev->is_atom_bios) {
434254885Sdumbbell		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
435254885Sdumbbell		lvds->bl_dev = bd;
436254885Sdumbbell	} else {
437254885Sdumbbell		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
438254885Sdumbbell		lvds->bl_dev = bd;
439254885Sdumbbell	}
440254885Sdumbbell
441254885Sdumbbell	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
442254885Sdumbbell	bd->props.power = FB_BLANK_UNBLANK;
443254885Sdumbbell	backlight_update_status(bd);
444254885Sdumbbell
445254885Sdumbbell	DRM_INFO("radeon legacy LVDS backlight initialized\n");
446254885Sdumbbell
447254885Sdumbbell	return;
448254885Sdumbbell
449254885Sdumbbellerror:
450254885Sdumbbell	free(pdata, DRM_MEM_DRIVER);
451254885Sdumbbell	return;
452254885Sdumbbell}
453254885Sdumbbell
454254885Sdumbbellstatic void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
455254885Sdumbbell{
456254885Sdumbbell	struct drm_device *dev = radeon_encoder->base.dev;
457254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
458254885Sdumbbell	struct backlight_device *bd = NULL;
459254885Sdumbbell
460254885Sdumbbell	if (!radeon_encoder->enc_priv)
461254885Sdumbbell		return;
462254885Sdumbbell
463254885Sdumbbell	if (rdev->is_atom_bios) {
464254885Sdumbbell		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
465254885Sdumbbell		bd = lvds->bl_dev;
466254885Sdumbbell		lvds->bl_dev = NULL;
467254885Sdumbbell	} else {
468254885Sdumbbell		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
469254885Sdumbbell		bd = lvds->bl_dev;
470254885Sdumbbell		lvds->bl_dev = NULL;
471254885Sdumbbell	}
472254885Sdumbbell
473254885Sdumbbell	if (bd) {
474254885Sdumbbell		struct radeon_backlight_privdata *pdata;
475254885Sdumbbell
476254885Sdumbbell		pdata = bl_get_data(bd);
477254885Sdumbbell		backlight_device_unregister(bd);
478254885Sdumbbell		free(pdata, DRM_MEM_DRIVER);
479254885Sdumbbell
480254885Sdumbbell		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
481254885Sdumbbell	}
482254885Sdumbbell}
483254885Sdumbbell
484254885Sdumbbell#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
485254885Sdumbbell
486254885Sdumbbellvoid radeon_legacy_backlight_init(struct radeon_encoder *encoder,
487254885Sdumbbell				  struct drm_connector *drm_connector)
488254885Sdumbbell{
489254885Sdumbbell}
490254885Sdumbbell
491254885Sdumbbellstatic void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
492254885Sdumbbell{
493254885Sdumbbell}
494254885Sdumbbell
495254885Sdumbbell#endif
496254885Sdumbbell
497254885Sdumbbell
498254885Sdumbbellstatic void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
499254885Sdumbbell{
500254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
501254885Sdumbbell
502254885Sdumbbell	if (radeon_encoder->enc_priv) {
503254885Sdumbbell		radeon_legacy_backlight_exit(radeon_encoder);
504254885Sdumbbell		free(radeon_encoder->enc_priv, DRM_MEM_DRIVER);
505254885Sdumbbell	}
506254885Sdumbbell	drm_encoder_cleanup(encoder);
507254885Sdumbbell	free(radeon_encoder, DRM_MEM_DRIVER);
508254885Sdumbbell}
509254885Sdumbbell
510254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
511254885Sdumbbell	.destroy = radeon_lvds_enc_destroy,
512254885Sdumbbell};
513254885Sdumbbell
514254885Sdumbbellstatic void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
515254885Sdumbbell{
516254885Sdumbbell	struct drm_device *dev = encoder->dev;
517254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
518254885Sdumbbell	uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
519254885Sdumbbell	uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL);
520254885Sdumbbell	uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
521254885Sdumbbell
522254885Sdumbbell	DRM_DEBUG_KMS("\n");
523254885Sdumbbell
524254885Sdumbbell	switch (mode) {
525254885Sdumbbell	case DRM_MODE_DPMS_ON:
526254885Sdumbbell		crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
527254885Sdumbbell		dac_cntl &= ~RADEON_DAC_PDWN;
528254885Sdumbbell		dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
529254885Sdumbbell				    RADEON_DAC_PDWN_G |
530254885Sdumbbell				    RADEON_DAC_PDWN_B);
531254885Sdumbbell		break;
532254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
533254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
534254885Sdumbbell	case DRM_MODE_DPMS_OFF:
535254885Sdumbbell		crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
536254885Sdumbbell		dac_cntl |= RADEON_DAC_PDWN;
537254885Sdumbbell		dac_macro_cntl |= (RADEON_DAC_PDWN_R |
538254885Sdumbbell				   RADEON_DAC_PDWN_G |
539254885Sdumbbell				   RADEON_DAC_PDWN_B);
540254885Sdumbbell		break;
541254885Sdumbbell	}
542254885Sdumbbell
543254885Sdumbbell	/* handled in radeon_crtc_dpms() */
544254885Sdumbbell	if (!(rdev->flags & RADEON_SINGLE_CRTC))
545254885Sdumbbell		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
546254885Sdumbbell	WREG32(RADEON_DAC_CNTL, dac_cntl);
547254885Sdumbbell	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
548254885Sdumbbell
549254885Sdumbbell	if (rdev->is_atom_bios)
550254885Sdumbbell		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
551254885Sdumbbell	else
552254885Sdumbbell		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
553254885Sdumbbell
554254885Sdumbbell}
555254885Sdumbbell
556254885Sdumbbellstatic void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
557254885Sdumbbell{
558254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
559254885Sdumbbell
560254885Sdumbbell	if (rdev->is_atom_bios)
561254885Sdumbbell		radeon_atom_output_lock(encoder, true);
562254885Sdumbbell	else
563254885Sdumbbell		radeon_combios_output_lock(encoder, true);
564254885Sdumbbell	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
565254885Sdumbbell}
566254885Sdumbbell
567254885Sdumbbellstatic void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
568254885Sdumbbell{
569254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
570254885Sdumbbell
571254885Sdumbbell	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON);
572254885Sdumbbell
573254885Sdumbbell	if (rdev->is_atom_bios)
574254885Sdumbbell		radeon_atom_output_lock(encoder, false);
575254885Sdumbbell	else
576254885Sdumbbell		radeon_combios_output_lock(encoder, false);
577254885Sdumbbell}
578254885Sdumbbell
579254885Sdumbbellstatic void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
580254885Sdumbbell					       struct drm_display_mode *mode,
581254885Sdumbbell					       struct drm_display_mode *adjusted_mode)
582254885Sdumbbell{
583254885Sdumbbell	struct drm_device *dev = encoder->dev;
584254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
585254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
586254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
587254885Sdumbbell	uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl;
588254885Sdumbbell
589254885Sdumbbell	DRM_DEBUG_KMS("\n");
590254885Sdumbbell
591254885Sdumbbell	if (radeon_crtc->crtc_id == 0) {
592254885Sdumbbell		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
593254885Sdumbbell			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
594254885Sdumbbell				~(RADEON_DISP_DAC_SOURCE_MASK);
595254885Sdumbbell			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
596254885Sdumbbell		} else {
597254885Sdumbbell			dac2_cntl = RREG32(RADEON_DAC_CNTL2)  & ~(RADEON_DAC2_DAC_CLK_SEL);
598254885Sdumbbell			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
599254885Sdumbbell		}
600254885Sdumbbell	} else {
601254885Sdumbbell		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
602254885Sdumbbell			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
603254885Sdumbbell				~(RADEON_DISP_DAC_SOURCE_MASK);
604254885Sdumbbell			disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
605254885Sdumbbell			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
606254885Sdumbbell		} else {
607254885Sdumbbell			dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL;
608254885Sdumbbell			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
609254885Sdumbbell		}
610254885Sdumbbell	}
611254885Sdumbbell
612254885Sdumbbell	dac_cntl = (RADEON_DAC_MASK_ALL |
613254885Sdumbbell		    RADEON_DAC_VGA_ADR_EN |
614254885Sdumbbell		    /* TODO 6-bits */
615254885Sdumbbell		    RADEON_DAC_8BIT_EN);
616254885Sdumbbell
617254885Sdumbbell	WREG32_P(RADEON_DAC_CNTL,
618254885Sdumbbell		       dac_cntl,
619254885Sdumbbell		       RADEON_DAC_RANGE_CNTL |
620254885Sdumbbell		       RADEON_DAC_BLANKING);
621254885Sdumbbell
622254885Sdumbbell	if (radeon_encoder->enc_priv) {
623254885Sdumbbell		struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv;
624254885Sdumbbell		dac_macro_cntl = p_dac->ps2_pdac_adj;
625254885Sdumbbell	} else
626254885Sdumbbell		dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
627254885Sdumbbell	dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B;
628254885Sdumbbell	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
629254885Sdumbbell
630254885Sdumbbell	if (rdev->is_atom_bios)
631254885Sdumbbell		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
632254885Sdumbbell	else
633254885Sdumbbell		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
634254885Sdumbbell}
635254885Sdumbbell
636254885Sdumbbellstatic enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder,
637254885Sdumbbell								  struct drm_connector *connector)
638254885Sdumbbell{
639254885Sdumbbell	struct drm_device *dev = encoder->dev;
640254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
641254885Sdumbbell	uint32_t vclk_ecp_cntl, crtc_ext_cntl;
642254885Sdumbbell	uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
643254885Sdumbbell	enum drm_connector_status found = connector_status_disconnected;
644254885Sdumbbell	bool color = true;
645254885Sdumbbell
646254885Sdumbbell	/* just don't bother on RN50 those chip are often connected to remoting
647254885Sdumbbell	 * console hw and often we get failure to load detect those. So to make
648254885Sdumbbell	 * everyone happy report the encoder as always connected.
649254885Sdumbbell	 */
650254885Sdumbbell	if (ASIC_IS_RN50(rdev)) {
651254885Sdumbbell		return connector_status_connected;
652254885Sdumbbell	}
653254885Sdumbbell
654254885Sdumbbell	/* save the regs we need */
655254885Sdumbbell	vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
656254885Sdumbbell	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
657254885Sdumbbell	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
658254885Sdumbbell	dac_cntl = RREG32(RADEON_DAC_CNTL);
659254885Sdumbbell	dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
660254885Sdumbbell
661254885Sdumbbell	tmp = vclk_ecp_cntl &
662254885Sdumbbell		~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
663254885Sdumbbell	WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
664254885Sdumbbell
665254885Sdumbbell	tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
666254885Sdumbbell	WREG32(RADEON_CRTC_EXT_CNTL, tmp);
667254885Sdumbbell
668254885Sdumbbell	tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
669254885Sdumbbell		RADEON_DAC_FORCE_DATA_EN;
670254885Sdumbbell
671254885Sdumbbell	if (color)
672254885Sdumbbell		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
673254885Sdumbbell	else
674254885Sdumbbell		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
675254885Sdumbbell
676254885Sdumbbell	if (ASIC_IS_R300(rdev))
677254885Sdumbbell		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
678254885Sdumbbell	else if (ASIC_IS_RV100(rdev))
679254885Sdumbbell		tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
680254885Sdumbbell	else
681254885Sdumbbell		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
682254885Sdumbbell
683254885Sdumbbell	WREG32(RADEON_DAC_EXT_CNTL, tmp);
684254885Sdumbbell
685254885Sdumbbell	tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
686254885Sdumbbell	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
687254885Sdumbbell	WREG32(RADEON_DAC_CNTL, tmp);
688254885Sdumbbell
689254885Sdumbbell	tmp = dac_macro_cntl;
690254885Sdumbbell	tmp &= ~(RADEON_DAC_PDWN_R |
691254885Sdumbbell		 RADEON_DAC_PDWN_G |
692254885Sdumbbell		 RADEON_DAC_PDWN_B);
693254885Sdumbbell
694254885Sdumbbell	WREG32(RADEON_DAC_MACRO_CNTL, tmp);
695254885Sdumbbell
696280183Sdumbbell	mdelay(2);
697254885Sdumbbell
698254885Sdumbbell	if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
699254885Sdumbbell		found = connector_status_connected;
700254885Sdumbbell
701254885Sdumbbell	/* restore the regs we used */
702254885Sdumbbell	WREG32(RADEON_DAC_CNTL, dac_cntl);
703254885Sdumbbell	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
704254885Sdumbbell	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
705254885Sdumbbell	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
706254885Sdumbbell	WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
707254885Sdumbbell
708254885Sdumbbell	return found;
709254885Sdumbbell}
710254885Sdumbbell
711254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
712254885Sdumbbell	.dpms = radeon_legacy_primary_dac_dpms,
713254885Sdumbbell	.mode_fixup = radeon_legacy_mode_fixup,
714254885Sdumbbell	.prepare = radeon_legacy_primary_dac_prepare,
715254885Sdumbbell	.mode_set = radeon_legacy_primary_dac_mode_set,
716254885Sdumbbell	.commit = radeon_legacy_primary_dac_commit,
717254885Sdumbbell	.detect = radeon_legacy_primary_dac_detect,
718254885Sdumbbell	.disable = radeon_legacy_encoder_disable,
719254885Sdumbbell};
720254885Sdumbbell
721254885Sdumbbell
722254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = {
723254885Sdumbbell	.destroy = radeon_enc_destroy,
724254885Sdumbbell};
725254885Sdumbbell
726254885Sdumbbellstatic void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
727254885Sdumbbell{
728254885Sdumbbell	struct drm_device *dev = encoder->dev;
729254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
730254885Sdumbbell	uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL);
731254885Sdumbbell	DRM_DEBUG_KMS("\n");
732254885Sdumbbell
733254885Sdumbbell	switch (mode) {
734254885Sdumbbell	case DRM_MODE_DPMS_ON:
735254885Sdumbbell		fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
736254885Sdumbbell		break;
737254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
738254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
739254885Sdumbbell	case DRM_MODE_DPMS_OFF:
740254885Sdumbbell		fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
741254885Sdumbbell		break;
742254885Sdumbbell	}
743254885Sdumbbell
744254885Sdumbbell	WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
745254885Sdumbbell
746254885Sdumbbell	if (rdev->is_atom_bios)
747254885Sdumbbell		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
748254885Sdumbbell	else
749254885Sdumbbell		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
750254885Sdumbbell
751254885Sdumbbell}
752254885Sdumbbell
753254885Sdumbbellstatic void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
754254885Sdumbbell{
755254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
756254885Sdumbbell
757254885Sdumbbell	if (rdev->is_atom_bios)
758254885Sdumbbell		radeon_atom_output_lock(encoder, true);
759254885Sdumbbell	else
760254885Sdumbbell		radeon_combios_output_lock(encoder, true);
761254885Sdumbbell	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
762254885Sdumbbell}
763254885Sdumbbell
764254885Sdumbbellstatic void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
765254885Sdumbbell{
766254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
767254885Sdumbbell
768254885Sdumbbell	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON);
769254885Sdumbbell
770254885Sdumbbell	if (rdev->is_atom_bios)
771254885Sdumbbell		radeon_atom_output_lock(encoder, true);
772254885Sdumbbell	else
773254885Sdumbbell		radeon_combios_output_lock(encoder, true);
774254885Sdumbbell}
775254885Sdumbbell
776254885Sdumbbellstatic void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
777254885Sdumbbell					    struct drm_display_mode *mode,
778254885Sdumbbell					    struct drm_display_mode *adjusted_mode)
779254885Sdumbbell{
780254885Sdumbbell	struct drm_device *dev = encoder->dev;
781254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
782254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
783254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
784254885Sdumbbell	uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl;
785254885Sdumbbell	int i;
786254885Sdumbbell
787254885Sdumbbell	DRM_DEBUG_KMS("\n");
788254885Sdumbbell
789254885Sdumbbell	tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
790254885Sdumbbell	tmp &= 0xfffff;
791254885Sdumbbell	if (rdev->family == CHIP_RV280) {
792254885Sdumbbell		/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
793254885Sdumbbell		tmp ^= (1 << 22);
794254885Sdumbbell		tmds_pll_cntl ^= (1 << 22);
795254885Sdumbbell	}
796254885Sdumbbell
797254885Sdumbbell	if (radeon_encoder->enc_priv) {
798254885Sdumbbell		struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv;
799254885Sdumbbell
800254885Sdumbbell		for (i = 0; i < 4; i++) {
801254885Sdumbbell			if (tmds->tmds_pll[i].freq == 0)
802254885Sdumbbell				break;
803254885Sdumbbell			if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) {
804254885Sdumbbell				tmp = tmds->tmds_pll[i].value ;
805254885Sdumbbell				break;
806254885Sdumbbell			}
807254885Sdumbbell		}
808254885Sdumbbell	}
809254885Sdumbbell
810254885Sdumbbell	if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) {
811254885Sdumbbell		if (tmp & 0xfff00000)
812254885Sdumbbell			tmds_pll_cntl = tmp;
813254885Sdumbbell		else {
814254885Sdumbbell			tmds_pll_cntl &= 0xfff00000;
815254885Sdumbbell			tmds_pll_cntl |= tmp;
816254885Sdumbbell		}
817254885Sdumbbell	} else
818254885Sdumbbell		tmds_pll_cntl = tmp;
819254885Sdumbbell
820254885Sdumbbell	tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) &
821254885Sdumbbell		~(RADEON_TMDS_TRANSMITTER_PLLRST);
822254885Sdumbbell
823254885Sdumbbell    if (rdev->family == CHIP_R200 ||
824254885Sdumbbell	rdev->family == CHIP_R100 ||
825254885Sdumbbell	ASIC_IS_R300(rdev))
826254885Sdumbbell	    tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
827254885Sdumbbell    else /* RV chips got this bit reversed */
828254885Sdumbbell	    tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN;
829254885Sdumbbell
830254885Sdumbbell    fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) |
831254885Sdumbbell		   (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
832254885Sdumbbell		    RADEON_FP_CRTC_DONT_SHADOW_HEND));
833254885Sdumbbell
834254885Sdumbbell    fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
835254885Sdumbbell
836254885Sdumbbell    fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
837254885Sdumbbell		     RADEON_FP_DFP_SYNC_SEL |
838254885Sdumbbell		     RADEON_FP_CRT_SYNC_SEL |
839254885Sdumbbell		     RADEON_FP_CRTC_LOCK_8DOT |
840254885Sdumbbell		     RADEON_FP_USE_SHADOW_EN |
841254885Sdumbbell		     RADEON_FP_CRTC_USE_SHADOW_VEND |
842254885Sdumbbell		     RADEON_FP_CRT_SYNC_ALT);
843254885Sdumbbell
844254885Sdumbbell    if (1) /*  FIXME rgbBits == 8 */
845254885Sdumbbell	    fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
846254885Sdumbbell    else
847254885Sdumbbell	    fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
848254885Sdumbbell
849254885Sdumbbell    if (radeon_crtc->crtc_id == 0) {
850254885Sdumbbell	    if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
851254885Sdumbbell		    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
852254885Sdumbbell		    if (radeon_encoder->rmx_type != RMX_OFF)
853254885Sdumbbell			    fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
854254885Sdumbbell		    else
855254885Sdumbbell			    fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
856254885Sdumbbell	    } else
857254885Sdumbbell		    fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
858254885Sdumbbell    } else {
859254885Sdumbbell	    if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
860254885Sdumbbell		    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
861254885Sdumbbell		    fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
862254885Sdumbbell	    } else
863254885Sdumbbell		    fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
864254885Sdumbbell    }
865254885Sdumbbell
866254885Sdumbbell    WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl);
867254885Sdumbbell    WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl);
868254885Sdumbbell    WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
869254885Sdumbbell
870254885Sdumbbell	if (rdev->is_atom_bios)
871254885Sdumbbell		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
872254885Sdumbbell	else
873254885Sdumbbell		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
874254885Sdumbbell}
875254885Sdumbbell
876254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
877254885Sdumbbell	.dpms = radeon_legacy_tmds_int_dpms,
878254885Sdumbbell	.mode_fixup = radeon_legacy_mode_fixup,
879254885Sdumbbell	.prepare = radeon_legacy_tmds_int_prepare,
880254885Sdumbbell	.mode_set = radeon_legacy_tmds_int_mode_set,
881254885Sdumbbell	.commit = radeon_legacy_tmds_int_commit,
882254885Sdumbbell	.disable = radeon_legacy_encoder_disable,
883254885Sdumbbell};
884254885Sdumbbell
885254885Sdumbbell
886254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = {
887254885Sdumbbell	.destroy = radeon_enc_destroy,
888254885Sdumbbell};
889254885Sdumbbell
890254885Sdumbbellstatic void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
891254885Sdumbbell{
892254885Sdumbbell	struct drm_device *dev = encoder->dev;
893254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
894254885Sdumbbell	uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
895254885Sdumbbell	DRM_DEBUG_KMS("\n");
896254885Sdumbbell
897254885Sdumbbell	switch (mode) {
898254885Sdumbbell	case DRM_MODE_DPMS_ON:
899254885Sdumbbell		fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
900254885Sdumbbell		fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
901254885Sdumbbell		break;
902254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
903254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
904254885Sdumbbell	case DRM_MODE_DPMS_OFF:
905254885Sdumbbell		fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
906254885Sdumbbell		fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
907254885Sdumbbell		break;
908254885Sdumbbell	}
909254885Sdumbbell
910254885Sdumbbell	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
911254885Sdumbbell
912254885Sdumbbell	if (rdev->is_atom_bios)
913254885Sdumbbell		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
914254885Sdumbbell	else
915254885Sdumbbell		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
916254885Sdumbbell
917254885Sdumbbell}
918254885Sdumbbell
919254885Sdumbbellstatic void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
920254885Sdumbbell{
921254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
922254885Sdumbbell
923254885Sdumbbell	if (rdev->is_atom_bios)
924254885Sdumbbell		radeon_atom_output_lock(encoder, true);
925254885Sdumbbell	else
926254885Sdumbbell		radeon_combios_output_lock(encoder, true);
927254885Sdumbbell	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
928254885Sdumbbell}
929254885Sdumbbell
930254885Sdumbbellstatic void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
931254885Sdumbbell{
932254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
933254885Sdumbbell	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON);
934254885Sdumbbell
935254885Sdumbbell	if (rdev->is_atom_bios)
936254885Sdumbbell		radeon_atom_output_lock(encoder, false);
937254885Sdumbbell	else
938254885Sdumbbell		radeon_combios_output_lock(encoder, false);
939254885Sdumbbell}
940254885Sdumbbell
941254885Sdumbbellstatic void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
942254885Sdumbbell					    struct drm_display_mode *mode,
943254885Sdumbbell					    struct drm_display_mode *adjusted_mode)
944254885Sdumbbell{
945254885Sdumbbell	struct drm_device *dev = encoder->dev;
946254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
947254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
948254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
949254885Sdumbbell	uint32_t fp2_gen_cntl;
950254885Sdumbbell
951254885Sdumbbell	DRM_DEBUG_KMS("\n");
952254885Sdumbbell
953254885Sdumbbell	if (rdev->is_atom_bios) {
954254885Sdumbbell		radeon_encoder->pixel_clock = adjusted_mode->clock;
955254885Sdumbbell		atombios_dvo_setup(encoder, ATOM_ENABLE);
956254885Sdumbbell		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
957254885Sdumbbell	} else {
958254885Sdumbbell		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
959254885Sdumbbell
960254885Sdumbbell		if (1) /*  FIXME rgbBits == 8 */
961254885Sdumbbell			fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
962254885Sdumbbell		else
963254885Sdumbbell			fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
964254885Sdumbbell
965254885Sdumbbell		fp2_gen_cntl &= ~(RADEON_FP2_ON |
966254885Sdumbbell				  RADEON_FP2_DVO_EN |
967254885Sdumbbell				  RADEON_FP2_DVO_RATE_SEL_SDR);
968254885Sdumbbell
969254885Sdumbbell		/* XXX: these are oem specific */
970254885Sdumbbell		if (ASIC_IS_R300(rdev)) {
971254885Sdumbbell			if ((dev->pci_device == 0x4850) &&
972254885Sdumbbell			    (dev->pci_subvendor == 0x1028) &&
973254885Sdumbbell			    (dev->pci_subdevice == 0x2001)) /* Dell Inspiron 8600 */
974254885Sdumbbell				fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE;
975254885Sdumbbell			else
976254885Sdumbbell				fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
977254885Sdumbbell
978254885Sdumbbell			/*if (mode->clock > 165000)
979254885Sdumbbell			  fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
980254885Sdumbbell		}
981254885Sdumbbell		if (!radeon_combios_external_tmds_setup(encoder))
982254885Sdumbbell			radeon_external_tmds_setup(encoder);
983254885Sdumbbell	}
984254885Sdumbbell
985254885Sdumbbell	if (radeon_crtc->crtc_id == 0) {
986254885Sdumbbell		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
987254885Sdumbbell			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
988254885Sdumbbell			if (radeon_encoder->rmx_type != RMX_OFF)
989254885Sdumbbell				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
990254885Sdumbbell			else
991254885Sdumbbell				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
992254885Sdumbbell		} else
993254885Sdumbbell			fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
994254885Sdumbbell	} else {
995254885Sdumbbell		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
996254885Sdumbbell			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
997254885Sdumbbell			fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
998254885Sdumbbell		} else
999254885Sdumbbell			fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
1000254885Sdumbbell	}
1001254885Sdumbbell
1002254885Sdumbbell	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1003254885Sdumbbell
1004254885Sdumbbell	if (rdev->is_atom_bios)
1005254885Sdumbbell		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1006254885Sdumbbell	else
1007254885Sdumbbell		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1008254885Sdumbbell}
1009254885Sdumbbell
1010254885Sdumbbellstatic void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
1011254885Sdumbbell{
1012254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1013254885Sdumbbell	/* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */
1014254885Sdumbbell	free(radeon_encoder->enc_priv, DRM_MEM_DRIVER);
1015254885Sdumbbell	drm_encoder_cleanup(encoder);
1016254885Sdumbbell	free(radeon_encoder, DRM_MEM_DRIVER);
1017254885Sdumbbell}
1018254885Sdumbbell
1019254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
1020254885Sdumbbell	.dpms = radeon_legacy_tmds_ext_dpms,
1021254885Sdumbbell	.mode_fixup = radeon_legacy_mode_fixup,
1022254885Sdumbbell	.prepare = radeon_legacy_tmds_ext_prepare,
1023254885Sdumbbell	.mode_set = radeon_legacy_tmds_ext_mode_set,
1024254885Sdumbbell	.commit = radeon_legacy_tmds_ext_commit,
1025254885Sdumbbell	.disable = radeon_legacy_encoder_disable,
1026254885Sdumbbell};
1027254885Sdumbbell
1028254885Sdumbbell
1029254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
1030254885Sdumbbell	.destroy = radeon_ext_tmds_enc_destroy,
1031254885Sdumbbell};
1032254885Sdumbbell
1033254885Sdumbbellstatic void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
1034254885Sdumbbell{
1035254885Sdumbbell	struct drm_device *dev = encoder->dev;
1036254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1037254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1038254885Sdumbbell	uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
1039254885Sdumbbell	uint32_t tv_master_cntl = 0;
1040254885Sdumbbell	bool is_tv;
1041254885Sdumbbell	DRM_DEBUG_KMS("\n");
1042254885Sdumbbell
1043254885Sdumbbell	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
1044254885Sdumbbell
1045254885Sdumbbell	if (rdev->family == CHIP_R200)
1046254885Sdumbbell		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
1047254885Sdumbbell	else {
1048254885Sdumbbell		if (is_tv)
1049254885Sdumbbell			tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
1050254885Sdumbbell		else
1051254885Sdumbbell			crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1052254885Sdumbbell		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1053254885Sdumbbell	}
1054254885Sdumbbell
1055254885Sdumbbell	switch (mode) {
1056254885Sdumbbell	case DRM_MODE_DPMS_ON:
1057254885Sdumbbell		if (rdev->family == CHIP_R200) {
1058254885Sdumbbell			fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1059254885Sdumbbell		} else {
1060254885Sdumbbell			if (is_tv)
1061254885Sdumbbell				tv_master_cntl |= RADEON_TV_ON;
1062254885Sdumbbell			else
1063254885Sdumbbell				crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
1064254885Sdumbbell
1065254885Sdumbbell			if (rdev->family == CHIP_R420 ||
1066254885Sdumbbell			    rdev->family == CHIP_R423 ||
1067254885Sdumbbell			    rdev->family == CHIP_RV410)
1068254885Sdumbbell				tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
1069254885Sdumbbell						 R420_TV_DAC_GDACPD |
1070254885Sdumbbell						 R420_TV_DAC_BDACPD |
1071254885Sdumbbell						 RADEON_TV_DAC_BGSLEEP);
1072254885Sdumbbell			else
1073254885Sdumbbell				tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
1074254885Sdumbbell						 RADEON_TV_DAC_GDACPD |
1075254885Sdumbbell						 RADEON_TV_DAC_BDACPD |
1076254885Sdumbbell						 RADEON_TV_DAC_BGSLEEP);
1077254885Sdumbbell		}
1078254885Sdumbbell		break;
1079254885Sdumbbell	case DRM_MODE_DPMS_STANDBY:
1080254885Sdumbbell	case DRM_MODE_DPMS_SUSPEND:
1081254885Sdumbbell	case DRM_MODE_DPMS_OFF:
1082254885Sdumbbell		if (rdev->family == CHIP_R200)
1083254885Sdumbbell			fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1084254885Sdumbbell		else {
1085254885Sdumbbell			if (is_tv)
1086254885Sdumbbell				tv_master_cntl &= ~RADEON_TV_ON;
1087254885Sdumbbell			else
1088254885Sdumbbell				crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
1089254885Sdumbbell
1090254885Sdumbbell			if (rdev->family == CHIP_R420 ||
1091254885Sdumbbell			    rdev->family == CHIP_R423 ||
1092254885Sdumbbell			    rdev->family == CHIP_RV410)
1093254885Sdumbbell				tv_dac_cntl |= (R420_TV_DAC_RDACPD |
1094254885Sdumbbell						R420_TV_DAC_GDACPD |
1095254885Sdumbbell						R420_TV_DAC_BDACPD |
1096254885Sdumbbell						RADEON_TV_DAC_BGSLEEP);
1097254885Sdumbbell			else
1098254885Sdumbbell				tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
1099254885Sdumbbell						RADEON_TV_DAC_GDACPD |
1100254885Sdumbbell						RADEON_TV_DAC_BDACPD |
1101254885Sdumbbell						RADEON_TV_DAC_BGSLEEP);
1102254885Sdumbbell		}
1103254885Sdumbbell		break;
1104254885Sdumbbell	}
1105254885Sdumbbell
1106254885Sdumbbell	if (rdev->family == CHIP_R200) {
1107254885Sdumbbell		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1108254885Sdumbbell	} else {
1109254885Sdumbbell		if (is_tv)
1110254885Sdumbbell			WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
1111254885Sdumbbell		/* handled in radeon_crtc_dpms() */
1112254885Sdumbbell		else if (!(rdev->flags & RADEON_SINGLE_CRTC))
1113254885Sdumbbell			WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1114254885Sdumbbell		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1115254885Sdumbbell	}
1116254885Sdumbbell
1117254885Sdumbbell	if (rdev->is_atom_bios)
1118254885Sdumbbell		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1119254885Sdumbbell	else
1120254885Sdumbbell		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1121254885Sdumbbell
1122254885Sdumbbell}
1123254885Sdumbbell
1124254885Sdumbbellstatic void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
1125254885Sdumbbell{
1126254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
1127254885Sdumbbell
1128254885Sdumbbell	if (rdev->is_atom_bios)
1129254885Sdumbbell		radeon_atom_output_lock(encoder, true);
1130254885Sdumbbell	else
1131254885Sdumbbell		radeon_combios_output_lock(encoder, true);
1132254885Sdumbbell	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
1133254885Sdumbbell}
1134254885Sdumbbell
1135254885Sdumbbellstatic void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
1136254885Sdumbbell{
1137254885Sdumbbell	struct radeon_device *rdev = encoder->dev->dev_private;
1138254885Sdumbbell
1139254885Sdumbbell	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON);
1140254885Sdumbbell
1141254885Sdumbbell	if (rdev->is_atom_bios)
1142254885Sdumbbell		radeon_atom_output_lock(encoder, true);
1143254885Sdumbbell	else
1144254885Sdumbbell		radeon_combios_output_lock(encoder, true);
1145254885Sdumbbell}
1146254885Sdumbbell
1147254885Sdumbbellstatic void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
1148254885Sdumbbell		struct drm_display_mode *mode,
1149254885Sdumbbell		struct drm_display_mode *adjusted_mode)
1150254885Sdumbbell{
1151254885Sdumbbell	struct drm_device *dev = encoder->dev;
1152254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1153254885Sdumbbell	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1154254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1155254885Sdumbbell	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
1156254885Sdumbbell	uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
1157254885Sdumbbell	uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0;
1158254885Sdumbbell	bool is_tv = false;
1159254885Sdumbbell
1160254885Sdumbbell	DRM_DEBUG_KMS("\n");
1161254885Sdumbbell
1162254885Sdumbbell	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
1163254885Sdumbbell
1164254885Sdumbbell	if (rdev->family != CHIP_R200) {
1165254885Sdumbbell		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1166254885Sdumbbell		if (rdev->family == CHIP_R420 ||
1167254885Sdumbbell		    rdev->family == CHIP_R423 ||
1168254885Sdumbbell		    rdev->family == CHIP_RV410) {
1169254885Sdumbbell			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
1170254885Sdumbbell					 RADEON_TV_DAC_BGADJ_MASK |
1171254885Sdumbbell					 R420_TV_DAC_DACADJ_MASK |
1172254885Sdumbbell					 R420_TV_DAC_RDACPD |
1173254885Sdumbbell					 R420_TV_DAC_GDACPD |
1174254885Sdumbbell					 R420_TV_DAC_BDACPD |
1175254885Sdumbbell					 R420_TV_DAC_TVENABLE);
1176254885Sdumbbell		} else {
1177254885Sdumbbell			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
1178254885Sdumbbell					 RADEON_TV_DAC_BGADJ_MASK |
1179254885Sdumbbell					 RADEON_TV_DAC_DACADJ_MASK |
1180254885Sdumbbell					 RADEON_TV_DAC_RDACPD |
1181254885Sdumbbell					 RADEON_TV_DAC_GDACPD |
1182254885Sdumbbell					 RADEON_TV_DAC_BDACPD);
1183254885Sdumbbell		}
1184254885Sdumbbell
1185254885Sdumbbell		tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
1186254885Sdumbbell
1187254885Sdumbbell		if (is_tv) {
1188254885Sdumbbell			if (tv_dac->tv_std == TV_STD_NTSC ||
1189254885Sdumbbell			    tv_dac->tv_std == TV_STD_NTSC_J ||
1190254885Sdumbbell			    tv_dac->tv_std == TV_STD_PAL_M ||
1191254885Sdumbbell			    tv_dac->tv_std == TV_STD_PAL_60)
1192254885Sdumbbell				tv_dac_cntl |= tv_dac->ntsc_tvdac_adj;
1193254885Sdumbbell			else
1194254885Sdumbbell				tv_dac_cntl |= tv_dac->pal_tvdac_adj;
1195254885Sdumbbell
1196254885Sdumbbell			if (tv_dac->tv_std == TV_STD_NTSC ||
1197254885Sdumbbell			    tv_dac->tv_std == TV_STD_NTSC_J)
1198254885Sdumbbell				tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
1199254885Sdumbbell			else
1200254885Sdumbbell				tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
1201254885Sdumbbell		} else
1202254885Sdumbbell			tv_dac_cntl |= (RADEON_TV_DAC_STD_PS2 |
1203254885Sdumbbell					tv_dac->ps2_tvdac_adj);
1204254885Sdumbbell
1205254885Sdumbbell		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1206254885Sdumbbell	}
1207254885Sdumbbell
1208254885Sdumbbell	if (ASIC_IS_R300(rdev)) {
1209254885Sdumbbell		gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
1210254885Sdumbbell		disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1211254885Sdumbbell	} else if (rdev->family != CHIP_R200)
1212254885Sdumbbell		disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
1213254885Sdumbbell	else if (rdev->family == CHIP_R200)
1214254885Sdumbbell		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
1215254885Sdumbbell
1216254885Sdumbbell	if (rdev->family >= CHIP_R200)
1217254885Sdumbbell		disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
1218254885Sdumbbell
1219254885Sdumbbell	if (is_tv) {
1220254885Sdumbbell		uint32_t dac_cntl;
1221254885Sdumbbell
1222254885Sdumbbell		dac_cntl = RREG32(RADEON_DAC_CNTL);
1223254885Sdumbbell		dac_cntl &= ~RADEON_DAC_TVO_EN;
1224254885Sdumbbell		WREG32(RADEON_DAC_CNTL, dac_cntl);
1225254885Sdumbbell
1226254885Sdumbbell		if (ASIC_IS_R300(rdev))
1227254885Sdumbbell			gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1;
1228254885Sdumbbell
1229254885Sdumbbell		dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL;
1230254885Sdumbbell		if (radeon_crtc->crtc_id == 0) {
1231254885Sdumbbell			if (ASIC_IS_R300(rdev)) {
1232254885Sdumbbell				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1233254885Sdumbbell				disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC |
1234254885Sdumbbell						     RADEON_DISP_TV_SOURCE_CRTC);
1235254885Sdumbbell			}
1236254885Sdumbbell			if (rdev->family >= CHIP_R200) {
1237254885Sdumbbell				disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
1238254885Sdumbbell			} else {
1239254885Sdumbbell				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
1240254885Sdumbbell			}
1241254885Sdumbbell		} else {
1242254885Sdumbbell			if (ASIC_IS_R300(rdev)) {
1243254885Sdumbbell				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1244254885Sdumbbell				disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
1245254885Sdumbbell			}
1246254885Sdumbbell			if (rdev->family >= CHIP_R200) {
1247254885Sdumbbell				disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
1248254885Sdumbbell			} else {
1249254885Sdumbbell				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
1250254885Sdumbbell			}
1251254885Sdumbbell		}
1252254885Sdumbbell		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
1253254885Sdumbbell	} else {
1254254885Sdumbbell
1255254885Sdumbbell		dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
1256254885Sdumbbell
1257254885Sdumbbell		if (radeon_crtc->crtc_id == 0) {
1258254885Sdumbbell			if (ASIC_IS_R300(rdev)) {
1259254885Sdumbbell				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1260254885Sdumbbell				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
1261254885Sdumbbell			} else if (rdev->family == CHIP_R200) {
1262254885Sdumbbell				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
1263254885Sdumbbell						  RADEON_FP2_DVO_RATE_SEL_SDR);
1264254885Sdumbbell			} else
1265254885Sdumbbell				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
1266254885Sdumbbell		} else {
1267254885Sdumbbell			if (ASIC_IS_R300(rdev)) {
1268254885Sdumbbell				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1269254885Sdumbbell				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1270254885Sdumbbell			} else if (rdev->family == CHIP_R200) {
1271254885Sdumbbell				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
1272254885Sdumbbell						  RADEON_FP2_DVO_RATE_SEL_SDR);
1273254885Sdumbbell				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
1274254885Sdumbbell			} else
1275254885Sdumbbell				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
1276254885Sdumbbell		}
1277254885Sdumbbell		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
1278254885Sdumbbell	}
1279254885Sdumbbell
1280254885Sdumbbell	if (ASIC_IS_R300(rdev)) {
1281254885Sdumbbell		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1282254885Sdumbbell		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1283254885Sdumbbell	} else if (rdev->family != CHIP_R200)
1284254885Sdumbbell		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
1285254885Sdumbbell	else if (rdev->family == CHIP_R200)
1286254885Sdumbbell		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1287254885Sdumbbell
1288254885Sdumbbell	if (rdev->family >= CHIP_R200)
1289254885Sdumbbell		WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
1290254885Sdumbbell
1291254885Sdumbbell	if (is_tv)
1292254885Sdumbbell		radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
1293254885Sdumbbell
1294254885Sdumbbell	if (rdev->is_atom_bios)
1295254885Sdumbbell		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1296254885Sdumbbell	else
1297254885Sdumbbell		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1298254885Sdumbbell
1299254885Sdumbbell}
1300254885Sdumbbell
1301254885Sdumbbellstatic bool r300_legacy_tv_detect(struct drm_encoder *encoder,
1302254885Sdumbbell				  struct drm_connector *connector)
1303254885Sdumbbell{
1304254885Sdumbbell	struct drm_device *dev = encoder->dev;
1305254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1306254885Sdumbbell	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
1307254885Sdumbbell	uint32_t disp_output_cntl, gpiopad_a, tmp;
1308254885Sdumbbell	bool found = false;
1309254885Sdumbbell
1310254885Sdumbbell	/* save regs needed */
1311254885Sdumbbell	gpiopad_a = RREG32(RADEON_GPIOPAD_A);
1312254885Sdumbbell	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1313254885Sdumbbell	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1314254885Sdumbbell	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
1315254885Sdumbbell	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1316254885Sdumbbell	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1317254885Sdumbbell
1318254885Sdumbbell	WREG32_P(RADEON_GPIOPAD_A, 0, ~1);
1319254885Sdumbbell
1320254885Sdumbbell	WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL);
1321254885Sdumbbell
1322254885Sdumbbell	WREG32(RADEON_CRTC2_GEN_CNTL,
1323254885Sdumbbell	       RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
1324254885Sdumbbell
1325254885Sdumbbell	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1326254885Sdumbbell	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1327254885Sdumbbell	WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
1328254885Sdumbbell
1329254885Sdumbbell	WREG32(RADEON_DAC_EXT_CNTL,
1330254885Sdumbbell	       RADEON_DAC2_FORCE_BLANK_OFF_EN |
1331254885Sdumbbell	       RADEON_DAC2_FORCE_DATA_EN |
1332254885Sdumbbell	       RADEON_DAC_FORCE_DATA_SEL_RGB |
1333254885Sdumbbell	       (0xec << RADEON_DAC_FORCE_DATA_SHIFT));
1334254885Sdumbbell
1335254885Sdumbbell	WREG32(RADEON_TV_DAC_CNTL,
1336254885Sdumbbell	       RADEON_TV_DAC_STD_NTSC |
1337254885Sdumbbell	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1338254885Sdumbbell	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
1339254885Sdumbbell
1340254885Sdumbbell	RREG32(RADEON_TV_DAC_CNTL);
1341280183Sdumbbell	mdelay(4);
1342254885Sdumbbell
1343254885Sdumbbell	WREG32(RADEON_TV_DAC_CNTL,
1344254885Sdumbbell	       RADEON_TV_DAC_NBLANK |
1345254885Sdumbbell	       RADEON_TV_DAC_NHOLD |
1346254885Sdumbbell	       RADEON_TV_MONITOR_DETECT_EN |
1347254885Sdumbbell	       RADEON_TV_DAC_STD_NTSC |
1348254885Sdumbbell	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1349254885Sdumbbell	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
1350254885Sdumbbell
1351254885Sdumbbell	RREG32(RADEON_TV_DAC_CNTL);
1352280183Sdumbbell	mdelay(6);
1353254885Sdumbbell
1354254885Sdumbbell	tmp = RREG32(RADEON_TV_DAC_CNTL);
1355254885Sdumbbell	if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
1356254885Sdumbbell		found = true;
1357254885Sdumbbell		DRM_DEBUG_KMS("S-video TV connection detected\n");
1358254885Sdumbbell	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
1359254885Sdumbbell		found = true;
1360254885Sdumbbell		DRM_DEBUG_KMS("Composite TV connection detected\n");
1361254885Sdumbbell	}
1362254885Sdumbbell
1363254885Sdumbbell	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1364254885Sdumbbell	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1365254885Sdumbbell	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1366254885Sdumbbell	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1367254885Sdumbbell	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1368254885Sdumbbell	WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1369254885Sdumbbell	return found;
1370254885Sdumbbell}
1371254885Sdumbbell
1372254885Sdumbbellstatic bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
1373254885Sdumbbell				    struct drm_connector *connector)
1374254885Sdumbbell{
1375254885Sdumbbell	struct drm_device *dev = encoder->dev;
1376254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1377254885Sdumbbell	uint32_t tv_dac_cntl, dac_cntl2;
1378254885Sdumbbell	uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp;
1379254885Sdumbbell	bool found = false;
1380254885Sdumbbell
1381254885Sdumbbell	if (ASIC_IS_R300(rdev))
1382254885Sdumbbell		return r300_legacy_tv_detect(encoder, connector);
1383254885Sdumbbell
1384254885Sdumbbell	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1385254885Sdumbbell	tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
1386254885Sdumbbell	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1387254885Sdumbbell	config_cntl = RREG32(RADEON_CONFIG_CNTL);
1388254885Sdumbbell	tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL);
1389254885Sdumbbell
1390254885Sdumbbell	tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
1391254885Sdumbbell	WREG32(RADEON_DAC_CNTL2, tmp);
1392254885Sdumbbell
1393254885Sdumbbell	tmp = tv_master_cntl | RADEON_TV_ON;
1394254885Sdumbbell	tmp &= ~(RADEON_TV_ASYNC_RST |
1395254885Sdumbbell		 RADEON_RESTART_PHASE_FIX |
1396254885Sdumbbell		 RADEON_CRT_FIFO_CE_EN |
1397254885Sdumbbell		 RADEON_TV_FIFO_CE_EN |
1398254885Sdumbbell		 RADEON_RE_SYNC_NOW_SEL_MASK);
1399254885Sdumbbell	tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
1400254885Sdumbbell	WREG32(RADEON_TV_MASTER_CNTL, tmp);
1401254885Sdumbbell
1402254885Sdumbbell	tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
1403254885Sdumbbell		RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
1404254885Sdumbbell		(8 << RADEON_TV_DAC_BGADJ_SHIFT);
1405254885Sdumbbell
1406254885Sdumbbell	if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
1407254885Sdumbbell		tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
1408254885Sdumbbell	else
1409254885Sdumbbell		tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
1410254885Sdumbbell	WREG32(RADEON_TV_DAC_CNTL, tmp);
1411254885Sdumbbell
1412254885Sdumbbell	tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
1413254885Sdumbbell		RADEON_RED_MX_FORCE_DAC_DATA |
1414254885Sdumbbell		RADEON_GRN_MX_FORCE_DAC_DATA |
1415254885Sdumbbell		RADEON_BLU_MX_FORCE_DAC_DATA |
1416254885Sdumbbell		(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
1417254885Sdumbbell	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
1418254885Sdumbbell
1419280183Sdumbbell	mdelay(3);
1420254885Sdumbbell	tmp = RREG32(RADEON_TV_DAC_CNTL);
1421254885Sdumbbell	if (tmp & RADEON_TV_DAC_GDACDET) {
1422254885Sdumbbell		found = true;
1423254885Sdumbbell		DRM_DEBUG_KMS("S-video TV connection detected\n");
1424254885Sdumbbell	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
1425254885Sdumbbell		found = true;
1426254885Sdumbbell		DRM_DEBUG_KMS("Composite TV connection detected\n");
1427254885Sdumbbell	}
1428254885Sdumbbell
1429254885Sdumbbell	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
1430254885Sdumbbell	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1431254885Sdumbbell	WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
1432254885Sdumbbell	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1433254885Sdumbbell	return found;
1434254885Sdumbbell}
1435254885Sdumbbell
1436254885Sdumbbellstatic bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
1437254885Sdumbbell					 struct drm_connector *connector)
1438254885Sdumbbell{
1439254885Sdumbbell	struct drm_device *dev = encoder->dev;
1440254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1441254885Sdumbbell	uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
1442254885Sdumbbell	uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
1443254885Sdumbbell	uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
1444254885Sdumbbell	uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
1445254885Sdumbbell	uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
1446254885Sdumbbell	bool found = false;
1447254885Sdumbbell	int i;
1448254885Sdumbbell
1449254885Sdumbbell	/* save the regs we need */
1450254885Sdumbbell	gpio_monid = RREG32(RADEON_GPIO_MONID);
1451254885Sdumbbell	fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
1452254885Sdumbbell	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1453254885Sdumbbell	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1454254885Sdumbbell	disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
1455254885Sdumbbell	disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
1456254885Sdumbbell	disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
1457254885Sdumbbell	disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
1458254885Sdumbbell	disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
1459254885Sdumbbell	disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
1460254885Sdumbbell	crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
1461254885Sdumbbell	crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
1462254885Sdumbbell	crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
1463254885Sdumbbell	crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
1464254885Sdumbbell
1465254885Sdumbbell	tmp = RREG32(RADEON_GPIO_MONID);
1466254885Sdumbbell	tmp &= ~RADEON_GPIO_A_0;
1467254885Sdumbbell	WREG32(RADEON_GPIO_MONID, tmp);
1468254885Sdumbbell
1469254885Sdumbbell	WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
1470254885Sdumbbell				     RADEON_FP2_PANEL_FORMAT |
1471254885Sdumbbell				     R200_FP2_SOURCE_SEL_TRANS_UNIT |
1472254885Sdumbbell				     RADEON_FP2_DVO_EN |
1473254885Sdumbbell				     R200_FP2_DVO_RATE_SEL_SDR));
1474254885Sdumbbell
1475254885Sdumbbell	WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
1476254885Sdumbbell					 RADEON_DISP_TRANS_MATRIX_GRAPHICS));
1477254885Sdumbbell
1478254885Sdumbbell	WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
1479254885Sdumbbell				       RADEON_CRTC2_DISP_REQ_EN_B));
1480254885Sdumbbell
1481254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
1482254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
1483254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
1484254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
1485254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
1486254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
1487254885Sdumbbell
1488254885Sdumbbell	WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
1489254885Sdumbbell	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
1490254885Sdumbbell	WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
1491254885Sdumbbell	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
1492254885Sdumbbell
1493254885Sdumbbell	for (i = 0; i < 200; i++) {
1494254885Sdumbbell		tmp = RREG32(RADEON_GPIO_MONID);
1495254885Sdumbbell		if (tmp & RADEON_GPIO_Y_0)
1496254885Sdumbbell			found = true;
1497254885Sdumbbell
1498254885Sdumbbell		if (found)
1499254885Sdumbbell			break;
1500254885Sdumbbell
1501254885Sdumbbell		if (!drm_can_sleep())
1502280183Sdumbbell			mdelay(1);
1503254885Sdumbbell		else
1504254885Sdumbbell			DRM_MSLEEP(1);
1505254885Sdumbbell	}
1506254885Sdumbbell
1507254885Sdumbbell	/* restore the regs we used */
1508254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
1509254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
1510254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
1511254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
1512254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
1513254885Sdumbbell	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
1514254885Sdumbbell	WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
1515254885Sdumbbell	WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
1516254885Sdumbbell	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
1517254885Sdumbbell	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
1518254885Sdumbbell	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1519254885Sdumbbell	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1520254885Sdumbbell	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1521254885Sdumbbell	WREG32(RADEON_GPIO_MONID, gpio_monid);
1522254885Sdumbbell
1523254885Sdumbbell	return found;
1524254885Sdumbbell}
1525254885Sdumbbell
1526254885Sdumbbellstatic enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
1527254885Sdumbbell							     struct drm_connector *connector)
1528254885Sdumbbell{
1529254885Sdumbbell	struct drm_device *dev = encoder->dev;
1530254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1531254885Sdumbbell	uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
1532254885Sdumbbell	uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
1533254885Sdumbbell	uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
1534254885Sdumbbell	enum drm_connector_status found = connector_status_disconnected;
1535254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1536254885Sdumbbell	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
1537254885Sdumbbell	bool color = true;
1538254885Sdumbbell	struct drm_crtc *crtc;
1539254885Sdumbbell
1540254885Sdumbbell	/* find out if crtc2 is in use or if this encoder is using it */
1541254885Sdumbbell	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1542254885Sdumbbell		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1543254885Sdumbbell		if ((radeon_crtc->crtc_id == 1) && crtc->enabled) {
1544254885Sdumbbell			if (encoder->crtc != crtc) {
1545254885Sdumbbell				return connector_status_disconnected;
1546254885Sdumbbell			}
1547254885Sdumbbell		}
1548254885Sdumbbell	}
1549254885Sdumbbell
1550254885Sdumbbell	if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
1551254885Sdumbbell	    connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
1552254885Sdumbbell	    connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) {
1553254885Sdumbbell		bool tv_detect;
1554254885Sdumbbell
1555254885Sdumbbell		if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT))
1556254885Sdumbbell			return connector_status_disconnected;
1557254885Sdumbbell
1558254885Sdumbbell		tv_detect = radeon_legacy_tv_detect(encoder, connector);
1559254885Sdumbbell		if (tv_detect && tv_dac)
1560254885Sdumbbell			found = connector_status_connected;
1561254885Sdumbbell		return found;
1562254885Sdumbbell	}
1563254885Sdumbbell
1564254885Sdumbbell	/* don't probe if the encoder is being used for something else not CRT related */
1565254885Sdumbbell	if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) {
1566254885Sdumbbell		DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device);
1567254885Sdumbbell		return connector_status_disconnected;
1568254885Sdumbbell	}
1569254885Sdumbbell
1570254885Sdumbbell	/* R200 uses an external DAC for secondary DAC */
1571254885Sdumbbell	if (rdev->family == CHIP_R200) {
1572254885Sdumbbell		if (radeon_legacy_ext_dac_detect(encoder, connector))
1573254885Sdumbbell			found = connector_status_connected;
1574254885Sdumbbell		return found;
1575254885Sdumbbell	}
1576254885Sdumbbell
1577254885Sdumbbell	/* save the regs we need */
1578254885Sdumbbell	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
1579254885Sdumbbell
1580254885Sdumbbell	if (rdev->flags & RADEON_SINGLE_CRTC) {
1581254885Sdumbbell		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
1582254885Sdumbbell	} else {
1583254885Sdumbbell		if (ASIC_IS_R300(rdev)) {
1584254885Sdumbbell			gpiopad_a = RREG32(RADEON_GPIOPAD_A);
1585254885Sdumbbell			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1586254885Sdumbbell		} else {
1587254885Sdumbbell			disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
1588254885Sdumbbell		}
1589254885Sdumbbell		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1590254885Sdumbbell	}
1591254885Sdumbbell	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1592254885Sdumbbell	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
1593254885Sdumbbell	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1594254885Sdumbbell
1595254885Sdumbbell	tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
1596254885Sdumbbell			       | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
1597254885Sdumbbell	WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
1598254885Sdumbbell
1599254885Sdumbbell	if (rdev->flags & RADEON_SINGLE_CRTC) {
1600254885Sdumbbell		tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
1601254885Sdumbbell		WREG32(RADEON_CRTC_EXT_CNTL, tmp);
1602254885Sdumbbell	} else {
1603254885Sdumbbell		tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
1604254885Sdumbbell		tmp |= RADEON_CRTC2_CRT2_ON |
1605254885Sdumbbell			(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
1606254885Sdumbbell		WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
1607254885Sdumbbell
1608254885Sdumbbell		if (ASIC_IS_R300(rdev)) {
1609254885Sdumbbell			WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
1610254885Sdumbbell			tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1611254885Sdumbbell			tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1612254885Sdumbbell			WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
1613254885Sdumbbell		} else {
1614254885Sdumbbell			tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
1615254885Sdumbbell			WREG32(RADEON_DISP_HW_DEBUG, tmp);
1616254885Sdumbbell		}
1617254885Sdumbbell	}
1618254885Sdumbbell
1619254885Sdumbbell	tmp = RADEON_TV_DAC_NBLANK |
1620254885Sdumbbell		RADEON_TV_DAC_NHOLD |
1621254885Sdumbbell		RADEON_TV_MONITOR_DETECT_EN |
1622254885Sdumbbell		RADEON_TV_DAC_STD_PS2;
1623254885Sdumbbell
1624254885Sdumbbell	WREG32(RADEON_TV_DAC_CNTL, tmp);
1625254885Sdumbbell
1626254885Sdumbbell	tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
1627254885Sdumbbell		RADEON_DAC2_FORCE_DATA_EN;
1628254885Sdumbbell
1629254885Sdumbbell	if (color)
1630254885Sdumbbell		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
1631254885Sdumbbell	else
1632254885Sdumbbell		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
1633254885Sdumbbell
1634254885Sdumbbell	if (ASIC_IS_R300(rdev))
1635254885Sdumbbell		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
1636254885Sdumbbell	else
1637254885Sdumbbell		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
1638254885Sdumbbell
1639254885Sdumbbell	WREG32(RADEON_DAC_EXT_CNTL, tmp);
1640254885Sdumbbell
1641254885Sdumbbell	tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
1642254885Sdumbbell	WREG32(RADEON_DAC_CNTL2, tmp);
1643254885Sdumbbell
1644280183Sdumbbell	mdelay(10);
1645254885Sdumbbell
1646254885Sdumbbell	if (ASIC_IS_R300(rdev)) {
1647254885Sdumbbell		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
1648254885Sdumbbell			found = connector_status_connected;
1649254885Sdumbbell	} else {
1650254885Sdumbbell		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT)
1651254885Sdumbbell			found = connector_status_connected;
1652254885Sdumbbell	}
1653254885Sdumbbell
1654254885Sdumbbell	/* restore regs we used */
1655254885Sdumbbell	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1656254885Sdumbbell	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1657254885Sdumbbell	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1658254885Sdumbbell
1659254885Sdumbbell	if (rdev->flags & RADEON_SINGLE_CRTC) {
1660254885Sdumbbell		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
1661254885Sdumbbell	} else {
1662254885Sdumbbell		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1663254885Sdumbbell		if (ASIC_IS_R300(rdev)) {
1664254885Sdumbbell			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1665254885Sdumbbell			WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1666254885Sdumbbell		} else {
1667254885Sdumbbell			WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
1668254885Sdumbbell		}
1669254885Sdumbbell	}
1670254885Sdumbbell
1671254885Sdumbbell	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
1672254885Sdumbbell
1673254885Sdumbbell	return found;
1674254885Sdumbbell
1675254885Sdumbbell}
1676254885Sdumbbell
1677254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
1678254885Sdumbbell	.dpms = radeon_legacy_tv_dac_dpms,
1679254885Sdumbbell	.mode_fixup = radeon_legacy_mode_fixup,
1680254885Sdumbbell	.prepare = radeon_legacy_tv_dac_prepare,
1681254885Sdumbbell	.mode_set = radeon_legacy_tv_dac_mode_set,
1682254885Sdumbbell	.commit = radeon_legacy_tv_dac_commit,
1683254885Sdumbbell	.detect = radeon_legacy_tv_dac_detect,
1684254885Sdumbbell	.disable = radeon_legacy_encoder_disable,
1685254885Sdumbbell};
1686254885Sdumbbell
1687254885Sdumbbell
1688254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = {
1689254885Sdumbbell	.destroy = radeon_enc_destroy,
1690254885Sdumbbell};
1691254885Sdumbbell
1692254885Sdumbbell
1693254885Sdumbbellstatic struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder)
1694254885Sdumbbell{
1695254885Sdumbbell	struct drm_device *dev = encoder->base.dev;
1696254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1697254885Sdumbbell	struct radeon_encoder_int_tmds *tmds = NULL;
1698254885Sdumbbell	bool ret;
1699254885Sdumbbell
1700254885Sdumbbell	tmds = malloc(sizeof(struct radeon_encoder_int_tmds),
1701280183Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1702254885Sdumbbell
1703254885Sdumbbell	if (!tmds)
1704254885Sdumbbell		return NULL;
1705254885Sdumbbell
1706254885Sdumbbell	if (rdev->is_atom_bios)
1707254885Sdumbbell		ret = radeon_atombios_get_tmds_info(encoder, tmds);
1708254885Sdumbbell	else
1709254885Sdumbbell		ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
1710254885Sdumbbell
1711254885Sdumbbell	if (ret == false)
1712254885Sdumbbell		radeon_legacy_get_tmds_info_from_table(encoder, tmds);
1713254885Sdumbbell
1714254885Sdumbbell	return tmds;
1715254885Sdumbbell}
1716254885Sdumbbell
1717254885Sdumbbellstatic struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
1718254885Sdumbbell{
1719254885Sdumbbell	struct drm_device *dev = encoder->base.dev;
1720254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1721254885Sdumbbell	struct radeon_encoder_ext_tmds *tmds = NULL;
1722254885Sdumbbell	bool ret;
1723254885Sdumbbell
1724254885Sdumbbell	if (rdev->is_atom_bios)
1725254885Sdumbbell		return NULL;
1726254885Sdumbbell
1727254885Sdumbbell	tmds = malloc(sizeof(struct radeon_encoder_ext_tmds),
1728280183Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1729254885Sdumbbell
1730254885Sdumbbell	if (!tmds)
1731254885Sdumbbell		return NULL;
1732254885Sdumbbell
1733254885Sdumbbell	ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
1734254885Sdumbbell
1735254885Sdumbbell	if (ret == false)
1736254885Sdumbbell		radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
1737254885Sdumbbell
1738254885Sdumbbell	return tmds;
1739254885Sdumbbell}
1740254885Sdumbbell
1741254885Sdumbbellvoid
1742254885Sdumbbellradeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device)
1743254885Sdumbbell{
1744254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1745254885Sdumbbell	struct drm_encoder *encoder;
1746254885Sdumbbell	struct radeon_encoder *radeon_encoder;
1747254885Sdumbbell
1748254885Sdumbbell	/* see if we already added it */
1749254885Sdumbbell	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1750254885Sdumbbell		radeon_encoder = to_radeon_encoder(encoder);
1751254885Sdumbbell		if (radeon_encoder->encoder_enum == encoder_enum) {
1752254885Sdumbbell			radeon_encoder->devices |= supported_device;
1753254885Sdumbbell			return;
1754254885Sdumbbell		}
1755254885Sdumbbell
1756254885Sdumbbell	}
1757254885Sdumbbell
1758254885Sdumbbell	/* add a new one */
1759254885Sdumbbell	radeon_encoder = malloc(sizeof(struct radeon_encoder),
1760280183Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1761254885Sdumbbell	if (!radeon_encoder)
1762254885Sdumbbell		return;
1763254885Sdumbbell
1764254885Sdumbbell	encoder = &radeon_encoder->base;
1765254885Sdumbbell	if (rdev->flags & RADEON_SINGLE_CRTC)
1766254885Sdumbbell		encoder->possible_crtcs = 0x1;
1767254885Sdumbbell	else
1768254885Sdumbbell		encoder->possible_crtcs = 0x3;
1769254885Sdumbbell
1770254885Sdumbbell	radeon_encoder->enc_priv = NULL;
1771254885Sdumbbell
1772254885Sdumbbell	radeon_encoder->encoder_enum = encoder_enum;
1773254885Sdumbbell	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1774254885Sdumbbell	radeon_encoder->devices = supported_device;
1775254885Sdumbbell	radeon_encoder->rmx_type = RMX_OFF;
1776254885Sdumbbell
1777254885Sdumbbell	switch (radeon_encoder->encoder_id) {
1778254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1779254885Sdumbbell		encoder->possible_crtcs = 0x1;
1780254885Sdumbbell		drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS);
1781254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
1782254885Sdumbbell		if (rdev->is_atom_bios)
1783254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
1784254885Sdumbbell		else
1785254885Sdumbbell			radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder);
1786254885Sdumbbell		radeon_encoder->rmx_type = RMX_FULL;
1787254885Sdumbbell		break;
1788254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1789254885Sdumbbell		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS);
1790254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
1791254885Sdumbbell		radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder);
1792254885Sdumbbell		break;
1793254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1794254885Sdumbbell		drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
1795254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs);
1796254885Sdumbbell		if (rdev->is_atom_bios)
1797254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder);
1798254885Sdumbbell		else
1799254885Sdumbbell			radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder);
1800254885Sdumbbell		break;
1801254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1802254885Sdumbbell		drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC);
1803254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs);
1804254885Sdumbbell		if (rdev->is_atom_bios)
1805254885Sdumbbell			radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder);
1806254885Sdumbbell		else
1807254885Sdumbbell			radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder);
1808254885Sdumbbell		break;
1809254885Sdumbbell	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1810254885Sdumbbell		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
1811254885Sdumbbell		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
1812254885Sdumbbell		if (!rdev->is_atom_bios)
1813254885Sdumbbell			radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
1814254885Sdumbbell		break;
1815254885Sdumbbell	}
1816254885Sdumbbell}
1817