1251881Speter/*
2251881Speter * Copyright 2007-8 Advanced Micro Devices, Inc.
3251881Speter * Copyright 2008 Red Hat Inc.
4251881Speter *
5251881Speter * Permission is hereby granted, free of charge, to any person obtaining a
6251881Speter * copy of this software and associated documentation files (the "Software"),
7251881Speter * to deal in the Software without restriction, including without limitation
8251881Speter * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9251881Speter * and/or sell copies of the Software, and to permit persons to whom the
10251881Speter * Software is furnished to do so, subject to the following conditions:
11251881Speter *
12251881Speter * The above copyright notice and this permission notice shall be included in
13251881Speter * all copies or substantial portions of the Software.
14251881Speter *
15251881Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16251881Speter * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17251881Speter * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18251881Speter * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19251881Speter * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20251881Speter * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21251881Speter * OTHER DEALINGS IN THE SOFTWARE.
22251881Speter *
23251881Speter * Authors: Dave Airlie
24251881Speter *          Alex Deucher
25251881Speter */
26251881Speter
27251881Speter#include <sys/cdefs.h>
28251881Speter__FBSDID("$FreeBSD$");
29251881Speter
30251881Speter#include <dev/drm2/drmP.h>
31251881Speter#include <dev/drm2/drm_crtc_helper.h>
32251881Speter#include <dev/drm2/radeon/radeon_drm.h>
33251881Speter#include "radeon.h"
34251881Speter#include "radeon_asic.h"
35251881Speter#include "atom.h"
36251881Speter
37251881Speterstatic void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
38251881Speter{
39251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
40251881Speter	struct drm_encoder_helper_funcs *encoder_funcs;
41251881Speter
42251881Speter	encoder_funcs = encoder->helper_private;
43251881Speter	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
44251881Speter	radeon_encoder->active_device = 0;
45251881Speter}
46251881Speter
47251881Speterstatic void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
48251881Speter{
49251881Speter	struct drm_device *dev = encoder->dev;
50251881Speter	struct radeon_device *rdev = dev->dev_private;
51251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
52251881Speter	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
53251881Speter	int panel_pwr_delay = 2000;
54251881Speter	bool is_mac = false;
55251881Speter	uint8_t backlight_level;
56251881Speter	DRM_DEBUG_KMS("\n");
57251881Speter
58251881Speter	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
59251881Speter	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
60251881Speter
61251881Speter	if (radeon_encoder->enc_priv) {
62251881Speter		if (rdev->is_atom_bios) {
63251881Speter			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
64251881Speter			panel_pwr_delay = lvds->panel_pwr_delay;
65251881Speter			if (lvds->bl_dev)
66251881Speter				backlight_level = lvds->backlight_level;
67251881Speter		} else {
68251881Speter			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
69251881Speter			panel_pwr_delay = lvds->panel_pwr_delay;
70251881Speter			if (lvds->bl_dev)
71251881Speter				backlight_level = lvds->backlight_level;
72251881Speter		}
73251881Speter	}
74251881Speter
75251881Speter	/* macs (and possibly some x86 oem systems?) wire up LVDS strangely
76251881Speter	 * Taken from radeonfb.
77251881Speter	 */
78251881Speter	if ((rdev->mode_info.connector_table == CT_IBOOK) ||
79251881Speter	    (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) ||
80251881Speter	    (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) ||
81251881Speter	    (rdev->mode_info.connector_table == CT_POWERBOOK_VGA))
82251881Speter		is_mac = true;
83251881Speter
84251881Speter	switch (mode) {
85251881Speter	case DRM_MODE_DPMS_ON:
86251881Speter		disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
87251881Speter		disp_pwr_man |= RADEON_AUTO_PWRUP_EN;
88251881Speter		WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man);
89251881Speter		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
90251881Speter		lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
91251881Speter		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
92251881Speter		mdelay(1);
93251881Speter
94251881Speter		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
95251881Speter		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
96251881Speter		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
97251881Speter
98251881Speter		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
99251881Speter				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
100251881Speter		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
101251881Speter				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
102251881Speter				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
103251881Speter		if (is_mac)
104251881Speter			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
105251881Speter		mdelay(panel_pwr_delay);
106251881Speter		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
107251881Speter		break;
108251881Speter	case DRM_MODE_DPMS_STANDBY:
109251881Speter	case DRM_MODE_DPMS_SUSPEND:
110251881Speter	case DRM_MODE_DPMS_OFF:
111251881Speter		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
112251881Speter		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
113251881Speter		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
114251881Speter		if (is_mac) {
115251881Speter			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
116251881Speter			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
117251881Speter			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN);
118251881Speter		} else {
119251881Speter			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
120251881Speter			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
121251881Speter		}
122251881Speter		mdelay(panel_pwr_delay);
123251881Speter		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
124251881Speter		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
125251881Speter		mdelay(panel_pwr_delay);
126251881Speter		break;
127251881Speter	}
128251881Speter
129251881Speter	if (rdev->is_atom_bios)
130251881Speter		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
131251881Speter	else
132251881Speter		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
133251881Speter
134251881Speter}
135251881Speter
136251881Speterstatic void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
137251881Speter{
138251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
139251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
140251881Speter	DRM_DEBUG("\n");
141251881Speter
142251881Speter	if (radeon_encoder->enc_priv) {
143251881Speter		if (rdev->is_atom_bios) {
144251881Speter			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
145251881Speter			lvds->dpms_mode = mode;
146251881Speter		} else {
147251881Speter			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
148251881Speter			lvds->dpms_mode = mode;
149251881Speter		}
150251881Speter	}
151251881Speter
152251881Speter	radeon_legacy_lvds_update(encoder, mode);
153251881Speter}
154251881Speter
155251881Speterstatic void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
156251881Speter{
157251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
158251881Speter
159251881Speter	if (rdev->is_atom_bios)
160251881Speter		radeon_atom_output_lock(encoder, true);
161251881Speter	else
162251881Speter		radeon_combios_output_lock(encoder, true);
163251881Speter	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
164251881Speter}
165251881Speter
166251881Speterstatic void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
167251881Speter{
168251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
169251881Speter
170251881Speter	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON);
171251881Speter	if (rdev->is_atom_bios)
172251881Speter		radeon_atom_output_lock(encoder, false);
173251881Speter	else
174251881Speter		radeon_combios_output_lock(encoder, false);
175251881Speter}
176251881Speter
177251881Speterstatic void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
178251881Speter					struct drm_display_mode *mode,
179251881Speter					struct drm_display_mode *adjusted_mode)
180251881Speter{
181251881Speter	struct drm_device *dev = encoder->dev;
182251881Speter	struct radeon_device *rdev = dev->dev_private;
183251881Speter	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
184251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
185251881Speter	uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl;
186251881Speter
187251881Speter	DRM_DEBUG_KMS("\n");
188251881Speter
189251881Speter	lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
190251881Speter	lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
191251881Speter
192251881Speter	lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
193251881Speter	if (rdev->is_atom_bios) {
194251881Speter		/* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
195251881Speter		 * need to call that on resume to set up the reg properly.
196251881Speter		 */
197251881Speter		radeon_encoder->pixel_clock = adjusted_mode->clock;
198251881Speter		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
199251881Speter		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
200251881Speter	} else {
201251881Speter		struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
202251881Speter		if (lvds) {
203251881Speter			DRM_DEBUG_KMS("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
204251881Speter			lvds_gen_cntl = lvds->lvds_gen_cntl;
205251881Speter			lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
206251881Speter					      (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
207251881Speter			lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
208251881Speter					     (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
209251881Speter		} else
210251881Speter			lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
211251881Speter	}
212251881Speter	lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
213251881Speter	lvds_gen_cntl &= ~(RADEON_LVDS_ON |
214251881Speter			   RADEON_LVDS_BLON |
215251881Speter			   RADEON_LVDS_EN |
216251881Speter			   RADEON_LVDS_RST_FM);
217251881Speter
218251881Speter	if (ASIC_IS_R300(rdev))
219251881Speter		lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
220251881Speter
221251881Speter	if (radeon_crtc->crtc_id == 0) {
222251881Speter		if (ASIC_IS_R300(rdev)) {
223251881Speter			if (radeon_encoder->rmx_type != RMX_OFF)
224251881Speter				lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
225251881Speter		} else
226251881Speter			lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
227251881Speter	} else {
228251881Speter		if (ASIC_IS_R300(rdev))
229251881Speter			lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
230251881Speter		else
231251881Speter			lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
232251881Speter	}
233251881Speter
234251881Speter	WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
235251881Speter	WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
236251881Speter	WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl);
237251881Speter
238251881Speter	if (rdev->family == CHIP_RV410)
239251881Speter		WREG32(RADEON_CLOCK_CNTL_INDEX, 0);
240251881Speter
241251881Speter	if (rdev->is_atom_bios)
242251881Speter		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
243251881Speter	else
244251881Speter		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
245251881Speter}
246251881Speter
247251881Speterstatic bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
248251881Speter				     const struct drm_display_mode *mode,
249251881Speter				     struct drm_display_mode *adjusted_mode)
250251881Speter{
251251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
252251881Speter
253251881Speter	/* set the active encoder to connector routing */
254251881Speter	radeon_encoder_set_active_device(encoder);
255251881Speter	drm_mode_set_crtcinfo(adjusted_mode, 0);
256251881Speter
257251881Speter	/* get the native mode for LVDS */
258251881Speter	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
259251881Speter		radeon_panel_mode_fixup(encoder, adjusted_mode);
260251881Speter
261251881Speter	return true;
262251881Speter}
263251881Speter
264251881Speterstatic const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
265251881Speter	.dpms = radeon_legacy_lvds_dpms,
266251881Speter	.mode_fixup = radeon_legacy_mode_fixup,
267251881Speter	.prepare = radeon_legacy_lvds_prepare,
268251881Speter	.mode_set = radeon_legacy_lvds_mode_set,
269251881Speter	.commit = radeon_legacy_lvds_commit,
270251881Speter	.disable = radeon_legacy_encoder_disable,
271251881Speter};
272251881Speter
273251881Speteru8
274251881Speterradeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder)
275251881Speter{
276251881Speter	struct drm_device *dev = radeon_encoder->base.dev;
277251881Speter	struct radeon_device *rdev = dev->dev_private;
278251881Speter	u8 backlight_level;
279251881Speter
280251881Speter	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
281251881Speter			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
282251881Speter
283251881Speter	return backlight_level;
284251881Speter}
285251881Speter
286251881Spetervoid
287251881Speterradeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
288251881Speter{
289251881Speter	struct drm_device *dev = radeon_encoder->base.dev;
290251881Speter	struct radeon_device *rdev = dev->dev_private;
291251881Speter	int dpms_mode = DRM_MODE_DPMS_ON;
292251881Speter
293251881Speter	if (radeon_encoder->enc_priv) {
294251881Speter		if (rdev->is_atom_bios) {
295251881Speter			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
296251881Speter			if (lvds->backlight_level > 0)
297251881Speter				dpms_mode = lvds->dpms_mode;
298251881Speter			else
299251881Speter				dpms_mode = DRM_MODE_DPMS_OFF;
300251881Speter			lvds->backlight_level = level;
301251881Speter		} else {
302251881Speter			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
303251881Speter			if (lvds->backlight_level > 0)
304251881Speter				dpms_mode = lvds->dpms_mode;
305251881Speter			else
306251881Speter				dpms_mode = DRM_MODE_DPMS_OFF;
307251881Speter			lvds->backlight_level = level;
308251881Speter		}
309251881Speter	}
310251881Speter
311251881Speter	radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
312251881Speter}
313251881Speter
314251881Speter#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
315251881Speter
316251881Speterstatic uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
317251881Speter{
318251881Speter	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
319251881Speter	uint8_t level;
320251881Speter
321251881Speter	/* Convert brightness to hardware level */
322251881Speter	if (bd->props.brightness < 0)
323251881Speter		level = 0;
324251881Speter	else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
325251881Speter		level = RADEON_MAX_BL_LEVEL;
326251881Speter	else
327251881Speter		level = bd->props.brightness;
328251881Speter
329251881Speter	if (pdata->negative)
330251881Speter		level = RADEON_MAX_BL_LEVEL - level;
331251881Speter
332251881Speter	return level;
333251881Speter}
334251881Speter
335251881Speterstatic int radeon_legacy_backlight_update_status(struct backlight_device *bd)
336251881Speter{
337251881Speter	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
338251881Speter	struct radeon_encoder *radeon_encoder = pdata->encoder;
339251881Speter
340251881Speter	radeon_legacy_set_backlight_level(radeon_encoder,
341251881Speter					  radeon_legacy_lvds_level(bd));
342251881Speter
343251881Speter	return 0;
344251881Speter}
345251881Speter
346251881Speterstatic int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
347251881Speter{
348251881Speter	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
349251881Speter	struct radeon_encoder *radeon_encoder = pdata->encoder;
350251881Speter	struct drm_device *dev = radeon_encoder->base.dev;
351251881Speter	struct radeon_device *rdev = dev->dev_private;
352251881Speter	uint8_t backlight_level;
353251881Speter
354251881Speter	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
355251881Speter			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
356251881Speter
357251881Speter	return pdata->negative ? RADEON_MAX_BL_LEVEL - backlight_level : backlight_level;
358251881Speter}
359251881Speter
360251881Speterstatic const struct backlight_ops radeon_backlight_ops = {
361251881Speter	.get_brightness = radeon_legacy_backlight_get_brightness,
362251881Speter	.update_status	= radeon_legacy_backlight_update_status,
363251881Speter};
364251881Speter
365251881Spetervoid radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
366251881Speter				  struct drm_connector *drm_connector)
367251881Speter{
368251881Speter	struct drm_device *dev = radeon_encoder->base.dev;
369251881Speter	struct radeon_device *rdev = dev->dev_private;
370251881Speter	struct backlight_device *bd;
371251881Speter	struct backlight_properties props;
372251881Speter	struct radeon_backlight_privdata *pdata;
373251881Speter	uint8_t backlight_level;
374251881Speter	char bl_name[16];
375251881Speter
376251881Speter	if (!radeon_encoder->enc_priv)
377251881Speter		return;
378251881Speter
379251881Speter#ifdef CONFIG_PMAC_BACKLIGHT
380251881Speter	if (!pmac_has_backlight_type("ati") &&
381251881Speter	    !pmac_has_backlight_type("mnca"))
382251881Speter		return;
383251881Speter#endif
384251881Speter
385251881Speter	pdata = malloc(sizeof(struct radeon_backlight_privdata),
386251881Speter	    DRM_MEM_DRIVER, M_NOWAIT);
387251881Speter	if (!pdata) {
388251881Speter		DRM_ERROR("Memory allocation failed\n");
389251881Speter		goto error;
390251881Speter	}
391251881Speter
392251881Speter	memset(&props, 0, sizeof(props));
393251881Speter	props.max_brightness = RADEON_MAX_BL_LEVEL;
394251881Speter	props.type = BACKLIGHT_RAW;
395251881Speter	snprintf(bl_name, sizeof(bl_name),
396251881Speter		 "radeon_bl%d", dev->primary->index);
397251881Speter	bd = backlight_device_register(bl_name, &drm_connector->kdev,
398251881Speter				       pdata, &radeon_backlight_ops, &props);
399251881Speter	if (IS_ERR(bd)) {
400251881Speter		DRM_ERROR("Backlight registration failed\n");
401251881Speter		goto error;
402251881Speter	}
403251881Speter
404251881Speter	pdata->encoder = radeon_encoder;
405251881Speter
406251881Speter	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
407251881Speter			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
408251881Speter
409251881Speter	/* First, try to detect backlight level sense based on the assumption
410251881Speter	 * that firmware set it up at full brightness
411251881Speter	 */
412251881Speter	if (backlight_level == 0)
413251881Speter		pdata->negative = true;
414251881Speter	else if (backlight_level == 0xff)
415251881Speter		pdata->negative = false;
416251881Speter	else {
417251881Speter		/* XXX hack... maybe some day we can figure out in what direction
418251881Speter		 * backlight should work on a given panel?
419251881Speter		 */
420251881Speter		pdata->negative = (rdev->family != CHIP_RV200 &&
421251881Speter				   rdev->family != CHIP_RV250 &&
422251881Speter				   rdev->family != CHIP_RV280 &&
423251881Speter				   rdev->family != CHIP_RV350);
424251881Speter
425251881Speter#ifdef CONFIG_PMAC_BACKLIGHT
426251881Speter		pdata->negative = (pdata->negative ||
427251881Speter				   of_machine_is_compatible("PowerBook4,3") ||
428251881Speter				   of_machine_is_compatible("PowerBook6,3") ||
429251881Speter				   of_machine_is_compatible("PowerBook6,5"));
430251881Speter#endif
431251881Speter	}
432251881Speter
433251881Speter	if (rdev->is_atom_bios) {
434251881Speter		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
435251881Speter		lvds->bl_dev = bd;
436251881Speter	} else {
437251881Speter		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
438251881Speter		lvds->bl_dev = bd;
439251881Speter	}
440251881Speter
441251881Speter	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
442251881Speter	bd->props.power = FB_BLANK_UNBLANK;
443251881Speter	backlight_update_status(bd);
444251881Speter
445251881Speter	DRM_INFO("radeon legacy LVDS backlight initialized\n");
446251881Speter
447251881Speter	return;
448251881Speter
449251881Spetererror:
450251881Speter	free(pdata, DRM_MEM_DRIVER);
451251881Speter	return;
452251881Speter}
453251881Speter
454251881Speterstatic void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
455251881Speter{
456251881Speter	struct drm_device *dev = radeon_encoder->base.dev;
457251881Speter	struct radeon_device *rdev = dev->dev_private;
458251881Speter	struct backlight_device *bd = NULL;
459251881Speter
460251881Speter	if (!radeon_encoder->enc_priv)
461251881Speter		return;
462251881Speter
463251881Speter	if (rdev->is_atom_bios) {
464251881Speter		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
465251881Speter		bd = lvds->bl_dev;
466251881Speter		lvds->bl_dev = NULL;
467251881Speter	} else {
468251881Speter		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
469251881Speter		bd = lvds->bl_dev;
470251881Speter		lvds->bl_dev = NULL;
471251881Speter	}
472251881Speter
473251881Speter	if (bd) {
474251881Speter		struct radeon_backlight_privdata *pdata;
475251881Speter
476251881Speter		pdata = bl_get_data(bd);
477251881Speter		backlight_device_unregister(bd);
478251881Speter		free(pdata, DRM_MEM_DRIVER);
479251881Speter
480251881Speter		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
481251881Speter	}
482251881Speter}
483251881Speter
484251881Speter#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
485251881Speter
486251881Spetervoid radeon_legacy_backlight_init(struct radeon_encoder *encoder,
487251881Speter				  struct drm_connector *drm_connector)
488251881Speter{
489251881Speter}
490251881Speter
491251881Speterstatic void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
492251881Speter{
493251881Speter}
494251881Speter
495251881Speter#endif
496251881Speter
497251881Speter
498251881Speterstatic void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
499251881Speter{
500251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
501251881Speter
502251881Speter	if (radeon_encoder->enc_priv) {
503251881Speter		radeon_legacy_backlight_exit(radeon_encoder);
504251881Speter		free(radeon_encoder->enc_priv, DRM_MEM_DRIVER);
505251881Speter	}
506251881Speter	drm_encoder_cleanup(encoder);
507251881Speter	free(radeon_encoder, DRM_MEM_DRIVER);
508251881Speter}
509251881Speter
510251881Speterstatic const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
511251881Speter	.destroy = radeon_lvds_enc_destroy,
512251881Speter};
513251881Speter
514251881Speterstatic void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
515251881Speter{
516251881Speter	struct drm_device *dev = encoder->dev;
517251881Speter	struct radeon_device *rdev = dev->dev_private;
518251881Speter	uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
519251881Speter	uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL);
520251881Speter	uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
521251881Speter
522251881Speter	DRM_DEBUG_KMS("\n");
523251881Speter
524251881Speter	switch (mode) {
525251881Speter	case DRM_MODE_DPMS_ON:
526251881Speter		crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
527251881Speter		dac_cntl &= ~RADEON_DAC_PDWN;
528251881Speter		dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
529251881Speter				    RADEON_DAC_PDWN_G |
530251881Speter				    RADEON_DAC_PDWN_B);
531251881Speter		break;
532251881Speter	case DRM_MODE_DPMS_STANDBY:
533251881Speter	case DRM_MODE_DPMS_SUSPEND:
534251881Speter	case DRM_MODE_DPMS_OFF:
535251881Speter		crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
536251881Speter		dac_cntl |= RADEON_DAC_PDWN;
537251881Speter		dac_macro_cntl |= (RADEON_DAC_PDWN_R |
538251881Speter				   RADEON_DAC_PDWN_G |
539251881Speter				   RADEON_DAC_PDWN_B);
540251881Speter		break;
541251881Speter	}
542251881Speter
543251881Speter	/* handled in radeon_crtc_dpms() */
544251881Speter	if (!(rdev->flags & RADEON_SINGLE_CRTC))
545251881Speter		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
546251881Speter	WREG32(RADEON_DAC_CNTL, dac_cntl);
547251881Speter	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
548251881Speter
549251881Speter	if (rdev->is_atom_bios)
550251881Speter		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
551251881Speter	else
552251881Speter		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
553251881Speter
554251881Speter}
555251881Speter
556251881Speterstatic void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
557251881Speter{
558251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
559251881Speter
560251881Speter	if (rdev->is_atom_bios)
561251881Speter		radeon_atom_output_lock(encoder, true);
562251881Speter	else
563251881Speter		radeon_combios_output_lock(encoder, true);
564251881Speter	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
565251881Speter}
566251881Speter
567251881Speterstatic void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
568251881Speter{
569251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
570251881Speter
571251881Speter	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON);
572251881Speter
573251881Speter	if (rdev->is_atom_bios)
574251881Speter		radeon_atom_output_lock(encoder, false);
575251881Speter	else
576251881Speter		radeon_combios_output_lock(encoder, false);
577251881Speter}
578251881Speter
579251881Speterstatic void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
580251881Speter					       struct drm_display_mode *mode,
581251881Speter					       struct drm_display_mode *adjusted_mode)
582251881Speter{
583251881Speter	struct drm_device *dev = encoder->dev;
584251881Speter	struct radeon_device *rdev = dev->dev_private;
585251881Speter	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
586251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
587251881Speter	uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl;
588251881Speter
589251881Speter	DRM_DEBUG_KMS("\n");
590251881Speter
591251881Speter	if (radeon_crtc->crtc_id == 0) {
592251881Speter		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
593251881Speter			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
594251881Speter				~(RADEON_DISP_DAC_SOURCE_MASK);
595251881Speter			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
596251881Speter		} else {
597251881Speter			dac2_cntl = RREG32(RADEON_DAC_CNTL2)  & ~(RADEON_DAC2_DAC_CLK_SEL);
598251881Speter			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
599251881Speter		}
600251881Speter	} else {
601251881Speter		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
602251881Speter			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
603251881Speter				~(RADEON_DISP_DAC_SOURCE_MASK);
604251881Speter			disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
605251881Speter			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
606251881Speter		} else {
607251881Speter			dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL;
608251881Speter			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
609251881Speter		}
610251881Speter	}
611251881Speter
612251881Speter	dac_cntl = (RADEON_DAC_MASK_ALL |
613251881Speter		    RADEON_DAC_VGA_ADR_EN |
614251881Speter		    /* TODO 6-bits */
615251881Speter		    RADEON_DAC_8BIT_EN);
616251881Speter
617251881Speter	WREG32_P(RADEON_DAC_CNTL,
618251881Speter		       dac_cntl,
619251881Speter		       RADEON_DAC_RANGE_CNTL |
620251881Speter		       RADEON_DAC_BLANKING);
621251881Speter
622251881Speter	if (radeon_encoder->enc_priv) {
623251881Speter		struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv;
624251881Speter		dac_macro_cntl = p_dac->ps2_pdac_adj;
625251881Speter	} else
626251881Speter		dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
627251881Speter	dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B;
628251881Speter	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
629251881Speter
630251881Speter	if (rdev->is_atom_bios)
631251881Speter		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
632251881Speter	else
633251881Speter		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
634251881Speter}
635251881Speter
636251881Speterstatic enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder,
637251881Speter								  struct drm_connector *connector)
638251881Speter{
639251881Speter	struct drm_device *dev = encoder->dev;
640251881Speter	struct radeon_device *rdev = dev->dev_private;
641251881Speter	uint32_t vclk_ecp_cntl, crtc_ext_cntl;
642251881Speter	uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
643251881Speter	enum drm_connector_status found = connector_status_disconnected;
644251881Speter	bool color = true;
645251881Speter
646251881Speter	/* just don't bother on RN50 those chip are often connected to remoting
647251881Speter	 * console hw and often we get failure to load detect those. So to make
648251881Speter	 * everyone happy report the encoder as always connected.
649251881Speter	 */
650251881Speter	if (ASIC_IS_RN50(rdev)) {
651251881Speter		return connector_status_connected;
652251881Speter	}
653251881Speter
654251881Speter	/* save the regs we need */
655251881Speter	vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
656251881Speter	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
657251881Speter	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
658251881Speter	dac_cntl = RREG32(RADEON_DAC_CNTL);
659251881Speter	dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
660251881Speter
661251881Speter	tmp = vclk_ecp_cntl &
662251881Speter		~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
663251881Speter	WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
664251881Speter
665251881Speter	tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
666251881Speter	WREG32(RADEON_CRTC_EXT_CNTL, tmp);
667251881Speter
668251881Speter	tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
669251881Speter		RADEON_DAC_FORCE_DATA_EN;
670251881Speter
671251881Speter	if (color)
672251881Speter		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
673251881Speter	else
674251881Speter		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
675251881Speter
676251881Speter	if (ASIC_IS_R300(rdev))
677251881Speter		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
678251881Speter	else if (ASIC_IS_RV100(rdev))
679251881Speter		tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
680251881Speter	else
681251881Speter		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
682251881Speter
683251881Speter	WREG32(RADEON_DAC_EXT_CNTL, tmp);
684251881Speter
685251881Speter	tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
686251881Speter	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
687251881Speter	WREG32(RADEON_DAC_CNTL, tmp);
688251881Speter
689251881Speter	tmp = dac_macro_cntl;
690251881Speter	tmp &= ~(RADEON_DAC_PDWN_R |
691251881Speter		 RADEON_DAC_PDWN_G |
692251881Speter		 RADEON_DAC_PDWN_B);
693251881Speter
694251881Speter	WREG32(RADEON_DAC_MACRO_CNTL, tmp);
695251881Speter
696251881Speter	mdelay(2);
697251881Speter
698251881Speter	if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
699251881Speter		found = connector_status_connected;
700251881Speter
701251881Speter	/* restore the regs we used */
702251881Speter	WREG32(RADEON_DAC_CNTL, dac_cntl);
703251881Speter	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
704251881Speter	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
705251881Speter	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
706251881Speter	WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
707251881Speter
708251881Speter	return found;
709251881Speter}
710251881Speter
711251881Speterstatic const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
712251881Speter	.dpms = radeon_legacy_primary_dac_dpms,
713251881Speter	.mode_fixup = radeon_legacy_mode_fixup,
714251881Speter	.prepare = radeon_legacy_primary_dac_prepare,
715251881Speter	.mode_set = radeon_legacy_primary_dac_mode_set,
716251881Speter	.commit = radeon_legacy_primary_dac_commit,
717251881Speter	.detect = radeon_legacy_primary_dac_detect,
718251881Speter	.disable = radeon_legacy_encoder_disable,
719251881Speter};
720251881Speter
721251881Speter
722251881Speterstatic const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = {
723251881Speter	.destroy = radeon_enc_destroy,
724251881Speter};
725251881Speter
726251881Speterstatic void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
727251881Speter{
728251881Speter	struct drm_device *dev = encoder->dev;
729251881Speter	struct radeon_device *rdev = dev->dev_private;
730251881Speter	uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL);
731251881Speter	DRM_DEBUG_KMS("\n");
732251881Speter
733251881Speter	switch (mode) {
734251881Speter	case DRM_MODE_DPMS_ON:
735251881Speter		fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
736251881Speter		break;
737251881Speter	case DRM_MODE_DPMS_STANDBY:
738251881Speter	case DRM_MODE_DPMS_SUSPEND:
739251881Speter	case DRM_MODE_DPMS_OFF:
740251881Speter		fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
741251881Speter		break;
742251881Speter	}
743251881Speter
744251881Speter	WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
745251881Speter
746251881Speter	if (rdev->is_atom_bios)
747251881Speter		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
748251881Speter	else
749251881Speter		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
750251881Speter
751251881Speter}
752251881Speter
753251881Speterstatic void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
754251881Speter{
755251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
756251881Speter
757251881Speter	if (rdev->is_atom_bios)
758251881Speter		radeon_atom_output_lock(encoder, true);
759251881Speter	else
760251881Speter		radeon_combios_output_lock(encoder, true);
761251881Speter	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
762251881Speter}
763251881Speter
764251881Speterstatic void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
765251881Speter{
766251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
767251881Speter
768251881Speter	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON);
769251881Speter
770251881Speter	if (rdev->is_atom_bios)
771251881Speter		radeon_atom_output_lock(encoder, true);
772251881Speter	else
773251881Speter		radeon_combios_output_lock(encoder, true);
774251881Speter}
775251881Speter
776251881Speterstatic void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
777251881Speter					    struct drm_display_mode *mode,
778251881Speter					    struct drm_display_mode *adjusted_mode)
779251881Speter{
780251881Speter	struct drm_device *dev = encoder->dev;
781251881Speter	struct radeon_device *rdev = dev->dev_private;
782251881Speter	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
783251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
784251881Speter	uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl;
785251881Speter	int i;
786251881Speter
787251881Speter	DRM_DEBUG_KMS("\n");
788251881Speter
789251881Speter	tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
790251881Speter	tmp &= 0xfffff;
791251881Speter	if (rdev->family == CHIP_RV280) {
792251881Speter		/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
793251881Speter		tmp ^= (1 << 22);
794251881Speter		tmds_pll_cntl ^= (1 << 22);
795251881Speter	}
796251881Speter
797251881Speter	if (radeon_encoder->enc_priv) {
798251881Speter		struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv;
799251881Speter
800251881Speter		for (i = 0; i < 4; i++) {
801251881Speter			if (tmds->tmds_pll[i].freq == 0)
802251881Speter				break;
803251881Speter			if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) {
804251881Speter				tmp = tmds->tmds_pll[i].value ;
805251881Speter				break;
806251881Speter			}
807251881Speter		}
808251881Speter	}
809251881Speter
810251881Speter	if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) {
811251881Speter		if (tmp & 0xfff00000)
812251881Speter			tmds_pll_cntl = tmp;
813251881Speter		else {
814251881Speter			tmds_pll_cntl &= 0xfff00000;
815251881Speter			tmds_pll_cntl |= tmp;
816251881Speter		}
817251881Speter	} else
818251881Speter		tmds_pll_cntl = tmp;
819251881Speter
820251881Speter	tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) &
821251881Speter		~(RADEON_TMDS_TRANSMITTER_PLLRST);
822251881Speter
823251881Speter    if (rdev->family == CHIP_R200 ||
824251881Speter	rdev->family == CHIP_R100 ||
825251881Speter	ASIC_IS_R300(rdev))
826251881Speter	    tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
827251881Speter    else /* RV chips got this bit reversed */
828251881Speter	    tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN;
829251881Speter
830251881Speter    fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) |
831251881Speter		   (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
832251881Speter		    RADEON_FP_CRTC_DONT_SHADOW_HEND));
833251881Speter
834251881Speter    fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
835251881Speter
836251881Speter    fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
837251881Speter		     RADEON_FP_DFP_SYNC_SEL |
838251881Speter		     RADEON_FP_CRT_SYNC_SEL |
839251881Speter		     RADEON_FP_CRTC_LOCK_8DOT |
840251881Speter		     RADEON_FP_USE_SHADOW_EN |
841251881Speter		     RADEON_FP_CRTC_USE_SHADOW_VEND |
842251881Speter		     RADEON_FP_CRT_SYNC_ALT);
843251881Speter
844251881Speter    if (1) /*  FIXME rgbBits == 8 */
845251881Speter	    fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
846251881Speter    else
847251881Speter	    fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
848251881Speter
849251881Speter    if (radeon_crtc->crtc_id == 0) {
850251881Speter	    if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
851251881Speter		    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
852251881Speter		    if (radeon_encoder->rmx_type != RMX_OFF)
853251881Speter			    fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
854251881Speter		    else
855251881Speter			    fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
856251881Speter	    } else
857251881Speter		    fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
858251881Speter    } else {
859251881Speter	    if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
860251881Speter		    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
861251881Speter		    fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
862251881Speter	    } else
863251881Speter		    fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
864251881Speter    }
865251881Speter
866251881Speter    WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl);
867251881Speter    WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl);
868251881Speter    WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
869251881Speter
870251881Speter	if (rdev->is_atom_bios)
871251881Speter		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
872251881Speter	else
873251881Speter		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
874251881Speter}
875251881Speter
876251881Speterstatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
877251881Speter	.dpms = radeon_legacy_tmds_int_dpms,
878251881Speter	.mode_fixup = radeon_legacy_mode_fixup,
879251881Speter	.prepare = radeon_legacy_tmds_int_prepare,
880251881Speter	.mode_set = radeon_legacy_tmds_int_mode_set,
881251881Speter	.commit = radeon_legacy_tmds_int_commit,
882251881Speter	.disable = radeon_legacy_encoder_disable,
883251881Speter};
884251881Speter
885251881Speter
886251881Speterstatic const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = {
887251881Speter	.destroy = radeon_enc_destroy,
888251881Speter};
889251881Speter
890251881Speterstatic void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
891251881Speter{
892251881Speter	struct drm_device *dev = encoder->dev;
893251881Speter	struct radeon_device *rdev = dev->dev_private;
894251881Speter	uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
895251881Speter	DRM_DEBUG_KMS("\n");
896251881Speter
897251881Speter	switch (mode) {
898251881Speter	case DRM_MODE_DPMS_ON:
899251881Speter		fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
900251881Speter		fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
901251881Speter		break;
902251881Speter	case DRM_MODE_DPMS_STANDBY:
903251881Speter	case DRM_MODE_DPMS_SUSPEND:
904251881Speter	case DRM_MODE_DPMS_OFF:
905251881Speter		fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
906251881Speter		fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
907251881Speter		break;
908251881Speter	}
909251881Speter
910251881Speter	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
911251881Speter
912251881Speter	if (rdev->is_atom_bios)
913251881Speter		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
914251881Speter	else
915251881Speter		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
916251881Speter
917251881Speter}
918251881Speter
919251881Speterstatic void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
920251881Speter{
921251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
922251881Speter
923251881Speter	if (rdev->is_atom_bios)
924251881Speter		radeon_atom_output_lock(encoder, true);
925251881Speter	else
926251881Speter		radeon_combios_output_lock(encoder, true);
927251881Speter	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
928251881Speter}
929251881Speter
930251881Speterstatic void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
931251881Speter{
932251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
933251881Speter	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON);
934251881Speter
935251881Speter	if (rdev->is_atom_bios)
936251881Speter		radeon_atom_output_lock(encoder, false);
937251881Speter	else
938251881Speter		radeon_combios_output_lock(encoder, false);
939251881Speter}
940251881Speter
941251881Speterstatic void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
942251881Speter					    struct drm_display_mode *mode,
943251881Speter					    struct drm_display_mode *adjusted_mode)
944251881Speter{
945251881Speter	struct drm_device *dev = encoder->dev;
946251881Speter	struct radeon_device *rdev = dev->dev_private;
947251881Speter	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
948251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
949251881Speter	uint32_t fp2_gen_cntl;
950251881Speter
951251881Speter	DRM_DEBUG_KMS("\n");
952251881Speter
953251881Speter	if (rdev->is_atom_bios) {
954251881Speter		radeon_encoder->pixel_clock = adjusted_mode->clock;
955251881Speter		atombios_dvo_setup(encoder, ATOM_ENABLE);
956251881Speter		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
957251881Speter	} else {
958251881Speter		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
959251881Speter
960251881Speter		if (1) /*  FIXME rgbBits == 8 */
961251881Speter			fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
962251881Speter		else
963251881Speter			fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
964251881Speter
965251881Speter		fp2_gen_cntl &= ~(RADEON_FP2_ON |
966251881Speter				  RADEON_FP2_DVO_EN |
967251881Speter				  RADEON_FP2_DVO_RATE_SEL_SDR);
968251881Speter
969251881Speter		/* XXX: these are oem specific */
970251881Speter		if (ASIC_IS_R300(rdev)) {
971251881Speter			if ((dev->pci_device == 0x4850) &&
972251881Speter			    (dev->pci_subvendor == 0x1028) &&
973251881Speter			    (dev->pci_subdevice == 0x2001)) /* Dell Inspiron 8600 */
974251881Speter				fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE;
975251881Speter			else
976251881Speter				fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
977251881Speter
978251881Speter			/*if (mode->clock > 165000)
979251881Speter			  fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
980251881Speter		}
981251881Speter		if (!radeon_combios_external_tmds_setup(encoder))
982251881Speter			radeon_external_tmds_setup(encoder);
983251881Speter	}
984251881Speter
985251881Speter	if (radeon_crtc->crtc_id == 0) {
986251881Speter		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
987251881Speter			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
988251881Speter			if (radeon_encoder->rmx_type != RMX_OFF)
989251881Speter				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
990251881Speter			else
991251881Speter				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
992251881Speter		} else
993251881Speter			fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
994251881Speter	} else {
995251881Speter		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
996251881Speter			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
997251881Speter			fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
998251881Speter		} else
999251881Speter			fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
1000251881Speter	}
1001251881Speter
1002251881Speter	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1003251881Speter
1004251881Speter	if (rdev->is_atom_bios)
1005251881Speter		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1006251881Speter	else
1007251881Speter		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1008251881Speter}
1009251881Speter
1010251881Speterstatic void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
1011251881Speter{
1012251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1013251881Speter	/* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */
1014251881Speter	free(radeon_encoder->enc_priv, DRM_MEM_DRIVER);
1015251881Speter	drm_encoder_cleanup(encoder);
1016251881Speter	free(radeon_encoder, DRM_MEM_DRIVER);
1017251881Speter}
1018251881Speter
1019251881Speterstatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
1020251881Speter	.dpms = radeon_legacy_tmds_ext_dpms,
1021251881Speter	.mode_fixup = radeon_legacy_mode_fixup,
1022251881Speter	.prepare = radeon_legacy_tmds_ext_prepare,
1023251881Speter	.mode_set = radeon_legacy_tmds_ext_mode_set,
1024251881Speter	.commit = radeon_legacy_tmds_ext_commit,
1025251881Speter	.disable = radeon_legacy_encoder_disable,
1026251881Speter};
1027251881Speter
1028251881Speter
1029251881Speterstatic const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
1030251881Speter	.destroy = radeon_ext_tmds_enc_destroy,
1031251881Speter};
1032251881Speter
1033251881Speterstatic void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
1034251881Speter{
1035251881Speter	struct drm_device *dev = encoder->dev;
1036251881Speter	struct radeon_device *rdev = dev->dev_private;
1037251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1038251881Speter	uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
1039251881Speter	uint32_t tv_master_cntl = 0;
1040251881Speter	bool is_tv;
1041251881Speter	DRM_DEBUG_KMS("\n");
1042251881Speter
1043251881Speter	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
1044251881Speter
1045251881Speter	if (rdev->family == CHIP_R200)
1046251881Speter		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
1047251881Speter	else {
1048251881Speter		if (is_tv)
1049251881Speter			tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
1050251881Speter		else
1051251881Speter			crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1052251881Speter		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1053251881Speter	}
1054251881Speter
1055251881Speter	switch (mode) {
1056251881Speter	case DRM_MODE_DPMS_ON:
1057251881Speter		if (rdev->family == CHIP_R200) {
1058251881Speter			fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1059251881Speter		} else {
1060251881Speter			if (is_tv)
1061251881Speter				tv_master_cntl |= RADEON_TV_ON;
1062251881Speter			else
1063251881Speter				crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
1064251881Speter
1065251881Speter			if (rdev->family == CHIP_R420 ||
1066251881Speter			    rdev->family == CHIP_R423 ||
1067251881Speter			    rdev->family == CHIP_RV410)
1068251881Speter				tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
1069251881Speter						 R420_TV_DAC_GDACPD |
1070251881Speter						 R420_TV_DAC_BDACPD |
1071251881Speter						 RADEON_TV_DAC_BGSLEEP);
1072251881Speter			else
1073251881Speter				tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
1074251881Speter						 RADEON_TV_DAC_GDACPD |
1075251881Speter						 RADEON_TV_DAC_BDACPD |
1076251881Speter						 RADEON_TV_DAC_BGSLEEP);
1077251881Speter		}
1078251881Speter		break;
1079251881Speter	case DRM_MODE_DPMS_STANDBY:
1080251881Speter	case DRM_MODE_DPMS_SUSPEND:
1081251881Speter	case DRM_MODE_DPMS_OFF:
1082251881Speter		if (rdev->family == CHIP_R200)
1083251881Speter			fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1084251881Speter		else {
1085251881Speter			if (is_tv)
1086251881Speter				tv_master_cntl &= ~RADEON_TV_ON;
1087251881Speter			else
1088251881Speter				crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
1089251881Speter
1090251881Speter			if (rdev->family == CHIP_R420 ||
1091251881Speter			    rdev->family == CHIP_R423 ||
1092251881Speter			    rdev->family == CHIP_RV410)
1093251881Speter				tv_dac_cntl |= (R420_TV_DAC_RDACPD |
1094251881Speter						R420_TV_DAC_GDACPD |
1095251881Speter						R420_TV_DAC_BDACPD |
1096251881Speter						RADEON_TV_DAC_BGSLEEP);
1097251881Speter			else
1098251881Speter				tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
1099251881Speter						RADEON_TV_DAC_GDACPD |
1100251881Speter						RADEON_TV_DAC_BDACPD |
1101251881Speter						RADEON_TV_DAC_BGSLEEP);
1102251881Speter		}
1103251881Speter		break;
1104251881Speter	}
1105251881Speter
1106251881Speter	if (rdev->family == CHIP_R200) {
1107251881Speter		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1108251881Speter	} else {
1109251881Speter		if (is_tv)
1110251881Speter			WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
1111251881Speter		/* handled in radeon_crtc_dpms() */
1112251881Speter		else if (!(rdev->flags & RADEON_SINGLE_CRTC))
1113251881Speter			WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1114251881Speter		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1115251881Speter	}
1116251881Speter
1117251881Speter	if (rdev->is_atom_bios)
1118251881Speter		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1119251881Speter	else
1120251881Speter		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
1121251881Speter
1122251881Speter}
1123251881Speter
1124251881Speterstatic void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
1125251881Speter{
1126251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
1127251881Speter
1128251881Speter	if (rdev->is_atom_bios)
1129251881Speter		radeon_atom_output_lock(encoder, true);
1130251881Speter	else
1131251881Speter		radeon_combios_output_lock(encoder, true);
1132251881Speter	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
1133251881Speter}
1134251881Speter
1135251881Speterstatic void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
1136251881Speter{
1137251881Speter	struct radeon_device *rdev = encoder->dev->dev_private;
1138251881Speter
1139251881Speter	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON);
1140251881Speter
1141251881Speter	if (rdev->is_atom_bios)
1142251881Speter		radeon_atom_output_lock(encoder, true);
1143251881Speter	else
1144251881Speter		radeon_combios_output_lock(encoder, true);
1145251881Speter}
1146251881Speter
1147251881Speterstatic void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
1148251881Speter		struct drm_display_mode *mode,
1149251881Speter		struct drm_display_mode *adjusted_mode)
1150251881Speter{
1151251881Speter	struct drm_device *dev = encoder->dev;
1152251881Speter	struct radeon_device *rdev = dev->dev_private;
1153251881Speter	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1154251881Speter	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1155251881Speter	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
1156251881Speter	uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
1157251881Speter	uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0;
1158251881Speter	bool is_tv = false;
1159251881Speter
1160251881Speter	DRM_DEBUG_KMS("\n");
1161251881Speter
1162251881Speter	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
1163251881Speter
1164251881Speter	if (rdev->family != CHIP_R200) {
1165251881Speter		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1166251881Speter		if (rdev->family == CHIP_R420 ||
1167251881Speter		    rdev->family == CHIP_R423 ||
1168251881Speter		    rdev->family == CHIP_RV410) {
1169251881Speter			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
1170251881Speter					 RADEON_TV_DAC_BGADJ_MASK |
1171251881Speter					 R420_TV_DAC_DACADJ_MASK |
1172251881Speter					 R420_TV_DAC_RDACPD |
1173251881Speter					 R420_TV_DAC_GDACPD |
1174251881Speter					 R420_TV_DAC_BDACPD |
1175251881Speter					 R420_TV_DAC_TVENABLE);
1176251881Speter		} else {
1177251881Speter			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
1178251881Speter					 RADEON_TV_DAC_BGADJ_MASK |
1179251881Speter					 RADEON_TV_DAC_DACADJ_MASK |
1180251881Speter					 RADEON_TV_DAC_RDACPD |
1181251881Speter					 RADEON_TV_DAC_GDACPD |
1182251881Speter					 RADEON_TV_DAC_BDACPD);
1183251881Speter		}
1184251881Speter
1185251881Speter		tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
1186251881Speter
1187251881Speter		if (is_tv) {
1188251881Speter			if (tv_dac->tv_std == TV_STD_NTSC ||
1189251881Speter			    tv_dac->tv_std == TV_STD_NTSC_J ||
1190251881Speter			    tv_dac->tv_std == TV_STD_PAL_M ||
1191251881Speter			    tv_dac->tv_std == TV_STD_PAL_60)
1192251881Speter				tv_dac_cntl |= tv_dac->ntsc_tvdac_adj;
1193251881Speter			else
1194251881Speter				tv_dac_cntl |= tv_dac->pal_tvdac_adj;
1195251881Speter
1196251881Speter			if (tv_dac->tv_std == TV_STD_NTSC ||
1197251881Speter			    tv_dac->tv_std == TV_STD_NTSC_J)
1198251881Speter				tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
1199251881Speter			else
1200251881Speter				tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
1201251881Speter		} else
1202251881Speter			tv_dac_cntl |= (RADEON_TV_DAC_STD_PS2 |
1203251881Speter					tv_dac->ps2_tvdac_adj);
1204251881Speter
1205251881Speter		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1206251881Speter	}
1207251881Speter
1208251881Speter	if (ASIC_IS_R300(rdev)) {
1209251881Speter		gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
1210251881Speter		disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1211251881Speter	} else if (rdev->family != CHIP_R200)
1212251881Speter		disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
1213251881Speter	else if (rdev->family == CHIP_R200)
1214251881Speter		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
1215251881Speter
1216251881Speter	if (rdev->family >= CHIP_R200)
1217251881Speter		disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
1218251881Speter
1219251881Speter	if (is_tv) {
1220251881Speter		uint32_t dac_cntl;
1221251881Speter
1222251881Speter		dac_cntl = RREG32(RADEON_DAC_CNTL);
1223251881Speter		dac_cntl &= ~RADEON_DAC_TVO_EN;
1224251881Speter		WREG32(RADEON_DAC_CNTL, dac_cntl);
1225251881Speter
1226251881Speter		if (ASIC_IS_R300(rdev))
1227251881Speter			gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1;
1228251881Speter
1229251881Speter		dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL;
1230251881Speter		if (radeon_crtc->crtc_id == 0) {
1231251881Speter			if (ASIC_IS_R300(rdev)) {
1232251881Speter				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1233251881Speter				disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC |
1234251881Speter						     RADEON_DISP_TV_SOURCE_CRTC);
1235251881Speter			}
1236251881Speter			if (rdev->family >= CHIP_R200) {
1237251881Speter				disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
1238251881Speter			} else {
1239251881Speter				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
1240251881Speter			}
1241251881Speter		} else {
1242251881Speter			if (ASIC_IS_R300(rdev)) {
1243251881Speter				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1244251881Speter				disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
1245251881Speter			}
1246251881Speter			if (rdev->family >= CHIP_R200) {
1247251881Speter				disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
1248251881Speter			} else {
1249251881Speter				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
1250251881Speter			}
1251251881Speter		}
1252251881Speter		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
1253251881Speter	} else {
1254251881Speter
1255251881Speter		dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
1256251881Speter
1257251881Speter		if (radeon_crtc->crtc_id == 0) {
1258251881Speter			if (ASIC_IS_R300(rdev)) {
1259251881Speter				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1260251881Speter				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
1261251881Speter			} else if (rdev->family == CHIP_R200) {
1262251881Speter				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
1263251881Speter						  RADEON_FP2_DVO_RATE_SEL_SDR);
1264251881Speter			} else
1265251881Speter				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
1266251881Speter		} else {
1267251881Speter			if (ASIC_IS_R300(rdev)) {
1268251881Speter				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
1269251881Speter				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1270251881Speter			} else if (rdev->family == CHIP_R200) {
1271251881Speter				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
1272251881Speter						  RADEON_FP2_DVO_RATE_SEL_SDR);
1273251881Speter				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
1274251881Speter			} else
1275251881Speter				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
1276251881Speter		}
1277251881Speter		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
1278251881Speter	}
1279251881Speter
1280251881Speter	if (ASIC_IS_R300(rdev)) {
1281251881Speter		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1282251881Speter		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1283251881Speter	} else if (rdev->family != CHIP_R200)
1284251881Speter		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
1285251881Speter	else if (rdev->family == CHIP_R200)
1286251881Speter		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1287251881Speter
1288251881Speter	if (rdev->family >= CHIP_R200)
1289251881Speter		WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
1290251881Speter
1291251881Speter	if (is_tv)
1292251881Speter		radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
1293251881Speter
1294251881Speter	if (rdev->is_atom_bios)
1295251881Speter		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1296251881Speter	else
1297251881Speter		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1298251881Speter
1299251881Speter}
1300251881Speter
1301251881Speterstatic bool r300_legacy_tv_detect(struct drm_encoder *encoder,
1302251881Speter				  struct drm_connector *connector)
1303251881Speter{
1304251881Speter	struct drm_device *dev = encoder->dev;
1305251881Speter	struct radeon_device *rdev = dev->dev_private;
1306251881Speter	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
1307251881Speter	uint32_t disp_output_cntl, gpiopad_a, tmp;
1308251881Speter	bool found = false;
1309251881Speter
1310251881Speter	/* save regs needed */
1311251881Speter	gpiopad_a = RREG32(RADEON_GPIOPAD_A);
1312251881Speter	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1313251881Speter	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1314251881Speter	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
1315251881Speter	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1316251881Speter	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1317251881Speter
1318251881Speter	WREG32_P(RADEON_GPIOPAD_A, 0, ~1);
1319251881Speter
1320251881Speter	WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL);
1321251881Speter
1322251881Speter	WREG32(RADEON_CRTC2_GEN_CNTL,
1323251881Speter	       RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
1324251881Speter
1325251881Speter	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1326251881Speter	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1327251881Speter	WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
1328251881Speter
1329251881Speter	WREG32(RADEON_DAC_EXT_CNTL,
1330251881Speter	       RADEON_DAC2_FORCE_BLANK_OFF_EN |
1331251881Speter	       RADEON_DAC2_FORCE_DATA_EN |
1332251881Speter	       RADEON_DAC_FORCE_DATA_SEL_RGB |
1333251881Speter	       (0xec << RADEON_DAC_FORCE_DATA_SHIFT));
1334251881Speter
1335251881Speter	WREG32(RADEON_TV_DAC_CNTL,
1336251881Speter	       RADEON_TV_DAC_STD_NTSC |
1337251881Speter	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1338251881Speter	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
1339251881Speter
1340251881Speter	RREG32(RADEON_TV_DAC_CNTL);
1341251881Speter	mdelay(4);
1342
1343	WREG32(RADEON_TV_DAC_CNTL,
1344	       RADEON_TV_DAC_NBLANK |
1345	       RADEON_TV_DAC_NHOLD |
1346	       RADEON_TV_MONITOR_DETECT_EN |
1347	       RADEON_TV_DAC_STD_NTSC |
1348	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1349	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
1350
1351	RREG32(RADEON_TV_DAC_CNTL);
1352	mdelay(6);
1353
1354	tmp = RREG32(RADEON_TV_DAC_CNTL);
1355	if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
1356		found = true;
1357		DRM_DEBUG_KMS("S-video TV connection detected\n");
1358	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
1359		found = true;
1360		DRM_DEBUG_KMS("Composite TV connection detected\n");
1361	}
1362
1363	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1364	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1365	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1366	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1367	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1368	WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1369	return found;
1370}
1371
1372static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
1373				    struct drm_connector *connector)
1374{
1375	struct drm_device *dev = encoder->dev;
1376	struct radeon_device *rdev = dev->dev_private;
1377	uint32_t tv_dac_cntl, dac_cntl2;
1378	uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp;
1379	bool found = false;
1380
1381	if (ASIC_IS_R300(rdev))
1382		return r300_legacy_tv_detect(encoder, connector);
1383
1384	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1385	tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
1386	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1387	config_cntl = RREG32(RADEON_CONFIG_CNTL);
1388	tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL);
1389
1390	tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
1391	WREG32(RADEON_DAC_CNTL2, tmp);
1392
1393	tmp = tv_master_cntl | RADEON_TV_ON;
1394	tmp &= ~(RADEON_TV_ASYNC_RST |
1395		 RADEON_RESTART_PHASE_FIX |
1396		 RADEON_CRT_FIFO_CE_EN |
1397		 RADEON_TV_FIFO_CE_EN |
1398		 RADEON_RE_SYNC_NOW_SEL_MASK);
1399	tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
1400	WREG32(RADEON_TV_MASTER_CNTL, tmp);
1401
1402	tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
1403		RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
1404		(8 << RADEON_TV_DAC_BGADJ_SHIFT);
1405
1406	if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
1407		tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
1408	else
1409		tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
1410	WREG32(RADEON_TV_DAC_CNTL, tmp);
1411
1412	tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
1413		RADEON_RED_MX_FORCE_DAC_DATA |
1414		RADEON_GRN_MX_FORCE_DAC_DATA |
1415		RADEON_BLU_MX_FORCE_DAC_DATA |
1416		(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
1417	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
1418
1419	mdelay(3);
1420	tmp = RREG32(RADEON_TV_DAC_CNTL);
1421	if (tmp & RADEON_TV_DAC_GDACDET) {
1422		found = true;
1423		DRM_DEBUG_KMS("S-video TV connection detected\n");
1424	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
1425		found = true;
1426		DRM_DEBUG_KMS("Composite TV connection detected\n");
1427	}
1428
1429	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
1430	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1431	WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
1432	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1433	return found;
1434}
1435
1436static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
1437					 struct drm_connector *connector)
1438{
1439	struct drm_device *dev = encoder->dev;
1440	struct radeon_device *rdev = dev->dev_private;
1441	uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
1442	uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
1443	uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
1444	uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
1445	uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
1446	bool found = false;
1447	int i;
1448
1449	/* save the regs we need */
1450	gpio_monid = RREG32(RADEON_GPIO_MONID);
1451	fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
1452	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1453	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1454	disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
1455	disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
1456	disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
1457	disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
1458	disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
1459	disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
1460	crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
1461	crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
1462	crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
1463	crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
1464
1465	tmp = RREG32(RADEON_GPIO_MONID);
1466	tmp &= ~RADEON_GPIO_A_0;
1467	WREG32(RADEON_GPIO_MONID, tmp);
1468
1469	WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
1470				     RADEON_FP2_PANEL_FORMAT |
1471				     R200_FP2_SOURCE_SEL_TRANS_UNIT |
1472				     RADEON_FP2_DVO_EN |
1473				     R200_FP2_DVO_RATE_SEL_SDR));
1474
1475	WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
1476					 RADEON_DISP_TRANS_MATRIX_GRAPHICS));
1477
1478	WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
1479				       RADEON_CRTC2_DISP_REQ_EN_B));
1480
1481	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
1482	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
1483	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
1484	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
1485	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
1486	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
1487
1488	WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
1489	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
1490	WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
1491	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
1492
1493	for (i = 0; i < 200; i++) {
1494		tmp = RREG32(RADEON_GPIO_MONID);
1495		if (tmp & RADEON_GPIO_Y_0)
1496			found = true;
1497
1498		if (found)
1499			break;
1500
1501		if (!drm_can_sleep())
1502			mdelay(1);
1503		else
1504			DRM_MSLEEP(1);
1505	}
1506
1507	/* restore the regs we used */
1508	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
1509	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
1510	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
1511	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
1512	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
1513	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
1514	WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
1515	WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
1516	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
1517	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
1518	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1519	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1520	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1521	WREG32(RADEON_GPIO_MONID, gpio_monid);
1522
1523	return found;
1524}
1525
1526static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
1527							     struct drm_connector *connector)
1528{
1529	struct drm_device *dev = encoder->dev;
1530	struct radeon_device *rdev = dev->dev_private;
1531	uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
1532	uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
1533	uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
1534	enum drm_connector_status found = connector_status_disconnected;
1535	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1536	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
1537	bool color = true;
1538	struct drm_crtc *crtc;
1539
1540	/* find out if crtc2 is in use or if this encoder is using it */
1541	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1542		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1543		if ((radeon_crtc->crtc_id == 1) && crtc->enabled) {
1544			if (encoder->crtc != crtc) {
1545				return connector_status_disconnected;
1546			}
1547		}
1548	}
1549
1550	if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
1551	    connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
1552	    connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) {
1553		bool tv_detect;
1554
1555		if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT))
1556			return connector_status_disconnected;
1557
1558		tv_detect = radeon_legacy_tv_detect(encoder, connector);
1559		if (tv_detect && tv_dac)
1560			found = connector_status_connected;
1561		return found;
1562	}
1563
1564	/* don't probe if the encoder is being used for something else not CRT related */
1565	if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) {
1566		DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device);
1567		return connector_status_disconnected;
1568	}
1569
1570	/* R200 uses an external DAC for secondary DAC */
1571	if (rdev->family == CHIP_R200) {
1572		if (radeon_legacy_ext_dac_detect(encoder, connector))
1573			found = connector_status_connected;
1574		return found;
1575	}
1576
1577	/* save the regs we need */
1578	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
1579
1580	if (rdev->flags & RADEON_SINGLE_CRTC) {
1581		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
1582	} else {
1583		if (ASIC_IS_R300(rdev)) {
1584			gpiopad_a = RREG32(RADEON_GPIOPAD_A);
1585			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1586		} else {
1587			disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
1588		}
1589		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1590	}
1591	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1592	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
1593	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1594
1595	tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
1596			       | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
1597	WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
1598
1599	if (rdev->flags & RADEON_SINGLE_CRTC) {
1600		tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
1601		WREG32(RADEON_CRTC_EXT_CNTL, tmp);
1602	} else {
1603		tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
1604		tmp |= RADEON_CRTC2_CRT2_ON |
1605			(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
1606		WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
1607
1608		if (ASIC_IS_R300(rdev)) {
1609			WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
1610			tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1611			tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1612			WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
1613		} else {
1614			tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
1615			WREG32(RADEON_DISP_HW_DEBUG, tmp);
1616		}
1617	}
1618
1619	tmp = RADEON_TV_DAC_NBLANK |
1620		RADEON_TV_DAC_NHOLD |
1621		RADEON_TV_MONITOR_DETECT_EN |
1622		RADEON_TV_DAC_STD_PS2;
1623
1624	WREG32(RADEON_TV_DAC_CNTL, tmp);
1625
1626	tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
1627		RADEON_DAC2_FORCE_DATA_EN;
1628
1629	if (color)
1630		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
1631	else
1632		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
1633
1634	if (ASIC_IS_R300(rdev))
1635		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
1636	else
1637		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
1638
1639	WREG32(RADEON_DAC_EXT_CNTL, tmp);
1640
1641	tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
1642	WREG32(RADEON_DAC_CNTL2, tmp);
1643
1644	mdelay(10);
1645
1646	if (ASIC_IS_R300(rdev)) {
1647		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
1648			found = connector_status_connected;
1649	} else {
1650		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT)
1651			found = connector_status_connected;
1652	}
1653
1654	/* restore regs we used */
1655	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1656	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1657	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1658
1659	if (rdev->flags & RADEON_SINGLE_CRTC) {
1660		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
1661	} else {
1662		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1663		if (ASIC_IS_R300(rdev)) {
1664			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1665			WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1666		} else {
1667			WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
1668		}
1669	}
1670
1671	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
1672
1673	return found;
1674
1675}
1676
1677static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
1678	.dpms = radeon_legacy_tv_dac_dpms,
1679	.mode_fixup = radeon_legacy_mode_fixup,
1680	.prepare = radeon_legacy_tv_dac_prepare,
1681	.mode_set = radeon_legacy_tv_dac_mode_set,
1682	.commit = radeon_legacy_tv_dac_commit,
1683	.detect = radeon_legacy_tv_dac_detect,
1684	.disable = radeon_legacy_encoder_disable,
1685};
1686
1687
1688static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = {
1689	.destroy = radeon_enc_destroy,
1690};
1691
1692
1693static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder)
1694{
1695	struct drm_device *dev = encoder->base.dev;
1696	struct radeon_device *rdev = dev->dev_private;
1697	struct radeon_encoder_int_tmds *tmds = NULL;
1698	bool ret;
1699
1700	tmds = malloc(sizeof(struct radeon_encoder_int_tmds),
1701	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1702
1703	if (!tmds)
1704		return NULL;
1705
1706	if (rdev->is_atom_bios)
1707		ret = radeon_atombios_get_tmds_info(encoder, tmds);
1708	else
1709		ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
1710
1711	if (ret == false)
1712		radeon_legacy_get_tmds_info_from_table(encoder, tmds);
1713
1714	return tmds;
1715}
1716
1717static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
1718{
1719	struct drm_device *dev = encoder->base.dev;
1720	struct radeon_device *rdev = dev->dev_private;
1721	struct radeon_encoder_ext_tmds *tmds = NULL;
1722	bool ret;
1723
1724	if (rdev->is_atom_bios)
1725		return NULL;
1726
1727	tmds = malloc(sizeof(struct radeon_encoder_ext_tmds),
1728	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1729
1730	if (!tmds)
1731		return NULL;
1732
1733	ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
1734
1735	if (ret == false)
1736		radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
1737
1738	return tmds;
1739}
1740
1741void
1742radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device)
1743{
1744	struct radeon_device *rdev = dev->dev_private;
1745	struct drm_encoder *encoder;
1746	struct radeon_encoder *radeon_encoder;
1747
1748	/* see if we already added it */
1749	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1750		radeon_encoder = to_radeon_encoder(encoder);
1751		if (radeon_encoder->encoder_enum == encoder_enum) {
1752			radeon_encoder->devices |= supported_device;
1753			return;
1754		}
1755
1756	}
1757
1758	/* add a new one */
1759	radeon_encoder = malloc(sizeof(struct radeon_encoder),
1760	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1761	if (!radeon_encoder)
1762		return;
1763
1764	encoder = &radeon_encoder->base;
1765	if (rdev->flags & RADEON_SINGLE_CRTC)
1766		encoder->possible_crtcs = 0x1;
1767	else
1768		encoder->possible_crtcs = 0x3;
1769
1770	radeon_encoder->enc_priv = NULL;
1771
1772	radeon_encoder->encoder_enum = encoder_enum;
1773	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
1774	radeon_encoder->devices = supported_device;
1775	radeon_encoder->rmx_type = RMX_OFF;
1776
1777	switch (radeon_encoder->encoder_id) {
1778	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1779		encoder->possible_crtcs = 0x1;
1780		drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS);
1781		drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
1782		if (rdev->is_atom_bios)
1783			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
1784		else
1785			radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder);
1786		radeon_encoder->rmx_type = RMX_FULL;
1787		break;
1788	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1789		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS);
1790		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
1791		radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder);
1792		break;
1793	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1794		drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
1795		drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs);
1796		if (rdev->is_atom_bios)
1797			radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder);
1798		else
1799			radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder);
1800		break;
1801	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1802		drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC);
1803		drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs);
1804		if (rdev->is_atom_bios)
1805			radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder);
1806		else
1807			radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder);
1808		break;
1809	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1810		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
1811		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
1812		if (!rdev->is_atom_bios)
1813			radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
1814		break;
1815	}
1816}
1817