xref: /dragonfly/sys/dev/drm/radeon/radeon_combios.c (revision a85cb24f)
1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot  * Copyright 2004 ATI Technologies Inc., Markham, Ontario
3926deccbSFrançois Tigeot  * Copyright 2007-8 Advanced Micro Devices, Inc.
4926deccbSFrançois Tigeot  * Copyright 2008 Red Hat Inc.
5926deccbSFrançois Tigeot  *
6926deccbSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
7926deccbSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
8926deccbSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
9926deccbSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10926deccbSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
11926deccbSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
12926deccbSFrançois Tigeot  *
13926deccbSFrançois Tigeot  * The above copyright notice and this permission notice shall be included in
14926deccbSFrançois Tigeot  * all copies or substantial portions of the Software.
15926deccbSFrançois Tigeot  *
16926deccbSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17926deccbSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18926deccbSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19926deccbSFrançois Tigeot  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20926deccbSFrançois Tigeot  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21926deccbSFrançois Tigeot  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22926deccbSFrançois Tigeot  * OTHER DEALINGS IN THE SOFTWARE.
23926deccbSFrançois Tigeot  *
24926deccbSFrançois Tigeot  * Authors: Dave Airlie
25926deccbSFrançois Tigeot  *          Alex Deucher
26926deccbSFrançois Tigeot  */
27926deccbSFrançois Tigeot #include <drm/drmP.h>
2883b4b9b9SFrançois Tigeot #include <drm/radeon_drm.h>
29926deccbSFrançois Tigeot #include "radeon.h"
30926deccbSFrançois Tigeot #include "atom.h"
31926deccbSFrançois Tigeot 
32926deccbSFrançois Tigeot #ifdef CONFIG_PPC_PMAC
33926deccbSFrançois Tigeot /* not sure which of these are needed */
34926deccbSFrançois Tigeot #include <asm/machdep.h>
35926deccbSFrançois Tigeot #include <asm/pmac_feature.h>
36926deccbSFrançois Tigeot #include <asm/prom.h>
37926deccbSFrançois Tigeot #endif /* CONFIG_PPC_PMAC */
38926deccbSFrançois Tigeot 
39926deccbSFrançois Tigeot /* old legacy ATI BIOS routines */
40926deccbSFrançois Tigeot 
41926deccbSFrançois Tigeot /* COMBIOS table offsets */
42926deccbSFrançois Tigeot enum radeon_combios_table_offset {
43926deccbSFrançois Tigeot 	/* absolute offset tables */
44926deccbSFrançois Tigeot 	COMBIOS_ASIC_INIT_1_TABLE,
45926deccbSFrançois Tigeot 	COMBIOS_BIOS_SUPPORT_TABLE,
46926deccbSFrançois Tigeot 	COMBIOS_DAC_PROGRAMMING_TABLE,
47926deccbSFrançois Tigeot 	COMBIOS_MAX_COLOR_DEPTH_TABLE,
48926deccbSFrançois Tigeot 	COMBIOS_CRTC_INFO_TABLE,
49926deccbSFrançois Tigeot 	COMBIOS_PLL_INFO_TABLE,
50926deccbSFrançois Tigeot 	COMBIOS_TV_INFO_TABLE,
51926deccbSFrançois Tigeot 	COMBIOS_DFP_INFO_TABLE,
52926deccbSFrançois Tigeot 	COMBIOS_HW_CONFIG_INFO_TABLE,
53926deccbSFrançois Tigeot 	COMBIOS_MULTIMEDIA_INFO_TABLE,
54926deccbSFrançois Tigeot 	COMBIOS_TV_STD_PATCH_TABLE,
55926deccbSFrançois Tigeot 	COMBIOS_LCD_INFO_TABLE,
56926deccbSFrançois Tigeot 	COMBIOS_MOBILE_INFO_TABLE,
57926deccbSFrançois Tigeot 	COMBIOS_PLL_INIT_TABLE,
58926deccbSFrançois Tigeot 	COMBIOS_MEM_CONFIG_TABLE,
59926deccbSFrançois Tigeot 	COMBIOS_SAVE_MASK_TABLE,
60926deccbSFrançois Tigeot 	COMBIOS_HARDCODED_EDID_TABLE,
61926deccbSFrançois Tigeot 	COMBIOS_ASIC_INIT_2_TABLE,
62926deccbSFrançois Tigeot 	COMBIOS_CONNECTOR_INFO_TABLE,
63926deccbSFrançois Tigeot 	COMBIOS_DYN_CLK_1_TABLE,
64926deccbSFrançois Tigeot 	COMBIOS_RESERVED_MEM_TABLE,
65926deccbSFrançois Tigeot 	COMBIOS_EXT_TMDS_INFO_TABLE,
66926deccbSFrançois Tigeot 	COMBIOS_MEM_CLK_INFO_TABLE,
67926deccbSFrançois Tigeot 	COMBIOS_EXT_DAC_INFO_TABLE,
68926deccbSFrançois Tigeot 	COMBIOS_MISC_INFO_TABLE,
69926deccbSFrançois Tigeot 	COMBIOS_CRT_INFO_TABLE,
70926deccbSFrançois Tigeot 	COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE,
71926deccbSFrançois Tigeot 	COMBIOS_COMPONENT_VIDEO_INFO_TABLE,
72926deccbSFrançois Tigeot 	COMBIOS_FAN_SPEED_INFO_TABLE,
73926deccbSFrançois Tigeot 	COMBIOS_OVERDRIVE_INFO_TABLE,
74926deccbSFrançois Tigeot 	COMBIOS_OEM_INFO_TABLE,
75926deccbSFrançois Tigeot 	COMBIOS_DYN_CLK_2_TABLE,
76926deccbSFrançois Tigeot 	COMBIOS_POWER_CONNECTOR_INFO_TABLE,
77926deccbSFrançois Tigeot 	COMBIOS_I2C_INFO_TABLE,
78926deccbSFrançois Tigeot 	/* relative offset tables */
79926deccbSFrançois Tigeot 	COMBIOS_ASIC_INIT_3_TABLE,	/* offset from misc info */
80926deccbSFrançois Tigeot 	COMBIOS_ASIC_INIT_4_TABLE,	/* offset from misc info */
81926deccbSFrançois Tigeot 	COMBIOS_DETECTED_MEM_TABLE,	/* offset from misc info */
82926deccbSFrançois Tigeot 	COMBIOS_ASIC_INIT_5_TABLE,	/* offset from misc info */
83926deccbSFrançois Tigeot 	COMBIOS_RAM_RESET_TABLE,	/* offset from mem config */
84926deccbSFrançois Tigeot 	COMBIOS_POWERPLAY_INFO_TABLE,	/* offset from mobile info */
85926deccbSFrançois Tigeot 	COMBIOS_GPIO_INFO_TABLE,	/* offset from mobile info */
86926deccbSFrançois Tigeot 	COMBIOS_LCD_DDC_INFO_TABLE,	/* offset from mobile info */
87926deccbSFrançois Tigeot 	COMBIOS_TMDS_POWER_TABLE,	/* offset from mobile info */
88926deccbSFrançois Tigeot 	COMBIOS_TMDS_POWER_ON_TABLE,	/* offset from tmds power */
89926deccbSFrançois Tigeot 	COMBIOS_TMDS_POWER_OFF_TABLE,	/* offset from tmds power */
90926deccbSFrançois Tigeot };
91926deccbSFrançois Tigeot 
92926deccbSFrançois Tigeot enum radeon_combios_ddc {
93926deccbSFrançois Tigeot 	DDC_NONE_DETECTED,
94926deccbSFrançois Tigeot 	DDC_MONID,
95926deccbSFrançois Tigeot 	DDC_DVI,
96926deccbSFrançois Tigeot 	DDC_VGA,
97926deccbSFrançois Tigeot 	DDC_CRT2,
98926deccbSFrançois Tigeot 	DDC_LCD,
99926deccbSFrançois Tigeot 	DDC_GPIO,
100926deccbSFrançois Tigeot };
101926deccbSFrançois Tigeot 
102926deccbSFrançois Tigeot enum radeon_combios_connector {
103926deccbSFrançois Tigeot 	CONNECTOR_NONE_LEGACY,
104926deccbSFrançois Tigeot 	CONNECTOR_PROPRIETARY_LEGACY,
105926deccbSFrançois Tigeot 	CONNECTOR_CRT_LEGACY,
106926deccbSFrançois Tigeot 	CONNECTOR_DVI_I_LEGACY,
107926deccbSFrançois Tigeot 	CONNECTOR_DVI_D_LEGACY,
108926deccbSFrançois Tigeot 	CONNECTOR_CTV_LEGACY,
109926deccbSFrançois Tigeot 	CONNECTOR_STV_LEGACY,
110926deccbSFrançois Tigeot 	CONNECTOR_UNSUPPORTED_LEGACY
111926deccbSFrançois Tigeot };
112926deccbSFrançois Tigeot 
113591d5043SFrançois Tigeot static const int legacy_connector_convert[] = {
114926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_Unknown,
115926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_DVID,
116926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_VGA,
117926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_DVII,
118926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_DVID,
119926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_Composite,
120926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_SVIDEO,
121926deccbSFrançois Tigeot 	DRM_MODE_CONNECTOR_Unknown,
122926deccbSFrançois Tigeot };
123926deccbSFrançois Tigeot 
combios_get_table_offset(struct drm_device * dev,enum radeon_combios_table_offset table)124926deccbSFrançois Tigeot static uint16_t combios_get_table_offset(struct drm_device *dev,
125926deccbSFrançois Tigeot 					 enum radeon_combios_table_offset table)
126926deccbSFrançois Tigeot {
127926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
12857e252bfSMichael Neumann 	int rev, size;
129926deccbSFrançois Tigeot 	uint16_t offset = 0, check_offset;
130926deccbSFrançois Tigeot 
131926deccbSFrançois Tigeot 	if (!rdev->bios)
132926deccbSFrançois Tigeot 		return 0;
133926deccbSFrançois Tigeot 
134926deccbSFrançois Tigeot 	switch (table) {
135926deccbSFrançois Tigeot 		/* absolute offset tables */
136926deccbSFrançois Tigeot 	case COMBIOS_ASIC_INIT_1_TABLE:
13757e252bfSMichael Neumann 		check_offset = 0xc;
138926deccbSFrançois Tigeot 		break;
139926deccbSFrançois Tigeot 	case COMBIOS_BIOS_SUPPORT_TABLE:
14057e252bfSMichael Neumann 		check_offset = 0x14;
141926deccbSFrançois Tigeot 		break;
142926deccbSFrançois Tigeot 	case COMBIOS_DAC_PROGRAMMING_TABLE:
14357e252bfSMichael Neumann 		check_offset = 0x2a;
144926deccbSFrançois Tigeot 		break;
145926deccbSFrançois Tigeot 	case COMBIOS_MAX_COLOR_DEPTH_TABLE:
14657e252bfSMichael Neumann 		check_offset = 0x2c;
147926deccbSFrançois Tigeot 		break;
148926deccbSFrançois Tigeot 	case COMBIOS_CRTC_INFO_TABLE:
14957e252bfSMichael Neumann 		check_offset = 0x2e;
150926deccbSFrançois Tigeot 		break;
151926deccbSFrançois Tigeot 	case COMBIOS_PLL_INFO_TABLE:
15257e252bfSMichael Neumann 		check_offset = 0x30;
153926deccbSFrançois Tigeot 		break;
154926deccbSFrançois Tigeot 	case COMBIOS_TV_INFO_TABLE:
15557e252bfSMichael Neumann 		check_offset = 0x32;
156926deccbSFrançois Tigeot 		break;
157926deccbSFrançois Tigeot 	case COMBIOS_DFP_INFO_TABLE:
15857e252bfSMichael Neumann 		check_offset = 0x34;
159926deccbSFrançois Tigeot 		break;
160926deccbSFrançois Tigeot 	case COMBIOS_HW_CONFIG_INFO_TABLE:
16157e252bfSMichael Neumann 		check_offset = 0x36;
162926deccbSFrançois Tigeot 		break;
163926deccbSFrançois Tigeot 	case COMBIOS_MULTIMEDIA_INFO_TABLE:
16457e252bfSMichael Neumann 		check_offset = 0x38;
165926deccbSFrançois Tigeot 		break;
166926deccbSFrançois Tigeot 	case COMBIOS_TV_STD_PATCH_TABLE:
16757e252bfSMichael Neumann 		check_offset = 0x3e;
168926deccbSFrançois Tigeot 		break;
169926deccbSFrançois Tigeot 	case COMBIOS_LCD_INFO_TABLE:
17057e252bfSMichael Neumann 		check_offset = 0x40;
171926deccbSFrançois Tigeot 		break;
172926deccbSFrançois Tigeot 	case COMBIOS_MOBILE_INFO_TABLE:
17357e252bfSMichael Neumann 		check_offset = 0x42;
174926deccbSFrançois Tigeot 		break;
175926deccbSFrançois Tigeot 	case COMBIOS_PLL_INIT_TABLE:
17657e252bfSMichael Neumann 		check_offset = 0x46;
177926deccbSFrançois Tigeot 		break;
178926deccbSFrançois Tigeot 	case COMBIOS_MEM_CONFIG_TABLE:
17957e252bfSMichael Neumann 		check_offset = 0x48;
180926deccbSFrançois Tigeot 		break;
181926deccbSFrançois Tigeot 	case COMBIOS_SAVE_MASK_TABLE:
18257e252bfSMichael Neumann 		check_offset = 0x4a;
183926deccbSFrançois Tigeot 		break;
184926deccbSFrançois Tigeot 	case COMBIOS_HARDCODED_EDID_TABLE:
18557e252bfSMichael Neumann 		check_offset = 0x4c;
186926deccbSFrançois Tigeot 		break;
187926deccbSFrançois Tigeot 	case COMBIOS_ASIC_INIT_2_TABLE:
18857e252bfSMichael Neumann 		check_offset = 0x4e;
189926deccbSFrançois Tigeot 		break;
190926deccbSFrançois Tigeot 	case COMBIOS_CONNECTOR_INFO_TABLE:
19157e252bfSMichael Neumann 		check_offset = 0x50;
192926deccbSFrançois Tigeot 		break;
193926deccbSFrançois Tigeot 	case COMBIOS_DYN_CLK_1_TABLE:
19457e252bfSMichael Neumann 		check_offset = 0x52;
195926deccbSFrançois Tigeot 		break;
196926deccbSFrançois Tigeot 	case COMBIOS_RESERVED_MEM_TABLE:
19757e252bfSMichael Neumann 		check_offset = 0x54;
198926deccbSFrançois Tigeot 		break;
199926deccbSFrançois Tigeot 	case COMBIOS_EXT_TMDS_INFO_TABLE:
20057e252bfSMichael Neumann 		check_offset = 0x58;
201926deccbSFrançois Tigeot 		break;
202926deccbSFrançois Tigeot 	case COMBIOS_MEM_CLK_INFO_TABLE:
20357e252bfSMichael Neumann 		check_offset = 0x5a;
204926deccbSFrançois Tigeot 		break;
205926deccbSFrançois Tigeot 	case COMBIOS_EXT_DAC_INFO_TABLE:
20657e252bfSMichael Neumann 		check_offset = 0x5c;
207926deccbSFrançois Tigeot 		break;
208926deccbSFrançois Tigeot 	case COMBIOS_MISC_INFO_TABLE:
20957e252bfSMichael Neumann 		check_offset = 0x5e;
210926deccbSFrançois Tigeot 		break;
211926deccbSFrançois Tigeot 	case COMBIOS_CRT_INFO_TABLE:
21257e252bfSMichael Neumann 		check_offset = 0x60;
213926deccbSFrançois Tigeot 		break;
214926deccbSFrançois Tigeot 	case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE:
21557e252bfSMichael Neumann 		check_offset = 0x62;
216926deccbSFrançois Tigeot 		break;
217926deccbSFrançois Tigeot 	case COMBIOS_COMPONENT_VIDEO_INFO_TABLE:
21857e252bfSMichael Neumann 		check_offset = 0x64;
219926deccbSFrançois Tigeot 		break;
220926deccbSFrançois Tigeot 	case COMBIOS_FAN_SPEED_INFO_TABLE:
22157e252bfSMichael Neumann 		check_offset = 0x66;
222926deccbSFrançois Tigeot 		break;
223926deccbSFrançois Tigeot 	case COMBIOS_OVERDRIVE_INFO_TABLE:
22457e252bfSMichael Neumann 		check_offset = 0x68;
225926deccbSFrançois Tigeot 		break;
226926deccbSFrançois Tigeot 	case COMBIOS_OEM_INFO_TABLE:
22757e252bfSMichael Neumann 		check_offset = 0x6a;
228926deccbSFrançois Tigeot 		break;
229926deccbSFrançois Tigeot 	case COMBIOS_DYN_CLK_2_TABLE:
23057e252bfSMichael Neumann 		check_offset = 0x6c;
231926deccbSFrançois Tigeot 		break;
232926deccbSFrançois Tigeot 	case COMBIOS_POWER_CONNECTOR_INFO_TABLE:
23357e252bfSMichael Neumann 		check_offset = 0x6e;
234926deccbSFrançois Tigeot 		break;
235926deccbSFrançois Tigeot 	case COMBIOS_I2C_INFO_TABLE:
23657e252bfSMichael Neumann 		check_offset = 0x70;
237926deccbSFrançois Tigeot 		break;
238926deccbSFrançois Tigeot 		/* relative offset tables */
239926deccbSFrançois Tigeot 	case COMBIOS_ASIC_INIT_3_TABLE:	/* offset from misc info */
240926deccbSFrançois Tigeot 		check_offset =
241926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
242926deccbSFrançois Tigeot 		if (check_offset) {
243926deccbSFrançois Tigeot 			rev = RBIOS8(check_offset);
244926deccbSFrançois Tigeot 			if (rev > 0) {
245926deccbSFrançois Tigeot 				check_offset = RBIOS16(check_offset + 0x3);
246926deccbSFrançois Tigeot 				if (check_offset)
247926deccbSFrançois Tigeot 					offset = check_offset;
248926deccbSFrançois Tigeot 			}
249926deccbSFrançois Tigeot 		}
250926deccbSFrançois Tigeot 		break;
251926deccbSFrançois Tigeot 	case COMBIOS_ASIC_INIT_4_TABLE:	/* offset from misc info */
252926deccbSFrançois Tigeot 		check_offset =
253926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
254926deccbSFrançois Tigeot 		if (check_offset) {
255926deccbSFrançois Tigeot 			rev = RBIOS8(check_offset);
256926deccbSFrançois Tigeot 			if (rev > 0) {
257926deccbSFrançois Tigeot 				check_offset = RBIOS16(check_offset + 0x5);
258926deccbSFrançois Tigeot 				if (check_offset)
259926deccbSFrançois Tigeot 					offset = check_offset;
260926deccbSFrançois Tigeot 			}
261926deccbSFrançois Tigeot 		}
262926deccbSFrançois Tigeot 		break;
263926deccbSFrançois Tigeot 	case COMBIOS_DETECTED_MEM_TABLE:	/* offset from misc info */
264926deccbSFrançois Tigeot 		check_offset =
265926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
266926deccbSFrançois Tigeot 		if (check_offset) {
267926deccbSFrançois Tigeot 			rev = RBIOS8(check_offset);
268926deccbSFrançois Tigeot 			if (rev > 0) {
269926deccbSFrançois Tigeot 				check_offset = RBIOS16(check_offset + 0x7);
270926deccbSFrançois Tigeot 				if (check_offset)
271926deccbSFrançois Tigeot 					offset = check_offset;
272926deccbSFrançois Tigeot 			}
273926deccbSFrançois Tigeot 		}
274926deccbSFrançois Tigeot 		break;
275926deccbSFrançois Tigeot 	case COMBIOS_ASIC_INIT_5_TABLE:	/* offset from misc info */
276926deccbSFrançois Tigeot 		check_offset =
277926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
278926deccbSFrançois Tigeot 		if (check_offset) {
279926deccbSFrançois Tigeot 			rev = RBIOS8(check_offset);
280926deccbSFrançois Tigeot 			if (rev == 2) {
281926deccbSFrançois Tigeot 				check_offset = RBIOS16(check_offset + 0x9);
282926deccbSFrançois Tigeot 				if (check_offset)
283926deccbSFrançois Tigeot 					offset = check_offset;
284926deccbSFrançois Tigeot 			}
285926deccbSFrançois Tigeot 		}
286926deccbSFrançois Tigeot 		break;
287926deccbSFrançois Tigeot 	case COMBIOS_RAM_RESET_TABLE:	/* offset from mem config */
288926deccbSFrançois Tigeot 		check_offset =
289926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE);
290926deccbSFrançois Tigeot 		if (check_offset) {
291926deccbSFrançois Tigeot 			while (RBIOS8(check_offset++));
292926deccbSFrançois Tigeot 			check_offset += 2;
293926deccbSFrançois Tigeot 			if (check_offset)
294926deccbSFrançois Tigeot 				offset = check_offset;
295926deccbSFrançois Tigeot 		}
296926deccbSFrançois Tigeot 		break;
297926deccbSFrançois Tigeot 	case COMBIOS_POWERPLAY_INFO_TABLE:	/* offset from mobile info */
298926deccbSFrançois Tigeot 		check_offset =
299926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
300926deccbSFrançois Tigeot 		if (check_offset) {
301926deccbSFrançois Tigeot 			check_offset = RBIOS16(check_offset + 0x11);
302926deccbSFrançois Tigeot 			if (check_offset)
303926deccbSFrançois Tigeot 				offset = check_offset;
304926deccbSFrançois Tigeot 		}
305926deccbSFrançois Tigeot 		break;
306926deccbSFrançois Tigeot 	case COMBIOS_GPIO_INFO_TABLE:	/* offset from mobile info */
307926deccbSFrançois Tigeot 		check_offset =
308926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
309926deccbSFrançois Tigeot 		if (check_offset) {
310926deccbSFrançois Tigeot 			check_offset = RBIOS16(check_offset + 0x13);
311926deccbSFrançois Tigeot 			if (check_offset)
312926deccbSFrançois Tigeot 				offset = check_offset;
313926deccbSFrançois Tigeot 		}
314926deccbSFrançois Tigeot 		break;
315926deccbSFrançois Tigeot 	case COMBIOS_LCD_DDC_INFO_TABLE:	/* offset from mobile info */
316926deccbSFrançois Tigeot 		check_offset =
317926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
318926deccbSFrançois Tigeot 		if (check_offset) {
319926deccbSFrançois Tigeot 			check_offset = RBIOS16(check_offset + 0x15);
320926deccbSFrançois Tigeot 			if (check_offset)
321926deccbSFrançois Tigeot 				offset = check_offset;
322926deccbSFrançois Tigeot 		}
323926deccbSFrançois Tigeot 		break;
324926deccbSFrançois Tigeot 	case COMBIOS_TMDS_POWER_TABLE:	/* offset from mobile info */
325926deccbSFrançois Tigeot 		check_offset =
326926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
327926deccbSFrançois Tigeot 		if (check_offset) {
328926deccbSFrançois Tigeot 			check_offset = RBIOS16(check_offset + 0x17);
329926deccbSFrançois Tigeot 			if (check_offset)
330926deccbSFrançois Tigeot 				offset = check_offset;
331926deccbSFrançois Tigeot 		}
332926deccbSFrançois Tigeot 		break;
333926deccbSFrançois Tigeot 	case COMBIOS_TMDS_POWER_ON_TABLE:	/* offset from tmds power */
334926deccbSFrançois Tigeot 		check_offset =
335926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE);
336926deccbSFrançois Tigeot 		if (check_offset) {
337926deccbSFrançois Tigeot 			check_offset = RBIOS16(check_offset + 0x2);
338926deccbSFrançois Tigeot 			if (check_offset)
339926deccbSFrançois Tigeot 				offset = check_offset;
340926deccbSFrançois Tigeot 		}
341926deccbSFrançois Tigeot 		break;
342926deccbSFrançois Tigeot 	case COMBIOS_TMDS_POWER_OFF_TABLE:	/* offset from tmds power */
343926deccbSFrançois Tigeot 		check_offset =
344926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE);
345926deccbSFrançois Tigeot 		if (check_offset) {
346926deccbSFrançois Tigeot 			check_offset = RBIOS16(check_offset + 0x4);
347926deccbSFrançois Tigeot 			if (check_offset)
348926deccbSFrançois Tigeot 				offset = check_offset;
349926deccbSFrançois Tigeot 		}
350926deccbSFrançois Tigeot 		break;
351926deccbSFrançois Tigeot 	default:
35257e252bfSMichael Neumann 		check_offset = 0;
353926deccbSFrançois Tigeot 		break;
354926deccbSFrançois Tigeot 	}
355926deccbSFrançois Tigeot 
35657e252bfSMichael Neumann 	size = RBIOS8(rdev->bios_header_start + 0x6);
35757e252bfSMichael Neumann 	/* check absolute offset tables */
35857e252bfSMichael Neumann 	if (table < COMBIOS_ASIC_INIT_3_TABLE && check_offset && check_offset < size)
35957e252bfSMichael Neumann 		offset = RBIOS16(rdev->bios_header_start + check_offset);
360926deccbSFrançois Tigeot 
36157e252bfSMichael Neumann 	return offset;
362926deccbSFrançois Tigeot }
363926deccbSFrançois Tigeot 
radeon_combios_check_hardcoded_edid(struct radeon_device * rdev)364926deccbSFrançois Tigeot bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
365926deccbSFrançois Tigeot {
366926deccbSFrançois Tigeot 	int edid_info, size;
367926deccbSFrançois Tigeot 	struct edid *edid;
368926deccbSFrançois Tigeot 	unsigned char *raw;
369926deccbSFrançois Tigeot 	edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
370926deccbSFrançois Tigeot 	if (!edid_info)
371926deccbSFrançois Tigeot 		return false;
372926deccbSFrançois Tigeot 
373926deccbSFrançois Tigeot 	raw = rdev->bios + edid_info;
374926deccbSFrançois Tigeot 	size = EDID_LENGTH * (raw[0x7e] + 1);
3755a3b77d5SFrançois Tigeot 	edid = kmalloc(size, M_DRM, M_WAITOK);
376926deccbSFrançois Tigeot 	if (edid == NULL)
377926deccbSFrançois Tigeot 		return false;
378926deccbSFrançois Tigeot 
379926deccbSFrançois Tigeot 	memcpy((unsigned char *)edid, raw, size);
380926deccbSFrançois Tigeot 
381926deccbSFrançois Tigeot 	if (!drm_edid_is_valid(edid)) {
382c4ef309bSzrj 		kfree(edid);
383926deccbSFrançois Tigeot 		return false;
384926deccbSFrançois Tigeot 	}
385926deccbSFrançois Tigeot 
386926deccbSFrançois Tigeot 	rdev->mode_info.bios_hardcoded_edid = edid;
387926deccbSFrançois Tigeot 	rdev->mode_info.bios_hardcoded_edid_size = size;
388926deccbSFrançois Tigeot 	return true;
389926deccbSFrançois Tigeot }
390926deccbSFrançois Tigeot 
391926deccbSFrançois Tigeot /* this is used for atom LCDs as well */
392926deccbSFrançois Tigeot struct edid *
radeon_bios_get_hardcoded_edid(struct radeon_device * rdev)393926deccbSFrançois Tigeot radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
394926deccbSFrançois Tigeot {
395926deccbSFrançois Tigeot 	struct edid *edid;
396926deccbSFrançois Tigeot 
397926deccbSFrançois Tigeot 	if (rdev->mode_info.bios_hardcoded_edid) {
398926deccbSFrançois Tigeot 		edid = kmalloc(rdev->mode_info.bios_hardcoded_edid_size,
3995a3b77d5SFrançois Tigeot 			       M_DRM, M_WAITOK);
400926deccbSFrançois Tigeot 		if (edid) {
401926deccbSFrançois Tigeot 			memcpy((unsigned char *)edid,
402926deccbSFrançois Tigeot 			       (unsigned char *)rdev->mode_info.bios_hardcoded_edid,
403926deccbSFrançois Tigeot 			       rdev->mode_info.bios_hardcoded_edid_size);
404926deccbSFrançois Tigeot 			return edid;
405926deccbSFrançois Tigeot 		}
406926deccbSFrançois Tigeot 	}
407926deccbSFrançois Tigeot 	return NULL;
408926deccbSFrançois Tigeot }
409926deccbSFrançois Tigeot 
combios_setup_i2c_bus(struct radeon_device * rdev,enum radeon_combios_ddc ddc,u32 clk_mask,u32 data_mask)410926deccbSFrançois Tigeot static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
411926deccbSFrançois Tigeot 						       enum radeon_combios_ddc ddc,
412926deccbSFrançois Tigeot 						       u32 clk_mask,
413926deccbSFrançois Tigeot 						       u32 data_mask)
414926deccbSFrançois Tigeot {
415926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec i2c;
416926deccbSFrançois Tigeot 	int ddc_line = 0;
417926deccbSFrançois Tigeot 
418926deccbSFrançois Tigeot 	/* ddc id            = mask reg
419926deccbSFrançois Tigeot 	 * DDC_NONE_DETECTED = none
420926deccbSFrançois Tigeot 	 * DDC_DVI           = RADEON_GPIO_DVI_DDC
421926deccbSFrançois Tigeot 	 * DDC_VGA           = RADEON_GPIO_VGA_DDC
422926deccbSFrançois Tigeot 	 * DDC_LCD           = RADEON_GPIOPAD_MASK
423926deccbSFrançois Tigeot 	 * DDC_GPIO          = RADEON_MDGPIO_MASK
424926deccbSFrançois Tigeot 	 * r1xx
425926deccbSFrançois Tigeot 	 * DDC_MONID         = RADEON_GPIO_MONID
426926deccbSFrançois Tigeot 	 * DDC_CRT2          = RADEON_GPIO_CRT2_DDC
427926deccbSFrançois Tigeot 	 * r200
428926deccbSFrançois Tigeot 	 * DDC_MONID         = RADEON_GPIO_MONID
429926deccbSFrançois Tigeot 	 * DDC_CRT2          = RADEON_GPIO_DVI_DDC
430926deccbSFrançois Tigeot 	 * r300/r350
431926deccbSFrançois Tigeot 	 * DDC_MONID         = RADEON_GPIO_DVI_DDC
432926deccbSFrançois Tigeot 	 * DDC_CRT2          = RADEON_GPIO_DVI_DDC
433926deccbSFrançois Tigeot 	 * rv2xx/rv3xx
434926deccbSFrançois Tigeot 	 * DDC_MONID         = RADEON_GPIO_MONID
435926deccbSFrançois Tigeot 	 * DDC_CRT2          = RADEON_GPIO_MONID
436926deccbSFrançois Tigeot 	 * rs3xx/rs4xx
437926deccbSFrançois Tigeot 	 * DDC_MONID         = RADEON_GPIOPAD_MASK
438926deccbSFrançois Tigeot 	 * DDC_CRT2          = RADEON_GPIO_MONID
439926deccbSFrançois Tigeot 	 */
440926deccbSFrançois Tigeot 	switch (ddc) {
441926deccbSFrançois Tigeot 	case DDC_NONE_DETECTED:
442926deccbSFrançois Tigeot 	default:
443926deccbSFrançois Tigeot 		ddc_line = 0;
444926deccbSFrançois Tigeot 		break;
445926deccbSFrançois Tigeot 	case DDC_DVI:
446926deccbSFrançois Tigeot 		ddc_line = RADEON_GPIO_DVI_DDC;
447926deccbSFrançois Tigeot 		break;
448926deccbSFrançois Tigeot 	case DDC_VGA:
449926deccbSFrançois Tigeot 		ddc_line = RADEON_GPIO_VGA_DDC;
450926deccbSFrançois Tigeot 		break;
451926deccbSFrançois Tigeot 	case DDC_LCD:
452926deccbSFrançois Tigeot 		ddc_line = RADEON_GPIOPAD_MASK;
453926deccbSFrançois Tigeot 		break;
454926deccbSFrançois Tigeot 	case DDC_GPIO:
455926deccbSFrançois Tigeot 		ddc_line = RADEON_MDGPIO_MASK;
456926deccbSFrançois Tigeot 		break;
457926deccbSFrançois Tigeot 	case DDC_MONID:
458926deccbSFrançois Tigeot 		if (rdev->family == CHIP_RS300 ||
459926deccbSFrançois Tigeot 		    rdev->family == CHIP_RS400 ||
460926deccbSFrançois Tigeot 		    rdev->family == CHIP_RS480)
461926deccbSFrançois Tigeot 			ddc_line = RADEON_GPIOPAD_MASK;
462926deccbSFrançois Tigeot 		else if (rdev->family == CHIP_R300 ||
463926deccbSFrançois Tigeot 			 rdev->family == CHIP_R350) {
464926deccbSFrançois Tigeot 			ddc_line = RADEON_GPIO_DVI_DDC;
465926deccbSFrançois Tigeot 			ddc = DDC_DVI;
466926deccbSFrançois Tigeot 		} else
467926deccbSFrançois Tigeot 			ddc_line = RADEON_GPIO_MONID;
468926deccbSFrançois Tigeot 		break;
469926deccbSFrançois Tigeot 	case DDC_CRT2:
470926deccbSFrançois Tigeot 		if (rdev->family == CHIP_R200 ||
471926deccbSFrançois Tigeot 		    rdev->family == CHIP_R300 ||
472926deccbSFrançois Tigeot 		    rdev->family == CHIP_R350) {
473926deccbSFrançois Tigeot 			ddc_line = RADEON_GPIO_DVI_DDC;
474926deccbSFrançois Tigeot 			ddc = DDC_DVI;
475926deccbSFrançois Tigeot 		} else if (rdev->family == CHIP_RS300 ||
476926deccbSFrançois Tigeot 			   rdev->family == CHIP_RS400 ||
477926deccbSFrançois Tigeot 			   rdev->family == CHIP_RS480)
478926deccbSFrançois Tigeot 			ddc_line = RADEON_GPIO_MONID;
479926deccbSFrançois Tigeot 		else if (rdev->family >= CHIP_RV350) {
480926deccbSFrançois Tigeot 			ddc_line = RADEON_GPIO_MONID;
481926deccbSFrançois Tigeot 			ddc = DDC_MONID;
482926deccbSFrançois Tigeot 		} else
483926deccbSFrançois Tigeot 			ddc_line = RADEON_GPIO_CRT2_DDC;
484926deccbSFrançois Tigeot 		break;
485926deccbSFrançois Tigeot 	}
486926deccbSFrançois Tigeot 
487926deccbSFrançois Tigeot 	if (ddc_line == RADEON_GPIOPAD_MASK) {
488926deccbSFrançois Tigeot 		i2c.mask_clk_reg = RADEON_GPIOPAD_MASK;
489926deccbSFrançois Tigeot 		i2c.mask_data_reg = RADEON_GPIOPAD_MASK;
490926deccbSFrançois Tigeot 		i2c.a_clk_reg = RADEON_GPIOPAD_A;
491926deccbSFrançois Tigeot 		i2c.a_data_reg = RADEON_GPIOPAD_A;
492926deccbSFrançois Tigeot 		i2c.en_clk_reg = RADEON_GPIOPAD_EN;
493926deccbSFrançois Tigeot 		i2c.en_data_reg = RADEON_GPIOPAD_EN;
494926deccbSFrançois Tigeot 		i2c.y_clk_reg = RADEON_GPIOPAD_Y;
495926deccbSFrançois Tigeot 		i2c.y_data_reg = RADEON_GPIOPAD_Y;
496926deccbSFrançois Tigeot 	} else if (ddc_line == RADEON_MDGPIO_MASK) {
497926deccbSFrançois Tigeot 		i2c.mask_clk_reg = RADEON_MDGPIO_MASK;
498926deccbSFrançois Tigeot 		i2c.mask_data_reg = RADEON_MDGPIO_MASK;
499926deccbSFrançois Tigeot 		i2c.a_clk_reg = RADEON_MDGPIO_A;
500926deccbSFrançois Tigeot 		i2c.a_data_reg = RADEON_MDGPIO_A;
501926deccbSFrançois Tigeot 		i2c.en_clk_reg = RADEON_MDGPIO_EN;
502926deccbSFrançois Tigeot 		i2c.en_data_reg = RADEON_MDGPIO_EN;
503926deccbSFrançois Tigeot 		i2c.y_clk_reg = RADEON_MDGPIO_Y;
504926deccbSFrançois Tigeot 		i2c.y_data_reg = RADEON_MDGPIO_Y;
505926deccbSFrançois Tigeot 	} else {
506926deccbSFrançois Tigeot 		i2c.mask_clk_reg = ddc_line;
507926deccbSFrançois Tigeot 		i2c.mask_data_reg = ddc_line;
508926deccbSFrançois Tigeot 		i2c.a_clk_reg = ddc_line;
509926deccbSFrançois Tigeot 		i2c.a_data_reg = ddc_line;
510926deccbSFrançois Tigeot 		i2c.en_clk_reg = ddc_line;
511926deccbSFrançois Tigeot 		i2c.en_data_reg = ddc_line;
512926deccbSFrançois Tigeot 		i2c.y_clk_reg = ddc_line;
513926deccbSFrançois Tigeot 		i2c.y_data_reg = ddc_line;
514926deccbSFrançois Tigeot 	}
515926deccbSFrançois Tigeot 
516926deccbSFrançois Tigeot 	if (clk_mask && data_mask) {
517926deccbSFrançois Tigeot 		/* system specific masks */
518926deccbSFrançois Tigeot 		i2c.mask_clk_mask = clk_mask;
519926deccbSFrançois Tigeot 		i2c.mask_data_mask = data_mask;
520926deccbSFrançois Tigeot 		i2c.a_clk_mask = clk_mask;
521926deccbSFrançois Tigeot 		i2c.a_data_mask = data_mask;
522926deccbSFrançois Tigeot 		i2c.en_clk_mask = clk_mask;
523926deccbSFrançois Tigeot 		i2c.en_data_mask = data_mask;
524926deccbSFrançois Tigeot 		i2c.y_clk_mask = clk_mask;
525926deccbSFrançois Tigeot 		i2c.y_data_mask = data_mask;
526926deccbSFrançois Tigeot 	} else if ((ddc_line == RADEON_GPIOPAD_MASK) ||
527926deccbSFrançois Tigeot 		   (ddc_line == RADEON_MDGPIO_MASK)) {
528926deccbSFrançois Tigeot 		/* default gpiopad masks */
529926deccbSFrançois Tigeot 		i2c.mask_clk_mask = (0x20 << 8);
530926deccbSFrançois Tigeot 		i2c.mask_data_mask = 0x80;
531926deccbSFrançois Tigeot 		i2c.a_clk_mask = (0x20 << 8);
532926deccbSFrançois Tigeot 		i2c.a_data_mask = 0x80;
533926deccbSFrançois Tigeot 		i2c.en_clk_mask = (0x20 << 8);
534926deccbSFrançois Tigeot 		i2c.en_data_mask = 0x80;
535926deccbSFrançois Tigeot 		i2c.y_clk_mask = (0x20 << 8);
536926deccbSFrançois Tigeot 		i2c.y_data_mask = 0x80;
537926deccbSFrançois Tigeot 	} else {
538926deccbSFrançois Tigeot 		/* default masks for ddc pads */
539926deccbSFrançois Tigeot 		i2c.mask_clk_mask = RADEON_GPIO_MASK_1;
540926deccbSFrançois Tigeot 		i2c.mask_data_mask = RADEON_GPIO_MASK_0;
541926deccbSFrançois Tigeot 		i2c.a_clk_mask = RADEON_GPIO_A_1;
542926deccbSFrançois Tigeot 		i2c.a_data_mask = RADEON_GPIO_A_0;
543926deccbSFrançois Tigeot 		i2c.en_clk_mask = RADEON_GPIO_EN_1;
544926deccbSFrançois Tigeot 		i2c.en_data_mask = RADEON_GPIO_EN_0;
545926deccbSFrançois Tigeot 		i2c.y_clk_mask = RADEON_GPIO_Y_1;
546926deccbSFrançois Tigeot 		i2c.y_data_mask = RADEON_GPIO_Y_0;
547926deccbSFrançois Tigeot 	}
548926deccbSFrançois Tigeot 
549926deccbSFrançois Tigeot 	switch (rdev->family) {
550926deccbSFrançois Tigeot 	case CHIP_R100:
551926deccbSFrançois Tigeot 	case CHIP_RV100:
552926deccbSFrançois Tigeot 	case CHIP_RS100:
553926deccbSFrançois Tigeot 	case CHIP_RV200:
554926deccbSFrançois Tigeot 	case CHIP_RS200:
555926deccbSFrançois Tigeot 	case CHIP_RS300:
556926deccbSFrançois Tigeot 		switch (ddc_line) {
557926deccbSFrançois Tigeot 		case RADEON_GPIO_DVI_DDC:
558926deccbSFrançois Tigeot 			i2c.hw_capable = true;
559926deccbSFrançois Tigeot 			break;
560926deccbSFrançois Tigeot 		default:
561926deccbSFrançois Tigeot 			i2c.hw_capable = false;
562926deccbSFrançois Tigeot 			break;
563926deccbSFrançois Tigeot 		}
564926deccbSFrançois Tigeot 		break;
565926deccbSFrançois Tigeot 	case CHIP_R200:
566926deccbSFrançois Tigeot 		switch (ddc_line) {
567926deccbSFrançois Tigeot 		case RADEON_GPIO_DVI_DDC:
568926deccbSFrançois Tigeot 		case RADEON_GPIO_MONID:
569926deccbSFrançois Tigeot 			i2c.hw_capable = true;
570926deccbSFrançois Tigeot 			break;
571926deccbSFrançois Tigeot 		default:
572926deccbSFrançois Tigeot 			i2c.hw_capable = false;
573926deccbSFrançois Tigeot 			break;
574926deccbSFrançois Tigeot 		}
575926deccbSFrançois Tigeot 		break;
576926deccbSFrançois Tigeot 	case CHIP_RV250:
577926deccbSFrançois Tigeot 	case CHIP_RV280:
578926deccbSFrançois Tigeot 		switch (ddc_line) {
579926deccbSFrançois Tigeot 		case RADEON_GPIO_VGA_DDC:
580926deccbSFrançois Tigeot 		case RADEON_GPIO_DVI_DDC:
581926deccbSFrançois Tigeot 		case RADEON_GPIO_CRT2_DDC:
582926deccbSFrançois Tigeot 			i2c.hw_capable = true;
583926deccbSFrançois Tigeot 			break;
584926deccbSFrançois Tigeot 		default:
585926deccbSFrançois Tigeot 			i2c.hw_capable = false;
586926deccbSFrançois Tigeot 			break;
587926deccbSFrançois Tigeot 		}
588926deccbSFrançois Tigeot 		break;
589926deccbSFrançois Tigeot 	case CHIP_R300:
590926deccbSFrançois Tigeot 	case CHIP_R350:
591926deccbSFrançois Tigeot 		switch (ddc_line) {
592926deccbSFrançois Tigeot 		case RADEON_GPIO_VGA_DDC:
593926deccbSFrançois Tigeot 		case RADEON_GPIO_DVI_DDC:
594926deccbSFrançois Tigeot 			i2c.hw_capable = true;
595926deccbSFrançois Tigeot 			break;
596926deccbSFrançois Tigeot 		default:
597926deccbSFrançois Tigeot 			i2c.hw_capable = false;
598926deccbSFrançois Tigeot 			break;
599926deccbSFrançois Tigeot 		}
600926deccbSFrançois Tigeot 		break;
601926deccbSFrançois Tigeot 	case CHIP_RV350:
602926deccbSFrançois Tigeot 	case CHIP_RV380:
603926deccbSFrançois Tigeot 	case CHIP_RS400:
604926deccbSFrançois Tigeot 	case CHIP_RS480:
605926deccbSFrançois Tigeot 		switch (ddc_line) {
606926deccbSFrançois Tigeot 		case RADEON_GPIO_VGA_DDC:
607926deccbSFrançois Tigeot 		case RADEON_GPIO_DVI_DDC:
608926deccbSFrançois Tigeot 			i2c.hw_capable = true;
609926deccbSFrançois Tigeot 			break;
610926deccbSFrançois Tigeot 		case RADEON_GPIO_MONID:
611926deccbSFrançois Tigeot 			/* hw i2c on RADEON_GPIO_MONID doesn't seem to work
612926deccbSFrançois Tigeot 			 * reliably on some pre-r4xx hardware; not sure why.
613926deccbSFrançois Tigeot 			 */
614926deccbSFrançois Tigeot 			i2c.hw_capable = false;
615926deccbSFrançois Tigeot 			break;
616926deccbSFrançois Tigeot 		default:
617926deccbSFrançois Tigeot 			i2c.hw_capable = false;
618926deccbSFrançois Tigeot 			break;
619926deccbSFrançois Tigeot 		}
620926deccbSFrançois Tigeot 		break;
621926deccbSFrançois Tigeot 	default:
622926deccbSFrançois Tigeot 		i2c.hw_capable = false;
623926deccbSFrançois Tigeot 		break;
624926deccbSFrançois Tigeot 	}
625926deccbSFrançois Tigeot 	i2c.mm_i2c = false;
626926deccbSFrançois Tigeot 
627926deccbSFrançois Tigeot 	i2c.i2c_id = ddc;
628926deccbSFrançois Tigeot 	i2c.hpd = RADEON_HPD_NONE;
629926deccbSFrançois Tigeot 
630926deccbSFrançois Tigeot 	if (ddc_line)
631926deccbSFrançois Tigeot 		i2c.valid = true;
632926deccbSFrançois Tigeot 	else
633926deccbSFrançois Tigeot 		i2c.valid = false;
634926deccbSFrançois Tigeot 
635926deccbSFrançois Tigeot 	return i2c;
636926deccbSFrançois Tigeot }
637926deccbSFrançois Tigeot 
radeon_combios_get_i2c_info_from_table(struct radeon_device * rdev)638926deccbSFrançois Tigeot static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev)
639926deccbSFrançois Tigeot {
640926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
641926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec i2c;
642926deccbSFrançois Tigeot 	u16 offset;
643926deccbSFrançois Tigeot 	u8 id, blocks, clk, data;
644926deccbSFrançois Tigeot 	int i;
645926deccbSFrançois Tigeot 
646926deccbSFrançois Tigeot 	i2c.valid = false;
647926deccbSFrançois Tigeot 
648926deccbSFrançois Tigeot 	offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE);
649926deccbSFrançois Tigeot 	if (offset) {
650926deccbSFrançois Tigeot 		blocks = RBIOS8(offset + 2);
651926deccbSFrançois Tigeot 		for (i = 0; i < blocks; i++) {
652926deccbSFrançois Tigeot 			id = RBIOS8(offset + 3 + (i * 5) + 0);
653926deccbSFrançois Tigeot 			if (id == 136) {
654926deccbSFrançois Tigeot 				clk = RBIOS8(offset + 3 + (i * 5) + 3);
655926deccbSFrançois Tigeot 				data = RBIOS8(offset + 3 + (i * 5) + 4);
656926deccbSFrançois Tigeot 				/* gpiopad */
657926deccbSFrançois Tigeot 				i2c = combios_setup_i2c_bus(rdev, DDC_MONID,
658926deccbSFrançois Tigeot 							    (1 << clk), (1 << data));
659926deccbSFrançois Tigeot 				break;
660926deccbSFrançois Tigeot 			}
661926deccbSFrançois Tigeot 		}
662926deccbSFrançois Tigeot 	}
663926deccbSFrançois Tigeot 	return i2c;
664926deccbSFrançois Tigeot }
665926deccbSFrançois Tigeot 
radeon_combios_i2c_init(struct radeon_device * rdev)666926deccbSFrançois Tigeot void radeon_combios_i2c_init(struct radeon_device *rdev)
667926deccbSFrançois Tigeot {
668926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
669926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec i2c;
670926deccbSFrançois Tigeot 
671926deccbSFrançois Tigeot 	/* actual hw pads
672926deccbSFrançois Tigeot 	 * r1xx/rs2xx/rs3xx
673926deccbSFrançois Tigeot 	 * 0x60, 0x64, 0x68, 0x6c, gpiopads, mm
674926deccbSFrançois Tigeot 	 * r200
675926deccbSFrançois Tigeot 	 * 0x60, 0x64, 0x68, mm
676926deccbSFrançois Tigeot 	 * r300/r350
677926deccbSFrançois Tigeot 	 * 0x60, 0x64, mm
678926deccbSFrançois Tigeot 	 * rv2xx/rv3xx/rs4xx
679926deccbSFrançois Tigeot 	 * 0x60, 0x64, 0x68, gpiopads, mm
680926deccbSFrançois Tigeot 	 */
681926deccbSFrançois Tigeot 
682926deccbSFrançois Tigeot 	/* 0x60 */
683926deccbSFrançois Tigeot 	i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
684926deccbSFrançois Tigeot 	rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "DVI_DDC");
685926deccbSFrançois Tigeot 	/* 0x64 */
686926deccbSFrançois Tigeot 	i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
687926deccbSFrançois Tigeot 	rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "VGA_DDC");
688926deccbSFrançois Tigeot 
689926deccbSFrançois Tigeot 	/* mm i2c */
690926deccbSFrançois Tigeot 	i2c.valid = true;
691926deccbSFrançois Tigeot 	i2c.hw_capable = true;
692926deccbSFrançois Tigeot 	i2c.mm_i2c = true;
693926deccbSFrançois Tigeot 	i2c.i2c_id = 0xa0;
694926deccbSFrançois Tigeot 	rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "MM_I2C");
695926deccbSFrançois Tigeot 
696926deccbSFrançois Tigeot 	if (rdev->family == CHIP_R300 ||
697926deccbSFrançois Tigeot 	    rdev->family == CHIP_R350) {
698926deccbSFrançois Tigeot 		/* only 2 sw i2c pads */
699926deccbSFrançois Tigeot 	} else if (rdev->family == CHIP_RS300 ||
700926deccbSFrançois Tigeot 		   rdev->family == CHIP_RS400 ||
701926deccbSFrançois Tigeot 		   rdev->family == CHIP_RS480) {
702926deccbSFrançois Tigeot 		/* 0x68 */
703926deccbSFrançois Tigeot 		i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
704926deccbSFrançois Tigeot 		rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
705926deccbSFrançois Tigeot 
706926deccbSFrançois Tigeot 		/* gpiopad */
707926deccbSFrançois Tigeot 		i2c = radeon_combios_get_i2c_info_from_table(rdev);
708926deccbSFrançois Tigeot 		if (i2c.valid)
709926deccbSFrançois Tigeot 			rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK");
710926deccbSFrançois Tigeot 	} else if ((rdev->family == CHIP_R200) ||
711926deccbSFrançois Tigeot 		   (rdev->family >= CHIP_R300)) {
712926deccbSFrançois Tigeot 		/* 0x68 */
713926deccbSFrançois Tigeot 		i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
714926deccbSFrançois Tigeot 		rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
715926deccbSFrançois Tigeot 	} else {
716926deccbSFrançois Tigeot 		/* 0x68 */
717926deccbSFrançois Tigeot 		i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
718926deccbSFrançois Tigeot 		rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
719926deccbSFrançois Tigeot 		/* 0x6c */
720926deccbSFrançois Tigeot 		i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
721926deccbSFrançois Tigeot 		rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "CRT2_DDC");
722926deccbSFrançois Tigeot 	}
723926deccbSFrançois Tigeot }
724926deccbSFrançois Tigeot 
radeon_combios_get_clock_info(struct drm_device * dev)725926deccbSFrançois Tigeot bool radeon_combios_get_clock_info(struct drm_device *dev)
726926deccbSFrançois Tigeot {
727926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
728926deccbSFrançois Tigeot 	uint16_t pll_info;
729926deccbSFrançois Tigeot 	struct radeon_pll *p1pll = &rdev->clock.p1pll;
730926deccbSFrançois Tigeot 	struct radeon_pll *p2pll = &rdev->clock.p2pll;
731926deccbSFrançois Tigeot 	struct radeon_pll *spll = &rdev->clock.spll;
732926deccbSFrançois Tigeot 	struct radeon_pll *mpll = &rdev->clock.mpll;
733926deccbSFrançois Tigeot 	int8_t rev;
734926deccbSFrançois Tigeot 	uint16_t sclk, mclk;
735926deccbSFrançois Tigeot 
736926deccbSFrançois Tigeot 	pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
737926deccbSFrançois Tigeot 	if (pll_info) {
738926deccbSFrançois Tigeot 		rev = RBIOS8(pll_info);
739926deccbSFrançois Tigeot 
740926deccbSFrançois Tigeot 		/* pixel clocks */
741926deccbSFrançois Tigeot 		p1pll->reference_freq = RBIOS16(pll_info + 0xe);
742926deccbSFrançois Tigeot 		p1pll->reference_div = RBIOS16(pll_info + 0x10);
743926deccbSFrançois Tigeot 		p1pll->pll_out_min = RBIOS32(pll_info + 0x12);
744926deccbSFrançois Tigeot 		p1pll->pll_out_max = RBIOS32(pll_info + 0x16);
745926deccbSFrançois Tigeot 		p1pll->lcd_pll_out_min = p1pll->pll_out_min;
746926deccbSFrançois Tigeot 		p1pll->lcd_pll_out_max = p1pll->pll_out_max;
747926deccbSFrançois Tigeot 
748926deccbSFrançois Tigeot 		if (rev > 9) {
749926deccbSFrançois Tigeot 			p1pll->pll_in_min = RBIOS32(pll_info + 0x36);
750926deccbSFrançois Tigeot 			p1pll->pll_in_max = RBIOS32(pll_info + 0x3a);
751926deccbSFrançois Tigeot 		} else {
752926deccbSFrançois Tigeot 			p1pll->pll_in_min = 40;
753926deccbSFrançois Tigeot 			p1pll->pll_in_max = 500;
754926deccbSFrançois Tigeot 		}
755926deccbSFrançois Tigeot 		*p2pll = *p1pll;
756926deccbSFrançois Tigeot 
757926deccbSFrançois Tigeot 		/* system clock */
758926deccbSFrançois Tigeot 		spll->reference_freq = RBIOS16(pll_info + 0x1a);
759926deccbSFrançois Tigeot 		spll->reference_div = RBIOS16(pll_info + 0x1c);
760926deccbSFrançois Tigeot 		spll->pll_out_min = RBIOS32(pll_info + 0x1e);
761926deccbSFrançois Tigeot 		spll->pll_out_max = RBIOS32(pll_info + 0x22);
762926deccbSFrançois Tigeot 
763926deccbSFrançois Tigeot 		if (rev > 10) {
764926deccbSFrançois Tigeot 			spll->pll_in_min = RBIOS32(pll_info + 0x48);
765926deccbSFrançois Tigeot 			spll->pll_in_max = RBIOS32(pll_info + 0x4c);
766926deccbSFrançois Tigeot 		} else {
767926deccbSFrançois Tigeot 			/* ??? */
768926deccbSFrançois Tigeot 			spll->pll_in_min = 40;
769926deccbSFrançois Tigeot 			spll->pll_in_max = 500;
770926deccbSFrançois Tigeot 		}
771926deccbSFrançois Tigeot 
772926deccbSFrançois Tigeot 		/* memory clock */
773926deccbSFrançois Tigeot 		mpll->reference_freq = RBIOS16(pll_info + 0x26);
774926deccbSFrançois Tigeot 		mpll->reference_div = RBIOS16(pll_info + 0x28);
775926deccbSFrançois Tigeot 		mpll->pll_out_min = RBIOS32(pll_info + 0x2a);
776926deccbSFrançois Tigeot 		mpll->pll_out_max = RBIOS32(pll_info + 0x2e);
777926deccbSFrançois Tigeot 
778926deccbSFrançois Tigeot 		if (rev > 10) {
779926deccbSFrançois Tigeot 			mpll->pll_in_min = RBIOS32(pll_info + 0x5a);
780926deccbSFrançois Tigeot 			mpll->pll_in_max = RBIOS32(pll_info + 0x5e);
781926deccbSFrançois Tigeot 		} else {
782926deccbSFrançois Tigeot 			/* ??? */
783926deccbSFrançois Tigeot 			mpll->pll_in_min = 40;
784926deccbSFrançois Tigeot 			mpll->pll_in_max = 500;
785926deccbSFrançois Tigeot 		}
786926deccbSFrançois Tigeot 
787926deccbSFrançois Tigeot 		/* default sclk/mclk */
788926deccbSFrançois Tigeot 		sclk = RBIOS16(pll_info + 0xa);
789926deccbSFrançois Tigeot 		mclk = RBIOS16(pll_info + 0x8);
790926deccbSFrançois Tigeot 		if (sclk == 0)
791926deccbSFrançois Tigeot 			sclk = 200 * 100;
792926deccbSFrançois Tigeot 		if (mclk == 0)
793926deccbSFrançois Tigeot 			mclk = 200 * 100;
794926deccbSFrançois Tigeot 
795926deccbSFrançois Tigeot 		rdev->clock.default_sclk = sclk;
796926deccbSFrançois Tigeot 		rdev->clock.default_mclk = mclk;
797926deccbSFrançois Tigeot 
798926deccbSFrançois Tigeot 		if (RBIOS32(pll_info + 0x16))
799926deccbSFrançois Tigeot 			rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16);
800926deccbSFrançois Tigeot 		else
801926deccbSFrançois Tigeot 			rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */
802926deccbSFrançois Tigeot 
803926deccbSFrançois Tigeot 		return true;
804926deccbSFrançois Tigeot 	}
805926deccbSFrançois Tigeot 	return false;
806926deccbSFrançois Tigeot }
807926deccbSFrançois Tigeot 
radeon_combios_sideport_present(struct radeon_device * rdev)808926deccbSFrançois Tigeot bool radeon_combios_sideport_present(struct radeon_device *rdev)
809926deccbSFrançois Tigeot {
810926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
811926deccbSFrançois Tigeot 	u16 igp_info;
812926deccbSFrançois Tigeot 
813926deccbSFrançois Tigeot 	/* sideport is AMD only */
814926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RS400)
815926deccbSFrançois Tigeot 		return false;
816926deccbSFrançois Tigeot 
817926deccbSFrançois Tigeot 	igp_info = combios_get_table_offset(dev, COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE);
818926deccbSFrançois Tigeot 
819926deccbSFrançois Tigeot 	if (igp_info) {
820926deccbSFrançois Tigeot 		if (RBIOS16(igp_info + 0x4))
821926deccbSFrançois Tigeot 			return true;
822926deccbSFrançois Tigeot 	}
823926deccbSFrançois Tigeot 	return false;
824926deccbSFrançois Tigeot }
825926deccbSFrançois Tigeot 
826926deccbSFrançois Tigeot static const uint32_t default_primarydac_adj[CHIP_LAST] = {
827926deccbSFrançois Tigeot 	0x00000808,		/* r100  */
828926deccbSFrançois Tigeot 	0x00000808,		/* rv100 */
829926deccbSFrançois Tigeot 	0x00000808,		/* rs100 */
830926deccbSFrançois Tigeot 	0x00000808,		/* rv200 */
831926deccbSFrançois Tigeot 	0x00000808,		/* rs200 */
832926deccbSFrançois Tigeot 	0x00000808,		/* r200  */
833926deccbSFrançois Tigeot 	0x00000808,		/* rv250 */
834926deccbSFrançois Tigeot 	0x00000000,		/* rs300 */
835926deccbSFrançois Tigeot 	0x00000808,		/* rv280 */
836926deccbSFrançois Tigeot 	0x00000808,		/* r300  */
837926deccbSFrançois Tigeot 	0x00000808,		/* r350  */
838926deccbSFrançois Tigeot 	0x00000808,		/* rv350 */
839926deccbSFrançois Tigeot 	0x00000808,		/* rv380 */
840926deccbSFrançois Tigeot 	0x00000808,		/* r420  */
841926deccbSFrançois Tigeot 	0x00000808,		/* r423  */
842926deccbSFrançois Tigeot 	0x00000808,		/* rv410 */
843926deccbSFrançois Tigeot 	0x00000000,		/* rs400 */
844926deccbSFrançois Tigeot 	0x00000000,		/* rs480 */
845926deccbSFrançois Tigeot };
846926deccbSFrançois Tigeot 
radeon_legacy_get_primary_dac_info_from_table(struct radeon_device * rdev,struct radeon_encoder_primary_dac * p_dac)847926deccbSFrançois Tigeot static void radeon_legacy_get_primary_dac_info_from_table(struct radeon_device *rdev,
848926deccbSFrançois Tigeot 							  struct radeon_encoder_primary_dac *p_dac)
849926deccbSFrançois Tigeot {
850926deccbSFrançois Tigeot 	p_dac->ps2_pdac_adj = default_primarydac_adj[rdev->family];
851926deccbSFrançois Tigeot 	return;
852926deccbSFrançois Tigeot }
853926deccbSFrançois Tigeot 
radeon_combios_get_primary_dac_info(struct radeon_encoder * encoder)854926deccbSFrançois Tigeot struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
855926deccbSFrançois Tigeot 								       radeon_encoder
856926deccbSFrançois Tigeot 								       *encoder)
857926deccbSFrançois Tigeot {
858926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->base.dev;
859926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
860926deccbSFrançois Tigeot 	uint16_t dac_info;
861926deccbSFrançois Tigeot 	uint8_t rev, bg, dac;
862926deccbSFrançois Tigeot 	struct radeon_encoder_primary_dac *p_dac = NULL;
863926deccbSFrançois Tigeot 	int found = 0;
864926deccbSFrançois Tigeot 
865c4ef309bSzrj 	p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac),
866c4ef309bSzrj 			GFP_KERNEL);
867926deccbSFrançois Tigeot 
868926deccbSFrançois Tigeot 	if (!p_dac)
869926deccbSFrançois Tigeot 		return NULL;
870926deccbSFrançois Tigeot 
871926deccbSFrançois Tigeot 	/* check CRT table */
872926deccbSFrançois Tigeot 	dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
873926deccbSFrançois Tigeot 	if (dac_info) {
874926deccbSFrançois Tigeot 		rev = RBIOS8(dac_info) & 0x3;
875926deccbSFrançois Tigeot 		if (rev < 2) {
876926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0x2) & 0xf;
877926deccbSFrançois Tigeot 			dac = (RBIOS8(dac_info + 0x2) >> 4) & 0xf;
878926deccbSFrançois Tigeot 			p_dac->ps2_pdac_adj = (bg << 8) | (dac);
879926deccbSFrançois Tigeot 		} else {
880926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0x2) & 0xf;
881926deccbSFrançois Tigeot 			dac = RBIOS8(dac_info + 0x3) & 0xf;
882926deccbSFrançois Tigeot 			p_dac->ps2_pdac_adj = (bg << 8) | (dac);
883926deccbSFrançois Tigeot 		}
88457e252bfSMichael Neumann 		/* if the values are zeros, use the table */
88557e252bfSMichael Neumann 		if ((dac == 0) || (bg == 0))
88657e252bfSMichael Neumann 			found = 0;
88757e252bfSMichael Neumann 		else
888926deccbSFrançois Tigeot 			found = 1;
889926deccbSFrançois Tigeot 	}
890926deccbSFrançois Tigeot 
891b403bed8SMichael Neumann 	/* quirks */
89257e252bfSMichael Neumann 	/* Radeon 7000 (RV100) */
893c6f73aabSFrançois Tigeot 	if (((dev->pdev->device == 0x5159) &&
894c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_vendor == 0x174B) &&
895c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_device == 0x7c28)) ||
896b403bed8SMichael Neumann 	/* Radeon 9100 (R200) */
897c6f73aabSFrançois Tigeot 	   ((dev->pdev->device == 0x514D) &&
898c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_vendor == 0x174B) &&
899c6f73aabSFrançois Tigeot 	    (dev->pdev->subsystem_device == 0x7149))) {
900b403bed8SMichael Neumann 		/* vbios value is bad, use the default */
901b403bed8SMichael Neumann 		found = 0;
902b403bed8SMichael Neumann 	}
903b403bed8SMichael Neumann 
904926deccbSFrançois Tigeot 	if (!found) /* fallback to defaults */
905926deccbSFrançois Tigeot 		radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
906926deccbSFrançois Tigeot 
907926deccbSFrançois Tigeot 	return p_dac;
908926deccbSFrançois Tigeot }
909926deccbSFrançois Tigeot 
910926deccbSFrançois Tigeot enum radeon_tv_std
radeon_combios_get_tv_info(struct radeon_device * rdev)911926deccbSFrançois Tigeot radeon_combios_get_tv_info(struct radeon_device *rdev)
912926deccbSFrançois Tigeot {
913926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
914926deccbSFrançois Tigeot 	uint16_t tv_info;
915926deccbSFrançois Tigeot 	enum radeon_tv_std tv_std = TV_STD_NTSC;
916926deccbSFrançois Tigeot 
917926deccbSFrançois Tigeot 	tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
918926deccbSFrançois Tigeot 	if (tv_info) {
919926deccbSFrançois Tigeot 		if (RBIOS8(tv_info + 6) == 'T') {
920926deccbSFrançois Tigeot 			switch (RBIOS8(tv_info + 7) & 0xf) {
921926deccbSFrançois Tigeot 			case 1:
922926deccbSFrançois Tigeot 				tv_std = TV_STD_NTSC;
923926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("Default TV standard: NTSC\n");
924926deccbSFrançois Tigeot 				break;
925926deccbSFrançois Tigeot 			case 2:
926926deccbSFrançois Tigeot 				tv_std = TV_STD_PAL;
927926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("Default TV standard: PAL\n");
928926deccbSFrançois Tigeot 				break;
929926deccbSFrançois Tigeot 			case 3:
930926deccbSFrançois Tigeot 				tv_std = TV_STD_PAL_M;
931926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
932926deccbSFrançois Tigeot 				break;
933926deccbSFrançois Tigeot 			case 4:
934926deccbSFrançois Tigeot 				tv_std = TV_STD_PAL_60;
935926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
936926deccbSFrançois Tigeot 				break;
937926deccbSFrançois Tigeot 			case 5:
938926deccbSFrançois Tigeot 				tv_std = TV_STD_NTSC_J;
939926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
940926deccbSFrançois Tigeot 				break;
941926deccbSFrançois Tigeot 			case 6:
942926deccbSFrançois Tigeot 				tv_std = TV_STD_SCART_PAL;
943926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n");
944926deccbSFrançois Tigeot 				break;
945926deccbSFrançois Tigeot 			default:
946926deccbSFrançois Tigeot 				tv_std = TV_STD_NTSC;
947926deccbSFrançois Tigeot 				DRM_DEBUG_KMS
948926deccbSFrançois Tigeot 				    ("Unknown TV standard; defaulting to NTSC\n");
949926deccbSFrançois Tigeot 				break;
950926deccbSFrançois Tigeot 			}
951926deccbSFrançois Tigeot 
952926deccbSFrançois Tigeot 			switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) {
953926deccbSFrançois Tigeot 			case 0:
954926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n");
955926deccbSFrançois Tigeot 				break;
956926deccbSFrançois Tigeot 			case 1:
957926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n");
958926deccbSFrançois Tigeot 				break;
959926deccbSFrançois Tigeot 			case 2:
960926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n");
961926deccbSFrançois Tigeot 				break;
962926deccbSFrançois Tigeot 			case 3:
963926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n");
964926deccbSFrançois Tigeot 				break;
965926deccbSFrançois Tigeot 			default:
966926deccbSFrançois Tigeot 				break;
967926deccbSFrançois Tigeot 			}
968926deccbSFrançois Tigeot 		}
969926deccbSFrançois Tigeot 	}
970926deccbSFrançois Tigeot 	return tv_std;
971926deccbSFrançois Tigeot }
972926deccbSFrançois Tigeot 
973926deccbSFrançois Tigeot static const uint32_t default_tvdac_adj[CHIP_LAST] = {
974926deccbSFrançois Tigeot 	0x00000000,		/* r100  */
975926deccbSFrançois Tigeot 	0x00280000,		/* rv100 */
976926deccbSFrançois Tigeot 	0x00000000,		/* rs100 */
977926deccbSFrançois Tigeot 	0x00880000,		/* rv200 */
978926deccbSFrançois Tigeot 	0x00000000,		/* rs200 */
979926deccbSFrançois Tigeot 	0x00000000,		/* r200  */
980926deccbSFrançois Tigeot 	0x00770000,		/* rv250 */
981926deccbSFrançois Tigeot 	0x00290000,		/* rs300 */
982926deccbSFrançois Tigeot 	0x00560000,		/* rv280 */
983926deccbSFrançois Tigeot 	0x00780000,		/* r300  */
984926deccbSFrançois Tigeot 	0x00770000,		/* r350  */
985926deccbSFrançois Tigeot 	0x00780000,		/* rv350 */
986926deccbSFrançois Tigeot 	0x00780000,		/* rv380 */
987926deccbSFrançois Tigeot 	0x01080000,		/* r420  */
988926deccbSFrançois Tigeot 	0x01080000,		/* r423  */
989926deccbSFrançois Tigeot 	0x01080000,		/* rv410 */
990926deccbSFrançois Tigeot 	0x00780000,		/* rs400 */
991926deccbSFrançois Tigeot 	0x00780000,		/* rs480 */
992926deccbSFrançois Tigeot };
993926deccbSFrançois Tigeot 
radeon_legacy_get_tv_dac_info_from_table(struct radeon_device * rdev,struct radeon_encoder_tv_dac * tv_dac)994926deccbSFrançois Tigeot static void radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev,
995926deccbSFrançois Tigeot 						     struct radeon_encoder_tv_dac *tv_dac)
996926deccbSFrançois Tigeot {
997926deccbSFrançois Tigeot 	tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family];
998926deccbSFrançois Tigeot 	if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250))
999926deccbSFrançois Tigeot 		tv_dac->ps2_tvdac_adj = 0x00880000;
1000926deccbSFrançois Tigeot 	tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
1001926deccbSFrançois Tigeot 	tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
1002926deccbSFrançois Tigeot 	return;
1003926deccbSFrançois Tigeot }
1004926deccbSFrançois Tigeot 
radeon_combios_get_tv_dac_info(struct radeon_encoder * encoder)1005926deccbSFrançois Tigeot struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
1006926deccbSFrançois Tigeot 							     radeon_encoder
1007926deccbSFrançois Tigeot 							     *encoder)
1008926deccbSFrançois Tigeot {
1009926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->base.dev;
1010926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1011926deccbSFrançois Tigeot 	uint16_t dac_info;
1012926deccbSFrançois Tigeot 	uint8_t rev, bg, dac;
1013926deccbSFrançois Tigeot 	struct radeon_encoder_tv_dac *tv_dac = NULL;
1014926deccbSFrançois Tigeot 	int found = 0;
1015926deccbSFrançois Tigeot 
1016c4ef309bSzrj 	tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
1017926deccbSFrançois Tigeot 	if (!tv_dac)
1018926deccbSFrançois Tigeot 		return NULL;
1019926deccbSFrançois Tigeot 
1020926deccbSFrançois Tigeot 	/* first check TV table */
1021926deccbSFrançois Tigeot 	dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
1022926deccbSFrançois Tigeot 	if (dac_info) {
1023926deccbSFrançois Tigeot 		rev = RBIOS8(dac_info + 0x3);
1024926deccbSFrançois Tigeot 		if (rev > 4) {
1025926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0xc) & 0xf;
1026926deccbSFrançois Tigeot 			dac = RBIOS8(dac_info + 0xd) & 0xf;
1027926deccbSFrançois Tigeot 			tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
1028926deccbSFrançois Tigeot 
1029926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0xe) & 0xf;
1030926deccbSFrançois Tigeot 			dac = RBIOS8(dac_info + 0xf) & 0xf;
1031926deccbSFrançois Tigeot 			tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
1032926deccbSFrançois Tigeot 
1033926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0x10) & 0xf;
1034926deccbSFrançois Tigeot 			dac = RBIOS8(dac_info + 0x11) & 0xf;
1035926deccbSFrançois Tigeot 			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
1036926deccbSFrançois Tigeot 			/* if the values are all zeros, use the table */
1037926deccbSFrançois Tigeot 			if (tv_dac->ps2_tvdac_adj)
1038926deccbSFrançois Tigeot 				found = 1;
1039926deccbSFrançois Tigeot 		} else if (rev > 1) {
1040926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0xc) & 0xf;
1041926deccbSFrançois Tigeot 			dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf;
1042926deccbSFrançois Tigeot 			tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
1043926deccbSFrançois Tigeot 
1044926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0xd) & 0xf;
1045926deccbSFrançois Tigeot 			dac = (RBIOS8(dac_info + 0xd) >> 4) & 0xf;
1046926deccbSFrançois Tigeot 			tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
1047926deccbSFrançois Tigeot 
1048926deccbSFrançois Tigeot 			bg = RBIOS8(dac_info + 0xe) & 0xf;
1049926deccbSFrançois Tigeot 			dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf;
1050926deccbSFrançois Tigeot 			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
1051926deccbSFrançois Tigeot 			/* if the values are all zeros, use the table */
1052926deccbSFrançois Tigeot 			if (tv_dac->ps2_tvdac_adj)
1053926deccbSFrançois Tigeot 				found = 1;
1054926deccbSFrançois Tigeot 		}
1055926deccbSFrançois Tigeot 		tv_dac->tv_std = radeon_combios_get_tv_info(rdev);
1056926deccbSFrançois Tigeot 	}
1057926deccbSFrançois Tigeot 	if (!found) {
1058926deccbSFrançois Tigeot 		/* then check CRT table */
1059926deccbSFrançois Tigeot 		dac_info =
1060926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
1061926deccbSFrançois Tigeot 		if (dac_info) {
1062926deccbSFrançois Tigeot 			rev = RBIOS8(dac_info) & 0x3;
1063926deccbSFrançois Tigeot 			if (rev < 2) {
1064926deccbSFrançois Tigeot 				bg = RBIOS8(dac_info + 0x3) & 0xf;
1065926deccbSFrançois Tigeot 				dac = (RBIOS8(dac_info + 0x3) >> 4) & 0xf;
1066926deccbSFrançois Tigeot 				tv_dac->ps2_tvdac_adj =
1067926deccbSFrançois Tigeot 				    (bg << 16) | (dac << 20);
1068926deccbSFrançois Tigeot 				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
1069926deccbSFrançois Tigeot 				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
1070926deccbSFrançois Tigeot 				/* if the values are all zeros, use the table */
1071926deccbSFrançois Tigeot 				if (tv_dac->ps2_tvdac_adj)
1072926deccbSFrançois Tigeot 					found = 1;
1073926deccbSFrançois Tigeot 			} else {
1074926deccbSFrançois Tigeot 				bg = RBIOS8(dac_info + 0x4) & 0xf;
1075926deccbSFrançois Tigeot 				dac = RBIOS8(dac_info + 0x5) & 0xf;
1076926deccbSFrançois Tigeot 				tv_dac->ps2_tvdac_adj =
1077926deccbSFrançois Tigeot 				    (bg << 16) | (dac << 20);
1078926deccbSFrançois Tigeot 				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
1079926deccbSFrançois Tigeot 				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
1080926deccbSFrançois Tigeot 				/* if the values are all zeros, use the table */
1081926deccbSFrançois Tigeot 				if (tv_dac->ps2_tvdac_adj)
1082926deccbSFrançois Tigeot 					found = 1;
1083926deccbSFrançois Tigeot 			}
1084926deccbSFrançois Tigeot 		} else {
1085926deccbSFrançois Tigeot 			DRM_INFO("No TV DAC info found in BIOS\n");
1086926deccbSFrançois Tigeot 		}
1087926deccbSFrançois Tigeot 	}
1088926deccbSFrançois Tigeot 
1089926deccbSFrançois Tigeot 	if (!found) /* fallback to defaults */
1090926deccbSFrançois Tigeot 		radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac);
1091926deccbSFrançois Tigeot 
1092926deccbSFrançois Tigeot 	return tv_dac;
1093926deccbSFrançois Tigeot }
1094926deccbSFrançois Tigeot 
radeon_legacy_get_lvds_info_from_regs(struct radeon_device * rdev)1095926deccbSFrançois Tigeot static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct
1096926deccbSFrançois Tigeot 									 radeon_device
1097926deccbSFrançois Tigeot 									 *rdev)
1098926deccbSFrançois Tigeot {
1099926deccbSFrançois Tigeot 	struct radeon_encoder_lvds *lvds = NULL;
1100926deccbSFrançois Tigeot 	uint32_t fp_vert_stretch, fp_horz_stretch;
1101926deccbSFrançois Tigeot 	uint32_t ppll_div_sel, ppll_val;
1102926deccbSFrançois Tigeot 	uint32_t lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
1103926deccbSFrançois Tigeot 
1104c4ef309bSzrj 	lvds = kzalloc(sizeof(struct radeon_encoder_lvds), GFP_KERNEL);
1105926deccbSFrançois Tigeot 
1106926deccbSFrançois Tigeot 	if (!lvds)
1107926deccbSFrançois Tigeot 		return NULL;
1108926deccbSFrançois Tigeot 
1109926deccbSFrançois Tigeot 	fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH);
1110926deccbSFrançois Tigeot 	fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH);
1111926deccbSFrançois Tigeot 
1112926deccbSFrançois Tigeot 	/* These should be fail-safe defaults, fingers crossed */
1113926deccbSFrançois Tigeot 	lvds->panel_pwr_delay = 200;
1114926deccbSFrançois Tigeot 	lvds->panel_vcc_delay = 2000;
1115926deccbSFrançois Tigeot 
1116926deccbSFrançois Tigeot 	lvds->lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
1117926deccbSFrançois Tigeot 	lvds->panel_digon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) & 0xf;
1118926deccbSFrançois Tigeot 	lvds->panel_blon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY2_SHIFT) & 0xf;
1119926deccbSFrançois Tigeot 
1120926deccbSFrançois Tigeot 	if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE)
1121926deccbSFrançois Tigeot 		lvds->native_mode.vdisplay =
1122926deccbSFrançois Tigeot 		    ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >>
1123926deccbSFrançois Tigeot 		     RADEON_VERT_PANEL_SHIFT) + 1;
1124926deccbSFrançois Tigeot 	else
1125926deccbSFrançois Tigeot 		lvds->native_mode.vdisplay =
1126926deccbSFrançois Tigeot 		    (RREG32(RADEON_CRTC_V_TOTAL_DISP) >> 16) + 1;
1127926deccbSFrançois Tigeot 
1128926deccbSFrançois Tigeot 	if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE)
1129926deccbSFrançois Tigeot 		lvds->native_mode.hdisplay =
1130926deccbSFrançois Tigeot 		    (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >>
1131926deccbSFrançois Tigeot 		      RADEON_HORZ_PANEL_SHIFT) + 1) * 8;
1132926deccbSFrançois Tigeot 	else
1133926deccbSFrançois Tigeot 		lvds->native_mode.hdisplay =
1134926deccbSFrançois Tigeot 		    ((RREG32(RADEON_CRTC_H_TOTAL_DISP) >> 16) + 1) * 8;
1135926deccbSFrançois Tigeot 
1136926deccbSFrançois Tigeot 	if ((lvds->native_mode.hdisplay < 640) ||
1137926deccbSFrançois Tigeot 	    (lvds->native_mode.vdisplay < 480)) {
1138926deccbSFrançois Tigeot 		lvds->native_mode.hdisplay = 640;
1139926deccbSFrançois Tigeot 		lvds->native_mode.vdisplay = 480;
1140926deccbSFrançois Tigeot 	}
1141926deccbSFrançois Tigeot 
1142926deccbSFrançois Tigeot 	ppll_div_sel = RREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3;
1143926deccbSFrançois Tigeot 	ppll_val = RREG32_PLL(RADEON_PPLL_DIV_0 + ppll_div_sel);
1144926deccbSFrançois Tigeot 	if ((ppll_val & 0x000707ff) == 0x1bb)
1145926deccbSFrançois Tigeot 		lvds->use_bios_dividers = false;
1146926deccbSFrançois Tigeot 	else {
1147926deccbSFrançois Tigeot 		lvds->panel_ref_divider =
1148926deccbSFrançois Tigeot 		    RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
1149926deccbSFrançois Tigeot 		lvds->panel_post_divider = (ppll_val >> 16) & 0x7;
1150926deccbSFrançois Tigeot 		lvds->panel_fb_divider = ppll_val & 0x7ff;
1151926deccbSFrançois Tigeot 
1152926deccbSFrançois Tigeot 		if ((lvds->panel_ref_divider != 0) &&
1153926deccbSFrançois Tigeot 		    (lvds->panel_fb_divider > 3))
1154926deccbSFrançois Tigeot 			lvds->use_bios_dividers = true;
1155926deccbSFrançois Tigeot 	}
1156926deccbSFrançois Tigeot 	lvds->panel_vcc_delay = 200;
1157926deccbSFrançois Tigeot 
1158926deccbSFrançois Tigeot 	DRM_INFO("Panel info derived from registers\n");
1159926deccbSFrançois Tigeot 	DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.hdisplay,
1160926deccbSFrançois Tigeot 		 lvds->native_mode.vdisplay);
1161926deccbSFrançois Tigeot 
1162926deccbSFrançois Tigeot 	return lvds;
1163926deccbSFrançois Tigeot }
1164926deccbSFrançois Tigeot 
radeon_combios_get_lvds_info(struct radeon_encoder * encoder)1165926deccbSFrançois Tigeot struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
1166926deccbSFrançois Tigeot 							 *encoder)
1167926deccbSFrançois Tigeot {
1168926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->base.dev;
1169926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1170926deccbSFrançois Tigeot 	uint16_t lcd_info;
1171926deccbSFrançois Tigeot 	uint32_t panel_setup;
1172926deccbSFrançois Tigeot 	char stmp[30];
1173926deccbSFrançois Tigeot 	int tmp, i;
1174926deccbSFrançois Tigeot 	struct radeon_encoder_lvds *lvds = NULL;
1175926deccbSFrançois Tigeot 
1176926deccbSFrançois Tigeot 	lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
1177926deccbSFrançois Tigeot 
1178926deccbSFrançois Tigeot 	if (lcd_info) {
1179c4ef309bSzrj 		lvds = kzalloc(sizeof(struct radeon_encoder_lvds), GFP_KERNEL);
1180926deccbSFrançois Tigeot 
1181926deccbSFrançois Tigeot 		if (!lvds)
1182926deccbSFrançois Tigeot 			return NULL;
1183926deccbSFrançois Tigeot 
1184926deccbSFrançois Tigeot 		for (i = 0; i < 24; i++)
1185926deccbSFrançois Tigeot 			stmp[i] = RBIOS8(lcd_info + i + 1);
1186926deccbSFrançois Tigeot 		stmp[24] = 0;
1187926deccbSFrançois Tigeot 
1188926deccbSFrançois Tigeot 		DRM_INFO("Panel ID String: %s\n", stmp);
1189926deccbSFrançois Tigeot 
1190926deccbSFrançois Tigeot 		lvds->native_mode.hdisplay = RBIOS16(lcd_info + 0x19);
1191926deccbSFrançois Tigeot 		lvds->native_mode.vdisplay = RBIOS16(lcd_info + 0x1b);
1192926deccbSFrançois Tigeot 
1193926deccbSFrançois Tigeot 		DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.hdisplay,
1194926deccbSFrançois Tigeot 			 lvds->native_mode.vdisplay);
1195926deccbSFrançois Tigeot 
1196926deccbSFrançois Tigeot 		lvds->panel_vcc_delay = RBIOS16(lcd_info + 0x2c);
1197926deccbSFrançois Tigeot 		lvds->panel_vcc_delay = min_t(u16, lvds->panel_vcc_delay, 2000);
1198926deccbSFrançois Tigeot 
1199926deccbSFrançois Tigeot 		lvds->panel_pwr_delay = RBIOS8(lcd_info + 0x24);
1200926deccbSFrançois Tigeot 		lvds->panel_digon_delay = RBIOS16(lcd_info + 0x38) & 0xf;
1201926deccbSFrançois Tigeot 		lvds->panel_blon_delay = (RBIOS16(lcd_info + 0x38) >> 4) & 0xf;
1202926deccbSFrançois Tigeot 
1203926deccbSFrançois Tigeot 		lvds->panel_ref_divider = RBIOS16(lcd_info + 0x2e);
1204926deccbSFrançois Tigeot 		lvds->panel_post_divider = RBIOS8(lcd_info + 0x30);
1205926deccbSFrançois Tigeot 		lvds->panel_fb_divider = RBIOS16(lcd_info + 0x31);
1206926deccbSFrançois Tigeot 		if ((lvds->panel_ref_divider != 0) &&
1207926deccbSFrançois Tigeot 		    (lvds->panel_fb_divider > 3))
1208926deccbSFrançois Tigeot 			lvds->use_bios_dividers = true;
1209926deccbSFrançois Tigeot 
1210926deccbSFrançois Tigeot 		panel_setup = RBIOS32(lcd_info + 0x39);
1211926deccbSFrançois Tigeot 		lvds->lvds_gen_cntl = 0xff00;
1212926deccbSFrançois Tigeot 		if (panel_setup & 0x1)
1213926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_FORMAT;
1214926deccbSFrançois Tigeot 
1215926deccbSFrançois Tigeot 		if ((panel_setup >> 4) & 0x1)
1216926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_TYPE;
1217926deccbSFrançois Tigeot 
1218926deccbSFrançois Tigeot 		switch ((panel_setup >> 8) & 0x7) {
1219926deccbSFrançois Tigeot 		case 0:
1220926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_NO_FM;
1221926deccbSFrançois Tigeot 			break;
1222926deccbSFrançois Tigeot 		case 1:
1223926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_2_GREY;
1224926deccbSFrançois Tigeot 			break;
1225926deccbSFrançois Tigeot 		case 2:
1226926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_4_GREY;
1227926deccbSFrançois Tigeot 			break;
1228926deccbSFrançois Tigeot 		default:
1229926deccbSFrançois Tigeot 			break;
1230926deccbSFrançois Tigeot 		}
1231926deccbSFrançois Tigeot 
1232926deccbSFrançois Tigeot 		if ((panel_setup >> 16) & 0x1)
1233926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_FP_POL_LOW;
1234926deccbSFrançois Tigeot 
1235926deccbSFrançois Tigeot 		if ((panel_setup >> 17) & 0x1)
1236926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_LP_POL_LOW;
1237926deccbSFrançois Tigeot 
1238926deccbSFrançois Tigeot 		if ((panel_setup >> 18) & 0x1)
1239926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_DTM_POL_LOW;
1240926deccbSFrançois Tigeot 
1241926deccbSFrançois Tigeot 		if ((panel_setup >> 23) & 0x1)
1242926deccbSFrançois Tigeot 			lvds->lvds_gen_cntl |= RADEON_LVDS_BL_CLK_SEL;
1243926deccbSFrançois Tigeot 
1244926deccbSFrançois Tigeot 		lvds->lvds_gen_cntl |= (panel_setup & 0xf0000000);
1245926deccbSFrançois Tigeot 
1246926deccbSFrançois Tigeot 		for (i = 0; i < 32; i++) {
1247926deccbSFrançois Tigeot 			tmp = RBIOS16(lcd_info + 64 + i * 2);
1248926deccbSFrançois Tigeot 			if (tmp == 0)
1249926deccbSFrançois Tigeot 				break;
1250926deccbSFrançois Tigeot 
1251926deccbSFrançois Tigeot 			if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) &&
1252926deccbSFrançois Tigeot 			    (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) {
1253c59a5c48SFrançois Tigeot 				u32 hss = (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8;
1254c59a5c48SFrançois Tigeot 
1255c59a5c48SFrançois Tigeot 				if (hss > lvds->native_mode.hdisplay)
1256c59a5c48SFrançois Tigeot 					hss = (10 - 1) * 8;
1257c59a5c48SFrançois Tigeot 
1258926deccbSFrançois Tigeot 				lvds->native_mode.htotal = lvds->native_mode.hdisplay +
1259926deccbSFrançois Tigeot 					(RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8;
1260926deccbSFrançois Tigeot 				lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
1261c59a5c48SFrançois Tigeot 					hss;
1262926deccbSFrançois Tigeot 				lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
1263926deccbSFrançois Tigeot 					(RBIOS8(tmp + 23) * 8);
1264926deccbSFrançois Tigeot 
1265926deccbSFrançois Tigeot 				lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
1266926deccbSFrançois Tigeot 					(RBIOS16(tmp + 24) - RBIOS16(tmp + 26));
1267926deccbSFrançois Tigeot 				lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
1268926deccbSFrançois Tigeot 					((RBIOS16(tmp + 28) & 0x7ff) - RBIOS16(tmp + 26));
1269926deccbSFrançois Tigeot 				lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
1270926deccbSFrançois Tigeot 					((RBIOS16(tmp + 28) & 0xf800) >> 11);
1271926deccbSFrançois Tigeot 
1272926deccbSFrançois Tigeot 				lvds->native_mode.clock = RBIOS16(tmp + 9) * 10;
1273926deccbSFrançois Tigeot 				lvds->native_mode.flags = 0;
1274926deccbSFrançois Tigeot 				/* set crtc values */
1275926deccbSFrançois Tigeot 				drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
1276926deccbSFrançois Tigeot 
1277926deccbSFrançois Tigeot 			}
1278926deccbSFrançois Tigeot 		}
1279926deccbSFrançois Tigeot 	} else {
1280926deccbSFrançois Tigeot 		DRM_INFO("No panel info found in BIOS\n");
1281926deccbSFrançois Tigeot 		lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
1282926deccbSFrançois Tigeot 	}
1283926deccbSFrançois Tigeot 
1284926deccbSFrançois Tigeot 	if (lvds)
1285926deccbSFrançois Tigeot 		encoder->native_mode = lvds->native_mode;
1286926deccbSFrançois Tigeot 	return lvds;
1287926deccbSFrançois Tigeot }
1288926deccbSFrançois Tigeot 
1289926deccbSFrançois Tigeot static const struct radeon_tmds_pll default_tmds_pll[CHIP_LAST][4] = {
1290926deccbSFrançois Tigeot 	{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_R100  */
1291926deccbSFrançois Tigeot 	{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_RV100 */
1292926deccbSFrançois Tigeot 	{{0, 0}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_RS100 */
1293926deccbSFrançois Tigeot 	{{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_RV200 */
1294926deccbSFrançois Tigeot 	{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_RS200 */
1295926deccbSFrançois Tigeot 	{{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_R200  */
1296926deccbSFrançois Tigeot 	{{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}},	/* CHIP_RV250 */
1297926deccbSFrançois Tigeot 	{{0, 0}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_RS300 */
1298926deccbSFrançois Tigeot 	{{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}},	/* CHIP_RV280 */
1299926deccbSFrançois Tigeot 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R300  */
1300926deccbSFrançois Tigeot 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R350  */
1301926deccbSFrançois Tigeot 	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RV350 */
1302926deccbSFrançois Tigeot 	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RV380 */
1303926deccbSFrançois Tigeot 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R420  */
1304926deccbSFrançois Tigeot 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R423  */
1305926deccbSFrançois Tigeot 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_RV410 */
1306926deccbSFrançois Tigeot 	{ {0, 0}, {0, 0}, {0, 0}, {0, 0} },	/* CHIP_RS400 */
1307926deccbSFrançois Tigeot 	{ {0, 0}, {0, 0}, {0, 0}, {0, 0} },	/* CHIP_RS480 */
1308926deccbSFrançois Tigeot };
1309926deccbSFrançois Tigeot 
radeon_legacy_get_tmds_info_from_table(struct radeon_encoder * encoder,struct radeon_encoder_int_tmds * tmds)1310926deccbSFrançois Tigeot bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
1311926deccbSFrançois Tigeot 					    struct radeon_encoder_int_tmds *tmds)
1312926deccbSFrançois Tigeot {
1313926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->base.dev;
1314926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1315926deccbSFrançois Tigeot 	int i;
1316926deccbSFrançois Tigeot 
1317926deccbSFrançois Tigeot 	for (i = 0; i < 4; i++) {
1318926deccbSFrançois Tigeot 		tmds->tmds_pll[i].value =
1319926deccbSFrançois Tigeot 			default_tmds_pll[rdev->family][i].value;
1320926deccbSFrançois Tigeot 		tmds->tmds_pll[i].freq = default_tmds_pll[rdev->family][i].freq;
1321926deccbSFrançois Tigeot 	}
1322926deccbSFrançois Tigeot 
1323926deccbSFrançois Tigeot 	return true;
1324926deccbSFrançois Tigeot }
1325926deccbSFrançois Tigeot 
radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder * encoder,struct radeon_encoder_int_tmds * tmds)1326926deccbSFrançois Tigeot bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
1327926deccbSFrançois Tigeot 					      struct radeon_encoder_int_tmds *tmds)
1328926deccbSFrançois Tigeot {
1329926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->base.dev;
1330926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1331926deccbSFrançois Tigeot 	uint16_t tmds_info;
1332926deccbSFrançois Tigeot 	int i, n;
1333926deccbSFrançois Tigeot 	uint8_t ver;
1334926deccbSFrançois Tigeot 
1335926deccbSFrançois Tigeot 	tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
1336926deccbSFrançois Tigeot 
1337926deccbSFrançois Tigeot 	if (tmds_info) {
1338926deccbSFrançois Tigeot 		ver = RBIOS8(tmds_info);
1339926deccbSFrançois Tigeot 		DRM_DEBUG_KMS("DFP table revision: %d\n", ver);
1340926deccbSFrançois Tigeot 		if (ver == 3) {
1341926deccbSFrançois Tigeot 			n = RBIOS8(tmds_info + 5) + 1;
1342926deccbSFrançois Tigeot 			if (n > 4)
1343926deccbSFrançois Tigeot 				n = 4;
1344926deccbSFrançois Tigeot 			for (i = 0; i < n; i++) {
1345926deccbSFrançois Tigeot 				tmds->tmds_pll[i].value =
1346926deccbSFrançois Tigeot 				    RBIOS32(tmds_info + i * 10 + 0x08);
1347926deccbSFrançois Tigeot 				tmds->tmds_pll[i].freq =
1348926deccbSFrançois Tigeot 				    RBIOS16(tmds_info + i * 10 + 0x10);
1349926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("TMDS PLL From COMBIOS %u %x\n",
1350926deccbSFrançois Tigeot 					  tmds->tmds_pll[i].freq,
1351926deccbSFrançois Tigeot 					  tmds->tmds_pll[i].value);
1352926deccbSFrançois Tigeot 			}
1353926deccbSFrançois Tigeot 		} else if (ver == 4) {
1354926deccbSFrançois Tigeot 			int stride = 0;
1355926deccbSFrançois Tigeot 			n = RBIOS8(tmds_info + 5) + 1;
1356926deccbSFrançois Tigeot 			if (n > 4)
1357926deccbSFrançois Tigeot 				n = 4;
1358926deccbSFrançois Tigeot 			for (i = 0; i < n; i++) {
1359926deccbSFrançois Tigeot 				tmds->tmds_pll[i].value =
1360926deccbSFrançois Tigeot 				    RBIOS32(tmds_info + stride + 0x08);
1361926deccbSFrançois Tigeot 				tmds->tmds_pll[i].freq =
1362926deccbSFrançois Tigeot 				    RBIOS16(tmds_info + stride + 0x10);
1363926deccbSFrançois Tigeot 				if (i == 0)
1364926deccbSFrançois Tigeot 					stride += 10;
1365926deccbSFrançois Tigeot 				else
1366926deccbSFrançois Tigeot 					stride += 6;
1367926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("TMDS PLL From COMBIOS %u %x\n",
1368926deccbSFrançois Tigeot 					  tmds->tmds_pll[i].freq,
1369926deccbSFrançois Tigeot 					  tmds->tmds_pll[i].value);
1370926deccbSFrançois Tigeot 			}
1371926deccbSFrançois Tigeot 		}
1372926deccbSFrançois Tigeot 	} else {
1373926deccbSFrançois Tigeot 		DRM_INFO("No TMDS info found in BIOS\n");
1374926deccbSFrançois Tigeot 		return false;
1375926deccbSFrançois Tigeot 	}
1376926deccbSFrançois Tigeot 	return true;
1377926deccbSFrançois Tigeot }
1378926deccbSFrançois Tigeot 
radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder * encoder,struct radeon_encoder_ext_tmds * tmds)1379926deccbSFrançois Tigeot bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
1380926deccbSFrançois Tigeot 						struct radeon_encoder_ext_tmds *tmds)
1381926deccbSFrançois Tigeot {
1382926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->base.dev;
1383926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1384926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec i2c_bus;
1385926deccbSFrançois Tigeot 
1386926deccbSFrançois Tigeot 	/* default for macs */
1387926deccbSFrançois Tigeot 	i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
1388926deccbSFrançois Tigeot 	tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
1389926deccbSFrançois Tigeot 
1390926deccbSFrançois Tigeot 	/* XXX some macs have duallink chips */
1391926deccbSFrançois Tigeot 	switch (rdev->mode_info.connector_table) {
1392926deccbSFrançois Tigeot 	case CT_POWERBOOK_EXTERNAL:
1393926deccbSFrançois Tigeot 	case CT_MINI_EXTERNAL:
1394926deccbSFrançois Tigeot 	default:
1395926deccbSFrançois Tigeot 		tmds->dvo_chip = DVO_SIL164;
1396926deccbSFrançois Tigeot 		tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
1397926deccbSFrançois Tigeot 		break;
1398926deccbSFrançois Tigeot 	}
1399926deccbSFrançois Tigeot 
1400926deccbSFrançois Tigeot 	return true;
1401926deccbSFrançois Tigeot }
1402926deccbSFrançois Tigeot 
radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder * encoder,struct radeon_encoder_ext_tmds * tmds)1403926deccbSFrançois Tigeot bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder,
1404926deccbSFrançois Tigeot 						  struct radeon_encoder_ext_tmds *tmds)
1405926deccbSFrançois Tigeot {
1406926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->base.dev;
1407926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1408926deccbSFrançois Tigeot 	uint16_t offset;
1409926deccbSFrançois Tigeot 	uint8_t ver;
1410926deccbSFrançois Tigeot 	enum radeon_combios_ddc gpio;
1411926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec i2c_bus;
1412926deccbSFrançois Tigeot 
1413926deccbSFrançois Tigeot 	tmds->i2c_bus = NULL;
1414926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP) {
1415926deccbSFrançois Tigeot 		i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
1416926deccbSFrançois Tigeot 		tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
1417926deccbSFrançois Tigeot 		tmds->dvo_chip = DVO_SIL164;
1418926deccbSFrançois Tigeot 		tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
1419926deccbSFrançois Tigeot 	} else {
1420926deccbSFrançois Tigeot 		offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
1421926deccbSFrançois Tigeot 		if (offset) {
1422926deccbSFrançois Tigeot 			ver = RBIOS8(offset);
1423926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver);
1424926deccbSFrançois Tigeot 			tmds->slave_addr = RBIOS8(offset + 4 + 2);
1425926deccbSFrançois Tigeot 			tmds->slave_addr >>= 1; /* 7 bit addressing */
1426926deccbSFrançois Tigeot 			gpio = RBIOS8(offset + 4 + 3);
1427926deccbSFrançois Tigeot 			if (gpio == DDC_LCD) {
1428926deccbSFrançois Tigeot 				/* MM i2c */
1429926deccbSFrançois Tigeot 				i2c_bus.valid = true;
1430926deccbSFrançois Tigeot 				i2c_bus.hw_capable = true;
1431926deccbSFrançois Tigeot 				i2c_bus.mm_i2c = true;
1432926deccbSFrançois Tigeot 				i2c_bus.i2c_id = 0xa0;
1433926deccbSFrançois Tigeot 			} else
1434926deccbSFrançois Tigeot 				i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0);
1435926deccbSFrançois Tigeot 			tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
1436926deccbSFrançois Tigeot 		}
1437926deccbSFrançois Tigeot 	}
1438926deccbSFrançois Tigeot 
1439926deccbSFrançois Tigeot 	if (!tmds->i2c_bus) {
1440926deccbSFrançois Tigeot 		DRM_INFO("No valid Ext TMDS info found in BIOS\n");
1441926deccbSFrançois Tigeot 		return false;
1442926deccbSFrançois Tigeot 	}
1443926deccbSFrançois Tigeot 
1444926deccbSFrançois Tigeot 	return true;
1445926deccbSFrançois Tigeot }
1446926deccbSFrançois Tigeot 
radeon_get_legacy_connector_info_from_table(struct drm_device * dev)1447926deccbSFrançois Tigeot bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
1448926deccbSFrançois Tigeot {
1449926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
1450926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec ddc_i2c;
1451926deccbSFrançois Tigeot 	struct radeon_hpd hpd;
1452926deccbSFrançois Tigeot 
1453926deccbSFrançois Tigeot 	rdev->mode_info.connector_table = radeon_connector_table;
1454926deccbSFrançois Tigeot 	if (rdev->mode_info.connector_table == CT_NONE) {
1455926deccbSFrançois Tigeot #ifdef CONFIG_PPC_PMAC
1456926deccbSFrançois Tigeot 		if (of_machine_is_compatible("PowerBook3,3")) {
1457926deccbSFrançois Tigeot 			/* powerbook with VGA */
1458926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_POWERBOOK_VGA;
1459926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerBook3,4") ||
1460926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook3,5")) {
1461926deccbSFrançois Tigeot 			/* powerbook with internal tmds */
1462926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_POWERBOOK_INTERNAL;
1463926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerBook5,1") ||
1464926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook5,2") ||
1465926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook5,3") ||
1466926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook5,4") ||
1467926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook5,5")) {
1468926deccbSFrançois Tigeot 			/* powerbook with external single link tmds (sil164) */
1469926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL;
1470926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerBook5,6")) {
1471926deccbSFrançois Tigeot 			/* powerbook with external dual or single link tmds */
1472926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL;
1473926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerBook5,7") ||
1474926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook5,8") ||
1475926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook5,9")) {
1476926deccbSFrançois Tigeot 			/* PowerBook6,2 ? */
1477926deccbSFrançois Tigeot 			/* powerbook with external dual link tmds (sil1178?) */
1478926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL;
1479926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerBook4,1") ||
1480926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook4,2") ||
1481926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook4,3") ||
1482926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook6,3") ||
1483926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook6,5") ||
1484926deccbSFrançois Tigeot 			   of_machine_is_compatible("PowerBook6,7")) {
1485926deccbSFrançois Tigeot 			/* ibook */
1486926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_IBOOK;
1487926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerMac3,5")) {
1488926deccbSFrançois Tigeot 			/* PowerMac G4 Silver radeon 7500 */
1489926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_MAC_G4_SILVER;
1490926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerMac4,4")) {
1491926deccbSFrançois Tigeot 			/* emac */
1492926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_EMAC;
1493926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerMac10,1")) {
1494926deccbSFrançois Tigeot 			/* mini with internal tmds */
1495926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_MINI_INTERNAL;
1496926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerMac10,2")) {
1497926deccbSFrançois Tigeot 			/* mini with external tmds */
1498926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_MINI_EXTERNAL;
1499926deccbSFrançois Tigeot 		} else if (of_machine_is_compatible("PowerMac12,1")) {
1500926deccbSFrançois Tigeot 			/* PowerMac8,1 ? */
1501926deccbSFrançois Tigeot 			/* imac g5 isight */
1502926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;
1503c6f73aabSFrançois Tigeot 		} else if ((rdev->pdev->device == 0x4a48) &&
1504c6f73aabSFrançois Tigeot 			   (rdev->pdev->subsystem_vendor == 0x1002) &&
1505c6f73aabSFrançois Tigeot 			   (rdev->pdev->subsystem_device == 0x4a48)) {
1506926deccbSFrançois Tigeot 			/* Mac X800 */
1507926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_MAC_X800;
1508926deccbSFrançois Tigeot 		} else if ((of_machine_is_compatible("PowerMac7,2") ||
1509926deccbSFrançois Tigeot 			    of_machine_is_compatible("PowerMac7,3")) &&
1510c6f73aabSFrançois Tigeot 			   (rdev->pdev->device == 0x4150) &&
1511c6f73aabSFrançois Tigeot 			   (rdev->pdev->subsystem_vendor == 0x1002) &&
1512c6f73aabSFrançois Tigeot 			   (rdev->pdev->subsystem_device == 0x4150)) {
1513926deccbSFrançois Tigeot 			/* Mac G5 tower 9600 */
1514926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_MAC_G5_9600;
1515c6f73aabSFrançois Tigeot 		} else if ((rdev->pdev->device == 0x4c66) &&
1516c6f73aabSFrançois Tigeot 			   (rdev->pdev->subsystem_vendor == 0x1002) &&
1517c6f73aabSFrançois Tigeot 			   (rdev->pdev->subsystem_device == 0x4c66)) {
1518926deccbSFrançois Tigeot 			/* SAM440ep RV250 embedded board */
1519926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_SAM440EP;
1520926deccbSFrançois Tigeot 		} else
1521926deccbSFrançois Tigeot #endif /* CONFIG_PPC_PMAC */
1522926deccbSFrançois Tigeot #ifdef CONFIG_PPC64
1523926deccbSFrançois Tigeot 		if (ASIC_IS_RN50(rdev))
1524926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_RN50_POWER;
1525926deccbSFrançois Tigeot 		else
1526926deccbSFrançois Tigeot #endif
1527926deccbSFrançois Tigeot 			rdev->mode_info.connector_table = CT_GENERIC;
1528926deccbSFrançois Tigeot 	}
1529926deccbSFrançois Tigeot 
1530926deccbSFrançois Tigeot 	switch (rdev->mode_info.connector_table) {
1531926deccbSFrançois Tigeot 	case CT_GENERIC:
1532926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (generic)\n",
1533926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1534926deccbSFrançois Tigeot 		/* these are the most common settings */
1535926deccbSFrançois Tigeot 		if (rdev->flags & RADEON_SINGLE_CRTC) {
1536926deccbSFrançois Tigeot 			/* VGA - primary dac */
1537926deccbSFrançois Tigeot 			ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1538926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_NONE;
1539926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
1540926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
1541926deccbSFrançois Tigeot 									ATOM_DEVICE_CRT1_SUPPORT,
1542926deccbSFrançois Tigeot 									1),
1543926deccbSFrançois Tigeot 						  ATOM_DEVICE_CRT1_SUPPORT);
1544926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev, 0,
1545926deccbSFrançois Tigeot 						    ATOM_DEVICE_CRT1_SUPPORT,
1546926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_VGA,
1547926deccbSFrançois Tigeot 						    &ddc_i2c,
1548926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_VGA,
1549926deccbSFrançois Tigeot 						    &hpd);
1550926deccbSFrançois Tigeot 		} else if (rdev->flags & RADEON_IS_MOBILITY) {
1551926deccbSFrançois Tigeot 			/* LVDS */
1552926deccbSFrançois Tigeot 			ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0);
1553926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_NONE;
1554926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
1555926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
1556926deccbSFrançois Tigeot 									ATOM_DEVICE_LCD1_SUPPORT,
1557926deccbSFrançois Tigeot 									0),
1558926deccbSFrançois Tigeot 						  ATOM_DEVICE_LCD1_SUPPORT);
1559926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev, 0,
1560926deccbSFrançois Tigeot 						    ATOM_DEVICE_LCD1_SUPPORT,
1561926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_LVDS,
1562926deccbSFrançois Tigeot 						    &ddc_i2c,
1563926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_LVDS,
1564926deccbSFrançois Tigeot 						    &hpd);
1565926deccbSFrançois Tigeot 
1566926deccbSFrançois Tigeot 			/* VGA - primary dac */
1567926deccbSFrançois Tigeot 			ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1568926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_NONE;
1569926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
1570926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
1571926deccbSFrançois Tigeot 									ATOM_DEVICE_CRT1_SUPPORT,
1572926deccbSFrançois Tigeot 									1),
1573926deccbSFrançois Tigeot 						  ATOM_DEVICE_CRT1_SUPPORT);
1574926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev, 1,
1575926deccbSFrançois Tigeot 						    ATOM_DEVICE_CRT1_SUPPORT,
1576926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_VGA,
1577926deccbSFrançois Tigeot 						    &ddc_i2c,
1578926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_VGA,
1579926deccbSFrançois Tigeot 						    &hpd);
1580926deccbSFrançois Tigeot 		} else {
1581926deccbSFrançois Tigeot 			/* DVI-I - tv dac, int tmds */
1582926deccbSFrançois Tigeot 			ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
1583926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_1;
1584926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
1585926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
1586926deccbSFrançois Tigeot 									ATOM_DEVICE_DFP1_SUPPORT,
1587926deccbSFrançois Tigeot 									0),
1588926deccbSFrançois Tigeot 						  ATOM_DEVICE_DFP1_SUPPORT);
1589926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
1590926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
1591926deccbSFrançois Tigeot 									ATOM_DEVICE_CRT2_SUPPORT,
1592926deccbSFrançois Tigeot 									2),
1593926deccbSFrançois Tigeot 						  ATOM_DEVICE_CRT2_SUPPORT);
1594926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev, 0,
1595926deccbSFrançois Tigeot 						    ATOM_DEVICE_DFP1_SUPPORT |
1596926deccbSFrançois Tigeot 						    ATOM_DEVICE_CRT2_SUPPORT,
1597926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_DVII,
1598926deccbSFrançois Tigeot 						    &ddc_i2c,
1599926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
1600926deccbSFrançois Tigeot 						    &hpd);
1601926deccbSFrançois Tigeot 
1602926deccbSFrançois Tigeot 			/* VGA - primary dac */
1603926deccbSFrançois Tigeot 			ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1604926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_NONE;
1605926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
1606926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
1607926deccbSFrançois Tigeot 									ATOM_DEVICE_CRT1_SUPPORT,
1608926deccbSFrançois Tigeot 									1),
1609926deccbSFrançois Tigeot 						  ATOM_DEVICE_CRT1_SUPPORT);
1610926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev, 1,
1611926deccbSFrançois Tigeot 						    ATOM_DEVICE_CRT1_SUPPORT,
1612926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_VGA,
1613926deccbSFrançois Tigeot 						    &ddc_i2c,
1614926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_VGA,
1615926deccbSFrançois Tigeot 						    &hpd);
1616926deccbSFrançois Tigeot 		}
1617926deccbSFrançois Tigeot 
1618926deccbSFrançois Tigeot 		if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
1619926deccbSFrançois Tigeot 			/* TV - tv dac */
1620926deccbSFrançois Tigeot 			ddc_i2c.valid = false;
1621926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_NONE;
1622926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
1623926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
1624926deccbSFrançois Tigeot 									ATOM_DEVICE_TV1_SUPPORT,
1625926deccbSFrançois Tigeot 									2),
1626926deccbSFrançois Tigeot 						  ATOM_DEVICE_TV1_SUPPORT);
1627926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev, 2,
1628926deccbSFrançois Tigeot 						    ATOM_DEVICE_TV1_SUPPORT,
1629926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_SVIDEO,
1630926deccbSFrançois Tigeot 						    &ddc_i2c,
1631926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_SVIDEO,
1632926deccbSFrançois Tigeot 						    &hpd);
1633926deccbSFrançois Tigeot 		}
1634926deccbSFrançois Tigeot 		break;
1635926deccbSFrançois Tigeot 	case CT_IBOOK:
1636926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (ibook)\n",
1637926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1638926deccbSFrançois Tigeot 		/* LVDS */
1639926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
1640926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1641926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1642926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1643926deccbSFrançois Tigeot 								ATOM_DEVICE_LCD1_SUPPORT,
1644926deccbSFrançois Tigeot 								0),
1645926deccbSFrançois Tigeot 					  ATOM_DEVICE_LCD1_SUPPORT);
1646926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
1647926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
1648926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_LVDS,
1649926deccbSFrançois Tigeot 					    &hpd);
1650926deccbSFrançois Tigeot 		/* VGA - TV DAC */
1651926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1652926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1653926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1654926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1655926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
1656926deccbSFrançois Tigeot 								2),
1657926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
1658926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
1659926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
1660926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
1661926deccbSFrançois Tigeot 					    &hpd);
1662926deccbSFrançois Tigeot 		/* TV - TV DAC */
1663926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1664926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1665926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1666926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1667926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1668926deccbSFrançois Tigeot 								2),
1669926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1670926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
1671926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1672926deccbSFrançois Tigeot 					    &ddc_i2c,
1673926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1674926deccbSFrançois Tigeot 					    &hpd);
1675926deccbSFrançois Tigeot 		break;
1676926deccbSFrançois Tigeot 	case CT_POWERBOOK_EXTERNAL:
1677926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (powerbook external tmds)\n",
1678926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1679926deccbSFrançois Tigeot 		/* LVDS */
1680926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
1681926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1682926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1683926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1684926deccbSFrançois Tigeot 								ATOM_DEVICE_LCD1_SUPPORT,
1685926deccbSFrançois Tigeot 								0),
1686926deccbSFrançois Tigeot 					  ATOM_DEVICE_LCD1_SUPPORT);
1687926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
1688926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
1689926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_LVDS,
1690926deccbSFrançois Tigeot 					    &hpd);
1691926deccbSFrançois Tigeot 		/* DVI-I - primary dac, ext tmds */
1692926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1693926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_2; /* ??? */
1694926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1695926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1696926deccbSFrançois Tigeot 								ATOM_DEVICE_DFP2_SUPPORT,
1697926deccbSFrançois Tigeot 								0),
1698926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP2_SUPPORT);
1699926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1700926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1701926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT1_SUPPORT,
1702926deccbSFrançois Tigeot 								1),
1703926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
1704926deccbSFrançois Tigeot 		/* XXX some are SL */
1705926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1,
1706926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP2_SUPPORT |
1707926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT1_SUPPORT,
1708926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
1709926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I,
1710926deccbSFrançois Tigeot 					    &hpd);
1711926deccbSFrançois Tigeot 		/* TV - TV DAC */
1712926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1713926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1714926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1715926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1716926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1717926deccbSFrançois Tigeot 								2),
1718926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1719926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
1720926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1721926deccbSFrançois Tigeot 					    &ddc_i2c,
1722926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1723926deccbSFrançois Tigeot 					    &hpd);
1724926deccbSFrançois Tigeot 		break;
1725926deccbSFrançois Tigeot 	case CT_POWERBOOK_INTERNAL:
1726926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (powerbook internal tmds)\n",
1727926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1728926deccbSFrançois Tigeot 		/* LVDS */
1729926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
1730926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1731926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1732926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1733926deccbSFrançois Tigeot 								ATOM_DEVICE_LCD1_SUPPORT,
1734926deccbSFrançois Tigeot 								0),
1735926deccbSFrançois Tigeot 					  ATOM_DEVICE_LCD1_SUPPORT);
1736926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
1737926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
1738926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_LVDS,
1739926deccbSFrançois Tigeot 					    &hpd);
1740926deccbSFrançois Tigeot 		/* DVI-I - primary dac, int tmds */
1741926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1742926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_1; /* ??? */
1743926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1744926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1745926deccbSFrançois Tigeot 								ATOM_DEVICE_DFP1_SUPPORT,
1746926deccbSFrançois Tigeot 								0),
1747926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP1_SUPPORT);
1748926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1749926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1750926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT1_SUPPORT,
1751926deccbSFrançois Tigeot 								1),
1752926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
1753926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1,
1754926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP1_SUPPORT |
1755926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT1_SUPPORT,
1756926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
1757926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
1758926deccbSFrançois Tigeot 					    &hpd);
1759926deccbSFrançois Tigeot 		/* TV - TV DAC */
1760926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1761926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1762926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1763926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1764926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1765926deccbSFrançois Tigeot 								2),
1766926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1767926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
1768926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1769926deccbSFrançois Tigeot 					    &ddc_i2c,
1770926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1771926deccbSFrançois Tigeot 					    &hpd);
1772926deccbSFrançois Tigeot 		break;
1773926deccbSFrançois Tigeot 	case CT_POWERBOOK_VGA:
1774926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (powerbook vga)\n",
1775926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1776926deccbSFrançois Tigeot 		/* LVDS */
1777926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
1778926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1779926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1780926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1781926deccbSFrançois Tigeot 								ATOM_DEVICE_LCD1_SUPPORT,
1782926deccbSFrançois Tigeot 								0),
1783926deccbSFrançois Tigeot 					  ATOM_DEVICE_LCD1_SUPPORT);
1784926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
1785926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
1786926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_LVDS,
1787926deccbSFrançois Tigeot 					    &hpd);
1788926deccbSFrançois Tigeot 		/* VGA - primary dac */
1789926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1790926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1791926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1792926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1793926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT1_SUPPORT,
1794926deccbSFrançois Tigeot 								1),
1795926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
1796926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
1797926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
1798926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
1799926deccbSFrançois Tigeot 					    &hpd);
1800926deccbSFrançois Tigeot 		/* TV - TV DAC */
1801926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1802926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1803926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1804926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1805926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1806926deccbSFrançois Tigeot 								2),
1807926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1808926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
1809926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1810926deccbSFrançois Tigeot 					    &ddc_i2c,
1811926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1812926deccbSFrançois Tigeot 					    &hpd);
1813926deccbSFrançois Tigeot 		break;
1814926deccbSFrançois Tigeot 	case CT_MINI_EXTERNAL:
1815926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (mini external tmds)\n",
1816926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1817926deccbSFrançois Tigeot 		/* DVI-I - tv dac, ext tmds */
1818926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
1819926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_2; /* ??? */
1820926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1821926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1822926deccbSFrançois Tigeot 								ATOM_DEVICE_DFP2_SUPPORT,
1823926deccbSFrançois Tigeot 								0),
1824926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP2_SUPPORT);
1825926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1826926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1827926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
1828926deccbSFrançois Tigeot 								2),
1829926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
1830926deccbSFrançois Tigeot 		/* XXX are any DL? */
1831926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0,
1832926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP2_SUPPORT |
1833926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT2_SUPPORT,
1834926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
1835926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
1836926deccbSFrançois Tigeot 					    &hpd);
1837926deccbSFrançois Tigeot 		/* TV - TV DAC */
1838926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1839926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1840926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1841926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1842926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1843926deccbSFrançois Tigeot 								2),
1844926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1845926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
1846926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1847926deccbSFrançois Tigeot 					    &ddc_i2c,
1848926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1849926deccbSFrançois Tigeot 					    &hpd);
1850926deccbSFrançois Tigeot 		break;
1851926deccbSFrançois Tigeot 	case CT_MINI_INTERNAL:
1852926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (mini internal tmds)\n",
1853926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1854926deccbSFrançois Tigeot 		/* DVI-I - tv dac, int tmds */
1855926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
1856926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_1; /* ??? */
1857926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1858926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1859926deccbSFrançois Tigeot 								ATOM_DEVICE_DFP1_SUPPORT,
1860926deccbSFrançois Tigeot 								0),
1861926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP1_SUPPORT);
1862926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1863926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1864926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
1865926deccbSFrançois Tigeot 								2),
1866926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
1867926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0,
1868926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP1_SUPPORT |
1869926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT2_SUPPORT,
1870926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
1871926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
1872926deccbSFrançois Tigeot 					    &hpd);
1873926deccbSFrançois Tigeot 		/* TV - TV DAC */
1874926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1875926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1876926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1877926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1878926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1879926deccbSFrançois Tigeot 								2),
1880926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1881926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
1882926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1883926deccbSFrançois Tigeot 					    &ddc_i2c,
1884926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1885926deccbSFrançois Tigeot 					    &hpd);
1886926deccbSFrançois Tigeot 		break;
1887926deccbSFrançois Tigeot 	case CT_IMAC_G5_ISIGHT:
1888926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (imac g5 isight)\n",
1889926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1890926deccbSFrançois Tigeot 		/* DVI-D - int tmds */
1891926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
1892926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_1; /* ??? */
1893926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1894926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1895926deccbSFrançois Tigeot 								ATOM_DEVICE_DFP1_SUPPORT,
1896926deccbSFrançois Tigeot 								0),
1897926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP1_SUPPORT);
1898926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT,
1899926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVID, &ddc_i2c,
1900926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D,
1901926deccbSFrançois Tigeot 					    &hpd);
1902926deccbSFrançois Tigeot 		/* VGA - tv dac */
1903926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
1904926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1905926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1906926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1907926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
1908926deccbSFrançois Tigeot 								2),
1909926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
1910926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
1911926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
1912926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
1913926deccbSFrançois Tigeot 					    &hpd);
1914926deccbSFrançois Tigeot 		/* TV - TV DAC */
1915926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1916926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1917926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1918926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1919926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1920926deccbSFrançois Tigeot 								2),
1921926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1922926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
1923926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1924926deccbSFrançois Tigeot 					    &ddc_i2c,
1925926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1926926deccbSFrançois Tigeot 					    &hpd);
1927926deccbSFrançois Tigeot 		break;
1928926deccbSFrançois Tigeot 	case CT_EMAC:
1929926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (emac)\n",
1930926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1931926deccbSFrançois Tigeot 		/* VGA - primary dac */
1932926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1933926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1934926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1935926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1936926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT1_SUPPORT,
1937926deccbSFrançois Tigeot 								1),
1938926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
1939926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
1940926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
1941926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
1942926deccbSFrançois Tigeot 					    &hpd);
1943926deccbSFrançois Tigeot 		/* VGA - tv dac */
1944926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
1945926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1946926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1947926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1948926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
1949926deccbSFrançois Tigeot 								2),
1950926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
1951926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
1952926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
1953926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
1954926deccbSFrançois Tigeot 					    &hpd);
1955926deccbSFrançois Tigeot 		/* TV - TV DAC */
1956926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
1957926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1958926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1959926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1960926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
1961926deccbSFrançois Tigeot 								2),
1962926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
1963926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
1964926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
1965926deccbSFrançois Tigeot 					    &ddc_i2c,
1966926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
1967926deccbSFrançois Tigeot 					    &hpd);
1968926deccbSFrançois Tigeot 		break;
1969926deccbSFrançois Tigeot 	case CT_RN50_POWER:
1970926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (rn50-power)\n",
1971926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1972926deccbSFrançois Tigeot 		/* VGA - primary dac */
1973926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
1974926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1975926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1976926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1977926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT1_SUPPORT,
1978926deccbSFrançois Tigeot 								1),
1979926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
1980926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
1981926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
1982926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
1983926deccbSFrançois Tigeot 					    &hpd);
1984926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
1985926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
1986926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
1987926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
1988926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
1989926deccbSFrançois Tigeot 								2),
1990926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
1991926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
1992926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
1993926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
1994926deccbSFrançois Tigeot 					    &hpd);
1995926deccbSFrançois Tigeot 		break;
1996926deccbSFrançois Tigeot 	case CT_MAC_X800:
1997926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (mac x800)\n",
1998926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
1999926deccbSFrançois Tigeot 		/* DVI - primary dac, internal tmds */
2000926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
2001926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_1; /* ??? */
2002926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2003926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2004926deccbSFrançois Tigeot 								  ATOM_DEVICE_DFP1_SUPPORT,
2005926deccbSFrançois Tigeot 								  0),
2006926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP1_SUPPORT);
2007926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2008926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2009926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT1_SUPPORT,
2010926deccbSFrançois Tigeot 								  1),
2011926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
2012926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0,
2013926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP1_SUPPORT |
2014926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT1_SUPPORT,
2015926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
2016926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
2017926deccbSFrançois Tigeot 					    &hpd);
2018926deccbSFrançois Tigeot 		/* DVI - tv dac, dvo */
2019926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
2020926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_2; /* ??? */
2021926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2022926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2023926deccbSFrançois Tigeot 								  ATOM_DEVICE_DFP2_SUPPORT,
2024926deccbSFrançois Tigeot 								  0),
2025926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP2_SUPPORT);
2026926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2027926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2028926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT2_SUPPORT,
2029926deccbSFrançois Tigeot 								  2),
2030926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
2031926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1,
2032926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP2_SUPPORT |
2033926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT2_SUPPORT,
2034926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
2035926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I,
2036926deccbSFrançois Tigeot 					    &hpd);
2037926deccbSFrançois Tigeot 		break;
2038926deccbSFrançois Tigeot 	case CT_MAC_G5_9600:
2039926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (mac g5 9600)\n",
2040926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
2041926deccbSFrançois Tigeot 		/* DVI - tv dac, dvo */
2042926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
2043926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_1; /* ??? */
2044926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2045926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2046926deccbSFrançois Tigeot 								  ATOM_DEVICE_DFP2_SUPPORT,
2047926deccbSFrançois Tigeot 								  0),
2048926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP2_SUPPORT);
2049926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2050926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2051926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT2_SUPPORT,
2052926deccbSFrançois Tigeot 								  2),
2053926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
2054926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0,
2055926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP2_SUPPORT |
2056926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT2_SUPPORT,
2057926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
2058926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
2059926deccbSFrançois Tigeot 					    &hpd);
2060926deccbSFrançois Tigeot 		/* ADC - primary dac, internal tmds */
2061926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
2062926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_2; /* ??? */
2063926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2064926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2065926deccbSFrançois Tigeot 								  ATOM_DEVICE_DFP1_SUPPORT,
2066926deccbSFrançois Tigeot 								  0),
2067926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP1_SUPPORT);
2068926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2069926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2070926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT1_SUPPORT,
2071926deccbSFrançois Tigeot 								  1),
2072926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
2073926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1,
2074926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP1_SUPPORT |
2075926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT1_SUPPORT,
2076926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
2077926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
2078926deccbSFrançois Tigeot 					    &hpd);
2079926deccbSFrançois Tigeot 		/* TV - TV DAC */
2080926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
2081926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
2082926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2083926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2084926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
2085926deccbSFrançois Tigeot 								2),
2086926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
2087926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
2088926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
2089926deccbSFrançois Tigeot 					    &ddc_i2c,
2090926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
2091926deccbSFrançois Tigeot 					    &hpd);
2092926deccbSFrançois Tigeot 		break;
2093926deccbSFrançois Tigeot 	case CT_SAM440EP:
2094926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (SAM440ep embedded board)\n",
2095926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
2096926deccbSFrançois Tigeot 		/* LVDS */
2097926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0);
2098926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
2099926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2100926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2101926deccbSFrançois Tigeot 								ATOM_DEVICE_LCD1_SUPPORT,
2102926deccbSFrançois Tigeot 								0),
2103926deccbSFrançois Tigeot 					  ATOM_DEVICE_LCD1_SUPPORT);
2104926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
2105926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
2106926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_LVDS,
2107926deccbSFrançois Tigeot 					    &hpd);
2108926deccbSFrançois Tigeot 		/* DVI-I - secondary dac, int tmds */
2109926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
2110926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_1; /* ??? */
2111926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2112926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2113926deccbSFrançois Tigeot 								ATOM_DEVICE_DFP1_SUPPORT,
2114926deccbSFrançois Tigeot 								0),
2115926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP1_SUPPORT);
2116926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2117926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2118926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
2119926deccbSFrançois Tigeot 								2),
2120926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
2121926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1,
2122926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP1_SUPPORT |
2123926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT2_SUPPORT,
2124926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
2125926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
2126926deccbSFrançois Tigeot 					    &hpd);
2127926deccbSFrançois Tigeot 		/* VGA - primary dac */
2128926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
2129926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
2130926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2131926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2132926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT1_SUPPORT,
2133926deccbSFrançois Tigeot 								1),
2134926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
2135926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2,
2136926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT1_SUPPORT,
2137926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
2138926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
2139926deccbSFrançois Tigeot 					    &hpd);
2140926deccbSFrançois Tigeot 		/* TV - TV DAC */
2141926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
2142926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
2143926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2144926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2145926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
2146926deccbSFrançois Tigeot 								2),
2147926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
2148926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 3, ATOM_DEVICE_TV1_SUPPORT,
2149926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
2150926deccbSFrançois Tigeot 					    &ddc_i2c,
2151926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
2152926deccbSFrançois Tigeot 					    &hpd);
2153926deccbSFrançois Tigeot 		break;
2154926deccbSFrançois Tigeot 	case CT_MAC_G4_SILVER:
2155926deccbSFrançois Tigeot 		DRM_INFO("Connector Table: %d (mac g4 silver)\n",
2156926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
2157926deccbSFrançois Tigeot 		/* DVI-I - tv dac, int tmds */
2158926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
2159926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_1; /* ??? */
2160926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2161926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2162926deccbSFrançois Tigeot 								ATOM_DEVICE_DFP1_SUPPORT,
2163926deccbSFrançois Tigeot 								0),
2164926deccbSFrançois Tigeot 					  ATOM_DEVICE_DFP1_SUPPORT);
2165926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2166926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2167926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT2_SUPPORT,
2168926deccbSFrançois Tigeot 								2),
2169926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT2_SUPPORT);
2170926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 0,
2171926deccbSFrançois Tigeot 					    ATOM_DEVICE_DFP1_SUPPORT |
2172926deccbSFrançois Tigeot 					    ATOM_DEVICE_CRT2_SUPPORT,
2173926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
2174926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
2175926deccbSFrançois Tigeot 					    &hpd);
2176926deccbSFrançois Tigeot 		/* VGA - primary dac */
2177926deccbSFrançois Tigeot 		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
2178926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
2179926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2180926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2181926deccbSFrançois Tigeot 								ATOM_DEVICE_CRT1_SUPPORT,
2182926deccbSFrançois Tigeot 								1),
2183926deccbSFrançois Tigeot 					  ATOM_DEVICE_CRT1_SUPPORT);
2184926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
2185926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
2186926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_VGA,
2187926deccbSFrançois Tigeot 					    &hpd);
2188926deccbSFrançois Tigeot 		/* TV - TV DAC */
2189926deccbSFrançois Tigeot 		ddc_i2c.valid = false;
2190926deccbSFrançois Tigeot 		hpd.hpd = RADEON_HPD_NONE;
2191926deccbSFrançois Tigeot 		radeon_add_legacy_encoder(dev,
2192926deccbSFrançois Tigeot 					  radeon_get_encoder_enum(dev,
2193926deccbSFrançois Tigeot 								ATOM_DEVICE_TV1_SUPPORT,
2194926deccbSFrançois Tigeot 								2),
2195926deccbSFrançois Tigeot 					  ATOM_DEVICE_TV1_SUPPORT);
2196926deccbSFrançois Tigeot 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
2197926deccbSFrançois Tigeot 					    DRM_MODE_CONNECTOR_SVIDEO,
2198926deccbSFrançois Tigeot 					    &ddc_i2c,
2199926deccbSFrançois Tigeot 					    CONNECTOR_OBJECT_ID_SVIDEO,
2200926deccbSFrançois Tigeot 					    &hpd);
2201926deccbSFrançois Tigeot 		break;
2202926deccbSFrançois Tigeot 	default:
2203926deccbSFrançois Tigeot 		DRM_INFO("Connector table: %d (invalid)\n",
2204926deccbSFrançois Tigeot 			 rdev->mode_info.connector_table);
2205926deccbSFrançois Tigeot 		return false;
2206926deccbSFrançois Tigeot 	}
2207926deccbSFrançois Tigeot 
2208926deccbSFrançois Tigeot 	radeon_link_encoder_connector(dev);
2209926deccbSFrançois Tigeot 
2210926deccbSFrançois Tigeot 	return true;
2211926deccbSFrançois Tigeot }
2212926deccbSFrançois Tigeot 
radeon_apply_legacy_quirks(struct drm_device * dev,int bios_index,enum radeon_combios_connector * legacy_connector,struct radeon_i2c_bus_rec * ddc_i2c,struct radeon_hpd * hpd)2213926deccbSFrançois Tigeot static bool radeon_apply_legacy_quirks(struct drm_device *dev,
2214926deccbSFrançois Tigeot 				       int bios_index,
2215926deccbSFrançois Tigeot 				       enum radeon_combios_connector
2216926deccbSFrançois Tigeot 				       *legacy_connector,
2217926deccbSFrançois Tigeot 				       struct radeon_i2c_bus_rec *ddc_i2c,
2218926deccbSFrançois Tigeot 				       struct radeon_hpd *hpd)
2219926deccbSFrançois Tigeot {
2220926deccbSFrançois Tigeot 
2221926deccbSFrançois Tigeot 	/* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
2222926deccbSFrançois Tigeot 	   one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */
2223c6f73aabSFrançois Tigeot 	if (dev->pdev->device == 0x515e &&
2224c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_vendor == 0x1014) {
2225926deccbSFrançois Tigeot 		if (*legacy_connector == CONNECTOR_CRT_LEGACY &&
2226926deccbSFrançois Tigeot 		    ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
2227926deccbSFrançois Tigeot 			return false;
2228926deccbSFrançois Tigeot 	}
2229926deccbSFrançois Tigeot 
2230926deccbSFrançois Tigeot 	/* X300 card with extra non-existent DVI port */
2231c6f73aabSFrançois Tigeot 	if (dev->pdev->device == 0x5B60 &&
2232c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_vendor == 0x17af &&
2233c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_device == 0x201e && bios_index == 2) {
2234926deccbSFrançois Tigeot 		if (*legacy_connector == CONNECTOR_DVI_I_LEGACY)
2235926deccbSFrançois Tigeot 			return false;
2236926deccbSFrançois Tigeot 	}
2237926deccbSFrançois Tigeot 
2238926deccbSFrançois Tigeot 	return true;
2239926deccbSFrançois Tigeot }
2240926deccbSFrançois Tigeot 
radeon_apply_legacy_tv_quirks(struct drm_device * dev)2241926deccbSFrançois Tigeot static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev)
2242926deccbSFrançois Tigeot {
2243926deccbSFrançois Tigeot 	/* Acer 5102 has non-existent TV port */
2244c6f73aabSFrançois Tigeot 	if (dev->pdev->device == 0x5975 &&
2245c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_vendor == 0x1025 &&
2246c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_device == 0x009f)
2247926deccbSFrançois Tigeot 		return false;
2248926deccbSFrançois Tigeot 
2249926deccbSFrançois Tigeot 	/* HP dc5750 has non-existent TV port */
2250c6f73aabSFrançois Tigeot 	if (dev->pdev->device == 0x5974 &&
2251c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_vendor == 0x103c &&
2252c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_device == 0x280a)
2253926deccbSFrançois Tigeot 		return false;
2254926deccbSFrançois Tigeot 
2255926deccbSFrançois Tigeot 	/* MSI S270 has non-existent TV port */
2256c6f73aabSFrançois Tigeot 	if (dev->pdev->device == 0x5955 &&
2257c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_vendor == 0x1462 &&
2258c6f73aabSFrançois Tigeot 	    dev->pdev->subsystem_device == 0x0131)
2259926deccbSFrançois Tigeot 		return false;
2260926deccbSFrançois Tigeot 
2261926deccbSFrançois Tigeot 	return true;
2262926deccbSFrançois Tigeot }
2263926deccbSFrançois Tigeot 
combios_check_dl_dvi(struct drm_device * dev,int is_dvi_d)2264926deccbSFrançois Tigeot static uint16_t combios_check_dl_dvi(struct drm_device *dev, int is_dvi_d)
2265926deccbSFrançois Tigeot {
2266926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2267926deccbSFrançois Tigeot 	uint32_t ext_tmds_info;
2268926deccbSFrançois Tigeot 
2269926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP) {
2270926deccbSFrançois Tigeot 		if (is_dvi_d)
2271926deccbSFrançois Tigeot 			return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
2272926deccbSFrançois Tigeot 		else
2273926deccbSFrançois Tigeot 			return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
2274926deccbSFrançois Tigeot 	}
2275926deccbSFrançois Tigeot 	ext_tmds_info = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
2276926deccbSFrançois Tigeot 	if (ext_tmds_info) {
2277926deccbSFrançois Tigeot 		uint8_t rev = RBIOS8(ext_tmds_info);
2278926deccbSFrançois Tigeot 		uint8_t flags = RBIOS8(ext_tmds_info + 4 + 5);
2279926deccbSFrançois Tigeot 		if (rev >= 3) {
2280926deccbSFrançois Tigeot 			if (is_dvi_d)
2281926deccbSFrançois Tigeot 				return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
2282926deccbSFrançois Tigeot 			else
2283926deccbSFrançois Tigeot 				return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
2284926deccbSFrançois Tigeot 		} else {
2285926deccbSFrançois Tigeot 			if (flags & 1) {
2286926deccbSFrançois Tigeot 				if (is_dvi_d)
2287926deccbSFrançois Tigeot 					return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
2288926deccbSFrançois Tigeot 				else
2289926deccbSFrançois Tigeot 					return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
2290926deccbSFrançois Tigeot 			}
2291926deccbSFrançois Tigeot 		}
2292926deccbSFrançois Tigeot 	}
2293926deccbSFrançois Tigeot 	if (is_dvi_d)
2294926deccbSFrançois Tigeot 		return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
2295926deccbSFrançois Tigeot 	else
2296926deccbSFrançois Tigeot 		return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
2297926deccbSFrançois Tigeot }
2298926deccbSFrançois Tigeot 
radeon_get_legacy_connector_info_from_bios(struct drm_device * dev)2299926deccbSFrançois Tigeot bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
2300926deccbSFrançois Tigeot {
2301926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2302926deccbSFrançois Tigeot 	uint32_t conn_info, entry, devices;
2303926deccbSFrançois Tigeot 	uint16_t tmp, connector_object_id;
2304926deccbSFrançois Tigeot 	enum radeon_combios_ddc ddc_type;
2305926deccbSFrançois Tigeot 	enum radeon_combios_connector connector;
2306926deccbSFrançois Tigeot 	int i = 0;
2307926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec ddc_i2c;
2308926deccbSFrançois Tigeot 	struct radeon_hpd hpd;
2309926deccbSFrançois Tigeot 
2310926deccbSFrançois Tigeot 	conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE);
2311926deccbSFrançois Tigeot 	if (conn_info) {
2312926deccbSFrançois Tigeot 		for (i = 0; i < 4; i++) {
2313926deccbSFrançois Tigeot 			entry = conn_info + 2 + i * 2;
2314926deccbSFrançois Tigeot 
2315926deccbSFrançois Tigeot 			if (!RBIOS16(entry))
2316926deccbSFrançois Tigeot 				break;
2317926deccbSFrançois Tigeot 
2318926deccbSFrançois Tigeot 			tmp = RBIOS16(entry);
2319926deccbSFrançois Tigeot 
2320926deccbSFrançois Tigeot 			connector = (tmp >> 12) & 0xf;
2321926deccbSFrançois Tigeot 
2322926deccbSFrançois Tigeot 			ddc_type = (tmp >> 8) & 0xf;
2323926deccbSFrançois Tigeot 			if (ddc_type == 5)
2324926deccbSFrançois Tigeot 				ddc_i2c = radeon_combios_get_i2c_info_from_table(rdev);
2325926deccbSFrançois Tigeot 			else
2326926deccbSFrançois Tigeot 				ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0);
2327926deccbSFrançois Tigeot 
2328926deccbSFrançois Tigeot 			switch (connector) {
2329926deccbSFrançois Tigeot 			case CONNECTOR_PROPRIETARY_LEGACY:
2330926deccbSFrançois Tigeot 			case CONNECTOR_DVI_I_LEGACY:
2331926deccbSFrançois Tigeot 			case CONNECTOR_DVI_D_LEGACY:
2332926deccbSFrançois Tigeot 				if ((tmp >> 4) & 0x1)
2333926deccbSFrançois Tigeot 					hpd.hpd = RADEON_HPD_2;
2334926deccbSFrançois Tigeot 				else
2335926deccbSFrançois Tigeot 					hpd.hpd = RADEON_HPD_1;
2336926deccbSFrançois Tigeot 				break;
2337926deccbSFrançois Tigeot 			default:
2338926deccbSFrançois Tigeot 				hpd.hpd = RADEON_HPD_NONE;
2339926deccbSFrançois Tigeot 				break;
2340926deccbSFrançois Tigeot 			}
2341926deccbSFrançois Tigeot 
2342926deccbSFrançois Tigeot 			if (!radeon_apply_legacy_quirks(dev, i, &connector,
2343926deccbSFrançois Tigeot 							&ddc_i2c, &hpd))
2344926deccbSFrançois Tigeot 				continue;
2345926deccbSFrançois Tigeot 
2346926deccbSFrançois Tigeot 			switch (connector) {
2347926deccbSFrançois Tigeot 			case CONNECTOR_PROPRIETARY_LEGACY:
2348926deccbSFrançois Tigeot 				if ((tmp >> 4) & 0x1)
2349926deccbSFrançois Tigeot 					devices = ATOM_DEVICE_DFP2_SUPPORT;
2350926deccbSFrançois Tigeot 				else
2351926deccbSFrançois Tigeot 					devices = ATOM_DEVICE_DFP1_SUPPORT;
2352926deccbSFrançois Tigeot 				radeon_add_legacy_encoder(dev,
2353926deccbSFrançois Tigeot 							  radeon_get_encoder_enum
2354926deccbSFrançois Tigeot 							  (dev, devices, 0),
2355926deccbSFrançois Tigeot 							  devices);
2356926deccbSFrançois Tigeot 				radeon_add_legacy_connector(dev, i, devices,
2357926deccbSFrançois Tigeot 							    legacy_connector_convert
2358926deccbSFrançois Tigeot 							    [connector],
2359926deccbSFrançois Tigeot 							    &ddc_i2c,
2360926deccbSFrançois Tigeot 							    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D,
2361926deccbSFrançois Tigeot 							    &hpd);
2362926deccbSFrançois Tigeot 				break;
2363926deccbSFrançois Tigeot 			case CONNECTOR_CRT_LEGACY:
2364926deccbSFrançois Tigeot 				if (tmp & 0x1) {
2365926deccbSFrançois Tigeot 					devices = ATOM_DEVICE_CRT2_SUPPORT;
2366926deccbSFrançois Tigeot 					radeon_add_legacy_encoder(dev,
2367926deccbSFrançois Tigeot 								  radeon_get_encoder_enum
2368926deccbSFrançois Tigeot 								  (dev,
2369926deccbSFrançois Tigeot 								   ATOM_DEVICE_CRT2_SUPPORT,
2370926deccbSFrançois Tigeot 								   2),
2371926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT2_SUPPORT);
2372926deccbSFrançois Tigeot 				} else {
2373926deccbSFrançois Tigeot 					devices = ATOM_DEVICE_CRT1_SUPPORT;
2374926deccbSFrançois Tigeot 					radeon_add_legacy_encoder(dev,
2375926deccbSFrançois Tigeot 								  radeon_get_encoder_enum
2376926deccbSFrançois Tigeot 								  (dev,
2377926deccbSFrançois Tigeot 								   ATOM_DEVICE_CRT1_SUPPORT,
2378926deccbSFrançois Tigeot 								   1),
2379926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT1_SUPPORT);
2380926deccbSFrançois Tigeot 				}
2381926deccbSFrançois Tigeot 				radeon_add_legacy_connector(dev,
2382926deccbSFrançois Tigeot 							    i,
2383926deccbSFrançois Tigeot 							    devices,
2384926deccbSFrançois Tigeot 							    legacy_connector_convert
2385926deccbSFrançois Tigeot 							    [connector],
2386926deccbSFrançois Tigeot 							    &ddc_i2c,
2387926deccbSFrançois Tigeot 							    CONNECTOR_OBJECT_ID_VGA,
2388926deccbSFrançois Tigeot 							    &hpd);
2389926deccbSFrançois Tigeot 				break;
2390926deccbSFrançois Tigeot 			case CONNECTOR_DVI_I_LEGACY:
2391926deccbSFrançois Tigeot 				devices = 0;
2392926deccbSFrançois Tigeot 				if (tmp & 0x1) {
2393926deccbSFrançois Tigeot 					devices |= ATOM_DEVICE_CRT2_SUPPORT;
2394926deccbSFrançois Tigeot 					radeon_add_legacy_encoder(dev,
2395926deccbSFrançois Tigeot 								  radeon_get_encoder_enum
2396926deccbSFrançois Tigeot 								  (dev,
2397926deccbSFrançois Tigeot 								   ATOM_DEVICE_CRT2_SUPPORT,
2398926deccbSFrançois Tigeot 								   2),
2399926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT2_SUPPORT);
2400926deccbSFrançois Tigeot 				} else {
2401926deccbSFrançois Tigeot 					devices |= ATOM_DEVICE_CRT1_SUPPORT;
2402926deccbSFrançois Tigeot 					radeon_add_legacy_encoder(dev,
2403926deccbSFrançois Tigeot 								  radeon_get_encoder_enum
2404926deccbSFrançois Tigeot 								  (dev,
2405926deccbSFrançois Tigeot 								   ATOM_DEVICE_CRT1_SUPPORT,
2406926deccbSFrançois Tigeot 								   1),
2407926deccbSFrançois Tigeot 								  ATOM_DEVICE_CRT1_SUPPORT);
2408926deccbSFrançois Tigeot 				}
2409926deccbSFrançois Tigeot 				/* RV100 board with external TDMS bit mis-set.
2410926deccbSFrançois Tigeot 				 * Actually uses internal TMDS, clear the bit.
2411926deccbSFrançois Tigeot 				 */
2412c6f73aabSFrançois Tigeot 				if (dev->pdev->device == 0x5159 &&
2413c6f73aabSFrançois Tigeot 				    dev->pdev->subsystem_vendor == 0x1014 &&
2414c6f73aabSFrançois Tigeot 				    dev->pdev->subsystem_device == 0x029A) {
2415926deccbSFrançois Tigeot 					tmp &= ~(1 << 4);
2416926deccbSFrançois Tigeot 				}
2417926deccbSFrançois Tigeot 				if ((tmp >> 4) & 0x1) {
2418926deccbSFrançois Tigeot 					devices |= ATOM_DEVICE_DFP2_SUPPORT;
2419926deccbSFrançois Tigeot 					radeon_add_legacy_encoder(dev,
2420926deccbSFrançois Tigeot 								  radeon_get_encoder_enum
2421926deccbSFrançois Tigeot 								  (dev,
2422926deccbSFrançois Tigeot 								   ATOM_DEVICE_DFP2_SUPPORT,
2423926deccbSFrançois Tigeot 								   0),
2424926deccbSFrançois Tigeot 								  ATOM_DEVICE_DFP2_SUPPORT);
2425926deccbSFrançois Tigeot 					connector_object_id = combios_check_dl_dvi(dev, 0);
2426926deccbSFrançois Tigeot 				} else {
2427926deccbSFrançois Tigeot 					devices |= ATOM_DEVICE_DFP1_SUPPORT;
2428926deccbSFrançois Tigeot 					radeon_add_legacy_encoder(dev,
2429926deccbSFrançois Tigeot 								  radeon_get_encoder_enum
2430926deccbSFrançois Tigeot 								  (dev,
2431926deccbSFrançois Tigeot 								   ATOM_DEVICE_DFP1_SUPPORT,
2432926deccbSFrançois Tigeot 								   0),
2433926deccbSFrançois Tigeot 								  ATOM_DEVICE_DFP1_SUPPORT);
2434926deccbSFrançois Tigeot 					connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
2435926deccbSFrançois Tigeot 				}
2436926deccbSFrançois Tigeot 				radeon_add_legacy_connector(dev,
2437926deccbSFrançois Tigeot 							    i,
2438926deccbSFrançois Tigeot 							    devices,
2439926deccbSFrançois Tigeot 							    legacy_connector_convert
2440926deccbSFrançois Tigeot 							    [connector],
2441926deccbSFrançois Tigeot 							    &ddc_i2c,
2442926deccbSFrançois Tigeot 							    connector_object_id,
2443926deccbSFrançois Tigeot 							    &hpd);
2444926deccbSFrançois Tigeot 				break;
2445926deccbSFrançois Tigeot 			case CONNECTOR_DVI_D_LEGACY:
2446926deccbSFrançois Tigeot 				if ((tmp >> 4) & 0x1) {
2447926deccbSFrançois Tigeot 					devices = ATOM_DEVICE_DFP2_SUPPORT;
2448926deccbSFrançois Tigeot 					connector_object_id = combios_check_dl_dvi(dev, 1);
2449926deccbSFrançois Tigeot 				} else {
2450926deccbSFrançois Tigeot 					devices = ATOM_DEVICE_DFP1_SUPPORT;
2451926deccbSFrançois Tigeot 					connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
2452926deccbSFrançois Tigeot 				}
2453926deccbSFrançois Tigeot 				radeon_add_legacy_encoder(dev,
2454926deccbSFrançois Tigeot 							  radeon_get_encoder_enum
2455926deccbSFrançois Tigeot 							  (dev, devices, 0),
2456926deccbSFrançois Tigeot 							  devices);
2457926deccbSFrançois Tigeot 				radeon_add_legacy_connector(dev, i, devices,
2458926deccbSFrançois Tigeot 							    legacy_connector_convert
2459926deccbSFrançois Tigeot 							    [connector],
2460926deccbSFrançois Tigeot 							    &ddc_i2c,
2461926deccbSFrançois Tigeot 							    connector_object_id,
2462926deccbSFrançois Tigeot 							    &hpd);
2463926deccbSFrançois Tigeot 				break;
2464926deccbSFrançois Tigeot 			case CONNECTOR_CTV_LEGACY:
2465926deccbSFrançois Tigeot 			case CONNECTOR_STV_LEGACY:
2466926deccbSFrançois Tigeot 				radeon_add_legacy_encoder(dev,
2467926deccbSFrançois Tigeot 							  radeon_get_encoder_enum
2468926deccbSFrançois Tigeot 							  (dev,
2469926deccbSFrançois Tigeot 							   ATOM_DEVICE_TV1_SUPPORT,
2470926deccbSFrançois Tigeot 							   2),
2471926deccbSFrançois Tigeot 							  ATOM_DEVICE_TV1_SUPPORT);
2472926deccbSFrançois Tigeot 				radeon_add_legacy_connector(dev, i,
2473926deccbSFrançois Tigeot 							    ATOM_DEVICE_TV1_SUPPORT,
2474926deccbSFrançois Tigeot 							    legacy_connector_convert
2475926deccbSFrançois Tigeot 							    [connector],
2476926deccbSFrançois Tigeot 							    &ddc_i2c,
2477926deccbSFrançois Tigeot 							    CONNECTOR_OBJECT_ID_SVIDEO,
2478926deccbSFrançois Tigeot 							    &hpd);
2479926deccbSFrançois Tigeot 				break;
2480926deccbSFrançois Tigeot 			default:
2481926deccbSFrançois Tigeot 				DRM_ERROR("Unknown connector type: %d\n",
2482926deccbSFrançois Tigeot 					  connector);
2483926deccbSFrançois Tigeot 				continue;
2484926deccbSFrançois Tigeot 			}
2485926deccbSFrançois Tigeot 
2486926deccbSFrançois Tigeot 		}
2487926deccbSFrançois Tigeot 	} else {
2488926deccbSFrançois Tigeot 		uint16_t tmds_info =
2489926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
2490926deccbSFrançois Tigeot 		if (tmds_info) {
2491926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("Found DFP table, assuming DVI connector\n");
2492926deccbSFrançois Tigeot 
2493926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
2494926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
2495926deccbSFrançois Tigeot 									ATOM_DEVICE_CRT1_SUPPORT,
2496926deccbSFrançois Tigeot 									1),
2497926deccbSFrançois Tigeot 						  ATOM_DEVICE_CRT1_SUPPORT);
2498926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
2499926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
2500926deccbSFrançois Tigeot 									ATOM_DEVICE_DFP1_SUPPORT,
2501926deccbSFrançois Tigeot 									0),
2502926deccbSFrançois Tigeot 						  ATOM_DEVICE_DFP1_SUPPORT);
2503926deccbSFrançois Tigeot 
2504926deccbSFrançois Tigeot 			ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
2505926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_1;
2506926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev,
2507926deccbSFrançois Tigeot 						    0,
2508926deccbSFrançois Tigeot 						    ATOM_DEVICE_CRT1_SUPPORT |
2509926deccbSFrançois Tigeot 						    ATOM_DEVICE_DFP1_SUPPORT,
2510926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_DVII,
2511926deccbSFrançois Tigeot 						    &ddc_i2c,
2512926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
2513926deccbSFrançois Tigeot 						    &hpd);
2514926deccbSFrançois Tigeot 		} else {
2515926deccbSFrançois Tigeot 			uint16_t crt_info =
2516926deccbSFrançois Tigeot 				combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
2517926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("Found CRT table, assuming VGA connector\n");
2518926deccbSFrançois Tigeot 			if (crt_info) {
2519926deccbSFrançois Tigeot 				radeon_add_legacy_encoder(dev,
2520926deccbSFrançois Tigeot 							  radeon_get_encoder_enum(dev,
2521926deccbSFrançois Tigeot 										ATOM_DEVICE_CRT1_SUPPORT,
2522926deccbSFrançois Tigeot 										1),
2523926deccbSFrançois Tigeot 							  ATOM_DEVICE_CRT1_SUPPORT);
2524926deccbSFrançois Tigeot 				ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
2525926deccbSFrançois Tigeot 				hpd.hpd = RADEON_HPD_NONE;
2526926deccbSFrançois Tigeot 				radeon_add_legacy_connector(dev,
2527926deccbSFrançois Tigeot 							    0,
2528926deccbSFrançois Tigeot 							    ATOM_DEVICE_CRT1_SUPPORT,
2529926deccbSFrançois Tigeot 							    DRM_MODE_CONNECTOR_VGA,
2530926deccbSFrançois Tigeot 							    &ddc_i2c,
2531926deccbSFrançois Tigeot 							    CONNECTOR_OBJECT_ID_VGA,
2532926deccbSFrançois Tigeot 							    &hpd);
2533926deccbSFrançois Tigeot 			} else {
2534926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("No connector info found\n");
2535926deccbSFrançois Tigeot 				return false;
2536926deccbSFrançois Tigeot 			}
2537926deccbSFrançois Tigeot 		}
2538926deccbSFrançois Tigeot 	}
2539926deccbSFrançois Tigeot 
2540926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_MOBILITY || rdev->flags & RADEON_IS_IGP) {
2541926deccbSFrançois Tigeot 		uint16_t lcd_info =
2542926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
2543926deccbSFrançois Tigeot 		if (lcd_info) {
2544926deccbSFrançois Tigeot 			uint16_t lcd_ddc_info =
2545926deccbSFrançois Tigeot 			    combios_get_table_offset(dev,
2546926deccbSFrançois Tigeot 						     COMBIOS_LCD_DDC_INFO_TABLE);
2547926deccbSFrançois Tigeot 
2548926deccbSFrançois Tigeot 			radeon_add_legacy_encoder(dev,
2549926deccbSFrançois Tigeot 						  radeon_get_encoder_enum(dev,
2550926deccbSFrançois Tigeot 									ATOM_DEVICE_LCD1_SUPPORT,
2551926deccbSFrançois Tigeot 									0),
2552926deccbSFrançois Tigeot 						  ATOM_DEVICE_LCD1_SUPPORT);
2553926deccbSFrançois Tigeot 
2554926deccbSFrançois Tigeot 			if (lcd_ddc_info) {
2555926deccbSFrançois Tigeot 				ddc_type = RBIOS8(lcd_ddc_info + 2);
2556926deccbSFrançois Tigeot 				switch (ddc_type) {
2557926deccbSFrançois Tigeot 				case DDC_LCD:
2558926deccbSFrançois Tigeot 					ddc_i2c =
2559926deccbSFrançois Tigeot 						combios_setup_i2c_bus(rdev,
2560926deccbSFrançois Tigeot 								      DDC_LCD,
2561926deccbSFrançois Tigeot 								      RBIOS32(lcd_ddc_info + 3),
2562926deccbSFrançois Tigeot 								      RBIOS32(lcd_ddc_info + 7));
2563926deccbSFrançois Tigeot 					radeon_i2c_add(rdev, &ddc_i2c, "LCD");
2564926deccbSFrançois Tigeot 					break;
2565926deccbSFrançois Tigeot 				case DDC_GPIO:
2566926deccbSFrançois Tigeot 					ddc_i2c =
2567926deccbSFrançois Tigeot 						combios_setup_i2c_bus(rdev,
2568926deccbSFrançois Tigeot 								      DDC_GPIO,
2569926deccbSFrançois Tigeot 								      RBIOS32(lcd_ddc_info + 3),
2570926deccbSFrançois Tigeot 								      RBIOS32(lcd_ddc_info + 7));
2571926deccbSFrançois Tigeot 					radeon_i2c_add(rdev, &ddc_i2c, "LCD");
2572926deccbSFrançois Tigeot 					break;
2573926deccbSFrançois Tigeot 				default:
2574926deccbSFrançois Tigeot 					ddc_i2c =
2575926deccbSFrançois Tigeot 						combios_setup_i2c_bus(rdev, ddc_type, 0, 0);
2576926deccbSFrançois Tigeot 					break;
2577926deccbSFrançois Tigeot 				}
2578926deccbSFrançois Tigeot 				DRM_DEBUG_KMS("LCD DDC Info Table found!\n");
2579926deccbSFrançois Tigeot 			} else
2580926deccbSFrançois Tigeot 				ddc_i2c.valid = false;
2581926deccbSFrançois Tigeot 
2582926deccbSFrançois Tigeot 			hpd.hpd = RADEON_HPD_NONE;
2583926deccbSFrançois Tigeot 			radeon_add_legacy_connector(dev,
2584926deccbSFrançois Tigeot 						    5,
2585926deccbSFrançois Tigeot 						    ATOM_DEVICE_LCD1_SUPPORT,
2586926deccbSFrançois Tigeot 						    DRM_MODE_CONNECTOR_LVDS,
2587926deccbSFrançois Tigeot 						    &ddc_i2c,
2588926deccbSFrançois Tigeot 						    CONNECTOR_OBJECT_ID_LVDS,
2589926deccbSFrançois Tigeot 						    &hpd);
2590926deccbSFrançois Tigeot 		}
2591926deccbSFrançois Tigeot 	}
2592926deccbSFrançois Tigeot 
2593926deccbSFrançois Tigeot 	/* check TV table */
2594926deccbSFrançois Tigeot 	if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
2595926deccbSFrançois Tigeot 		uint32_t tv_info =
2596926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
2597926deccbSFrançois Tigeot 		if (tv_info) {
2598926deccbSFrançois Tigeot 			if (RBIOS8(tv_info + 6) == 'T') {
2599926deccbSFrançois Tigeot 				if (radeon_apply_legacy_tv_quirks(dev)) {
2600926deccbSFrançois Tigeot 					hpd.hpd = RADEON_HPD_NONE;
2601926deccbSFrançois Tigeot 					ddc_i2c.valid = false;
2602926deccbSFrançois Tigeot 					radeon_add_legacy_encoder(dev,
2603926deccbSFrançois Tigeot 								  radeon_get_encoder_enum
2604926deccbSFrançois Tigeot 								  (dev,
2605926deccbSFrançois Tigeot 								   ATOM_DEVICE_TV1_SUPPORT,
2606926deccbSFrançois Tigeot 								   2),
2607926deccbSFrançois Tigeot 								  ATOM_DEVICE_TV1_SUPPORT);
2608926deccbSFrançois Tigeot 					radeon_add_legacy_connector(dev, 6,
2609926deccbSFrançois Tigeot 								    ATOM_DEVICE_TV1_SUPPORT,
2610926deccbSFrançois Tigeot 								    DRM_MODE_CONNECTOR_SVIDEO,
2611926deccbSFrançois Tigeot 								    &ddc_i2c,
2612926deccbSFrançois Tigeot 								    CONNECTOR_OBJECT_ID_SVIDEO,
2613926deccbSFrançois Tigeot 								    &hpd);
2614926deccbSFrançois Tigeot 				}
2615926deccbSFrançois Tigeot 			}
2616926deccbSFrançois Tigeot 		}
2617926deccbSFrançois Tigeot 	}
2618926deccbSFrançois Tigeot 
2619926deccbSFrançois Tigeot 	radeon_link_encoder_connector(dev);
2620926deccbSFrançois Tigeot 
2621926deccbSFrançois Tigeot 	return true;
2622926deccbSFrançois Tigeot }
2623926deccbSFrançois Tigeot 
2624926deccbSFrançois Tigeot static const char *thermal_controller_names[] = {
2625926deccbSFrançois Tigeot 	"NONE",
2626926deccbSFrançois Tigeot 	"lm63",
2627926deccbSFrançois Tigeot 	"adm1032",
2628926deccbSFrançois Tigeot };
2629926deccbSFrançois Tigeot 
radeon_combios_get_power_modes(struct radeon_device * rdev)2630926deccbSFrançois Tigeot void radeon_combios_get_power_modes(struct radeon_device *rdev)
2631926deccbSFrançois Tigeot {
2632926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
2633926deccbSFrançois Tigeot 	u16 offset, misc, misc2 = 0;
2634926deccbSFrançois Tigeot 	u8 rev, blocks, tmp;
2635926deccbSFrançois Tigeot 	int state_index = 0;
2636926deccbSFrançois Tigeot 	struct radeon_i2c_bus_rec i2c_bus;
2637926deccbSFrançois Tigeot 
2638926deccbSFrançois Tigeot 	rdev->pm.default_power_state_index = -1;
2639926deccbSFrançois Tigeot 
2640926deccbSFrançois Tigeot 	/* allocate 2 power states */
2641c4ef309bSzrj 	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL);
2642926deccbSFrançois Tigeot 	if (rdev->pm.power_state) {
2643926deccbSFrançois Tigeot 		/* allocate 1 clock mode per state */
2644926deccbSFrançois Tigeot 		rdev->pm.power_state[0].clock_info =
2645c4ef309bSzrj 			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
2646926deccbSFrançois Tigeot 		rdev->pm.power_state[1].clock_info =
2647c4ef309bSzrj 			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
2648926deccbSFrançois Tigeot 		if (!rdev->pm.power_state[0].clock_info ||
2649926deccbSFrançois Tigeot 		    !rdev->pm.power_state[1].clock_info)
2650926deccbSFrançois Tigeot 			goto pm_failed;
2651926deccbSFrançois Tigeot 	} else
2652926deccbSFrançois Tigeot 		goto pm_failed;
2653926deccbSFrançois Tigeot 
2654926deccbSFrançois Tigeot 	/* check for a thermal chip */
2655926deccbSFrançois Tigeot 	offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE);
2656926deccbSFrançois Tigeot 	if (offset) {
2657926deccbSFrançois Tigeot 		u8 thermal_controller = 0, gpio = 0, i2c_addr = 0, clk_bit = 0, data_bit = 0;
2658926deccbSFrançois Tigeot 
2659926deccbSFrançois Tigeot 		rev = RBIOS8(offset);
2660926deccbSFrançois Tigeot 
2661926deccbSFrançois Tigeot 		if (rev == 0) {
2662926deccbSFrançois Tigeot 			thermal_controller = RBIOS8(offset + 3);
2663926deccbSFrançois Tigeot 			gpio = RBIOS8(offset + 4) & 0x3f;
2664926deccbSFrançois Tigeot 			i2c_addr = RBIOS8(offset + 5);
2665926deccbSFrançois Tigeot 		} else if (rev == 1) {
2666926deccbSFrançois Tigeot 			thermal_controller = RBIOS8(offset + 4);
2667926deccbSFrançois Tigeot 			gpio = RBIOS8(offset + 5) & 0x3f;
2668926deccbSFrançois Tigeot 			i2c_addr = RBIOS8(offset + 6);
2669926deccbSFrançois Tigeot 		} else if (rev == 2) {
2670926deccbSFrançois Tigeot 			thermal_controller = RBIOS8(offset + 4);
2671926deccbSFrançois Tigeot 			gpio = RBIOS8(offset + 5) & 0x3f;
2672926deccbSFrançois Tigeot 			i2c_addr = RBIOS8(offset + 6);
2673926deccbSFrançois Tigeot 			clk_bit = RBIOS8(offset + 0xa);
2674926deccbSFrançois Tigeot 			data_bit = RBIOS8(offset + 0xb);
2675926deccbSFrançois Tigeot 		}
2676926deccbSFrançois Tigeot 		if ((thermal_controller > 0) && (thermal_controller < 3)) {
2677926deccbSFrançois Tigeot 			DRM_INFO("Possible %s thermal controller at 0x%02x\n",
2678926deccbSFrançois Tigeot 				 thermal_controller_names[thermal_controller],
2679926deccbSFrançois Tigeot 				 i2c_addr >> 1);
2680926deccbSFrançois Tigeot 			if (gpio == DDC_LCD) {
2681926deccbSFrançois Tigeot 				/* MM i2c */
2682926deccbSFrançois Tigeot 				i2c_bus.valid = true;
2683926deccbSFrançois Tigeot 				i2c_bus.hw_capable = true;
2684926deccbSFrançois Tigeot 				i2c_bus.mm_i2c = true;
2685926deccbSFrançois Tigeot 				i2c_bus.i2c_id = 0xa0;
2686926deccbSFrançois Tigeot 			} else if (gpio == DDC_GPIO)
2687926deccbSFrançois Tigeot 				i2c_bus = combios_setup_i2c_bus(rdev, gpio, 1 << clk_bit, 1 << data_bit);
2688926deccbSFrançois Tigeot 			else
2689926deccbSFrançois Tigeot 				i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0);
2690926deccbSFrançois Tigeot 			rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
2691926deccbSFrançois Tigeot 			if (rdev->pm.i2c_bus) {
2692926deccbSFrançois Tigeot 				struct i2c_board_info info = { };
2693926deccbSFrançois Tigeot 				const char *name = thermal_controller_names[thermal_controller];
2694926deccbSFrançois Tigeot 				info.addr = i2c_addr >> 1;
2695926deccbSFrançois Tigeot 				strlcpy(info.type, name, sizeof(info.type));
2696926deccbSFrançois Tigeot 				i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
2697926deccbSFrançois Tigeot 			}
2698926deccbSFrançois Tigeot 		}
2699926deccbSFrançois Tigeot 	} else {
2700926deccbSFrançois Tigeot 		/* boards with a thermal chip, but no overdrive table */
2701926deccbSFrançois Tigeot 
2702926deccbSFrançois Tigeot 		/* Asus 9600xt has an f75375 on the monid bus */
2703c6f73aabSFrançois Tigeot 		if ((dev->pdev->device == 0x4152) &&
2704c6f73aabSFrançois Tigeot 		    (dev->pdev->subsystem_vendor == 0x1043) &&
2705c6f73aabSFrançois Tigeot 		    (dev->pdev->subsystem_device == 0xc002)) {
2706926deccbSFrançois Tigeot 			i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
2707926deccbSFrançois Tigeot 			rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
2708926deccbSFrançois Tigeot 			if (rdev->pm.i2c_bus) {
2709926deccbSFrançois Tigeot 				struct i2c_board_info info = { };
2710926deccbSFrançois Tigeot 				const char *name = "f75375";
2711926deccbSFrançois Tigeot 				info.addr = 0x28;
2712926deccbSFrançois Tigeot 				strlcpy(info.type, name, sizeof(info.type));
2713926deccbSFrançois Tigeot 				i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
2714926deccbSFrançois Tigeot 				DRM_INFO("Possible %s thermal controller at 0x%02x\n",
2715926deccbSFrançois Tigeot 					 name, info.addr);
2716926deccbSFrançois Tigeot 			}
2717926deccbSFrançois Tigeot 		}
2718926deccbSFrançois Tigeot 	}
2719926deccbSFrançois Tigeot 
2720926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_MOBILITY) {
2721926deccbSFrançois Tigeot 		offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
2722926deccbSFrançois Tigeot 		if (offset) {
2723926deccbSFrançois Tigeot 			rev = RBIOS8(offset);
2724926deccbSFrançois Tigeot 			blocks = RBIOS8(offset + 0x2);
2725926deccbSFrançois Tigeot 			/* power mode 0 tends to be the only valid one */
2726926deccbSFrançois Tigeot 			rdev->pm.power_state[state_index].num_clock_modes = 1;
2727926deccbSFrançois Tigeot 			rdev->pm.power_state[state_index].clock_info[0].mclk = RBIOS32(offset + 0x5 + 0x2);
2728926deccbSFrançois Tigeot 			rdev->pm.power_state[state_index].clock_info[0].sclk = RBIOS32(offset + 0x5 + 0x6);
2729926deccbSFrançois Tigeot 			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
2730926deccbSFrançois Tigeot 			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
2731926deccbSFrançois Tigeot 				goto default_mode;
2732926deccbSFrançois Tigeot 			rdev->pm.power_state[state_index].type =
2733926deccbSFrançois Tigeot 				POWER_STATE_TYPE_BATTERY;
2734926deccbSFrançois Tigeot 			misc = RBIOS16(offset + 0x5 + 0x0);
2735926deccbSFrançois Tigeot 			if (rev > 4)
2736926deccbSFrançois Tigeot 				misc2 = RBIOS16(offset + 0x5 + 0xe);
2737926deccbSFrançois Tigeot 			rdev->pm.power_state[state_index].misc = misc;
2738926deccbSFrançois Tigeot 			rdev->pm.power_state[state_index].misc2 = misc2;
2739926deccbSFrançois Tigeot 			if (misc & 0x4) {
2740926deccbSFrançois Tigeot 				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO;
2741926deccbSFrançois Tigeot 				if (misc & 0x8)
2742926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2743926deccbSFrançois Tigeot 						true;
2744926deccbSFrançois Tigeot 				else
2745926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2746926deccbSFrançois Tigeot 						false;
2747926deccbSFrançois Tigeot 				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = true;
2748926deccbSFrançois Tigeot 				if (rev < 6) {
2749926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
2750926deccbSFrançois Tigeot 						RBIOS16(offset + 0x5 + 0xb) * 4;
2751926deccbSFrançois Tigeot 					tmp = RBIOS8(offset + 0x5 + 0xd);
2752926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
2753926deccbSFrançois Tigeot 				} else {
2754926deccbSFrançois Tigeot 					u8 entries = RBIOS8(offset + 0x5 + 0xb);
2755926deccbSFrançois Tigeot 					u16 voltage_table_offset = RBIOS16(offset + 0x5 + 0xc);
2756926deccbSFrançois Tigeot 					if (entries && voltage_table_offset) {
2757926deccbSFrançois Tigeot 						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
2758926deccbSFrançois Tigeot 							RBIOS16(voltage_table_offset) * 4;
2759926deccbSFrançois Tigeot 						tmp = RBIOS8(voltage_table_offset + 0x2);
2760926deccbSFrançois Tigeot 						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
2761926deccbSFrançois Tigeot 					} else
2762926deccbSFrançois Tigeot 						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = false;
2763926deccbSFrançois Tigeot 				}
2764926deccbSFrançois Tigeot 				switch ((misc2 & 0x700) >> 8) {
2765926deccbSFrançois Tigeot 				case 0:
2766926deccbSFrançois Tigeot 				default:
2767926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 0;
2768926deccbSFrançois Tigeot 					break;
2769926deccbSFrançois Tigeot 				case 1:
2770926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 33;
2771926deccbSFrançois Tigeot 					break;
2772926deccbSFrançois Tigeot 				case 2:
2773926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 66;
2774926deccbSFrançois Tigeot 					break;
2775926deccbSFrançois Tigeot 				case 3:
2776926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 99;
2777926deccbSFrançois Tigeot 					break;
2778926deccbSFrançois Tigeot 				case 4:
2779926deccbSFrançois Tigeot 					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 132;
2780926deccbSFrançois Tigeot 					break;
2781926deccbSFrançois Tigeot 				}
2782926deccbSFrançois Tigeot 			} else
2783926deccbSFrançois Tigeot 				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2784926deccbSFrançois Tigeot 			if (rev > 6)
2785926deccbSFrançois Tigeot 				rdev->pm.power_state[state_index].pcie_lanes =
2786926deccbSFrançois Tigeot 					RBIOS8(offset + 0x5 + 0x10);
2787926deccbSFrançois Tigeot 			rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2788926deccbSFrançois Tigeot 			state_index++;
2789926deccbSFrançois Tigeot 		} else {
2790926deccbSFrançois Tigeot 			/* XXX figure out some good default low power mode for mobility cards w/out power tables */
2791926deccbSFrançois Tigeot 		}
2792926deccbSFrançois Tigeot 	} else {
2793926deccbSFrançois Tigeot 		/* XXX figure out some good default low power mode for desktop cards */
2794926deccbSFrançois Tigeot 	}
2795926deccbSFrançois Tigeot 
2796926deccbSFrançois Tigeot default_mode:
2797926deccbSFrançois Tigeot 	/* add the default mode */
2798926deccbSFrançois Tigeot 	rdev->pm.power_state[state_index].type =
2799926deccbSFrançois Tigeot 		POWER_STATE_TYPE_DEFAULT;
2800926deccbSFrançois Tigeot 	rdev->pm.power_state[state_index].num_clock_modes = 1;
2801926deccbSFrançois Tigeot 	rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
2802926deccbSFrançois Tigeot 	rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
2803926deccbSFrançois Tigeot 	rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
2804926deccbSFrançois Tigeot 	if ((state_index > 0) &&
2805926deccbSFrançois Tigeot 	    (rdev->pm.power_state[0].clock_info[0].voltage.type == VOLTAGE_GPIO))
2806926deccbSFrançois Tigeot 		rdev->pm.power_state[state_index].clock_info[0].voltage =
2807926deccbSFrançois Tigeot 			rdev->pm.power_state[0].clock_info[0].voltage;
2808926deccbSFrançois Tigeot 	else
2809926deccbSFrançois Tigeot 		rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2810926deccbSFrançois Tigeot 	rdev->pm.power_state[state_index].pcie_lanes = 16;
2811926deccbSFrançois Tigeot 	rdev->pm.power_state[state_index].flags = 0;
2812926deccbSFrançois Tigeot 	rdev->pm.default_power_state_index = state_index;
2813926deccbSFrançois Tigeot 	rdev->pm.num_power_states = state_index + 1;
2814926deccbSFrançois Tigeot 
2815926deccbSFrançois Tigeot 	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
2816926deccbSFrançois Tigeot 	rdev->pm.current_clock_mode_index = 0;
2817926deccbSFrançois Tigeot 	return;
2818926deccbSFrançois Tigeot 
2819926deccbSFrançois Tigeot pm_failed:
2820926deccbSFrançois Tigeot 	rdev->pm.default_power_state_index = state_index;
2821926deccbSFrançois Tigeot 	rdev->pm.num_power_states = 0;
2822926deccbSFrançois Tigeot 
2823926deccbSFrançois Tigeot 	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
2824926deccbSFrançois Tigeot 	rdev->pm.current_clock_mode_index = 0;
2825926deccbSFrançois Tigeot }
2826926deccbSFrançois Tigeot 
radeon_external_tmds_setup(struct drm_encoder * encoder)2827926deccbSFrançois Tigeot void radeon_external_tmds_setup(struct drm_encoder *encoder)
2828926deccbSFrançois Tigeot {
2829926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2830926deccbSFrançois Tigeot 	struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
2831926deccbSFrançois Tigeot 
2832926deccbSFrançois Tigeot 	if (!tmds)
2833926deccbSFrançois Tigeot 		return;
2834926deccbSFrançois Tigeot 
2835926deccbSFrançois Tigeot 	switch (tmds->dvo_chip) {
2836926deccbSFrançois Tigeot 	case DVO_SIL164:
2837926deccbSFrançois Tigeot 		/* sil 164 */
2838926deccbSFrançois Tigeot 		radeon_i2c_put_byte(tmds->i2c_bus,
2839926deccbSFrançois Tigeot 				    tmds->slave_addr,
2840926deccbSFrançois Tigeot 				    0x08, 0x30);
2841926deccbSFrançois Tigeot 		radeon_i2c_put_byte(tmds->i2c_bus,
2842926deccbSFrançois Tigeot 				       tmds->slave_addr,
2843926deccbSFrançois Tigeot 				       0x09, 0x00);
2844926deccbSFrançois Tigeot 		radeon_i2c_put_byte(tmds->i2c_bus,
2845926deccbSFrançois Tigeot 				    tmds->slave_addr,
2846926deccbSFrançois Tigeot 				    0x0a, 0x90);
2847926deccbSFrançois Tigeot 		radeon_i2c_put_byte(tmds->i2c_bus,
2848926deccbSFrançois Tigeot 				    tmds->slave_addr,
2849926deccbSFrançois Tigeot 				    0x0c, 0x89);
2850926deccbSFrançois Tigeot 		radeon_i2c_put_byte(tmds->i2c_bus,
2851926deccbSFrançois Tigeot 				       tmds->slave_addr,
2852926deccbSFrançois Tigeot 				       0x08, 0x3b);
2853926deccbSFrançois Tigeot 		break;
2854926deccbSFrançois Tigeot 	case DVO_SIL1178:
2855926deccbSFrançois Tigeot 		/* sil 1178 - untested */
2856926deccbSFrançois Tigeot 		/*
2857926deccbSFrançois Tigeot 		 * 0x0f, 0x44
2858926deccbSFrançois Tigeot 		 * 0x0f, 0x4c
2859926deccbSFrançois Tigeot 		 * 0x0e, 0x01
2860926deccbSFrançois Tigeot 		 * 0x0a, 0x80
2861926deccbSFrançois Tigeot 		 * 0x09, 0x30
2862926deccbSFrançois Tigeot 		 * 0x0c, 0xc9
2863926deccbSFrançois Tigeot 		 * 0x0d, 0x70
2864926deccbSFrançois Tigeot 		 * 0x08, 0x32
2865926deccbSFrançois Tigeot 		 * 0x08, 0x33
2866926deccbSFrançois Tigeot 		 */
2867926deccbSFrançois Tigeot 		break;
2868926deccbSFrançois Tigeot 	default:
2869926deccbSFrançois Tigeot 		break;
2870926deccbSFrançois Tigeot 	}
2871926deccbSFrançois Tigeot 
2872926deccbSFrançois Tigeot }
2873926deccbSFrançois Tigeot 
radeon_combios_external_tmds_setup(struct drm_encoder * encoder)2874926deccbSFrançois Tigeot bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
2875926deccbSFrançois Tigeot {
2876926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
2877926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
2878926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2879926deccbSFrançois Tigeot 	uint16_t offset;
2880926deccbSFrançois Tigeot 	uint8_t blocks, slave_addr, rev;
2881926deccbSFrançois Tigeot 	uint32_t index, id;
2882926deccbSFrançois Tigeot 	uint32_t reg, val, and_mask, or_mask;
2883926deccbSFrançois Tigeot 	struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
2884926deccbSFrançois Tigeot 
2885926deccbSFrançois Tigeot 	if (!tmds)
2886926deccbSFrançois Tigeot 		return false;
2887926deccbSFrançois Tigeot 
2888926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP) {
2889926deccbSFrançois Tigeot 		offset = combios_get_table_offset(dev, COMBIOS_TMDS_POWER_ON_TABLE);
2890926deccbSFrançois Tigeot 		rev = RBIOS8(offset);
2891926deccbSFrançois Tigeot 		if (offset) {
2892926deccbSFrançois Tigeot 			rev = RBIOS8(offset);
2893926deccbSFrançois Tigeot 			if (rev > 1) {
2894926deccbSFrançois Tigeot 				blocks = RBIOS8(offset + 3);
2895926deccbSFrançois Tigeot 				index = offset + 4;
2896926deccbSFrançois Tigeot 				while (blocks > 0) {
2897926deccbSFrançois Tigeot 					id = RBIOS16(index);
2898926deccbSFrançois Tigeot 					index += 2;
2899926deccbSFrançois Tigeot 					switch (id >> 13) {
2900926deccbSFrançois Tigeot 					case 0:
2901926deccbSFrançois Tigeot 						reg = (id & 0x1fff) * 4;
2902926deccbSFrançois Tigeot 						val = RBIOS32(index);
2903926deccbSFrançois Tigeot 						index += 4;
2904926deccbSFrançois Tigeot 						WREG32(reg, val);
2905926deccbSFrançois Tigeot 						break;
2906926deccbSFrançois Tigeot 					case 2:
2907926deccbSFrançois Tigeot 						reg = (id & 0x1fff) * 4;
2908926deccbSFrançois Tigeot 						and_mask = RBIOS32(index);
2909926deccbSFrançois Tigeot 						index += 4;
2910926deccbSFrançois Tigeot 						or_mask = RBIOS32(index);
2911926deccbSFrançois Tigeot 						index += 4;
2912926deccbSFrançois Tigeot 						val = RREG32(reg);
2913926deccbSFrançois Tigeot 						val = (val & and_mask) | or_mask;
2914926deccbSFrançois Tigeot 						WREG32(reg, val);
2915926deccbSFrançois Tigeot 						break;
2916926deccbSFrançois Tigeot 					case 3:
2917926deccbSFrançois Tigeot 						val = RBIOS16(index);
2918926deccbSFrançois Tigeot 						index += 2;
2919c4ef309bSzrj 						udelay(val);
2920926deccbSFrançois Tigeot 						break;
2921926deccbSFrançois Tigeot 					case 4:
2922926deccbSFrançois Tigeot 						val = RBIOS16(index);
2923926deccbSFrançois Tigeot 						index += 2;
2924c4ef309bSzrj 						mdelay(val);
2925926deccbSFrançois Tigeot 						break;
2926926deccbSFrançois Tigeot 					case 6:
2927926deccbSFrançois Tigeot 						slave_addr = id & 0xff;
2928926deccbSFrançois Tigeot 						slave_addr >>= 1; /* 7 bit addressing */
2929926deccbSFrançois Tigeot 						index++;
2930926deccbSFrançois Tigeot 						reg = RBIOS8(index);
2931926deccbSFrançois Tigeot 						index++;
2932926deccbSFrançois Tigeot 						val = RBIOS8(index);
2933926deccbSFrançois Tigeot 						index++;
2934926deccbSFrançois Tigeot 						radeon_i2c_put_byte(tmds->i2c_bus,
2935926deccbSFrançois Tigeot 								    slave_addr,
2936926deccbSFrançois Tigeot 								    reg, val);
2937926deccbSFrançois Tigeot 						break;
2938926deccbSFrançois Tigeot 					default:
2939926deccbSFrançois Tigeot 						DRM_ERROR("Unknown id %d\n", id >> 13);
2940926deccbSFrançois Tigeot 						break;
2941926deccbSFrançois Tigeot 					}
2942926deccbSFrançois Tigeot 					blocks--;
2943926deccbSFrançois Tigeot 				}
2944926deccbSFrançois Tigeot 				return true;
2945926deccbSFrançois Tigeot 			}
2946926deccbSFrançois Tigeot 		}
2947926deccbSFrançois Tigeot 	} else {
2948926deccbSFrançois Tigeot 		offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
2949926deccbSFrançois Tigeot 		if (offset) {
2950926deccbSFrançois Tigeot 			index = offset + 10;
2951926deccbSFrançois Tigeot 			id = RBIOS16(index);
2952926deccbSFrançois Tigeot 			while (id != 0xffff) {
2953926deccbSFrançois Tigeot 				index += 2;
2954926deccbSFrançois Tigeot 				switch (id >> 13) {
2955926deccbSFrançois Tigeot 				case 0:
2956926deccbSFrançois Tigeot 					reg = (id & 0x1fff) * 4;
2957926deccbSFrançois Tigeot 					val = RBIOS32(index);
2958926deccbSFrançois Tigeot 					WREG32(reg, val);
2959926deccbSFrançois Tigeot 					break;
2960926deccbSFrançois Tigeot 				case 2:
2961926deccbSFrançois Tigeot 					reg = (id & 0x1fff) * 4;
2962926deccbSFrançois Tigeot 					and_mask = RBIOS32(index);
2963926deccbSFrançois Tigeot 					index += 4;
2964926deccbSFrançois Tigeot 					or_mask = RBIOS32(index);
2965926deccbSFrançois Tigeot 					index += 4;
2966926deccbSFrançois Tigeot 					val = RREG32(reg);
2967926deccbSFrançois Tigeot 					val = (val & and_mask) | or_mask;
2968926deccbSFrançois Tigeot 					WREG32(reg, val);
2969926deccbSFrançois Tigeot 					break;
2970926deccbSFrançois Tigeot 				case 4:
2971926deccbSFrançois Tigeot 					val = RBIOS16(index);
2972926deccbSFrançois Tigeot 					index += 2;
2973c4ef309bSzrj 					udelay(val);
2974926deccbSFrançois Tigeot 					break;
2975926deccbSFrançois Tigeot 				case 5:
2976926deccbSFrançois Tigeot 					reg = id & 0x1fff;
2977926deccbSFrançois Tigeot 					and_mask = RBIOS32(index);
2978926deccbSFrançois Tigeot 					index += 4;
2979926deccbSFrançois Tigeot 					or_mask = RBIOS32(index);
2980926deccbSFrançois Tigeot 					index += 4;
2981926deccbSFrançois Tigeot 					val = RREG32_PLL(reg);
2982926deccbSFrançois Tigeot 					val = (val & and_mask) | or_mask;
2983926deccbSFrançois Tigeot 					WREG32_PLL(reg, val);
2984926deccbSFrançois Tigeot 					break;
2985926deccbSFrançois Tigeot 				case 6:
2986926deccbSFrançois Tigeot 					reg = id & 0x1fff;
2987926deccbSFrançois Tigeot 					val = RBIOS8(index);
2988926deccbSFrançois Tigeot 					index += 1;
2989926deccbSFrançois Tigeot 					radeon_i2c_put_byte(tmds->i2c_bus,
2990926deccbSFrançois Tigeot 							    tmds->slave_addr,
2991926deccbSFrançois Tigeot 							    reg, val);
2992926deccbSFrançois Tigeot 					break;
2993926deccbSFrançois Tigeot 				default:
2994926deccbSFrançois Tigeot 					DRM_ERROR("Unknown id %d\n", id >> 13);
2995926deccbSFrançois Tigeot 					break;
2996926deccbSFrançois Tigeot 				}
2997926deccbSFrançois Tigeot 				id = RBIOS16(index);
2998926deccbSFrançois Tigeot 			}
2999926deccbSFrançois Tigeot 			return true;
3000926deccbSFrançois Tigeot 		}
3001926deccbSFrançois Tigeot 	}
3002926deccbSFrançois Tigeot 	return false;
3003926deccbSFrançois Tigeot }
3004926deccbSFrançois Tigeot 
combios_parse_mmio_table(struct drm_device * dev,uint16_t offset)3005926deccbSFrançois Tigeot static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset)
3006926deccbSFrançois Tigeot {
3007926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3008926deccbSFrançois Tigeot 
3009926deccbSFrançois Tigeot 	if (offset) {
3010926deccbSFrançois Tigeot 		while (RBIOS16(offset)) {
3011926deccbSFrançois Tigeot 			uint16_t cmd = ((RBIOS16(offset) & 0xe000) >> 13);
3012926deccbSFrançois Tigeot 			uint32_t addr = (RBIOS16(offset) & 0x1fff);
3013926deccbSFrançois Tigeot 			uint32_t val, and_mask, or_mask;
3014926deccbSFrançois Tigeot 			uint32_t tmp;
3015926deccbSFrançois Tigeot 
3016926deccbSFrançois Tigeot 			offset += 2;
3017926deccbSFrançois Tigeot 			switch (cmd) {
3018926deccbSFrançois Tigeot 			case 0:
3019926deccbSFrançois Tigeot 				val = RBIOS32(offset);
3020926deccbSFrançois Tigeot 				offset += 4;
3021926deccbSFrançois Tigeot 				WREG32(addr, val);
3022926deccbSFrançois Tigeot 				break;
3023926deccbSFrançois Tigeot 			case 1:
3024926deccbSFrançois Tigeot 				val = RBIOS32(offset);
3025926deccbSFrançois Tigeot 				offset += 4;
3026926deccbSFrançois Tigeot 				WREG32(addr, val);
3027926deccbSFrançois Tigeot 				break;
3028926deccbSFrançois Tigeot 			case 2:
3029926deccbSFrançois Tigeot 				and_mask = RBIOS32(offset);
3030926deccbSFrançois Tigeot 				offset += 4;
3031926deccbSFrançois Tigeot 				or_mask = RBIOS32(offset);
3032926deccbSFrançois Tigeot 				offset += 4;
3033926deccbSFrançois Tigeot 				tmp = RREG32(addr);
3034926deccbSFrançois Tigeot 				tmp &= and_mask;
3035926deccbSFrançois Tigeot 				tmp |= or_mask;
3036926deccbSFrançois Tigeot 				WREG32(addr, tmp);
3037926deccbSFrançois Tigeot 				break;
3038926deccbSFrançois Tigeot 			case 3:
3039926deccbSFrançois Tigeot 				and_mask = RBIOS32(offset);
3040926deccbSFrançois Tigeot 				offset += 4;
3041926deccbSFrançois Tigeot 				or_mask = RBIOS32(offset);
3042926deccbSFrançois Tigeot 				offset += 4;
3043926deccbSFrançois Tigeot 				tmp = RREG32(addr);
3044926deccbSFrançois Tigeot 				tmp &= and_mask;
3045926deccbSFrançois Tigeot 				tmp |= or_mask;
3046926deccbSFrançois Tigeot 				WREG32(addr, tmp);
3047926deccbSFrançois Tigeot 				break;
3048926deccbSFrançois Tigeot 			case 4:
3049926deccbSFrançois Tigeot 				val = RBIOS16(offset);
3050926deccbSFrançois Tigeot 				offset += 2;
3051c4ef309bSzrj 				udelay(val);
3052926deccbSFrançois Tigeot 				break;
3053926deccbSFrançois Tigeot 			case 5:
3054926deccbSFrançois Tigeot 				val = RBIOS16(offset);
3055926deccbSFrançois Tigeot 				offset += 2;
3056926deccbSFrançois Tigeot 				switch (addr) {
3057926deccbSFrançois Tigeot 				case 8:
3058926deccbSFrançois Tigeot 					while (val--) {
3059926deccbSFrançois Tigeot 						if (!
3060926deccbSFrançois Tigeot 						    (RREG32_PLL
3061926deccbSFrançois Tigeot 						     (RADEON_CLK_PWRMGT_CNTL) &
3062926deccbSFrançois Tigeot 						     RADEON_MC_BUSY))
3063926deccbSFrançois Tigeot 							break;
3064926deccbSFrançois Tigeot 					}
3065926deccbSFrançois Tigeot 					break;
3066926deccbSFrançois Tigeot 				case 9:
3067926deccbSFrançois Tigeot 					while (val--) {
3068926deccbSFrançois Tigeot 						if ((RREG32(RADEON_MC_STATUS) &
3069926deccbSFrançois Tigeot 						     RADEON_MC_IDLE))
3070926deccbSFrançois Tigeot 							break;
3071926deccbSFrançois Tigeot 					}
3072926deccbSFrançois Tigeot 					break;
3073926deccbSFrançois Tigeot 				default:
3074926deccbSFrançois Tigeot 					break;
3075926deccbSFrançois Tigeot 				}
3076926deccbSFrançois Tigeot 				break;
3077926deccbSFrançois Tigeot 			default:
3078926deccbSFrançois Tigeot 				break;
3079926deccbSFrançois Tigeot 			}
3080926deccbSFrançois Tigeot 		}
3081926deccbSFrançois Tigeot 	}
3082926deccbSFrançois Tigeot }
3083926deccbSFrançois Tigeot 
combios_parse_pll_table(struct drm_device * dev,uint16_t offset)3084926deccbSFrançois Tigeot static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset)
3085926deccbSFrançois Tigeot {
3086926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3087926deccbSFrançois Tigeot 
3088926deccbSFrançois Tigeot 	if (offset) {
3089926deccbSFrançois Tigeot 		while (RBIOS8(offset)) {
3090926deccbSFrançois Tigeot 			uint8_t cmd = ((RBIOS8(offset) & 0xc0) >> 6);
3091926deccbSFrançois Tigeot 			uint8_t addr = (RBIOS8(offset) & 0x3f);
3092926deccbSFrançois Tigeot 			uint32_t val, shift, tmp;
3093926deccbSFrançois Tigeot 			uint32_t and_mask, or_mask;
3094926deccbSFrançois Tigeot 
3095926deccbSFrançois Tigeot 			offset++;
3096926deccbSFrançois Tigeot 			switch (cmd) {
3097926deccbSFrançois Tigeot 			case 0:
3098926deccbSFrançois Tigeot 				val = RBIOS32(offset);
3099926deccbSFrançois Tigeot 				offset += 4;
3100926deccbSFrançois Tigeot 				WREG32_PLL(addr, val);
3101926deccbSFrançois Tigeot 				break;
3102926deccbSFrançois Tigeot 			case 1:
3103926deccbSFrançois Tigeot 				shift = RBIOS8(offset) * 8;
3104926deccbSFrançois Tigeot 				offset++;
3105926deccbSFrançois Tigeot 				and_mask = RBIOS8(offset) << shift;
3106926deccbSFrançois Tigeot 				and_mask |= ~(0xff << shift);
3107926deccbSFrançois Tigeot 				offset++;
3108926deccbSFrançois Tigeot 				or_mask = RBIOS8(offset) << shift;
3109926deccbSFrançois Tigeot 				offset++;
3110926deccbSFrançois Tigeot 				tmp = RREG32_PLL(addr);
3111926deccbSFrançois Tigeot 				tmp &= and_mask;
3112926deccbSFrançois Tigeot 				tmp |= or_mask;
3113926deccbSFrançois Tigeot 				WREG32_PLL(addr, tmp);
3114926deccbSFrançois Tigeot 				break;
3115926deccbSFrançois Tigeot 			case 2:
3116926deccbSFrançois Tigeot 			case 3:
3117926deccbSFrançois Tigeot 				tmp = 1000;
3118926deccbSFrançois Tigeot 				switch (addr) {
3119926deccbSFrançois Tigeot 				case 1:
3120c4ef309bSzrj 					udelay(150);
3121926deccbSFrançois Tigeot 					break;
3122926deccbSFrançois Tigeot 				case 2:
3123c4ef309bSzrj 					mdelay(1);
3124926deccbSFrançois Tigeot 					break;
3125926deccbSFrançois Tigeot 				case 3:
3126926deccbSFrançois Tigeot 					while (tmp--) {
3127926deccbSFrançois Tigeot 						if (!
3128926deccbSFrançois Tigeot 						    (RREG32_PLL
3129926deccbSFrançois Tigeot 						     (RADEON_CLK_PWRMGT_CNTL) &
3130926deccbSFrançois Tigeot 						     RADEON_MC_BUSY))
3131926deccbSFrançois Tigeot 							break;
3132926deccbSFrançois Tigeot 					}
3133926deccbSFrançois Tigeot 					break;
3134926deccbSFrançois Tigeot 				case 4:
3135926deccbSFrançois Tigeot 					while (tmp--) {
3136926deccbSFrançois Tigeot 						if (RREG32_PLL
3137926deccbSFrançois Tigeot 						    (RADEON_CLK_PWRMGT_CNTL) &
3138926deccbSFrançois Tigeot 						    RADEON_DLL_READY)
3139926deccbSFrançois Tigeot 							break;
3140926deccbSFrançois Tigeot 					}
3141926deccbSFrançois Tigeot 					break;
3142926deccbSFrançois Tigeot 				case 5:
3143926deccbSFrançois Tigeot 					tmp =
3144926deccbSFrançois Tigeot 					    RREG32_PLL(RADEON_CLK_PWRMGT_CNTL);
3145926deccbSFrançois Tigeot 					if (tmp & RADEON_CG_NO1_DEBUG_0) {
3146926deccbSFrançois Tigeot #if 0
3147926deccbSFrançois Tigeot 						uint32_t mclk_cntl =
3148926deccbSFrançois Tigeot 						    RREG32_PLL
3149926deccbSFrançois Tigeot 						    (RADEON_MCLK_CNTL);
3150926deccbSFrançois Tigeot 						mclk_cntl &= 0xffff0000;
3151926deccbSFrançois Tigeot 						/*mclk_cntl |= 0x00001111;*//* ??? */
3152926deccbSFrançois Tigeot 						WREG32_PLL(RADEON_MCLK_CNTL,
3153926deccbSFrançois Tigeot 							   mclk_cntl);
3154c4ef309bSzrj 						mdelay(10);
3155926deccbSFrançois Tigeot #endif
3156926deccbSFrançois Tigeot 						WREG32_PLL
3157926deccbSFrançois Tigeot 						    (RADEON_CLK_PWRMGT_CNTL,
3158926deccbSFrançois Tigeot 						     tmp &
3159926deccbSFrançois Tigeot 						     ~RADEON_CG_NO1_DEBUG_0);
3160c4ef309bSzrj 						mdelay(10);
3161926deccbSFrançois Tigeot 					}
3162926deccbSFrançois Tigeot 					break;
3163926deccbSFrançois Tigeot 				default:
3164926deccbSFrançois Tigeot 					break;
3165926deccbSFrançois Tigeot 				}
3166926deccbSFrançois Tigeot 				break;
3167926deccbSFrançois Tigeot 			default:
3168926deccbSFrançois Tigeot 				break;
3169926deccbSFrançois Tigeot 			}
3170926deccbSFrançois Tigeot 		}
3171926deccbSFrançois Tigeot 	}
3172926deccbSFrançois Tigeot }
3173926deccbSFrançois Tigeot 
combios_parse_ram_reset_table(struct drm_device * dev,uint16_t offset)3174926deccbSFrançois Tigeot static void combios_parse_ram_reset_table(struct drm_device *dev,
3175926deccbSFrançois Tigeot 					  uint16_t offset)
3176926deccbSFrançois Tigeot {
3177926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3178926deccbSFrançois Tigeot 	uint32_t tmp;
3179926deccbSFrançois Tigeot 
3180926deccbSFrançois Tigeot 	if (offset) {
3181926deccbSFrançois Tigeot 		uint8_t val = RBIOS8(offset);
3182926deccbSFrançois Tigeot 		while (val != 0xff) {
3183926deccbSFrançois Tigeot 			offset++;
3184926deccbSFrançois Tigeot 
3185926deccbSFrançois Tigeot 			if (val == 0x0f) {
3186926deccbSFrançois Tigeot 				uint32_t channel_complete_mask;
3187926deccbSFrançois Tigeot 
3188926deccbSFrançois Tigeot 				if (ASIC_IS_R300(rdev))
3189926deccbSFrançois Tigeot 					channel_complete_mask =
3190926deccbSFrançois Tigeot 					    R300_MEM_PWRUP_COMPLETE;
3191926deccbSFrançois Tigeot 				else
3192926deccbSFrançois Tigeot 					channel_complete_mask =
3193926deccbSFrançois Tigeot 					    RADEON_MEM_PWRUP_COMPLETE;
3194926deccbSFrançois Tigeot 				tmp = 20000;
3195926deccbSFrançois Tigeot 				while (tmp--) {
3196926deccbSFrançois Tigeot 					if ((RREG32(RADEON_MEM_STR_CNTL) &
3197926deccbSFrançois Tigeot 					     channel_complete_mask) ==
3198926deccbSFrançois Tigeot 					    channel_complete_mask)
3199926deccbSFrançois Tigeot 						break;
3200926deccbSFrançois Tigeot 				}
3201926deccbSFrançois Tigeot 			} else {
3202926deccbSFrançois Tigeot 				uint32_t or_mask = RBIOS16(offset);
3203926deccbSFrançois Tigeot 				offset += 2;
3204926deccbSFrançois Tigeot 
3205926deccbSFrançois Tigeot 				tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
3206926deccbSFrançois Tigeot 				tmp &= RADEON_SDRAM_MODE_MASK;
3207926deccbSFrançois Tigeot 				tmp |= or_mask;
3208926deccbSFrançois Tigeot 				WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp);
3209926deccbSFrançois Tigeot 
3210926deccbSFrançois Tigeot 				or_mask = val << 24;
3211926deccbSFrançois Tigeot 				tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
3212926deccbSFrançois Tigeot 				tmp &= RADEON_B3MEM_RESET_MASK;
3213926deccbSFrançois Tigeot 				tmp |= or_mask;
3214926deccbSFrançois Tigeot 				WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp);
3215926deccbSFrançois Tigeot 			}
3216926deccbSFrançois Tigeot 			val = RBIOS8(offset);
3217926deccbSFrançois Tigeot 		}
3218926deccbSFrançois Tigeot 	}
3219926deccbSFrançois Tigeot }
3220926deccbSFrançois Tigeot 
combios_detect_ram(struct drm_device * dev,int ram,int mem_addr_mapping)3221926deccbSFrançois Tigeot static uint32_t combios_detect_ram(struct drm_device *dev, int ram,
3222926deccbSFrançois Tigeot 				   int mem_addr_mapping)
3223926deccbSFrançois Tigeot {
3224926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3225926deccbSFrançois Tigeot 	uint32_t mem_cntl;
3226926deccbSFrançois Tigeot 	uint32_t mem_size;
3227926deccbSFrançois Tigeot 	uint32_t addr = 0;
3228926deccbSFrançois Tigeot 
3229926deccbSFrançois Tigeot 	mem_cntl = RREG32(RADEON_MEM_CNTL);
3230926deccbSFrançois Tigeot 	if (mem_cntl & RV100_HALF_MODE)
3231926deccbSFrançois Tigeot 		ram /= 2;
3232926deccbSFrançois Tigeot 	mem_size = ram;
3233926deccbSFrançois Tigeot 	mem_cntl &= ~(0xff << 8);
3234926deccbSFrançois Tigeot 	mem_cntl |= (mem_addr_mapping & 0xff) << 8;
3235926deccbSFrançois Tigeot 	WREG32(RADEON_MEM_CNTL, mem_cntl);
3236926deccbSFrançois Tigeot 	RREG32(RADEON_MEM_CNTL);
3237926deccbSFrançois Tigeot 
3238926deccbSFrançois Tigeot 	/* sdram reset ? */
3239926deccbSFrançois Tigeot 
3240926deccbSFrançois Tigeot 	/* something like this????  */
3241926deccbSFrançois Tigeot 	while (ram--) {
3242926deccbSFrançois Tigeot 		addr = ram * 1024 * 1024;
3243926deccbSFrançois Tigeot 		/* write to each page */
3244926deccbSFrançois Tigeot 		WREG32_IDX((addr) | RADEON_MM_APER, 0xdeadbeef);
3245926deccbSFrançois Tigeot 		/* read back and verify */
3246926deccbSFrançois Tigeot 		if (RREG32_IDX((addr) | RADEON_MM_APER) != 0xdeadbeef)
3247926deccbSFrançois Tigeot 			return 0;
3248926deccbSFrançois Tigeot 	}
3249926deccbSFrançois Tigeot 
3250926deccbSFrançois Tigeot 	return mem_size;
3251926deccbSFrançois Tigeot }
3252926deccbSFrançois Tigeot 
combios_write_ram_size(struct drm_device * dev)3253926deccbSFrançois Tigeot static void combios_write_ram_size(struct drm_device *dev)
3254926deccbSFrançois Tigeot {
3255926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3256926deccbSFrançois Tigeot 	uint8_t rev;
3257926deccbSFrançois Tigeot 	uint16_t offset;
3258926deccbSFrançois Tigeot 	uint32_t mem_size = 0;
3259926deccbSFrançois Tigeot 	uint32_t mem_cntl = 0;
3260926deccbSFrançois Tigeot 
3261926deccbSFrançois Tigeot 	/* should do something smarter here I guess... */
3262926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP)
3263926deccbSFrançois Tigeot 		return;
3264926deccbSFrançois Tigeot 
3265926deccbSFrançois Tigeot 	/* first check detected mem table */
3266926deccbSFrançois Tigeot 	offset = combios_get_table_offset(dev, COMBIOS_DETECTED_MEM_TABLE);
3267926deccbSFrançois Tigeot 	if (offset) {
3268926deccbSFrançois Tigeot 		rev = RBIOS8(offset);
3269926deccbSFrançois Tigeot 		if (rev < 3) {
3270926deccbSFrançois Tigeot 			mem_cntl = RBIOS32(offset + 1);
3271926deccbSFrançois Tigeot 			mem_size = RBIOS16(offset + 5);
3272926deccbSFrançois Tigeot 			if ((rdev->family < CHIP_R200) &&
3273926deccbSFrançois Tigeot 			    !ASIC_IS_RN50(rdev))
3274926deccbSFrançois Tigeot 				WREG32(RADEON_MEM_CNTL, mem_cntl);
3275926deccbSFrançois Tigeot 		}
3276926deccbSFrançois Tigeot 	}
3277926deccbSFrançois Tigeot 
3278926deccbSFrançois Tigeot 	if (!mem_size) {
3279926deccbSFrançois Tigeot 		offset =
3280926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE);
3281926deccbSFrançois Tigeot 		if (offset) {
3282926deccbSFrançois Tigeot 			rev = RBIOS8(offset - 1);
3283926deccbSFrançois Tigeot 			if (rev < 1) {
3284926deccbSFrançois Tigeot 				if ((rdev->family < CHIP_R200)
3285926deccbSFrançois Tigeot 				    && !ASIC_IS_RN50(rdev)) {
3286926deccbSFrançois Tigeot 					int ram = 0;
3287926deccbSFrançois Tigeot 					int mem_addr_mapping = 0;
3288926deccbSFrançois Tigeot 
3289926deccbSFrançois Tigeot 					while (RBIOS8(offset)) {
3290926deccbSFrançois Tigeot 						ram = RBIOS8(offset);
3291926deccbSFrançois Tigeot 						mem_addr_mapping =
3292926deccbSFrançois Tigeot 						    RBIOS8(offset + 1);
3293926deccbSFrançois Tigeot 						if (mem_addr_mapping != 0x25)
3294926deccbSFrançois Tigeot 							ram *= 2;
3295926deccbSFrançois Tigeot 						mem_size =
3296926deccbSFrançois Tigeot 						    combios_detect_ram(dev, ram,
3297926deccbSFrançois Tigeot 								       mem_addr_mapping);
3298926deccbSFrançois Tigeot 						if (mem_size)
3299926deccbSFrançois Tigeot 							break;
3300926deccbSFrançois Tigeot 						offset += 2;
3301926deccbSFrançois Tigeot 					}
3302926deccbSFrançois Tigeot 				} else
3303926deccbSFrançois Tigeot 					mem_size = RBIOS8(offset);
3304926deccbSFrançois Tigeot 			} else {
3305926deccbSFrançois Tigeot 				mem_size = RBIOS8(offset);
3306926deccbSFrançois Tigeot 				mem_size *= 2;	/* convert to MB */
3307926deccbSFrançois Tigeot 			}
3308926deccbSFrançois Tigeot 		}
3309926deccbSFrançois Tigeot 	}
3310926deccbSFrançois Tigeot 
3311926deccbSFrançois Tigeot 	mem_size *= (1024 * 1024);	/* convert to bytes */
3312926deccbSFrançois Tigeot 	WREG32(RADEON_CONFIG_MEMSIZE, mem_size);
3313926deccbSFrançois Tigeot }
3314926deccbSFrançois Tigeot 
radeon_combios_asic_init(struct drm_device * dev)3315926deccbSFrançois Tigeot void radeon_combios_asic_init(struct drm_device *dev)
3316926deccbSFrançois Tigeot {
3317926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3318926deccbSFrançois Tigeot 	uint16_t table;
3319926deccbSFrançois Tigeot 
3320926deccbSFrançois Tigeot 	/* port hardcoded mac stuff from radeonfb */
3321926deccbSFrançois Tigeot 	if (rdev->bios == NULL)
3322926deccbSFrançois Tigeot 		return;
3323926deccbSFrançois Tigeot 
3324926deccbSFrançois Tigeot 	/* ASIC INIT 1 */
3325926deccbSFrançois Tigeot 	table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_1_TABLE);
3326926deccbSFrançois Tigeot 	if (table)
3327926deccbSFrançois Tigeot 		combios_parse_mmio_table(dev, table);
3328926deccbSFrançois Tigeot 
3329926deccbSFrançois Tigeot 	/* PLL INIT */
3330926deccbSFrançois Tigeot 	table = combios_get_table_offset(dev, COMBIOS_PLL_INIT_TABLE);
3331926deccbSFrançois Tigeot 	if (table)
3332926deccbSFrançois Tigeot 		combios_parse_pll_table(dev, table);
3333926deccbSFrançois Tigeot 
3334926deccbSFrançois Tigeot 	/* ASIC INIT 2 */
3335926deccbSFrançois Tigeot 	table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_2_TABLE);
3336926deccbSFrançois Tigeot 	if (table)
3337926deccbSFrançois Tigeot 		combios_parse_mmio_table(dev, table);
3338926deccbSFrançois Tigeot 
3339926deccbSFrançois Tigeot 	if (!(rdev->flags & RADEON_IS_IGP)) {
3340926deccbSFrançois Tigeot 		/* ASIC INIT 4 */
3341926deccbSFrançois Tigeot 		table =
3342926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_ASIC_INIT_4_TABLE);
3343926deccbSFrançois Tigeot 		if (table)
3344926deccbSFrançois Tigeot 			combios_parse_mmio_table(dev, table);
3345926deccbSFrançois Tigeot 
3346926deccbSFrançois Tigeot 		/* RAM RESET */
3347926deccbSFrançois Tigeot 		table = combios_get_table_offset(dev, COMBIOS_RAM_RESET_TABLE);
3348926deccbSFrançois Tigeot 		if (table)
3349926deccbSFrançois Tigeot 			combios_parse_ram_reset_table(dev, table);
3350926deccbSFrançois Tigeot 
3351926deccbSFrançois Tigeot 		/* ASIC INIT 3 */
3352926deccbSFrançois Tigeot 		table =
3353926deccbSFrançois Tigeot 		    combios_get_table_offset(dev, COMBIOS_ASIC_INIT_3_TABLE);
3354926deccbSFrançois Tigeot 		if (table)
3355926deccbSFrançois Tigeot 			combios_parse_mmio_table(dev, table);
3356926deccbSFrançois Tigeot 
3357926deccbSFrançois Tigeot 		/* write CONFIG_MEMSIZE */
3358926deccbSFrançois Tigeot 		combios_write_ram_size(dev);
3359926deccbSFrançois Tigeot 	}
3360926deccbSFrançois Tigeot 
3361926deccbSFrançois Tigeot 	/* quirk for rs4xx HP nx6125 laptop to make it resume
3362926deccbSFrançois Tigeot 	 * - it hangs on resume inside the dynclk 1 table.
3363926deccbSFrançois Tigeot 	 */
3364926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RS480 &&
3365c6f73aabSFrançois Tigeot 	    rdev->pdev->subsystem_vendor == 0x103c &&
3366c6f73aabSFrançois Tigeot 	    rdev->pdev->subsystem_device == 0x308b)
3367926deccbSFrançois Tigeot 		return;
3368926deccbSFrançois Tigeot 
3369926deccbSFrançois Tigeot 	/* quirk for rs4xx HP dv5000 laptop to make it resume
3370926deccbSFrançois Tigeot 	 * - it hangs on resume inside the dynclk 1 table.
3371926deccbSFrançois Tigeot 	 */
3372926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RS480 &&
3373c6f73aabSFrançois Tigeot 	    rdev->pdev->subsystem_vendor == 0x103c &&
3374c6f73aabSFrançois Tigeot 	    rdev->pdev->subsystem_device == 0x30a4)
3375926deccbSFrançois Tigeot 		return;
3376926deccbSFrançois Tigeot 
3377926deccbSFrançois Tigeot 	/* quirk for rs4xx Compaq Presario V5245EU laptop to make it resume
3378926deccbSFrançois Tigeot 	 * - it hangs on resume inside the dynclk 1 table.
3379926deccbSFrançois Tigeot 	 */
3380926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RS480 &&
3381c6f73aabSFrançois Tigeot 	    rdev->pdev->subsystem_vendor == 0x103c &&
3382c6f73aabSFrançois Tigeot 	    rdev->pdev->subsystem_device == 0x30ae)
3383926deccbSFrançois Tigeot 		return;
3384*a85cb24fSFrançois Tigeot 	/* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume
3385*a85cb24fSFrançois Tigeot 	 * - it hangs on resume inside the dynclk 1 table.
3386*a85cb24fSFrançois Tigeot 	 */
3387*a85cb24fSFrançois Tigeot 	if (rdev->family == CHIP_RS400 &&
3388*a85cb24fSFrançois Tigeot 	    rdev->pdev->subsystem_vendor == 0x1179 &&
3389*a85cb24fSFrançois Tigeot 	    rdev->pdev->subsystem_device == 0xff31)
3390*a85cb24fSFrançois Tigeot 	        return;
3391926deccbSFrançois Tigeot 
3392c59a5c48SFrançois Tigeot 	/* quirk for rs4xx HP Compaq dc5750 Small Form Factor to make it resume
3393c59a5c48SFrançois Tigeot 	 * - it hangs on resume inside the dynclk 1 table.
3394c59a5c48SFrançois Tigeot 	 */
3395c59a5c48SFrançois Tigeot 	if (rdev->family == CHIP_RS480 &&
3396c59a5c48SFrançois Tigeot 	    rdev->pdev->subsystem_vendor == 0x103c &&
3397c59a5c48SFrançois Tigeot 	    rdev->pdev->subsystem_device == 0x280a)
3398c59a5c48SFrançois Tigeot 		return;
3399c59a5c48SFrançois Tigeot 	/* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume
3400c59a5c48SFrançois Tigeot 	 * - it hangs on resume inside the dynclk 1 table.
3401c59a5c48SFrançois Tigeot 	 */
3402c59a5c48SFrançois Tigeot 	if (rdev->family == CHIP_RS400 &&
3403c59a5c48SFrançois Tigeot 	    rdev->pdev->subsystem_vendor == 0x1179 &&
3404c59a5c48SFrançois Tigeot 	    rdev->pdev->subsystem_device == 0xff31)
3405c59a5c48SFrançois Tigeot 	        return;
3406c59a5c48SFrançois Tigeot 
3407926deccbSFrançois Tigeot 	/* DYN CLK 1 */
3408926deccbSFrançois Tigeot 	table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
3409926deccbSFrançois Tigeot 	if (table)
3410926deccbSFrançois Tigeot 		combios_parse_pll_table(dev, table);
3411926deccbSFrançois Tigeot 
3412926deccbSFrançois Tigeot }
3413926deccbSFrançois Tigeot 
radeon_combios_initialize_bios_scratch_regs(struct drm_device * dev)3414926deccbSFrançois Tigeot void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev)
3415926deccbSFrançois Tigeot {
3416926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3417926deccbSFrançois Tigeot 	uint32_t bios_0_scratch, bios_6_scratch, bios_7_scratch;
3418926deccbSFrançois Tigeot 
3419926deccbSFrançois Tigeot 	bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
3420926deccbSFrançois Tigeot 	bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
3421926deccbSFrançois Tigeot 	bios_7_scratch = RREG32(RADEON_BIOS_7_SCRATCH);
3422926deccbSFrançois Tigeot 
3423926deccbSFrançois Tigeot 	/* let the bios control the backlight */
3424926deccbSFrançois Tigeot 	bios_0_scratch &= ~RADEON_DRIVER_BRIGHTNESS_EN;
3425926deccbSFrançois Tigeot 
3426926deccbSFrançois Tigeot 	/* tell the bios not to handle mode switching */
3427926deccbSFrançois Tigeot 	bios_6_scratch |= (RADEON_DISPLAY_SWITCHING_DIS |
3428926deccbSFrançois Tigeot 			   RADEON_ACC_MODE_CHANGE);
3429926deccbSFrançois Tigeot 
3430926deccbSFrançois Tigeot 	/* tell the bios a driver is loaded */
3431926deccbSFrançois Tigeot 	bios_7_scratch |= RADEON_DRV_LOADED;
3432926deccbSFrançois Tigeot 
3433926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
3434926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
3435926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_7_SCRATCH, bios_7_scratch);
3436926deccbSFrançois Tigeot }
3437926deccbSFrançois Tigeot 
radeon_combios_output_lock(struct drm_encoder * encoder,bool lock)3438926deccbSFrançois Tigeot void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock)
3439926deccbSFrançois Tigeot {
3440926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
3441926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3442926deccbSFrançois Tigeot 	uint32_t bios_6_scratch;
3443926deccbSFrançois Tigeot 
3444926deccbSFrançois Tigeot 	bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
3445926deccbSFrançois Tigeot 
3446926deccbSFrançois Tigeot 	if (lock)
3447926deccbSFrançois Tigeot 		bios_6_scratch |= RADEON_DRIVER_CRITICAL;
3448926deccbSFrançois Tigeot 	else
3449926deccbSFrançois Tigeot 		bios_6_scratch &= ~RADEON_DRIVER_CRITICAL;
3450926deccbSFrançois Tigeot 
3451926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
3452926deccbSFrançois Tigeot }
3453926deccbSFrançois Tigeot 
3454926deccbSFrançois Tigeot void
radeon_combios_connected_scratch_regs(struct drm_connector * connector,struct drm_encoder * encoder,bool connected)3455926deccbSFrançois Tigeot radeon_combios_connected_scratch_regs(struct drm_connector *connector,
3456926deccbSFrançois Tigeot 				      struct drm_encoder *encoder,
3457926deccbSFrançois Tigeot 				      bool connected)
3458926deccbSFrançois Tigeot {
3459926deccbSFrançois Tigeot 	struct drm_device *dev = connector->dev;
3460926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3461926deccbSFrançois Tigeot 	struct radeon_connector *radeon_connector =
3462926deccbSFrançois Tigeot 	    to_radeon_connector(connector);
3463926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3464926deccbSFrançois Tigeot 	uint32_t bios_4_scratch = RREG32(RADEON_BIOS_4_SCRATCH);
3465926deccbSFrançois Tigeot 	uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH);
3466926deccbSFrançois Tigeot 
3467926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
3468926deccbSFrançois Tigeot 	    (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
3469926deccbSFrançois Tigeot 		if (connected) {
3470926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("TV1 connected\n");
3471926deccbSFrançois Tigeot 			/* fix me */
3472926deccbSFrançois Tigeot 			bios_4_scratch |= RADEON_TV1_ATTACHED_SVIDEO;
3473926deccbSFrançois Tigeot 			/*save->bios_4_scratch |= RADEON_TV1_ATTACHED_COMP; */
3474926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_TV1_ON;
3475926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_ACC_REQ_TV1;
3476926deccbSFrançois Tigeot 		} else {
3477926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("TV1 disconnected\n");
3478926deccbSFrançois Tigeot 			bios_4_scratch &= ~RADEON_TV1_ATTACHED_MASK;
3479926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_TV1_ON;
3480926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_ACC_REQ_TV1;
3481926deccbSFrançois Tigeot 		}
3482926deccbSFrançois Tigeot 	}
3483926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
3484926deccbSFrançois Tigeot 	    (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
3485926deccbSFrançois Tigeot 		if (connected) {
3486926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("LCD1 connected\n");
3487926deccbSFrançois Tigeot 			bios_4_scratch |= RADEON_LCD1_ATTACHED;
3488926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_LCD1_ON;
3489926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_ACC_REQ_LCD1;
3490926deccbSFrançois Tigeot 		} else {
3491926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("LCD1 disconnected\n");
3492926deccbSFrançois Tigeot 			bios_4_scratch &= ~RADEON_LCD1_ATTACHED;
3493926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_LCD1_ON;
3494926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_ACC_REQ_LCD1;
3495926deccbSFrançois Tigeot 		}
3496926deccbSFrançois Tigeot 	}
3497926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
3498926deccbSFrançois Tigeot 	    (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
3499926deccbSFrançois Tigeot 		if (connected) {
3500926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("CRT1 connected\n");
3501926deccbSFrançois Tigeot 			bios_4_scratch |= RADEON_CRT1_ATTACHED_COLOR;
3502926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_CRT1_ON;
3503926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_ACC_REQ_CRT1;
3504926deccbSFrançois Tigeot 		} else {
3505926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("CRT1 disconnected\n");
3506926deccbSFrançois Tigeot 			bios_4_scratch &= ~RADEON_CRT1_ATTACHED_MASK;
3507926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_CRT1_ON;
3508926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_ACC_REQ_CRT1;
3509926deccbSFrançois Tigeot 		}
3510926deccbSFrançois Tigeot 	}
3511926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
3512926deccbSFrançois Tigeot 	    (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
3513926deccbSFrançois Tigeot 		if (connected) {
3514926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("CRT2 connected\n");
3515926deccbSFrançois Tigeot 			bios_4_scratch |= RADEON_CRT2_ATTACHED_COLOR;
3516926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_CRT2_ON;
3517926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_ACC_REQ_CRT2;
3518926deccbSFrançois Tigeot 		} else {
3519926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("CRT2 disconnected\n");
3520926deccbSFrançois Tigeot 			bios_4_scratch &= ~RADEON_CRT2_ATTACHED_MASK;
3521926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_CRT2_ON;
3522926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_ACC_REQ_CRT2;
3523926deccbSFrançois Tigeot 		}
3524926deccbSFrançois Tigeot 	}
3525926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
3526926deccbSFrançois Tigeot 	    (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
3527926deccbSFrançois Tigeot 		if (connected) {
3528926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("DFP1 connected\n");
3529926deccbSFrançois Tigeot 			bios_4_scratch |= RADEON_DFP1_ATTACHED;
3530926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_DFP1_ON;
3531926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_ACC_REQ_DFP1;
3532926deccbSFrançois Tigeot 		} else {
3533926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("DFP1 disconnected\n");
3534926deccbSFrançois Tigeot 			bios_4_scratch &= ~RADEON_DFP1_ATTACHED;
3535926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_DFP1_ON;
3536926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_ACC_REQ_DFP1;
3537926deccbSFrançois Tigeot 		}
3538926deccbSFrançois Tigeot 	}
3539926deccbSFrançois Tigeot 	if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
3540926deccbSFrançois Tigeot 	    (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
3541926deccbSFrançois Tigeot 		if (connected) {
3542926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("DFP2 connected\n");
3543926deccbSFrançois Tigeot 			bios_4_scratch |= RADEON_DFP2_ATTACHED;
3544926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_DFP2_ON;
3545926deccbSFrançois Tigeot 			bios_5_scratch |= RADEON_ACC_REQ_DFP2;
3546926deccbSFrançois Tigeot 		} else {
3547926deccbSFrançois Tigeot 			DRM_DEBUG_KMS("DFP2 disconnected\n");
3548926deccbSFrançois Tigeot 			bios_4_scratch &= ~RADEON_DFP2_ATTACHED;
3549926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_DFP2_ON;
3550926deccbSFrançois Tigeot 			bios_5_scratch &= ~RADEON_ACC_REQ_DFP2;
3551926deccbSFrançois Tigeot 		}
3552926deccbSFrançois Tigeot 	}
3553926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_4_SCRATCH, bios_4_scratch);
3554926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
3555926deccbSFrançois Tigeot }
3556926deccbSFrançois Tigeot 
3557926deccbSFrançois Tigeot void
radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder * encoder,int crtc)3558926deccbSFrançois Tigeot radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
3559926deccbSFrançois Tigeot {
3560926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
3561926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3562926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3563926deccbSFrançois Tigeot 	uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH);
3564926deccbSFrançois Tigeot 
3565926deccbSFrançois Tigeot 	if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
3566926deccbSFrançois Tigeot 		bios_5_scratch &= ~RADEON_TV1_CRTC_MASK;
3567926deccbSFrançois Tigeot 		bios_5_scratch |= (crtc << RADEON_TV1_CRTC_SHIFT);
3568926deccbSFrançois Tigeot 	}
3569926deccbSFrançois Tigeot 	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
3570926deccbSFrançois Tigeot 		bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK;
3571926deccbSFrançois Tigeot 		bios_5_scratch |= (crtc << RADEON_CRT1_CRTC_SHIFT);
3572926deccbSFrançois Tigeot 	}
3573926deccbSFrançois Tigeot 	if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
3574926deccbSFrançois Tigeot 		bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK;
3575926deccbSFrançois Tigeot 		bios_5_scratch |= (crtc << RADEON_CRT2_CRTC_SHIFT);
3576926deccbSFrançois Tigeot 	}
3577926deccbSFrançois Tigeot 	if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
3578926deccbSFrançois Tigeot 		bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK;
3579926deccbSFrançois Tigeot 		bios_5_scratch |= (crtc << RADEON_LCD1_CRTC_SHIFT);
3580926deccbSFrançois Tigeot 	}
3581926deccbSFrançois Tigeot 	if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
3582926deccbSFrançois Tigeot 		bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK;
3583926deccbSFrançois Tigeot 		bios_5_scratch |= (crtc << RADEON_DFP1_CRTC_SHIFT);
3584926deccbSFrançois Tigeot 	}
3585926deccbSFrançois Tigeot 	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
3586926deccbSFrançois Tigeot 		bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK;
3587926deccbSFrançois Tigeot 		bios_5_scratch |= (crtc << RADEON_DFP2_CRTC_SHIFT);
3588926deccbSFrançois Tigeot 	}
3589926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
3590926deccbSFrançois Tigeot }
3591926deccbSFrançois Tigeot 
3592926deccbSFrançois Tigeot void
radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder * encoder,bool on)3593926deccbSFrançois Tigeot radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
3594926deccbSFrançois Tigeot {
3595926deccbSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
3596926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
3597926deccbSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3598926deccbSFrançois Tigeot 	uint32_t bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
3599926deccbSFrançois Tigeot 
3600926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
3601926deccbSFrançois Tigeot 		if (on)
3602926deccbSFrançois Tigeot 			bios_6_scratch |= RADEON_TV_DPMS_ON;
3603926deccbSFrançois Tigeot 		else
3604926deccbSFrançois Tigeot 			bios_6_scratch &= ~RADEON_TV_DPMS_ON;
3605926deccbSFrançois Tigeot 	}
3606926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
3607926deccbSFrançois Tigeot 		if (on)
3608926deccbSFrançois Tigeot 			bios_6_scratch |= RADEON_CRT_DPMS_ON;
3609926deccbSFrançois Tigeot 		else
3610926deccbSFrançois Tigeot 			bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
3611926deccbSFrançois Tigeot 	}
3612926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
3613926deccbSFrançois Tigeot 		if (on)
3614926deccbSFrançois Tigeot 			bios_6_scratch |= RADEON_LCD_DPMS_ON;
3615926deccbSFrançois Tigeot 		else
3616926deccbSFrançois Tigeot 			bios_6_scratch &= ~RADEON_LCD_DPMS_ON;
3617926deccbSFrançois Tigeot 	}
3618926deccbSFrançois Tigeot 	if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
3619926deccbSFrançois Tigeot 		if (on)
3620926deccbSFrançois Tigeot 			bios_6_scratch |= RADEON_DFP_DPMS_ON;
3621926deccbSFrançois Tigeot 		else
3622926deccbSFrançois Tigeot 			bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
3623926deccbSFrançois Tigeot 	}
3624926deccbSFrançois Tigeot 	WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
3625926deccbSFrançois Tigeot }
3626