1250079Scarl/*
2304380Smav * Copyright 2007-8 Advanced Micro Devices, Inc.
3250079Scarl * Copyright 2008 Red Hat Inc.
4300373Smav *
5250079Scarl * Permission is hereby granted, free of charge, to any person obtaining a
6250079Scarl * copy of this software and associated documentation files (the "Software"),
7250079Scarl * to deal in the Software without restriction, including without limitation
8250079Scarl * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9250079Scarl * and/or sell copies of the Software, and to permit persons to whom the
10250079Scarl * Software is furnished to do so, subject to the following conditions:
11250079Scarl *
12250079Scarl * The above copyright notice and this permission notice shall be included in
13250079Scarl * all copies or substantial portions of the Software.
14250079Scarl *
15250079Scarl * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16250079Scarl * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17250079Scarl * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18250079Scarl * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19250079Scarl * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20250079Scarl * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21250079Scarl * OTHER DEALINGS IN THE SOFTWARE.
22250079Scarl *
23250079Scarl * Authors: Dave Airlie
24250079Scarl *          Alex Deucher
25250079Scarl */
26250079Scarl
27250079Scarl#include <sys/cdefs.h>
28250079Scarl__FBSDID("$FreeBSD$");
29304380Smav
30304380Smav#include <dev/drm2/drmP.h>
31304380Smav#include <dev/drm2/radeon/radeon_drm.h>
32304380Smav#include "radeon.h"
33304380Smav#include "radeon_asic.h" /* Declares several prototypes; clang is pleased. */
34304380Smav
35304380Smav#include "atom.h"
36304380Smav#include "atom-bits.h"
37304380Smav
38304380Smav/* local */
39250079Scarlstatic int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type,
40250079Scarl				    u16 voltage_id, u16 *voltage);
41250079Scarl
42250079Scarlunion atom_supported_devices {
43250079Scarl	struct _ATOM_SUPPORTED_DEVICES_INFO info;
44250079Scarl	struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2;
45250079Scarl	struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
46300373Smav};
47304388Smav
48250079Scarlstatic void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev,
49250079Scarl					  ATOM_GPIO_I2C_ASSIGMENT *gpio,
50301811Sngie					  u8 index)
51301811Sngie{
52250079Scarl	/* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */
53250079Scarl	if ((rdev->family == CHIP_R420) ||
54300373Smav	    (rdev->family == CHIP_R423) ||
55300373Smav	    (rdev->family == CHIP_RV410)) {
56250079Scarl		if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) ||
57250079Scarl		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) ||
58250079Scarl		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) {
59301811Sngie			gpio->ucClkMaskShift = 0x19;
60250079Scarl			gpio->ucDataMaskShift = 0x18;
61250079Scarl		}
62250079Scarl	}
63250079Scarl
64250079Scarl	/* some evergreen boards have bad data for this entry */
65250079Scarl	if (ASIC_IS_DCE4(rdev)) {
66304380Smav		if ((index == 7) &&
67250079Scarl		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
68300373Smav		    (gpio->sucI2cId.ucAccess == 0)) {
69250079Scarl			gpio->sucI2cId.ucAccess = 0x97;
70300373Smav			gpio->ucDataMaskShift = 8;
71300373Smav			gpio->ucDataEnShift = 8;
72300373Smav			gpio->ucDataY_Shift = 8;
73250079Scarl			gpio->ucDataA_Shift = 8;
74301811Sngie		}
75301811Sngie	}
76301811Sngie
77301811Sngie	/* some DCE3 boards have bad data for this entry */
78301811Sngie	if (ASIC_IS_DCE3(rdev)) {
79301811Sngie		if ((index == 4) &&
80301811Sngie		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
81301811Sngie		    (gpio->sucI2cId.ucAccess == 0x94))
82301811Sngie			gpio->sucI2cId.ucAccess = 0x14;
83301811Sngie	}
84301811Sngie}
85301811Sngie
86250079Scarlstatic struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
87250079Scarl{
88300373Smav	struct radeon_i2c_bus_rec i2c;
89250079Scarl
90250079Scarl	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
91300373Smav
92300373Smav	i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
93300373Smav	i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
94300373Smav	i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
95300373Smav	i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
96300373Smav	i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
97300373Smav	i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
98300373Smav	i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
99300373Smav	i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
100300373Smav	i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
101300373Smav	i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
102300373Smav	i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
103300373Smav	i2c.en_data_mask = (1 << gpio->ucDataEnShift);
104300373Smav	i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
105300373Smav	i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
106300373Smav	i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
107300373Smav	i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
108300373Smav
109300373Smav	if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
110300373Smav		i2c.hw_capable = true;
111301811Sngie	else
112301811Sngie		i2c.hw_capable = false;
113301811Sngie
114301811Sngie	if (gpio->sucI2cId.ucAccess == 0xa0)
115301811Sngie		i2c.mm_i2c = true;
116301811Sngie	else
117301811Sngie		i2c.mm_i2c = false;
118301811Sngie
119301811Sngie	i2c.i2c_id = gpio->sucI2cId.ucAccess;
120301811Sngie
121301811Sngie	if (i2c.mask_clk_reg)
122301811Sngie		i2c.valid = true;
123255274Scarl	else
124304380Smav		i2c.valid = false;
125304380Smav
126255274Scarl	return i2c;
127250079Scarl}
128250079Scarl
129255274Scarlstatic struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
130250079Scarl							       uint8_t id)
131300373Smav{
132250079Scarl	struct atom_context *ctx = rdev->mode_info.atom_context;
133250079Scarl	ATOM_GPIO_I2C_ASSIGMENT *gpio;
134250079Scarl	struct radeon_i2c_bus_rec i2c;
135250079Scarl	int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
136250079Scarl	struct _ATOM_GPIO_I2C_INFO *i2c_info;
137250079Scarl	uint16_t data_offset, size;
138250079Scarl	int i, num_indices;
139250079Scarl
140300373Smav	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
141300373Smav	i2c.valid = false;
142300373Smav
143300373Smav	if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
144300373Smav		i2c_info = (struct _ATOM_GPIO_I2C_INFO *)((char *)ctx->bios + data_offset);
145300373Smav
146300373Smav		num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
147300373Smav			sizeof(ATOM_GPIO_I2C_ASSIGMENT);
148250079Scarl
149250079Scarl		for (i = 0; i < num_indices; i++) {
150250079Scarl			gpio = &i2c_info->asGPIO_Info[i];
151250079Scarl
152250079Scarl			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
153250079Scarl
154250079Scarl			if (gpio->sucI2cId.ucAccess == id) {
155250079Scarl				i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
156300373Smav				break;
157250079Scarl			}
158300373Smav		}
159301811Sngie	}
160250079Scarl
161250079Scarl	return i2c;
162300373Smav}
163300373Smav
164300373Smavvoid radeon_atombios_i2c_init(struct radeon_device *rdev)
165300373Smav{
166300373Smav	struct atom_context *ctx = rdev->mode_info.atom_context;
167300373Smav	ATOM_GPIO_I2C_ASSIGMENT *gpio;
168300373Smav	struct radeon_i2c_bus_rec i2c;
169300373Smav	int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
170300373Smav	struct _ATOM_GPIO_I2C_INFO *i2c_info;
171300373Smav	uint16_t data_offset, size;
172300373Smav	int i, num_indices;
173300373Smav	char stmp[32];
174300373Smav
175300373Smav	if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
176300373Smav		i2c_info = (struct _ATOM_GPIO_I2C_INFO *)((char *)ctx->bios + data_offset);
177300373Smav
178300373Smav		num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
179300373Smav			sizeof(ATOM_GPIO_I2C_ASSIGMENT);
180300373Smav
181300373Smav		for (i = 0; i < num_indices; i++) {
182300373Smav			gpio = &i2c_info->asGPIO_Info[i];
183300373Smav
184300373Smav			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
185300373Smav
186300373Smav			i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
187300373Smav
188300373Smav			if (i2c.valid) {
189300373Smav				sprintf(stmp, "0x%x", i2c.i2c_id);
190300373Smav				rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
191300373Smav			}
192300373Smav		}
193300373Smav	}
194300373Smav}
195300373Smav
196300373Smavstatic struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
197300373Smav							u8 id)
198301811Sngie{
199301811Sngie	struct atom_context *ctx = rdev->mode_info.atom_context;
200301811Sngie	struct radeon_gpio_rec gpio;
201301811Sngie	int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
202301811Sngie	struct _ATOM_GPIO_PIN_LUT *gpio_info;
203250079Scarl	ATOM_GPIO_PIN_ASSIGNMENT *pin;
204304404Smav	u16 data_offset, size;
205304404Smav	int i, num_indices;
206304404Smav
207250079Scarl	memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
208250079Scarl	gpio.valid = false;
209300373Smav
210250079Scarl	if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
211250079Scarl		gpio_info = (struct _ATOM_GPIO_PIN_LUT *)((char *)ctx->bios + data_offset);
212250079Scarl
213250079Scarl		num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
214250079Scarl			sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
215301811Sngie
216301811Sngie		for (i = 0; i < num_indices; i++) {
217301811Sngie			pin = &gpio_info->asGPIO_Pin[i];
218301811Sngie			if (id == pin->ucGPIO_ID) {
219301811Sngie				gpio.id = pin->ucGPIO_ID;
220301811Sngie				gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex) * 4;
221301811Sngie				gpio.mask = (1 << pin->ucGpioPinBitShift);
222250079Scarl				gpio.valid = true;
223250079Scarl				break;
224250079Scarl			}
225300373Smav		}
226250079Scarl	}
227300373Smav
228300373Smav	return gpio;
229300373Smav}
230300373Smav
231300373Smavstatic struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev,
232300373Smav							    struct radeon_gpio_rec *gpio)
233300373Smav{
234300373Smav	struct radeon_hpd hpd;
235300373Smav	u32 reg;
236301904Smav
237301811Sngie	memset(&hpd, 0, sizeof(struct radeon_hpd));
238300373Smav
239300373Smav	if (ASIC_IS_DCE6(rdev))
240300373Smav		reg = SI_DC_GPIO_HPD_A;
241300373Smav	else if (ASIC_IS_DCE4(rdev))
242300373Smav		reg = EVERGREEN_DC_GPIO_HPD_A;
243300373Smav	else
244300373Smav		reg = AVIVO_DC_GPIO_HPD_A;
245300373Smav
246300373Smav	hpd.gpio = *gpio;
247300373Smav	if (gpio->reg == reg) {
248300373Smav		switch(gpio->mask) {
249300373Smav		case (1 << 0):
250300373Smav			hpd.hpd = RADEON_HPD_1;
251300373Smav			break;
252300373Smav		case (1 << 8):
253300373Smav			hpd.hpd = RADEON_HPD_2;
254300373Smav			break;
255300373Smav		case (1 << 16):
256300373Smav			hpd.hpd = RADEON_HPD_3;
257304388Smav			break;
258300373Smav		case (1 << 24):
259300373Smav			hpd.hpd = RADEON_HPD_4;
260300373Smav			break;
261300373Smav		case (1 << 26):
262300373Smav			hpd.hpd = RADEON_HPD_5;
263300373Smav			break;
264300373Smav		case (1 << 28):
265250079Scarl			hpd.hpd = RADEON_HPD_6;
266250079Scarl			break;
267300373Smav		default:
268300373Smav			hpd.hpd = RADEON_HPD_NONE;
269300373Smav			break;
270300373Smav		}
271300373Smav	} else
272300373Smav		hpd.hpd = RADEON_HPD_NONE;
273300373Smav	return hpd;
274300373Smav}
275300373Smav
276300373Smavstatic bool radeon_atom_apply_quirks(struct drm_device *dev,
277300373Smav				     uint32_t supported_device,
278300373Smav				     int *connector_type,
279300373Smav				     struct radeon_i2c_bus_rec *i2c_bus,
280300373Smav				     uint16_t *line_mux,
281300373Smav				     struct radeon_hpd *hpd)
282300373Smav{
283300373Smav
284300373Smav	/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
285300373Smav	if ((dev->pci_device == 0x791e) &&
286300373Smav	    (dev->pci_subvendor == 0x1043) &&
287304404Smav	    (dev->pci_subdevice == 0x826d)) {
288255279Scarl		if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
289255279Scarl		    (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
290304404Smav			*connector_type = DRM_MODE_CONNECTOR_DVID;
291255279Scarl	}
292255279Scarl
293304404Smav	/* Asrock RS600 board lists the DVI port as HDMI */
294304404Smav	if ((dev->pci_device == 0x7941) &&
295304404Smav	    (dev->pci_subvendor == 0x1849) &&
296304404Smav	    (dev->pci_subdevice == 0x7941)) {
297304404Smav		if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
298304404Smav		    (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
299304404Smav			*connector_type = DRM_MODE_CONNECTOR_DVID;
300304404Smav	}
301304404Smav
302300373Smav	/* MSI K9A2GM V2/V3 board has no HDMI or DVI */
303250079Scarl	if ((dev->pci_device == 0x796e) &&
304304404Smav	    (dev->pci_subvendor == 0x1462) &&
305304404Smav	    (dev->pci_subdevice == 0x7302)) {
306304404Smav		if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) ||
307304404Smav		    (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
308304404Smav			return false;
309304404Smav	}
310304404Smav
311304380Smav	/* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
312304404Smav	if ((dev->pci_device == 0x7941) &&
313304380Smav	    (dev->pci_subvendor == 0x147b) &&
314304404Smav	    (dev->pci_subdevice == 0x2412)) {
315304404Smav		if (*connector_type == DRM_MODE_CONNECTOR_DVII)
316304404Smav			return false;
317304380Smav	}
318304404Smav
319304404Smav	/* Falcon NW laptop lists vga ddc line for LVDS */
320300373Smav	if ((dev->pci_device == 0x5653) &&
321300373Smav	    (dev->pci_subvendor == 0x1462) &&
322300373Smav	    (dev->pci_subdevice == 0x0291)) {
323304404Smav		if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
324304404Smav			i2c_bus->valid = false;
325300373Smav			*line_mux = 53;
326300373Smav		}
327300373Smav	}
328255272Scarl
329255272Scarl	/* HIS X1300 is DVI+VGA, not DVI+DVI */
330255272Scarl	if ((dev->pci_device == 0x7146) &&
331304404Smav	    (dev->pci_subvendor == 0x17af) &&
332304404Smav	    (dev->pci_subdevice == 0x2058)) {
333304404Smav		if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
334304404Smav			return false;
335304404Smav	}
336304404Smav
337304404Smav	/* Gigabyte X1300 is DVI+VGA, not DVI+DVI */
338304404Smav	if ((dev->pci_device == 0x7142) &&
339300373Smav	    (dev->pci_subvendor == 0x1458) &&
340300373Smav	    (dev->pci_subdevice == 0x2134)) {
341300373Smav		if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
342300373Smav			return false;
343300373Smav	}
344304404Smav
345304404Smav
346304404Smav	/* Funky macbooks */
347304404Smav	if ((dev->pci_device == 0x71C5) &&
348304404Smav	    (dev->pci_subvendor == 0x106b) &&
349304404Smav	    (dev->pci_subdevice == 0x0080)) {
350304404Smav		if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
351304404Smav		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
352304404Smav			return false;
353304404Smav		if (supported_device == ATOM_DEVICE_CRT2_SUPPORT)
354304404Smav			*line_mux = 0x90;
355300373Smav	}
356300373Smav
357300373Smav	/* mac rv630, rv730, others */
358300373Smav	if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) &&
359300373Smav	    (*connector_type == DRM_MODE_CONNECTOR_DVII)) {
360300373Smav		*connector_type = DRM_MODE_CONNECTOR_9PinDIN;
361300373Smav		*line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1;
362300373Smav	}
363300373Smav
364300373Smav	/* ASUS HD 3600 XT board lists the DVI port as HDMI */
365301811Sngie	if ((dev->pci_device == 0x9598) &&
366300373Smav	    (dev->pci_subvendor == 0x1043) &&
367304404Smav	    (dev->pci_subdevice == 0x01da)) {
368304404Smav		if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
369300373Smav			*connector_type = DRM_MODE_CONNECTOR_DVII;
370300373Smav		}
371304404Smav	}
372255274Scarl
373304404Smav	/* ASUS HD 3600 board lists the DVI port as HDMI */
374300373Smav	if ((dev->pci_device == 0x9598) &&
375301811Sngie	    (dev->pci_subvendor == 0x1043) &&
376301811Sngie	    (dev->pci_subdevice == 0x01e4)) {
377300373Smav		if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
378300373Smav			*connector_type = DRM_MODE_CONNECTOR_DVII;
379250079Scarl		}
380300373Smav	}
381300516Smav
382300373Smav	/* ASUS HD 3450 board lists the DVI port as HDMI */
383300373Smav	if ((dev->pci_device == 0x95C5) &&
384304404Smav	    (dev->pci_subvendor == 0x1043) &&
385300373Smav	    (dev->pci_subdevice == 0x01e2)) {
386300373Smav		if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
387300373Smav			*connector_type = DRM_MODE_CONNECTOR_DVII;
388300373Smav		}
389300373Smav	}
390300373Smav
391300373Smav	/* some BIOSes seem to report DAC on HDMI - usually this is a board with
392300373Smav	 * HDMI + VGA reporting as HDMI
393300373Smav	 */
394300373Smav	if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
395300373Smav		if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
396300373Smav			*connector_type = DRM_MODE_CONNECTOR_VGA;
397300516Smav			*line_mux = 0;
398300373Smav		}
399300373Smav	}
400300373Smav
401300373Smav	/* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port
402300373Smav	 * on the laptop and a DVI port on the docking station and
403300373Smav	 * both share the same encoder, hpd pin, and ddc line.
404300373Smav	 * So while the bios table is technically correct,
405300373Smav	 * we drop the DVI port here since xrandr has no concept of
406300373Smav	 * encoders and will try and drive both connectors
407300373Smav	 * with different crtcs which isn't possible on the hardware
408304404Smav	 * side and leaves no crtcs for LVDS or VGA.
409300373Smav	 */
410300373Smav	if (((dev->pci_device == 0x95c4) || (dev->pci_device == 0x9591)) &&
411300373Smav	    (dev->pci_subvendor == 0x1025) &&
412300373Smav	    (dev->pci_subdevice == 0x013c)) {
413300373Smav		if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
414300373Smav		    (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
415300373Smav			/* actually it's a DVI-D port not DVI-I */
416300373Smav			*connector_type = DRM_MODE_CONNECTOR_DVID;
417300373Smav			return false;
418300373Smav		}
419300373Smav	}
420300373Smav
421300373Smav	/* XFX Pine Group device rv730 reports no VGA DDC lines
422300373Smav	 * even though they are wired up to record 0x93
423300373Smav	 */
424300373Smav	if ((dev->pci_device == 0x9498) &&
425300373Smav	    (dev->pci_subvendor == 0x1682) &&
426300373Smav	    (dev->pci_subdevice == 0x2452) &&
427300373Smav	    (i2c_bus->valid == false) &&
428300373Smav	    !(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) {
429300373Smav		struct radeon_device *rdev = dev->dev_private;
430300373Smav		*i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
431300373Smav	}
432300373Smav
433300373Smav	/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
434304404Smav	if (((dev->pci_device == 0x9802) || (dev->pci_device == 0x9806)) &&
435300373Smav	    (dev->pci_subvendor == 0x1734) &&
436300373Smav	    (dev->pci_subdevice == 0x11bd)) {
437300373Smav		if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
438300373Smav			*connector_type = DRM_MODE_CONNECTOR_DVII;
439300373Smav			*line_mux = 0x3103;
440300373Smav		} else if (*connector_type == DRM_MODE_CONNECTOR_DVID) {
441300373Smav			*connector_type = DRM_MODE_CONNECTOR_DVII;
442300373Smav		}
443300373Smav	}
444300373Smav
445300373Smav
446300373Smav	return true;
447300373Smav}
448300373Smav
449300373Smavconst int supported_devices_connector_convert[] = {
450300373Smav	DRM_MODE_CONNECTOR_Unknown,
451300373Smav	DRM_MODE_CONNECTOR_VGA,
452300373Smav	DRM_MODE_CONNECTOR_DVII,
453300373Smav	DRM_MODE_CONNECTOR_DVID,
454300373Smav	DRM_MODE_CONNECTOR_DVIA,
455304394Smav	DRM_MODE_CONNECTOR_SVIDEO,
456304380Smav	DRM_MODE_CONNECTOR_Composite,
457301811Sngie	DRM_MODE_CONNECTOR_LVDS,
458301811Sngie	DRM_MODE_CONNECTOR_Unknown,
459301811Sngie	DRM_MODE_CONNECTOR_Unknown,
460301811Sngie	DRM_MODE_CONNECTOR_HDMIA,
461301811Sngie	DRM_MODE_CONNECTOR_HDMIB,
462301811Sngie	DRM_MODE_CONNECTOR_Unknown,
463300373Smav	DRM_MODE_CONNECTOR_Unknown,
464300516Smav	DRM_MODE_CONNECTOR_9PinDIN,
465300373Smav	DRM_MODE_CONNECTOR_DisplayPort
466300373Smav};
467300373Smav
468300373Smavconst uint16_t supported_devices_connector_object_id_convert[] = {
469300373Smav	CONNECTOR_OBJECT_ID_NONE,
470300373Smav	CONNECTOR_OBJECT_ID_VGA,
471300373Smav	CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
472304380Smav	CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
473304380Smav	CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
474304380Smav	CONNECTOR_OBJECT_ID_COMPOSITE,
475304380Smav	CONNECTOR_OBJECT_ID_SVIDEO,
476304380Smav	CONNECTOR_OBJECT_ID_LVDS,
477304380Smav	CONNECTOR_OBJECT_ID_9PIN_DIN,
478304380Smav	CONNECTOR_OBJECT_ID_9PIN_DIN,
479304380Smav	CONNECTOR_OBJECT_ID_DISPLAYPORT,
480304380Smav	CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
481304380Smav	CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
482304380Smav	CONNECTOR_OBJECT_ID_SVIDEO
483304380Smav};
484250079Scarl
485300373Smavconst int object_connector_convert[] = {
486300373Smav	DRM_MODE_CONNECTOR_Unknown,
487300373Smav	DRM_MODE_CONNECTOR_DVII,
488300373Smav	DRM_MODE_CONNECTOR_DVII,
489300373Smav	DRM_MODE_CONNECTOR_DVID,
490300373Smav	DRM_MODE_CONNECTOR_DVID,
491300373Smav	DRM_MODE_CONNECTOR_VGA,
492300373Smav	DRM_MODE_CONNECTOR_Composite,
493300373Smav	DRM_MODE_CONNECTOR_SVIDEO,
494300373Smav	DRM_MODE_CONNECTOR_Unknown,
495300373Smav	DRM_MODE_CONNECTOR_Unknown,
496300373Smav	DRM_MODE_CONNECTOR_9PinDIN,
497300373Smav	DRM_MODE_CONNECTOR_Unknown,
498300373Smav	DRM_MODE_CONNECTOR_HDMIA,
499300373Smav	DRM_MODE_CONNECTOR_HDMIB,
500300373Smav	DRM_MODE_CONNECTOR_LVDS,
501300373Smav	DRM_MODE_CONNECTOR_9PinDIN,
502300373Smav	DRM_MODE_CONNECTOR_Unknown,
503300373Smav	DRM_MODE_CONNECTOR_Unknown,
504250079Scarl	DRM_MODE_CONNECTOR_Unknown,
505250079Scarl	DRM_MODE_CONNECTOR_DisplayPort,
506300373Smav	DRM_MODE_CONNECTOR_eDP,
507300373Smav	DRM_MODE_CONNECTOR_Unknown
508300373Smav};
509300373Smav
510300373Smavbool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
511300373Smav{
512300373Smav	struct radeon_device *rdev = dev->dev_private;
513300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
514300373Smav	struct atom_context *ctx = mode_info->atom_context;
515300373Smav	int index = GetIndexIntoMasterTable(DATA, Object_Header);
516300373Smav	u16 size, data_offset;
517300373Smav	u8 frev, crev;
518300373Smav	ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
519300373Smav	ATOM_ENCODER_OBJECT_TABLE *enc_obj;
520300373Smav	ATOM_OBJECT_TABLE *router_obj;
521300373Smav	ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
522300373Smav	ATOM_OBJECT_HEADER *obj_header;
523300373Smav	int i, j, k, path_size, device_support;
524300373Smav	int connector_type;
525300373Smav	u16 igp_lane_info, conn_id, connector_object_id;
526300373Smav	struct radeon_i2c_bus_rec ddc_bus;
527300373Smav	struct radeon_router router;
528300373Smav	struct radeon_gpio_rec gpio;
529300373Smav	struct radeon_hpd hpd;
530300373Smav
531300373Smav	if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
532300373Smav		return false;
533300373Smav
534300373Smav	if (crev < 2)
535300373Smav		return false;
536300373Smav
537300373Smav	obj_header = (ATOM_OBJECT_HEADER *) ((char *)ctx->bios + data_offset);
538300373Smav	path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
539300373Smav	    ((char *)ctx->bios + data_offset +
540300373Smav	     le16_to_cpu(obj_header->usDisplayPathTableOffset));
541300373Smav	con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
542300373Smav	    ((char *)ctx->bios + data_offset +
543300373Smav	     le16_to_cpu(obj_header->usConnectorObjectTableOffset));
544300373Smav	enc_obj = (ATOM_ENCODER_OBJECT_TABLE *)
545300373Smav	    ((char *)ctx->bios + data_offset +
546300373Smav	     le16_to_cpu(obj_header->usEncoderObjectTableOffset));
547300373Smav	router_obj = (ATOM_OBJECT_TABLE *)
548300373Smav		((char *)ctx->bios + data_offset +
549300373Smav		 le16_to_cpu(obj_header->usRouterObjectTableOffset));
550300373Smav	device_support = le16_to_cpu(obj_header->usDeviceSupport);
551300373Smav
552300373Smav	path_size = 0;
553300373Smav	for (i = 0; i < path_obj->ucNumOfDispPath; i++) {
554300373Smav		uint8_t *addr = (uint8_t *) path_obj->asDispPath;
555300373Smav		ATOM_DISPLAY_OBJECT_PATH *path;
556300373Smav		addr += path_size;
557300373Smav		path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
558300373Smav		path_size += le16_to_cpu(path->usSize);
559300373Smav
560300373Smav		if (device_support & le16_to_cpu(path->usDeviceTag)) {
561300373Smav			uint8_t con_obj_id, con_obj_num, con_obj_type;
562300373Smav
563300373Smav			con_obj_id =
564300373Smav			    (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
565300373Smav			    >> OBJECT_ID_SHIFT;
566300373Smav			con_obj_num =
567300373Smav			    (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
568300373Smav			    >> ENUM_ID_SHIFT;
569300373Smav			con_obj_type =
570300373Smav			    (le16_to_cpu(path->usConnObjectId) &
571300373Smav			     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
572300373Smav
573300373Smav			/* TODO CV support */
574300373Smav			if (le16_to_cpu(path->usDeviceTag) ==
575300373Smav				ATOM_DEVICE_CV_SUPPORT)
576300373Smav				continue;
577300373Smav
578300373Smav			/* IGP chips */
579300373Smav			if ((rdev->flags & RADEON_IS_IGP) &&
580300373Smav			    (con_obj_id ==
581300373Smav			     CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
582300373Smav				uint16_t igp_offset = 0;
583300373Smav				ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj;
584300373Smav
585300373Smav				index =
586300373Smav				    GetIndexIntoMasterTable(DATA,
587300373Smav							    IntegratedSystemInfo);
588300373Smav
589300373Smav				if (atom_parse_data_header(ctx, index, &size, &frev,
590300373Smav							   &crev, &igp_offset)) {
591300516Smav
592300373Smav					if (crev >= 2) {
593300373Smav						igp_obj =
594300373Smav							(ATOM_INTEGRATED_SYSTEM_INFO_V2
595300373Smav							 *) ((char *)ctx->bios + igp_offset);
596300373Smav
597300516Smav						if (igp_obj) {
598300373Smav							uint32_t slot_config, ct;
599300373Smav
600300516Smav							if (con_obj_num == 1)
601300373Smav								slot_config =
602300373Smav									igp_obj->
603300373Smav									ulDDISlot1Config;
604300516Smav							else
605300373Smav								slot_config =
606300373Smav									igp_obj->
607300373Smav									ulDDISlot2Config;
608300373Smav
609300516Smav							ct = (slot_config >> 16) & 0xff;
610300373Smav							connector_type =
611300373Smav								object_connector_convert
612300373Smav								[ct];
613300373Smav							connector_object_id = ct;
614300373Smav							igp_lane_info =
615300516Smav								slot_config & 0xffff;
616300373Smav						} else
617300373Smav							continue;
618300516Smav					} else
619300373Smav						continue;
620300373Smav				} else {
621300373Smav					igp_lane_info = 0;
622300516Smav					connector_type =
623300373Smav						object_connector_convert[con_obj_id];
624300373Smav					connector_object_id = con_obj_id;
625300373Smav				}
626300373Smav			} else {
627250079Scarl				igp_lane_info = 0;
628250079Scarl				connector_type =
629250079Scarl				    object_connector_convert[con_obj_id];
630250079Scarl				connector_object_id = con_obj_id;
631250079Scarl			}
632250079Scarl
633250079Scarl			if (connector_type == DRM_MODE_CONNECTOR_Unknown)
634250079Scarl				continue;
635250079Scarl
636304404Smav			router.ddc_valid = false;
637250079Scarl			router.cd_valid = false;
638300373Smav			for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
639250079Scarl				uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
640304404Smav
641300373Smav				grph_obj_id =
642250079Scarl				    (le16_to_cpu(path->usGraphicObjIds[j]) &
643300373Smav				     OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
644300373Smav				grph_obj_num =
645300373Smav				    (le16_to_cpu(path->usGraphicObjIds[j]) &
646250079Scarl				     ENUM_ID_MASK) >> ENUM_ID_SHIFT;
647250079Scarl				grph_obj_type =
648250079Scarl				    (le16_to_cpu(path->usGraphicObjIds[j]) &
649304404Smav				     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
650250079Scarl
651300373Smav				if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
652300373Smav					for (k = 0; k < enc_obj->ucNumberOfObjects; k++) {
653250079Scarl						u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID);
654250079Scarl						if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) {
655304380Smav							ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
656304404Smav								((char *)ctx->bios + data_offset +
657300373Smav								 le16_to_cpu(enc_obj->asObjects[k].usRecordOffset));
658250079Scarl							ATOM_ENCODER_CAP_RECORD *cap_record;
659250079Scarl							u16 caps = 0;
660255274Scarl
661300373Smav							while (record->ucRecordSize > 0 &&
662301811Sngie							       record->ucRecordType > 0 &&
663250079Scarl							       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
664300373Smav								switch (record->ucRecordType) {
665314667Savg								case ATOM_ENCODER_CAP_RECORD_TYPE:
666314667Savg									cap_record =(ATOM_ENCODER_CAP_RECORD *)
667301811Sngie										record;
668300373Smav									caps = le16_to_cpu(cap_record->usEncoderCap);
669250079Scarl									break;
670300373Smav								}
671304404Smav								record = (ATOM_COMMON_RECORD_HEADER *)
672300373Smav									((char *)record + record->ucRecordSize);
673304404Smav							}
674300373Smav							radeon_add_atom_encoder(dev,
675300373Smav										encoder_obj,
676250079Scarl										le16_to_cpu
677304404Smav										(path->
678300373Smav										 usDeviceTag),
679250079Scarl										caps);
680250079Scarl						}
681304404Smav					}
682300373Smav				} else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
683300373Smav					for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
684300373Smav						u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID);
685304404Smav						if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
686300373Smav							ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
687304404Smav								((char *)ctx->bios + data_offset +
688300373Smav								 le16_to_cpu(router_obj->asObjects[k].usRecordOffset));
689300373Smav							ATOM_I2C_RECORD *i2c_record;
690300373Smav							ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
691304404Smav							ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
692301811Sngie							ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path;
693304404Smav							ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
694300373Smav								(ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
695304404Smav								((char *)ctx->bios + data_offset +
696300373Smav								 le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset));
697304380Smav							int enum_id;
698304404Smav
699304380Smav							router.router_id = router_obj_id;
700300373Smav							for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst;
701300373Smav							     enum_id++) {
702304404Smav								if (le16_to_cpu(path->usConnObjectId) ==
703250079Scarl								    le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id]))
704250079Scarl									break;
705250079Scarl							}
706250079Scarl
707304404Smav							while (record->ucRecordSize > 0 &&
708250079Scarl							       record->ucRecordType > 0 &&
709300373Smav							       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
710250079Scarl								switch (record->ucRecordType) {
711304380Smav								case ATOM_I2C_RECORD_TYPE:
712300373Smav									i2c_record =
713304380Smav										(ATOM_I2C_RECORD *)
714304404Smav										record;
715304380Smav									i2c_config =
716301811Sngie										(ATOM_I2C_ID_CONFIG_ACCESS *)
717301811Sngie										&i2c_record->sucI2cId;
718301811Sngie									router.i2c_info =
719301811Sngie										radeon_lookup_i2c_gpio(rdev,
720301811Sngie												       i2c_config->
721250079Scarl												       ucAccess);
722250079Scarl									router.i2c_addr = i2c_record->ucI2CAddr >> 1;
723301811Sngie									break;
724300373Smav								case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
725300373Smav									ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
726304404Smav										record;
727304404Smav									router.ddc_valid = true;
728300373Smav									router.ddc_mux_type = ddc_path->ucMuxType;
729300373Smav									router.ddc_mux_control_pin = ddc_path->ucMuxControlPin;
730300373Smav									router.ddc_mux_state = ddc_path->ucMuxState[enum_id];
731304404Smav									break;
732250079Scarl								case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE:
733250079Scarl									cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *)
734250079Scarl										record;
735250079Scarl									router.cd_valid = true;
736300373Smav									router.cd_mux_type = cd_path->ucMuxType;
737300373Smav									router.cd_mux_control_pin = cd_path->ucMuxControlPin;
738300373Smav									router.cd_mux_state = cd_path->ucMuxState[enum_id];
739300373Smav									break;
740304404Smav								}
741300373Smav								record = (ATOM_COMMON_RECORD_HEADER *)
742300373Smav									((char *)record + record->ucRecordSize);
743300373Smav							}
744300373Smav						}
745300373Smav					}
746300373Smav				}
747300373Smav			}
748300373Smav
749300373Smav			/* look up gpio for ddc, hpd */
750300373Smav			ddc_bus.valid = false;
751300373Smav			hpd.hpd = RADEON_HPD_NONE;
752300373Smav			if ((le16_to_cpu(path->usDeviceTag) &
753300373Smav			     (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
754300373Smav				for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
755304380Smav					if (le16_to_cpu(path->usConnObjectId) ==
756300373Smav					    le16_to_cpu(con_obj->asObjects[j].
757300373Smav							usObjectID)) {
758300373Smav						ATOM_COMMON_RECORD_HEADER
759300373Smav						    *record =
760300373Smav						    (ATOM_COMMON_RECORD_HEADER
761300373Smav						     *)
762300373Smav						    ((char *)ctx->bios + data_offset +
763300373Smav						     le16_to_cpu(con_obj->
764300373Smav								 asObjects[j].
765300373Smav								 usRecordOffset));
766300373Smav						ATOM_I2C_RECORD *i2c_record;
767300373Smav						ATOM_HPD_INT_RECORD *hpd_record;
768300373Smav						ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
769300373Smav
770300373Smav						while (record->ucRecordSize > 0 &&
771300373Smav						       record->ucRecordType > 0 &&
772300373Smav						       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
773300373Smav							switch (record->ucRecordType) {
774300373Smav							case ATOM_I2C_RECORD_TYPE:
775300373Smav								i2c_record =
776300373Smav								    (ATOM_I2C_RECORD *)
777300373Smav									record;
778300373Smav								i2c_config =
779300373Smav									(ATOM_I2C_ID_CONFIG_ACCESS *)
780300373Smav									&i2c_record->sucI2cId;
781300373Smav								ddc_bus = radeon_lookup_i2c_gpio(rdev,
782300373Smav												 i2c_config->
783300373Smav												 ucAccess);
784300373Smav								break;
785300373Smav							case ATOM_HPD_INT_RECORD_TYPE:
786300373Smav								hpd_record =
787300373Smav									(ATOM_HPD_INT_RECORD *)
788300373Smav									record;
789300373Smav								gpio = radeon_lookup_gpio(rdev,
790300373Smav											  hpd_record->ucHPDIntGPIOID);
791300373Smav								hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
792300373Smav								hpd.plugged_state = hpd_record->ucPlugged_PinState;
793300373Smav								break;
794300373Smav							}
795250079Scarl							record =
796304404Smav							    (ATOM_COMMON_RECORD_HEADER
797250079Scarl							     *) ((char *)record
798255272Scarl								 +
799250079Scarl								 record->
800250079Scarl								 ucRecordSize);
801300373Smav						}
802255272Scarl						break;
803300373Smav					}
804255272Scarl				}
805300373Smav			}
806300373Smav
807255272Scarl			/* needed for aux chan transactions */
808300373Smav			ddc_bus.hpd = hpd.hpd;
809300373Smav
810300373Smav			conn_id = le16_to_cpu(path->usConnObjectId);
811300373Smav
812255272Scarl			if (!radeon_atom_apply_quirks
813300373Smav			    (dev, le16_to_cpu(path->usDeviceTag), &connector_type,
814300373Smav			     &ddc_bus, &conn_id, &hpd))
815255272Scarl				continue;
816300373Smav
817300373Smav			radeon_add_atom_connector(dev,
818300373Smav						  conn_id,
819300373Smav						  le16_to_cpu(path->
820255274Scarl							      usDeviceTag),
821304380Smav						  connector_type, &ddc_bus,
822300373Smav						  igp_lane_info,
823250079Scarl						  connector_object_id,
824300373Smav						  &hpd,
825300373Smav						  &router);
826300373Smav
827300373Smav		}
828300373Smav	}
829255272Scarl
830300373Smav	radeon_link_encoder_connector(dev);
831300373Smav
832255272Scarl	return true;
833255272Scarl}
834255272Scarl
835255272Scarlstatic uint16_t atombios_get_connector_object_id(struct drm_device *dev,
836255272Scarl						 int connector_type,
837300373Smav						 uint16_t devices)
838300373Smav{
839300373Smav	struct radeon_device *rdev = dev->dev_private;
840300373Smav
841300373Smav	if (rdev->flags & RADEON_IS_IGP) {
842300373Smav		return supported_devices_connector_object_id_convert
843300373Smav			[connector_type];
844300373Smav	} else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
845300373Smav		    (connector_type == DRM_MODE_CONNECTOR_DVID)) &&
846300373Smav		   (devices & ATOM_DEVICE_DFP2_SUPPORT))  {
847300373Smav		struct radeon_mode_info *mode_info = &rdev->mode_info;
848300373Smav		struct atom_context *ctx = mode_info->atom_context;
849300373Smav		int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
850255272Scarl		uint16_t size, data_offset;
851255272Scarl		uint8_t frev, crev;
852255272Scarl		ATOM_XTMDS_INFO *xtmds;
853255272Scarl
854255275Scarl		if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
855300373Smav			xtmds = (ATOM_XTMDS_INFO *)((char *)ctx->bios + data_offset);
856255272Scarl
857255272Scarl			if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
858300373Smav				if (connector_type == DRM_MODE_CONNECTOR_DVII)
859300373Smav					return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
860300373Smav				else
861300373Smav					return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
862300373Smav			} else {
863255272Scarl				if (connector_type == DRM_MODE_CONNECTOR_DVII)
864255272Scarl					return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
865255272Scarl				else
866255272Scarl					return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
867255272Scarl			}
868255272Scarl		} else
869300373Smav			return supported_devices_connector_object_id_convert
870255276Scarl				[connector_type];
871255272Scarl	} else {
872300373Smav		return supported_devices_connector_object_id_convert
873300373Smav			[connector_type];
874250079Scarl	}
875255272Scarl}
876255272Scarl
877255276Scarlstruct bios_connector {
878300373Smav	bool valid;
879300373Smav	uint16_t line_mux;
880300373Smav	uint16_t devices;
881300373Smav	int connector_type;
882300373Smav	struct radeon_i2c_bus_rec ddc_bus;
883300373Smav	struct radeon_hpd hpd;
884300373Smav};
885300373Smav
886300373Smavbool radeon_get_atom_connector_info_from_supported_devices_table(struct
887300373Smav								 drm_device
888300373Smav								 *dev)
889300373Smav{
890300373Smav	struct radeon_device *rdev = dev->dev_private;
891300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
892300373Smav	struct atom_context *ctx = mode_info->atom_context;
893300373Smav	int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo);
894300373Smav	uint16_t size, data_offset;
895304380Smav	uint8_t frev, crev;
896300373Smav	uint16_t device_support;
897300373Smav	uint8_t dac;
898300373Smav	union atom_supported_devices *supported_devices;
899300373Smav	int i, j, max_device;
900300373Smav	struct bios_connector *bios_connectors;
901300373Smav	size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
902300373Smav	struct radeon_router router;
903300373Smav
904300373Smav	router.ddc_valid = false;
905300373Smav	router.cd_valid = false;
906255272Scarl
907300373Smav	bios_connectors = malloc(bc_size, DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
908300373Smav	if (!bios_connectors)
909255272Scarl		return false;
910250079Scarl
911300373Smav	if (!atom_parse_data_header(ctx, index, &size, &frev, &crev,
912300373Smav				    &data_offset)) {
913250079Scarl		free(bios_connectors, DRM_MEM_DRIVER);
914300373Smav		return false;
915300373Smav	}
916300373Smav
917300373Smav	supported_devices =
918300373Smav	    (union atom_supported_devices *)((char *)ctx->bios + data_offset);
919300373Smav
920300373Smav	device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
921300373Smav
922304404Smav	if (frev > 1)
923300373Smav		max_device = ATOM_MAX_SUPPORTED_DEVICE;
924300373Smav	else
925300373Smav		max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
926300373Smav
927300373Smav	for (i = 0; i < max_device; i++) {
928300373Smav		ATOM_CONNECTOR_INFO_I2C ci =
929300373Smav		    supported_devices->info.asConnInfo[i];
930300373Smav
931300373Smav		bios_connectors[i].valid = false;
932300373Smav
933300373Smav		if (!(device_support & (1 << i))) {
934300373Smav			continue;
935304404Smav		}
936300373Smav
937300373Smav		if (i == ATOM_DEVICE_CV_INDEX) {
938300373Smav			DRM_DEBUG_KMS("Skipping Component Video\n");
939300373Smav			continue;
940300373Smav		}
941300373Smav
942300373Smav		bios_connectors[i].connector_type =
943304404Smav		    supported_devices_connector_convert[ci.sucConnectorInfo.
944300373Smav							sbfAccess.
945250079Scarl							bfConnectorType];
946250079Scarl
947250079Scarl		if (bios_connectors[i].connector_type ==
948250079Scarl		    DRM_MODE_CONNECTOR_Unknown)
949304404Smav			continue;
950250079Scarl
951250079Scarl		dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
952250079Scarl
953250079Scarl		bios_connectors[i].line_mux =
954300373Smav			ci.sucI2cId.ucAccess;
955250079Scarl
956250079Scarl		/* give tv unique connector ids */
957250079Scarl		if (i == ATOM_DEVICE_TV1_INDEX) {
958250079Scarl			bios_connectors[i].ddc_bus.valid = false;
959250079Scarl			bios_connectors[i].line_mux = 50;
960250079Scarl		} else if (i == ATOM_DEVICE_TV2_INDEX) {
961250079Scarl			bios_connectors[i].ddc_bus.valid = false;
962250079Scarl			bios_connectors[i].line_mux = 51;
963250079Scarl		} else if (i == ATOM_DEVICE_CV_INDEX) {
964304404Smav			bios_connectors[i].ddc_bus.valid = false;
965250079Scarl			bios_connectors[i].line_mux = 52;
966300373Smav		} else
967300373Smav			bios_connectors[i].ddc_bus =
968250079Scarl			    radeon_lookup_i2c_gpio(rdev,
969300373Smav						   bios_connectors[i].line_mux);
970300373Smav
971300373Smav		if ((crev > 1) && (frev > 1)) {
972300373Smav			u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap;
973300373Smav			switch (isb) {
974300373Smav			case 0x4:
975300373Smav				bios_connectors[i].hpd.hpd = RADEON_HPD_1;
976300373Smav				break;
977300373Smav			case 0xa:
978300373Smav				bios_connectors[i].hpd.hpd = RADEON_HPD_2;
979300373Smav				break;
980300373Smav			default:
981300373Smav				bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
982300373Smav				break;
983300373Smav			}
984300373Smav		} else {
985300373Smav			if (i == ATOM_DEVICE_DFP1_INDEX)
986300373Smav				bios_connectors[i].hpd.hpd = RADEON_HPD_1;
987300373Smav			else if (i == ATOM_DEVICE_DFP2_INDEX)
988300373Smav				bios_connectors[i].hpd.hpd = RADEON_HPD_2;
989300373Smav			else
990300373Smav				bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
991300373Smav		}
992300373Smav
993300373Smav		/* Always set the connector type to VGA for CRT1/CRT2. if they are
994300373Smav		 * shared with a DVI port, we'll pick up the DVI connector when we
995300373Smav		 * merge the outputs.  Some bioses incorrectly list VGA ports as DVI.
996300373Smav		 */
997300373Smav		if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX)
998300516Smav			bios_connectors[i].connector_type =
999300373Smav			    DRM_MODE_CONNECTOR_VGA;
1000300373Smav
1001300373Smav		if (!radeon_atom_apply_quirks
1002300373Smav		    (dev, (1 << i), &bios_connectors[i].connector_type,
1003300373Smav		     &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux,
1004300373Smav		     &bios_connectors[i].hpd))
1005300373Smav			continue;
1006300373Smav
1007300373Smav		bios_connectors[i].valid = true;
1008300516Smav		bios_connectors[i].devices = (1 << i);
1009300373Smav
1010300373Smav		if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)
1011300373Smav			radeon_add_atom_encoder(dev,
1012300373Smav						radeon_get_encoder_enum(dev,
1013300373Smav								      (1 << i),
1014300373Smav								      dac),
1015300373Smav						(1 << i),
1016300373Smav						0);
1017300373Smav		else
1018300373Smav			radeon_add_legacy_encoder(dev,
1019304404Smav						  radeon_get_encoder_enum(dev,
1020300373Smav									(1 << i),
1021300373Smav									dac),
1022300373Smav						  (1 << i));
1023300373Smav	}
1024300373Smav
1025300373Smav	/* combine shared connectors */
1026300373Smav	for (i = 0; i < max_device; i++) {
1027300373Smav		if (bios_connectors[i].valid) {
1028300373Smav			for (j = 0; j < max_device; j++) {
1029300373Smav				if (bios_connectors[j].valid && (i != j)) {
1030300373Smav					if (bios_connectors[i].line_mux ==
1031300373Smav					    bios_connectors[j].line_mux) {
1032300373Smav						/* make sure not to combine LVDS */
1033300373Smav						if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1034300373Smav							bios_connectors[i].line_mux = 53;
1035300373Smav							bios_connectors[i].ddc_bus.valid = false;
1036300373Smav							continue;
1037300373Smav						}
1038300373Smav						if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1039304404Smav							bios_connectors[j].line_mux = 53;
1040300373Smav							bios_connectors[j].ddc_bus.valid = false;
1041300373Smav							continue;
1042300373Smav						}
1043300373Smav						/* combine analog and digital for DVI-I */
1044250079Scarl						if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
1045300373Smav						     (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) ||
1046300373Smav						    ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
1047250079Scarl						     (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) {
1048301811Sngie							bios_connectors[i].devices |=
1049250079Scarl								bios_connectors[j].devices;
1050301811Sngie							bios_connectors[i].connector_type =
1051301811Sngie								DRM_MODE_CONNECTOR_DVII;
1052301811Sngie							if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT))
1053301811Sngie								bios_connectors[i].hpd =
1054250079Scarl									bios_connectors[j].hpd;
1055300373Smav							bios_connectors[j].valid = false;
1056300373Smav						}
1057300373Smav					}
1058300373Smav				}
1059250079Scarl			}
1060300373Smav		}
1061300373Smav	}
1062300373Smav
1063300373Smav	/* add the connectors */
1064300373Smav	for (i = 0; i < max_device; i++) {
1065304404Smav		if (bios_connectors[i].valid) {
1066300373Smav			uint16_t connector_object_id =
1067300373Smav				atombios_get_connector_object_id(dev,
1068300373Smav						      bios_connectors[i].connector_type,
1069300373Smav						      bios_connectors[i].devices);
1070300373Smav			radeon_add_atom_connector(dev,
1071250079Scarl						  bios_connectors[i].line_mux,
1072300373Smav						  bios_connectors[i].devices,
1073300373Smav						  bios_connectors[i].
1074300373Smav						  connector_type,
1075300373Smav						  &bios_connectors[i].ddc_bus,
1076300373Smav						  0,
1077300373Smav						  connector_object_id,
1078304380Smav						  &bios_connectors[i].hpd,
1079301811Sngie						  &router);
1080301811Sngie		}
1081301811Sngie	}
1082301811Sngie
1083301811Sngie	radeon_link_encoder_connector(dev);
1084300373Smav
1085300373Smav	free(bios_connectors, DRM_MEM_DRIVER);
1086304404Smav	return true;
1087300373Smav}
1088301811Sngie
1089304380Smavunion firmware_info {
1090301811Sngie	ATOM_FIRMWARE_INFO info;
1091301811Sngie	ATOM_FIRMWARE_INFO_V1_2 info_12;
1092301811Sngie	ATOM_FIRMWARE_INFO_V1_3 info_13;
1093301811Sngie	ATOM_FIRMWARE_INFO_V1_4 info_14;
1094301811Sngie	ATOM_FIRMWARE_INFO_V2_1 info_21;
1095301811Sngie	ATOM_FIRMWARE_INFO_V2_2 info_22;
1096304404Smav};
1097304404Smav
1098250079Scarlbool radeon_atom_get_clock_info(struct drm_device *dev)
1099300373Smav{
1100300373Smav	struct radeon_device *rdev = dev->dev_private;
1101300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1102304404Smav	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
1103300373Smav	union firmware_info *firmware_info;
1104250079Scarl	uint8_t frev, crev;
1105300373Smav	struct radeon_pll *p1pll = &rdev->clock.p1pll;
1106300373Smav	struct radeon_pll *p2pll = &rdev->clock.p2pll;
1107250079Scarl	struct radeon_pll *dcpll = &rdev->clock.dcpll;
1108300373Smav	struct radeon_pll *spll = &rdev->clock.spll;
1109304404Smav	struct radeon_pll *mpll = &rdev->clock.mpll;
1110300373Smav	uint16_t data_offset;
1111300373Smav
1112300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1113300373Smav				   &frev, &crev, &data_offset)) {
1114300373Smav		firmware_info =
1115300373Smav			(union firmware_info *)((char *)mode_info->atom_context->bios +
1116300373Smav						data_offset);
1117300373Smav		/* pixel clocks */
1118300373Smav		p1pll->reference_freq =
1119250079Scarl		    le16_to_cpu(firmware_info->info.usReferenceClock);
1120250079Scarl		p1pll->reference_div = 0;
1121300373Smav
1122300373Smav		if (crev < 2)
1123300373Smav			p1pll->pll_out_min =
1124300373Smav				le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
1125300373Smav		else
1126300373Smav			p1pll->pll_out_min =
1127300373Smav				le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
1128300373Smav		p1pll->pll_out_max =
1129300373Smav		    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
1130300373Smav
1131300373Smav		if (crev >= 4) {
1132250079Scarl			p1pll->lcd_pll_out_min =
1133250079Scarl				le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
1134250079Scarl			if (p1pll->lcd_pll_out_min == 0)
1135250079Scarl				p1pll->lcd_pll_out_min = p1pll->pll_out_min;
1136304404Smav			p1pll->lcd_pll_out_max =
1137250079Scarl				le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
1138250079Scarl			if (p1pll->lcd_pll_out_max == 0)
1139250079Scarl				p1pll->lcd_pll_out_max = p1pll->pll_out_max;
1140250079Scarl		} else {
1141300373Smav			p1pll->lcd_pll_out_min = p1pll->pll_out_min;
1142250079Scarl			p1pll->lcd_pll_out_max = p1pll->pll_out_max;
1143250079Scarl		}
1144250079Scarl
1145250079Scarl		if (p1pll->pll_out_min == 0) {
1146250079Scarl			if (ASIC_IS_AVIVO(rdev))
1147250079Scarl				p1pll->pll_out_min = 64800;
1148250079Scarl			else
1149250079Scarl				p1pll->pll_out_min = 20000;
1150250079Scarl		}
1151250079Scarl
1152304404Smav		p1pll->pll_in_min =
1153250079Scarl		    le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
1154250079Scarl		p1pll->pll_in_max =
1155250079Scarl		    le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);
1156300373Smav
1157300373Smav		*p2pll = *p1pll;
1158300373Smav
1159300373Smav		/* system clock */
1160300373Smav		if (ASIC_IS_DCE4(rdev))
1161300373Smav			spll->reference_freq =
1162250079Scarl				le16_to_cpu(firmware_info->info_21.usCoreReferenceClock);
1163250079Scarl		else
1164300373Smav			spll->reference_freq =
1165304404Smav				le16_to_cpu(firmware_info->info.usReferenceClock);
1166250079Scarl		spll->reference_div = 0;
1167300373Smav
1168300373Smav		spll->pll_out_min =
1169304404Smav		    le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output);
1170250079Scarl		spll->pll_out_max =
1171250079Scarl		    le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output);
1172300373Smav
1173300373Smav		/* ??? */
1174250079Scarl		if (spll->pll_out_min == 0) {
1175250079Scarl			if (ASIC_IS_AVIVO(rdev))
1176300373Smav				spll->pll_out_min = 64800;
1177300373Smav			else
1178300373Smav				spll->pll_out_min = 20000;
1179300373Smav		}
1180250079Scarl
1181300373Smav		spll->pll_in_min =
1182300373Smav		    le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input);
1183300373Smav		spll->pll_in_max =
1184250079Scarl		    le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);
1185250079Scarl
1186300373Smav		/* memory clock */
1187300373Smav		if (ASIC_IS_DCE4(rdev))
1188250079Scarl			mpll->reference_freq =
1189250079Scarl				le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock);
1190300373Smav		else
1191304404Smav			mpll->reference_freq =
1192300373Smav				le16_to_cpu(firmware_info->info.usReferenceClock);
1193300373Smav		mpll->reference_div = 0;
1194250079Scarl
1195300373Smav		mpll->pll_out_min =
1196304404Smav		    le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output);
1197250079Scarl		mpll->pll_out_max =
1198250079Scarl		    le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output);
1199304380Smav
1200304404Smav		/* ??? */
1201250079Scarl		if (mpll->pll_out_min == 0) {
1202304380Smav			if (ASIC_IS_AVIVO(rdev))
1203250079Scarl				mpll->pll_out_min = 64800;
1204300373Smav			else
1205300373Smav				mpll->pll_out_min = 20000;
1206304388Smav		}
1207304388Smav
1208300373Smav		mpll->pll_in_min =
1209300373Smav		    le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input);
1210250079Scarl		mpll->pll_in_max =
1211304380Smav		    le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input);
1212304404Smav
1213300373Smav		rdev->clock.default_sclk =
1214304380Smav		    le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
1215304388Smav		rdev->clock.default_mclk =
1216304388Smav		    le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
1217250079Scarl
1218300373Smav		if (ASIC_IS_DCE4(rdev)) {
1219300373Smav			rdev->clock.default_dispclk =
1220300373Smav				le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
1221300373Smav			if (rdev->clock.default_dispclk == 0) {
1222250079Scarl				if (ASIC_IS_DCE5(rdev))
1223300373Smav					rdev->clock.default_dispclk = 54000; /* 540 Mhz */
1224304388Smav				else
1225300373Smav					rdev->clock.default_dispclk = 60000; /* 600 Mhz */
1226304388Smav			}
1227304388Smav			rdev->clock.dp_extclk =
1228304388Smav				le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
1229304404Smav		}
1230304388Smav		*dcpll = *p1pll;
1231304388Smav
1232304388Smav		rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock);
1233304388Smav		if (rdev->clock.max_pixel_clock == 0)
1234304388Smav			rdev->clock.max_pixel_clock = 40000;
1235300373Smav
1236300373Smav		/* not technically a clock, but... */
1237300373Smav		rdev->mode_info.firmware_flags =
1238304380Smav			le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess);
1239304404Smav
1240300373Smav		return true;
1241304380Smav	}
1242300373Smav
1243304388Smav	return false;
1244304388Smav}
1245301811Sngie
1246300373Smavunion igp_info {
1247300373Smav	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1248300373Smav	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1249304380Smav	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1250304404Smav	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1251300373Smav};
1252304380Smav
1253300373Smavbool radeon_atombios_sideport_present(struct radeon_device *rdev)
1254300373Smav{
1255300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1256300373Smav	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1257300373Smav	union igp_info *igp_info;
1258300373Smav	u8 frev, crev;
1259304380Smav	u16 data_offset;
1260304388Smav
1261304388Smav	/* sideport is AMD only */
1262304388Smav	if (rdev->family == CHIP_RS600)
1263301811Sngie		return false;
1264301811Sngie
1265301811Sngie	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1266300373Smav				   &frev, &crev, &data_offset)) {
1267300373Smav		igp_info = (union igp_info *)((char *)mode_info->atom_context->bios +
1268300373Smav				      data_offset);
1269300373Smav		switch (crev) {
1270304404Smav		case 1:
1271300373Smav			if (le32_to_cpu(igp_info->info.ulBootUpMemoryClock))
1272300373Smav				return true;
1273300373Smav			break;
1274304388Smav		case 2:
1275304388Smav			if (le32_to_cpu(igp_info->info_2.ulBootUpSidePortClock))
1276304388Smav				return true;
1277304388Smav			break;
1278304388Smav		default:
1279304388Smav			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1280304388Smav			break;
1281304388Smav		}
1282304388Smav	}
1283304388Smav	return false;
1284304388Smav}
1285304388Smav
1286304388Smavbool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
1287300373Smav				   struct radeon_encoder_int_tmds *tmds)
1288300373Smav{
1289300373Smav	struct drm_device *dev = encoder->base.dev;
1290300373Smav	struct radeon_device *rdev = dev->dev_private;
1291300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1292300373Smav	int index = GetIndexIntoMasterTable(DATA, TMDS_Info);
1293304404Smav	uint16_t data_offset;
1294300373Smav	struct _ATOM_TMDS_INFO *tmds_info;
1295300373Smav	uint8_t frev, crev;
1296300373Smav	uint16_t maxfreq;
1297300373Smav	int i;
1298304404Smav
1299300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1300300373Smav				   &frev, &crev, &data_offset)) {
1301304404Smav		tmds_info =
1302304380Smav			(struct _ATOM_TMDS_INFO *)((char *)mode_info->atom_context->bios +
1303250079Scarl						   data_offset);
1304250079Scarl
1305304380Smav		maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
1306301811Sngie		for (i = 0; i < 4; i++) {
1307301811Sngie			tmds->tmds_pll[i].freq =
1308304388Smav			    le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency);
1309304388Smav			tmds->tmds_pll[i].value =
1310304388Smav			    tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f;
1311304388Smav			tmds->tmds_pll[i].value |=
1312304388Smav			    (tmds_info->asMiscInfo[i].
1313304388Smav			     ucPLL_VCO_Gain & 0x3f) << 6;
1314304388Smav			tmds->tmds_pll[i].value |=
1315304388Smav			    (tmds_info->asMiscInfo[i].
1316304388Smav			     ucPLL_DutyCycle & 0xf) << 12;
1317304388Smav			tmds->tmds_pll[i].value |=
1318301811Sngie			    (tmds_info->asMiscInfo[i].
1319301811Sngie			     ucPLL_VoltageSwing & 0xf) << 16;
1320301811Sngie
1321300373Smav			DRM_DEBUG_KMS("TMDS PLL From ATOMBIOS %u %x\n",
1322304380Smav				  tmds->tmds_pll[i].freq,
1323250079Scarl				  tmds->tmds_pll[i].value);
1324250079Scarl
1325300373Smav			if (maxfreq == tmds->tmds_pll[i].freq) {
1326300373Smav				tmds->tmds_pll[i].freq = 0xffffffff;
1327300373Smav				break;
1328300373Smav			}
1329300373Smav		}
1330304404Smav		return true;
1331300373Smav	}
1332300373Smav	return false;
1333300373Smav}
1334300373Smav
1335300373Smavbool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev,
1336300373Smav				      struct radeon_atom_ss *ss,
1337304404Smav				      int id)
1338300373Smav{
1339300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1340250079Scarl	int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
1341304404Smav	uint16_t data_offset, size;
1342250079Scarl	struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
1343300373Smav	uint8_t frev, crev;
1344250079Scarl	int i, num_indices;
1345300373Smav
1346250079Scarl	memset(ss, 0, sizeof(struct radeon_atom_ss));
1347250079Scarl	if (atom_parse_data_header(mode_info->atom_context, index, &size,
1348300373Smav				   &frev, &crev, &data_offset)) {
1349300373Smav		ss_info =
1350250079Scarl			(struct _ATOM_SPREAD_SPECTRUM_INFO *)((char *)mode_info->atom_context->bios + data_offset);
1351250079Scarl
1352250079Scarl		num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1353250079Scarl			sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1354250079Scarl
1355250079Scarl		for (i = 0; i < num_indices; i++) {
1356304404Smav			if (ss_info->asSS_Info[i].ucSS_Id == id) {
1357250079Scarl				ss->percentage =
1358250079Scarl					le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage);
1359300373Smav				ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType;
1360300373Smav				ss->step = ss_info->asSS_Info[i].ucSS_Step;
1361250079Scarl				ss->delay = ss_info->asSS_Info[i].ucSS_Delay;
1362300373Smav				ss->range = ss_info->asSS_Info[i].ucSS_Range;
1363300373Smav				ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div;
1364250079Scarl				return true;
1365250079Scarl			}
1366301811Sngie		}
1367304404Smav	}
1368301811Sngie	return false;
1369301811Sngie}
1370301811Sngie
1371301811Sngiestatic void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev,
1372301811Sngie						 struct radeon_atom_ss *ss,
1373301811Sngie						 int id)
1374301811Sngie{
1375301811Sngie	struct radeon_mode_info *mode_info = &rdev->mode_info;
1376301811Sngie	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1377301811Sngie	u16 data_offset, size;
1378301811Sngie	union igp_info *igp_info;
1379301811Sngie	u8 frev, crev;
1380301811Sngie	u16 percentage = 0, rate = 0;
1381301811Sngie
1382301811Sngie	/* get any igp specific overrides */
1383304404Smav	if (atom_parse_data_header(mode_info->atom_context, index, &size,
1384301811Sngie				   &frev, &crev, &data_offset)) {
1385301811Sngie		igp_info = (union igp_info *)
1386301811Sngie			((char *)mode_info->atom_context->bios + data_offset);
1387301811Sngie		switch (crev) {
1388301904Smav		case 6:
1389301811Sngie			switch (id) {
1390301811Sngie			case ASIC_INTERNAL_SS_ON_TMDS:
1391301811Sngie				percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage);
1392304404Smav				rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz);
1393301811Sngie				break;
1394301811Sngie			case ASIC_INTERNAL_SS_ON_HDMI:
1395301811Sngie				percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage);
1396301811Sngie				rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz);
1397301811Sngie				break;
1398250079Scarl			case ASIC_INTERNAL_SS_ON_LVDS:
1399304404Smav				percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage);
1400250079Scarl				rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz);
1401250079Scarl				break;
1402250079Scarl			}
1403250079Scarl			break;
1404250079Scarl		case 7:
1405250079Scarl			switch (id) {
1406250079Scarl			case ASIC_INTERNAL_SS_ON_TMDS:
1407250079Scarl				percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage);
1408250079Scarl				rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz);
1409250079Scarl				break;
1410250079Scarl			case ASIC_INTERNAL_SS_ON_HDMI:
1411300373Smav				percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage);
1412304404Smav				rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz);
1413250079Scarl				break;
1414250079Scarl			case ASIC_INTERNAL_SS_ON_LVDS:
1415300373Smav				percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage);
1416304404Smav				rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz);
1417300373Smav				break;
1418300373Smav			}
1419300373Smav			break;
1420304404Smav		default:
1421300373Smav			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1422300373Smav			break;
1423300373Smav		}
1424300373Smav		if (percentage)
1425300373Smav			ss->percentage = percentage;
1426300373Smav		if (rate)
1427300373Smav			ss->rate = rate;
1428304380Smav	}
1429300373Smav}
1430250079Scarl
1431300373Smavunion asic_ss_info {
1432250079Scarl	struct _ATOM_ASIC_INTERNAL_SS_INFO info;
1433250079Scarl	struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2;
1434250079Scarl	struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3;
1435304404Smav};
1436250079Scarl
1437300373Smavbool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
1438250079Scarl				      struct radeon_atom_ss *ss,
1439300373Smav				      int id, u32 clock)
1440300373Smav{
1441250079Scarl	struct radeon_mode_info *mode_info = &rdev->mode_info;
1442300373Smav	int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
1443300373Smav	uint16_t data_offset, size;
1444300373Smav	union asic_ss_info *ss_info;
1445300373Smav	uint8_t frev, crev;
1446300373Smav	int i, num_indices;
1447300373Smav
1448300373Smav	memset(ss, 0, sizeof(struct radeon_atom_ss));
1449300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, &size,
1450304394Smav				   &frev, &crev, &data_offset)) {
1451304394Smav
1452304394Smav		ss_info =
1453304394Smav			(union asic_ss_info *)((char *)mode_info->atom_context->bios + data_offset);
1454304394Smav
1455304394Smav		switch (frev) {
1456304394Smav		case 1:
1457304394Smav			num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1458304394Smav				sizeof(ATOM_ASIC_SS_ASSIGNMENT);
1459304394Smav
1460301811Sngie			for (i = 0; i < num_indices; i++) {
1461301811Sngie				if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) &&
1462301811Sngie				    (clock <= le32_to_cpu(ss_info->info.asSpreadSpectrum[i].ulTargetClockRange))) {
1463301811Sngie					ss->percentage =
1464304380Smav						le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
1465301811Sngie					ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode;
1466300373Smav					ss->rate = le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz);
1467300373Smav					return true;
1468300373Smav				}
1469250079Scarl			}
1470300373Smav			break;
1471250079Scarl		case 2:
1472250079Scarl			num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1473300373Smav				sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1474250079Scarl			for (i = 0; i < num_indices; i++) {
1475300373Smav				if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) &&
1476300373Smav				    (clock <= le32_to_cpu(ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange))) {
1477250079Scarl					ss->percentage =
1478250079Scarl						le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
1479300373Smav					ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode;
1480300373Smav					ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz);
1481250079Scarl					return true;
1482300373Smav				}
1483304404Smav			}
1484300373Smav			break;
1485300373Smav		case 3:
1486300373Smav			num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1487300373Smav				sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
1488300373Smav			for (i = 0; i < num_indices; i++) {
1489300373Smav				if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) &&
1490300373Smav				    (clock <= le32_to_cpu(ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange))) {
1491250079Scarl					ss->percentage =
1492250079Scarl						le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
1493250079Scarl					ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode;
1494250079Scarl					ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz);
1495300373Smav					if (rdev->flags & RADEON_IS_IGP)
1496300373Smav						radeon_atombios_get_igp_ss_overrides(rdev, ss, id);
1497300373Smav					return true;
1498300373Smav				}
1499300373Smav			}
1500300373Smav			break;
1501300373Smav		default:
1502300373Smav			DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev);
1503250079Scarl			break;
1504250079Scarl		}
1505250079Scarl
1506250079Scarl	}
1507250079Scarl	return false;
1508304404Smav}
1509250079Scarl
1510300373Smavunion lvds_info {
1511250079Scarl	struct _ATOM_LVDS_INFO info;
1512300373Smav	struct _ATOM_LVDS_INFO_V12 info_12;
1513300373Smav};
1514300373Smav
1515300373Smavstruct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
1516300373Smav							      radeon_encoder
1517250079Scarl							      *encoder)
1518300373Smav{
1519250079Scarl	struct drm_device *dev = encoder->base.dev;
1520300373Smav	struct radeon_device *rdev = dev->dev_private;
1521250079Scarl	struct radeon_mode_info *mode_info = &rdev->mode_info;
1522250079Scarl	int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
1523250079Scarl	uint16_t data_offset, misc;
1524300373Smav	union lvds_info *lvds_info;
1525300373Smav	uint8_t frev, crev;
1526300373Smav	struct radeon_encoder_atom_dig *lvds = NULL;
1527300373Smav	int encoder_enum = (encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
1528300373Smav
1529304380Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1530304388Smav				   &frev, &crev, &data_offset)) {
1531301811Sngie		lvds_info =
1532301811Sngie			(union lvds_info *)((char *)mode_info->atom_context->bios + data_offset);
1533304404Smav		lvds =
1534301811Sngie		    malloc(sizeof(struct radeon_encoder_atom_dig),
1535304404Smav			DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
1536301811Sngie
1537301811Sngie		if (!lvds)
1538304380Smav			return NULL;
1539301811Sngie
1540301811Sngie		lvds->native_mode.clock =
1541301811Sngie		    le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
1542301811Sngie		lvds->native_mode.hdisplay =
1543301811Sngie		    le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
1544301811Sngie		lvds->native_mode.vdisplay =
1545301811Sngie		    le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
1546300373Smav		lvds->native_mode.htotal = lvds->native_mode.hdisplay +
1547300373Smav			le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
1548304404Smav		lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
1549300373Smav			le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
1550304404Smav		lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
1551301811Sngie			le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
1552300373Smav		lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
1553304380Smav			le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
1554300373Smav		lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
1555300373Smav			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
1556300373Smav		lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
1557300373Smav			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
1558300373Smav		lvds->panel_pwr_delay =
1559300373Smav		    le16_to_cpu(lvds_info->info.usOffDelayInMs);
1560300373Smav		lvds->lcd_misc = lvds_info->info.ucLVDS_Misc;
1561300373Smav
1562300373Smav		misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess);
1563300373Smav		if (misc & ATOM_VSYNC_POLARITY)
1564300373Smav			lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC;
1565300373Smav		if (misc & ATOM_HSYNC_POLARITY)
1566300373Smav			lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC;
1567300373Smav		if (misc & ATOM_COMPOSITESYNC)
1568300373Smav			lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC;
1569250079Scarl		if (misc & ATOM_INTERLACE)
1570300373Smav			lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE;
1571300373Smav		if (misc & ATOM_DOUBLE_CLOCK_MODE)
1572300373Smav			lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;
1573300373Smav
1574250079Scarl		lvds->native_mode.width_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageHSize);
1575300373Smav		lvds->native_mode.height_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageVSize);
1576304404Smav
1577300373Smav		/* set crtc values */
1578250079Scarl		drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
1579300373Smav
1580300373Smav		lvds->lcd_ss_id = lvds_info->info.ucSS_Id;
1581300373Smav
1582301811Sngie		encoder->native_mode = lvds->native_mode;
1583301811Sngie
1584301811Sngie		if (encoder_enum == 2)
1585301811Sngie			lvds->linkb = true;
1586250079Scarl		else
1587304404Smav			lvds->linkb = false;
1588300373Smav
1589300373Smav		/* parse the lcd record table */
1590250079Scarl		if (le16_to_cpu(lvds_info->info.usModePatchTableOffset)) {
1591300373Smav			ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
1592304404Smav			ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
1593300373Smav			bool bad_record = false;
1594300373Smav			u8 *record;
1595250079Scarl
1596300373Smav			if ((frev == 1) && (crev < 2))
1597300373Smav				/* absolute */
1598300373Smav				record = (u8 *)((char *)mode_info->atom_context->bios +
1599300373Smav						le16_to_cpu(lvds_info->info.usModePatchTableOffset));
1600300373Smav			else
1601300373Smav				/* relative */
1602300373Smav				record = (u8 *)((char *)mode_info->atom_context->bios +
1603300373Smav						data_offset +
1604300373Smav						le16_to_cpu(lvds_info->info.usModePatchTableOffset));
1605300373Smav			while (*record != ATOM_RECORD_END_TYPE) {
1606300373Smav				switch (*record) {
1607300373Smav				case LCD_MODE_PATCH_RECORD_MODE_TYPE:
1608300373Smav					record += sizeof(ATOM_PATCH_RECORD_MODE);
1609300373Smav					break;
1610250079Scarl				case LCD_RTS_RECORD_TYPE:
1611300373Smav					record += sizeof(ATOM_LCD_RTS_RECORD);
1612250079Scarl					break;
1613250079Scarl				case LCD_CAP_RECORD_TYPE:
1614250079Scarl					record += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
1615250079Scarl					break;
1616300373Smav				case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
1617250079Scarl					fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
1618250079Scarl					if (fake_edid_record->ucFakeEDIDLength) {
1619304404Smav						struct edid *edid;
1620250079Scarl						int edid_size =
1621250079Scarl							max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
1622304404Smav						edid = malloc(edid_size, DRM_MEM_KMS, M_WAITOK);
1623300373Smav						if (edid) {
1624300373Smav							memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
1625300373Smav							       fake_edid_record->ucFakeEDIDLength);
1626300373Smav
1627304404Smav							if (drm_edid_is_valid(edid)) {
1628300373Smav								rdev->mode_info.bios_hardcoded_edid = edid;
1629300373Smav								rdev->mode_info.bios_hardcoded_edid_size = edid_size;
1630300373Smav							} else
1631250079Scarl								free(edid, DRM_MEM_KMS);
1632250079Scarl						}
1633250079Scarl					}
1634300373Smav					record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
1635255279Scarl					break;
1636300373Smav				case LCD_PANEL_RESOLUTION_RECORD_TYPE:
1637255279Scarl					panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
1638255279Scarl					lvds->native_mode.width_mm = panel_res_record->usHSize;
1639255279Scarl					lvds->native_mode.height_mm = panel_res_record->usVSize;
1640304404Smav					record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
1641300373Smav					break;
1642304404Smav				default:
1643300373Smav					DRM_ERROR("Bad LCD record %d\n", *record);
1644304404Smav					bad_record = true;
1645304404Smav					break;
1646255279Scarl				}
1647304404Smav				if (bad_record)
1648300373Smav					break;
1649304404Smav			}
1650300373Smav		}
1651304404Smav	}
1652304404Smav	return lvds;
1653255279Scarl}
1654255279Scarl
1655255279Scarlstruct radeon_encoder_primary_dac *
1656300373Smavradeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
1657300373Smav{
1658300373Smav	struct drm_device *dev = encoder->base.dev;
1659300373Smav	struct radeon_device *rdev = dev->dev_private;
1660300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1661300373Smav	int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1662300373Smav	uint16_t data_offset;
1663300373Smav	struct _COMPASSIONATE_DATA *dac_info;
1664300373Smav	uint8_t frev, crev;
1665300373Smav	uint8_t bg, dac;
1666300516Smav	struct radeon_encoder_primary_dac *p_dac = NULL;
1667300373Smav
1668300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1669300373Smav				   &frev, &crev, &data_offset)) {
1670300373Smav		dac_info = (struct _COMPASSIONATE_DATA *)
1671300373Smav			((char *)mode_info->atom_context->bios + data_offset);
1672255279Scarl
1673300373Smav		p_dac = malloc(sizeof(struct radeon_encoder_primary_dac),
1674300373Smav		    DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
1675255279Scarl
1676300373Smav		if (!p_dac)
1677300373Smav			return NULL;
1678255279Scarl
1679304380Smav		bg = dac_info->ucDAC1_BG_Adjustment;
1680300373Smav		dac = dac_info->ucDAC1_DAC_Adjustment;
1681300373Smav		p_dac->ps2_pdac_adj = (bg << 8) | (dac);
1682300373Smav
1683300373Smav	}
1684300373Smav	return p_dac;
1685300373Smav}
1686300373Smav
1687255279Scarlbool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
1688300373Smav				struct drm_display_mode *mode)
1689300373Smav{
1690300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1691300373Smav	ATOM_ANALOG_TV_INFO *tv_info;
1692300373Smav	ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
1693300373Smav	ATOM_DTD_FORMAT *dtd_timings;
1694300373Smav	int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
1695300373Smav	u8 frev, crev;
1696300373Smav	u16 data_offset, misc;
1697300373Smav
1698300373Smav	if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
1699301904Smav				    &frev, &crev, &data_offset))
1700300373Smav		return false;
1701300373Smav
1702300373Smav	switch (crev) {
1703304376Smav	case 1:
1704304376Smav		tv_info = (ATOM_ANALOG_TV_INFO *)((char *)mode_info->atom_context->bios + data_offset);
1705304376Smav		if (index >= MAX_SUPPORTED_TV_TIMING)
1706304376Smav			return false;
1707304376Smav
1708304376Smav		mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
1709300373Smav		mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
1710300373Smav		mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
1711304404Smav		mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
1712304404Smav			le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
1713304399Smav
1714304399Smav		mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
1715304404Smav		mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
1716304404Smav		mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
1717301811Sngie		mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
1718304399Smav			le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
1719304404Smav
1720304404Smav		mode->flags = 0;
1721304399Smav		misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
1722301811Sngie		if (misc & ATOM_VSYNC_POLARITY)
1723304404Smav			mode->flags |= DRM_MODE_FLAG_NVSYNC;
1724304404Smav		if (misc & ATOM_HSYNC_POLARITY)
1725301811Sngie			mode->flags |= DRM_MODE_FLAG_NHSYNC;
1726255279Scarl		if (misc & ATOM_COMPOSITESYNC)
1727255279Scarl			mode->flags |= DRM_MODE_FLAG_CSYNC;
1728255279Scarl		if (misc & ATOM_INTERLACE)
1729250079Scarl			mode->flags |= DRM_MODE_FLAG_INTERLACE;
1730300373Smav		if (misc & ATOM_DOUBLE_CLOCK_MODE)
1731250079Scarl			mode->flags |= DRM_MODE_FLAG_DBLSCAN;
1732300373Smav
1733250079Scarl		mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
1734300373Smav
1735304380Smav		if (index == 1) {
1736304404Smav			/* PAL timings appear to have wrong values for totals */
1737304404Smav			mode->crtc_htotal -= 1;
1738300373Smav			mode->crtc_vtotal -= 1;
1739304404Smav		}
1740304404Smav		break;
1741300373Smav	case 2:
1742300373Smav		tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)((char *)mode_info->atom_context->bios + data_offset);
1743300373Smav		if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)
1744300373Smav			return false;
1745300373Smav
1746300373Smav		dtd_timings = &tv_info_v1_2->aModeTimings[index];
1747300373Smav		mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
1748300373Smav			le16_to_cpu(dtd_timings->usHBlanking_Time);
1749300373Smav		mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive);
1750300373Smav		mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) +
1751300373Smav			le16_to_cpu(dtd_timings->usHSyncOffset);
1752300373Smav		mode->crtc_hsync_end = mode->crtc_hsync_start +
1753300373Smav			le16_to_cpu(dtd_timings->usHSyncWidth);
1754300373Smav
1755300373Smav		mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) +
1756300373Smav			le16_to_cpu(dtd_timings->usVBlanking_Time);
1757300373Smav		mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive);
1758300373Smav		mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) +
1759304404Smav			le16_to_cpu(dtd_timings->usVSyncOffset);
1760300373Smav		mode->crtc_vsync_end = mode->crtc_vsync_start +
1761300373Smav			le16_to_cpu(dtd_timings->usVSyncWidth);
1762300373Smav
1763300373Smav		mode->flags = 0;
1764300373Smav		misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
1765300373Smav		if (misc & ATOM_VSYNC_POLARITY)
1766300373Smav			mode->flags |= DRM_MODE_FLAG_NVSYNC;
1767300373Smav		if (misc & ATOM_HSYNC_POLARITY)
1768300373Smav			mode->flags |= DRM_MODE_FLAG_NHSYNC;
1769300373Smav		if (misc & ATOM_COMPOSITESYNC)
1770300373Smav			mode->flags |= DRM_MODE_FLAG_CSYNC;
1771300373Smav		if (misc & ATOM_INTERLACE)
1772300373Smav			mode->flags |= DRM_MODE_FLAG_INTERLACE;
1773300373Smav		if (misc & ATOM_DOUBLE_CLOCK_MODE)
1774300373Smav			mode->flags |= DRM_MODE_FLAG_DBLSCAN;
1775250079Scarl
1776250079Scarl		mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
1777250079Scarl		break;
1778300373Smav	}
1779300373Smav	return true;
1780300373Smav}
1781300373Smav
1782300373Smavenum radeon_tv_std
1783300373Smavradeon_atombios_get_tv_info(struct radeon_device *rdev)
1784300373Smav{
1785300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1786300373Smav	int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
1787300373Smav	uint16_t data_offset;
1788300373Smav	uint8_t frev, crev;
1789300373Smav	struct _ATOM_ANALOG_TV_INFO *tv_info;
1790304380Smav	enum radeon_tv_std tv_std = TV_STD_NTSC;
1791300373Smav
1792300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1793300373Smav				   &frev, &crev, &data_offset)) {
1794300373Smav
1795300373Smav		tv_info = (struct _ATOM_ANALOG_TV_INFO *)
1796300373Smav			((char *)mode_info->atom_context->bios + data_offset);
1797300373Smav
1798300373Smav		switch (tv_info->ucTV_BootUpDefaultStandard) {
1799304404Smav		case ATOM_TV_NTSC:
1800300373Smav			tv_std = TV_STD_NTSC;
1801300373Smav			DRM_DEBUG_KMS("Default TV standard: NTSC\n");
1802300373Smav			break;
1803300373Smav		case ATOM_TV_NTSCJ:
1804300373Smav			tv_std = TV_STD_NTSC_J;
1805300373Smav			DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
1806300373Smav			break;
1807300373Smav		case ATOM_TV_PAL:
1808300373Smav			tv_std = TV_STD_PAL;
1809300373Smav			DRM_DEBUG_KMS("Default TV standard: PAL\n");
1810304380Smav			break;
1811300373Smav		case ATOM_TV_PALM:
1812300373Smav			tv_std = TV_STD_PAL_M;
1813300373Smav			DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
1814300373Smav			break;
1815300373Smav		case ATOM_TV_PALN:
1816300373Smav			tv_std = TV_STD_PAL_N;
1817300373Smav			DRM_DEBUG_KMS("Default TV standard: PAL-N\n");
1818300373Smav			break;
1819300373Smav		case ATOM_TV_PALCN:
1820304404Smav			tv_std = TV_STD_PAL_CN;
1821304404Smav			DRM_DEBUG_KMS("Default TV standard: PAL-CN\n");
1822300373Smav			break;
1823304380Smav		case ATOM_TV_PAL60:
1824304396Smav			tv_std = TV_STD_PAL_60;
1825304388Smav			DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
1826301811Sngie			break;
1827301811Sngie		case ATOM_TV_SECAM:
1828301811Sngie			tv_std = TV_STD_SECAM;
1829301811Sngie			DRM_DEBUG_KMS("Default TV standard: SECAM\n");
1830301811Sngie			break;
1831304404Smav		default:
1832304396Smav			tv_std = TV_STD_NTSC;
1833304396Smav			DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n");
1834304404Smav			break;
1835304404Smav		}
1836304404Smav	}
1837301904Smav	return tv_std;
1838304404Smav}
1839304404Smav
1840304404Smavstruct radeon_encoder_tv_dac *
1841301904Smavradeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
1842304388Smav{
1843304388Smav	struct drm_device *dev = encoder->base.dev;
1844301811Sngie	struct radeon_device *rdev = dev->dev_private;
1845304404Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1846304404Smav	int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1847301811Sngie	uint16_t data_offset;
1848300373Smav	struct _COMPASSIONATE_DATA *dac_info;
1849304404Smav	uint8_t frev, crev;
1850304404Smav	uint8_t bg, dac;
1851300373Smav	struct radeon_encoder_tv_dac *tv_dac = NULL;
1852300373Smav
1853300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1854304380Smav				   &frev, &crev, &data_offset)) {
1855300373Smav
1856300373Smav		dac_info = (struct _COMPASSIONATE_DATA *)
1857300373Smav			((char *)mode_info->atom_context->bios + data_offset);
1858300373Smav
1859300373Smav		tv_dac = malloc(sizeof(struct radeon_encoder_tv_dac),
1860300373Smav		    DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
1861300373Smav
1862300373Smav		if (!tv_dac)
1863300373Smav			return NULL;
1864300373Smav
1865300373Smav		bg = dac_info->ucDAC2_CRT2_BG_Adjustment;
1866304380Smav		dac = dac_info->ucDAC2_CRT2_DAC_Adjustment;
1867300373Smav		tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
1868300373Smav
1869300373Smav		bg = dac_info->ucDAC2_PAL_BG_Adjustment;
1870300373Smav		dac = dac_info->ucDAC2_PAL_DAC_Adjustment;
1871300373Smav		tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
1872300373Smav
1873300373Smav		bg = dac_info->ucDAC2_NTSC_BG_Adjustment;
1874300373Smav		dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
1875300373Smav		tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
1876300373Smav
1877300373Smav		tv_dac->tv_std = radeon_atombios_get_tv_info(rdev);
1878300373Smav	}
1879304404Smav	return tv_dac;
1880304404Smav}
1881300373Smav
1882250079Scarlstatic const char *thermal_controller_names[] = {
1883250079Scarl	"NONE",
1884300373Smav	"lm63",
1885301811Sngie	"adm1032",
1886301811Sngie	"adm1030",
1887301811Sngie	"max6649",
1888301811Sngie	"lm64",
1889301811Sngie	"f75375",
1890301811Sngie	"asc7xxx",
1891301811Sngie};
1892301811Sngie
1893301811Sngiestatic const char *pp_lib_thermal_controller_names[] = {
1894300373Smav	"NONE",
1895300373Smav	"lm63",
1896300373Smav	"adm1032",
1897301811Sngie	"adm1030",
1898301811Sngie	"max6649",
1899304380Smav	"lm64",
1900300373Smav	"f75375",
1901300373Smav	"RV6xx",
1902300373Smav	"RV770",
1903300373Smav	"adt7473",
1904300373Smav	"NONE",
1905300373Smav	"External GPIO",
1906300373Smav	"Evergreen",
1907300373Smav	"emc2103",
1908300373Smav	"Sumo",
1909300373Smav	"Northern Islands",
1910300373Smav	"Southern Islands",
1911300373Smav	"lm96163",
1912304404Smav};
1913300373Smav
1914300373Smavunion power_info {
1915300373Smav	struct _ATOM_POWERPLAY_INFO info;
1916304404Smav	struct _ATOM_POWERPLAY_INFO_V2 info_2;
1917300373Smav	struct _ATOM_POWERPLAY_INFO_V3 info_3;
1918300373Smav	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1919300373Smav	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1920300373Smav	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1921250079Scarl};
1922300373Smav
1923250079Scarlunion pplib_clock_info {
1924300373Smav	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1925300373Smav	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1926300373Smav	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1927300373Smav	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1928300373Smav	struct _ATOM_PPLIB_SI_CLOCK_INFO si;
1929300373Smav};
1930300373Smav
1931300373Smavunion pplib_power_state {
1932300373Smav	struct _ATOM_PPLIB_STATE v1;
1933300373Smav	struct _ATOM_PPLIB_STATE_V2 v2;
1934300373Smav};
1935300373Smav
1936300373Smavstatic void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev,
1937300373Smav						 int state_index,
1938300373Smav						 u32 misc, u32 misc2)
1939304404Smav{
1940304380Smav	rdev->pm.power_state[state_index].misc = misc;
1941300373Smav	rdev->pm.power_state[state_index].misc2 = misc2;
1942300373Smav	/* order matters! */
1943300373Smav	if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
1944300373Smav		rdev->pm.power_state[state_index].type =
1945300373Smav			POWER_STATE_TYPE_POWERSAVE;
1946300373Smav	if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
1947300373Smav		rdev->pm.power_state[state_index].type =
1948300373Smav			POWER_STATE_TYPE_BATTERY;
1949300373Smav	if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
1950300373Smav		rdev->pm.power_state[state_index].type =
1951300373Smav			POWER_STATE_TYPE_BATTERY;
1952300373Smav	if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
1953300373Smav		rdev->pm.power_state[state_index].type =
1954300373Smav			POWER_STATE_TYPE_BALANCED;
1955250079Scarl	if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
1956250079Scarl		rdev->pm.power_state[state_index].type =
1957250079Scarl			POWER_STATE_TYPE_PERFORMANCE;
1958304404Smav		rdev->pm.power_state[state_index].flags &=
1959304404Smav			~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
1960304404Smav	}
1961304404Smav	if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
1962250079Scarl		rdev->pm.power_state[state_index].type =
1963250079Scarl			POWER_STATE_TYPE_BALANCED;
1964250079Scarl	if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
1965250079Scarl		rdev->pm.power_state[state_index].type =
1966250079Scarl			POWER_STATE_TYPE_DEFAULT;
1967304404Smav		rdev->pm.default_power_state_index = state_index;
1968250079Scarl		rdev->pm.power_state[state_index].default_clock_mode =
1969304404Smav			&rdev->pm.power_state[state_index].clock_info[0];
1970250079Scarl	} else if (state_index == 0) {
1971250079Scarl		rdev->pm.power_state[state_index].clock_info[0].flags |=
1972304404Smav			RADEON_PM_MODE_NO_DISPLAY;
1973300373Smav	}
1974304404Smav}
1975250079Scarl
1976250079Scarlstatic int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
1977304404Smav{
1978300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
1979304404Smav	u32 misc, misc2 = 0;
1980250079Scarl	int num_modes = 0, i;
1981304404Smav	int state_index = 0;
1982300373Smav	struct radeon_i2c_bus_rec i2c_bus;
1983304404Smav	union power_info *power_info;
1984250079Scarl	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1985250079Scarl        u16 data_offset;
1986304404Smav	u8 frev, crev;
1987300373Smav
1988304404Smav	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1989250079Scarl				   &frev, &crev, &data_offset))
1990250079Scarl		return state_index;
1991304380Smav	power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset);
1992304404Smav
1993304380Smav	/* add the i2c bus for thermal/fan chip */
1994300373Smav	if ((power_info->info.ucOverdriveThermalController > 0) &&
1995304380Smav	    (power_info->info.ucOverdriveThermalController < DRM_ARRAY_SIZE(thermal_controller_names))) {
1996300373Smav		DRM_INFO("Possible %s thermal controller at 0x%02x\n",
1997250079Scarl			 thermal_controller_names[power_info->info.ucOverdriveThermalController],
1998304404Smav			 power_info->info.ucOverdriveControllerAddress >> 1);
1999301811Sngie		i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
2000300373Smav		rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
2001300373Smav#ifdef DUMBBELL_WIP
2002300373Smav		if (rdev->pm.i2c_bus) {
2003300373Smav			struct i2c_board_info info = { };
2004250079Scarl			const char *name = thermal_controller_names[power_info->info.
2005250079Scarl								    ucOverdriveThermalController];
2006300373Smav			info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
2007304380Smav			strlcpy(info.type, name, sizeof(info.type));
2008300373Smav			i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
2009300373Smav		}
2010300373Smav#endif /* DUMBBELL_WIP */
2011304404Smav	}
2012300373Smav	num_modes = power_info->info.ucNumOfPowerModeEntries;
2013300373Smav	if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
2014300373Smav		num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
2015304380Smav	rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * num_modes,
2016300373Smav	    DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2017304404Smav	if (!rdev->pm.power_state)
2018300373Smav		return state_index;
2019250079Scarl	/* last mode is usually default, array is low to high */
2020250079Scarl	for (i = 0; i < num_modes; i++) {
2021304380Smav		rdev->pm.power_state[state_index].clock_info =
2022304404Smav			malloc(sizeof(struct radeon_pm_clock_info) * 1,
2023300373Smav			    DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2024304380Smav		if (!rdev->pm.power_state[state_index].clock_info)
2025300373Smav			return state_index;
2026300373Smav		rdev->pm.power_state[state_index].num_clock_modes = 1;
2027304404Smav		rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2028301811Sngie		switch (frev) {
2029300373Smav		case 1:
2030304380Smav			rdev->pm.power_state[state_index].clock_info[0].mclk =
2031300373Smav				le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
2032300373Smav			rdev->pm.power_state[state_index].clock_info[0].sclk =
2033300373Smav				le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
2034304404Smav			/* skip invalid modes */
2035300373Smav			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
2036300373Smav			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
2037304380Smav				continue;
2038300373Smav			rdev->pm.power_state[state_index].pcie_lanes =
2039300373Smav				power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
2040304404Smav			misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
2041300373Smav			if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
2042300373Smav			    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
2043300373Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2044304380Smav					VOLTAGE_GPIO;
2045304404Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
2046301811Sngie					radeon_lookup_gpio(rdev,
2047304380Smav							   power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
2048301811Sngie				if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
2049301811Sngie					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2050301811Sngie						true;
2051301811Sngie				else
2052301811Sngie					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2053301811Sngie						false;
2054301811Sngie			} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
2055301811Sngie				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2056301811Sngie					VOLTAGE_VDDC;
2057301811Sngie				rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
2058304404Smav					power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
2059301811Sngie			}
2060301811Sngie			rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2061301811Sngie			radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0);
2062250079Scarl			state_index++;
2063300373Smav			break;
2064250079Scarl		case 2:
2065250079Scarl			rdev->pm.power_state[state_index].clock_info[0].mclk =
2066300373Smav				le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
2067250079Scarl			rdev->pm.power_state[state_index].clock_info[0].sclk =
2068250079Scarl				le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
2069300373Smav			/* skip invalid modes */
2070250079Scarl			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
2071300373Smav			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
2072300373Smav				continue;
2073300373Smav			rdev->pm.power_state[state_index].pcie_lanes =
2074300373Smav				power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
2075300373Smav			misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
2076300373Smav			misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
2077300373Smav			if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
2078300373Smav			    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
2079250079Scarl				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2080300373Smav					VOLTAGE_GPIO;
2081250079Scarl				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
2082250079Scarl					radeon_lookup_gpio(rdev,
2083304404Smav							   power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
2084300373Smav				if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
2085300373Smav					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2086300373Smav						true;
2087304404Smav				else
2088300373Smav					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2089300373Smav						false;
2090300373Smav			} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
2091300373Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2092300373Smav					VOLTAGE_VDDC;
2093300373Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
2094250079Scarl					power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
2095250079Scarl			}
2096300373Smav			rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2097300373Smav			radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
2098300373Smav			state_index++;
2099250079Scarl			break;
2100250079Scarl		case 3:
2101250079Scarl			rdev->pm.power_state[state_index].clock_info[0].mclk =
2102300373Smav				le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
2103250079Scarl			rdev->pm.power_state[state_index].clock_info[0].sclk =
2104250079Scarl				le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
2105250079Scarl			/* skip invalid modes */
2106300373Smav			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
2107300373Smav			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
2108300373Smav				continue;
2109300373Smav			rdev->pm.power_state[state_index].pcie_lanes =
2110304404Smav				power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
2111250079Scarl			misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
2112250079Scarl			misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
2113300373Smav			if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
2114250079Scarl			    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
2115300373Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2116304404Smav					VOLTAGE_GPIO;
2117300373Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
2118300373Smav					radeon_lookup_gpio(rdev,
2119300373Smav							   power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
2120300373Smav				if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
2121304404Smav					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2122250079Scarl						true;
2123300373Smav				else
2124250079Scarl					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2125300373Smav						false;
2126300373Smav			} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
2127300373Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2128300373Smav					VOLTAGE_VDDC;
2129300373Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
2130301811Sngie					power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
2131304380Smav				if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
2132301811Sngie					rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
2133301811Sngie						true;
2134301811Sngie					rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
2135304404Smav						power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
2136301811Sngie				}
2137301811Sngie			}
2138301811Sngie			rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2139301811Sngie			radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
2140301811Sngie			state_index++;
2141301811Sngie			break;
2142301811Sngie		}
2143250079Scarl	}
2144300373Smav	/* last mode is usually default */
2145300373Smav	if (rdev->pm.default_power_state_index == -1) {
2146250079Scarl		rdev->pm.power_state[state_index - 1].type =
2147300373Smav			POWER_STATE_TYPE_DEFAULT;
2148304404Smav		rdev->pm.default_power_state_index = state_index - 1;
2149300373Smav		rdev->pm.power_state[state_index - 1].default_clock_mode =
2150250079Scarl			&rdev->pm.power_state[state_index - 1].clock_info[0];
2151300373Smav		rdev->pm.power_state[state_index].flags &=
2152300373Smav			~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2153300373Smav		rdev->pm.power_state[state_index].misc = 0;
2154250079Scarl		rdev->pm.power_state[state_index].misc2 = 0;
2155250079Scarl	}
2156300373Smav	return state_index;
2157304404Smav}
2158250079Scarl
2159250079Scarlstatic void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev,
2160300373Smav							 ATOM_PPLIB_THERMALCONTROLLER *controller)
2161300373Smav{
2162300373Smav	struct radeon_i2c_bus_rec i2c_bus;
2163300373Smav
2164250079Scarl	/* add the i2c bus for thermal/fan chip */
2165300373Smav	if (controller->ucType > 0) {
2166300373Smav		if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
2167250079Scarl			DRM_INFO("Internal thermal controller %s fan control\n",
2168300373Smav				 (controller->ucFanParameters &
2169300373Smav				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2170300373Smav			rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
2171300373Smav		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
2172300373Smav			DRM_INFO("Internal thermal controller %s fan control\n",
2173250079Scarl				 (controller->ucFanParameters &
2174300373Smav				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2175300373Smav			rdev->pm.int_thermal_type = THERMAL_TYPE_RV770;
2176300373Smav		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
2177300373Smav			DRM_INFO("Internal thermal controller %s fan control\n",
2178300373Smav				 (controller->ucFanParameters &
2179304404Smav				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2180250079Scarl			rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
2181301811Sngie		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
2182300373Smav			DRM_INFO("Internal thermal controller %s fan control\n",
2183300373Smav				 (controller->ucFanParameters &
2184250079Scarl				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2185300373Smav			rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
2186301811Sngie		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
2187250079Scarl			DRM_INFO("Internal thermal controller %s fan control\n",
2188301811Sngie				 (controller->ucFanParameters &
2189301811Sngie				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2190301811Sngie			rdev->pm.int_thermal_type = THERMAL_TYPE_NI;
2191301811Sngie		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
2192301811Sngie			DRM_INFO("Internal thermal controller %s fan control\n",
2193301811Sngie				 (controller->ucFanParameters &
2194301811Sngie				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2195301811Sngie			rdev->pm.int_thermal_type = THERMAL_TYPE_SI;
2196301811Sngie		} else if ((controller->ucType ==
2197301811Sngie			    ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
2198301811Sngie			   (controller->ucType ==
2199301811Sngie			    ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) ||
2200301811Sngie			   (controller->ucType ==
2201300373Smav			    ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) {
2202250079Scarl			DRM_INFO("Special thermal controller config\n");
2203300373Smav		} else if (controller->ucType < DRM_ARRAY_SIZE(pp_lib_thermal_controller_names)) {
2204300373Smav			DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
2205300373Smav				 pp_lib_thermal_controller_names[controller->ucType],
2206300373Smav				 controller->ucI2cAddress >> 1,
2207300373Smav				 (controller->ucFanParameters &
2208300373Smav				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2209300373Smav			i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
2210300373Smav			rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
2211300373Smav#ifdef DUMBBELL_WIP
2212300373Smav			if (rdev->pm.i2c_bus) {
2213300373Smav				struct i2c_board_info info = { };
2214300373Smav				const char *name = pp_lib_thermal_controller_names[controller->ucType];
2215300373Smav				info.addr = controller->ucI2cAddress >> 1;
2216300373Smav				strlcpy(info.type, name, sizeof(info.type));
2217300373Smav				i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
2218300373Smav			}
2219250079Scarl#endif /* DUMBBELL_WIP */
2220250079Scarl		} else {
2221300373Smav			DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
2222300373Smav				 controller->ucType,
2223300373Smav				 controller->ucI2cAddress >> 1,
2224250079Scarl				 (controller->ucFanParameters &
2225300373Smav				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2226300373Smav		}
2227300373Smav	}
2228300373Smav}
2229300373Smav
2230300373Smavstatic void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
2231250079Scarl						 u16 *vddc, u16 *vddci)
2232300373Smav{
2233300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
2234300373Smav	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
2235300373Smav	u8 frev, crev;
2236300373Smav	u16 data_offset;
2237300373Smav	union firmware_info *firmware_info;
2238300373Smav
2239300373Smav	*vddc = 0;
2240300373Smav	*vddci = 0;
2241300373Smav
2242300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
2243300373Smav				   &frev, &crev, &data_offset)) {
2244250079Scarl		firmware_info =
2245300373Smav			(union firmware_info *)((char *)mode_info->atom_context->bios +
2246300373Smav						data_offset);
2247300373Smav		*vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
2248300373Smav		if ((frev == 2) && (crev >= 2))
2249300373Smav			*vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
2250300373Smav	}
2251300373Smav}
2252300373Smav
2253300373Smavstatic void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
2254300373Smav						       int state_index, int mode_index,
2255300373Smav						       struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info)
2256300373Smav{
2257300373Smav	int j;
2258300373Smav	u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
2259300373Smav	u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
2260300373Smav	u16 vddc, vddci;
2261300373Smav
2262300373Smav	radeon_atombios_get_default_voltages(rdev, &vddc, &vddci);
2263300373Smav
2264300373Smav	rdev->pm.power_state[state_index].misc = misc;
2265300373Smav	rdev->pm.power_state[state_index].misc2 = misc2;
2266300373Smav	rdev->pm.power_state[state_index].pcie_lanes =
2267300373Smav		((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
2268300373Smav		 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
2269300373Smav	switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
2270300373Smav	case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
2271300373Smav		rdev->pm.power_state[state_index].type =
2272300373Smav			POWER_STATE_TYPE_BATTERY;
2273300373Smav		break;
2274300373Smav	case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
2275300373Smav		rdev->pm.power_state[state_index].type =
2276300373Smav			POWER_STATE_TYPE_BALANCED;
2277300373Smav		break;
2278300373Smav	case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
2279300373Smav		rdev->pm.power_state[state_index].type =
2280300373Smav			POWER_STATE_TYPE_PERFORMANCE;
2281300373Smav		break;
2282304380Smav	case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
2283300373Smav		if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
2284300373Smav			rdev->pm.power_state[state_index].type =
2285300373Smav				POWER_STATE_TYPE_PERFORMANCE;
2286300373Smav		break;
2287300373Smav	}
2288300373Smav	rdev->pm.power_state[state_index].flags = 0;
2289300373Smav	if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
2290300373Smav		rdev->pm.power_state[state_index].flags |=
2291300373Smav			RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2292300373Smav	if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
2293300373Smav		rdev->pm.power_state[state_index].type =
2294300373Smav			POWER_STATE_TYPE_DEFAULT;
2295300373Smav		rdev->pm.default_power_state_index = state_index;
2296300373Smav		rdev->pm.power_state[state_index].default_clock_mode =
2297300373Smav			&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
2298300373Smav		if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
2299300373Smav			/* NI chips post without MC ucode, so default clocks are strobe mode only */
2300300373Smav			rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
2301300373Smav			rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
2302304380Smav			rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage;
2303300373Smav			rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci;
2304300373Smav		} else {
2305300373Smav			/* patch the table values with the default slck/mclk from firmware info */
2306300373Smav			for (j = 0; j < mode_index; j++) {
2307300373Smav				rdev->pm.power_state[state_index].clock_info[j].mclk =
2308300373Smav					rdev->clock.default_mclk;
2309300373Smav				rdev->pm.power_state[state_index].clock_info[j].sclk =
2310300373Smav					rdev->clock.default_sclk;
2311300373Smav				if (vddc)
2312300373Smav					rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
2313300373Smav						vddc;
2314300373Smav			}
2315300373Smav		}
2316300373Smav	}
2317300373Smav}
2318300373Smav
2319250079Scarlstatic bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,
2320250079Scarl						   int state_index, int mode_index,
2321300373Smav						   union pplib_clock_info *clock_info)
2322300373Smav{
2323300373Smav	u32 sclk, mclk;
2324300373Smav	u16 vddc;
2325300373Smav
2326300373Smav	if (rdev->flags & RADEON_IS_IGP) {
2327300373Smav		if (rdev->family >= CHIP_PALM) {
2328250079Scarl			sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
2329300373Smav			sclk |= clock_info->sumo.ucEngineClockHigh << 16;
2330300373Smav			rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2331300373Smav		} else {
2332300373Smav			sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow);
2333300373Smav			sclk |= clock_info->rs780.ucLowEngineClockHigh << 16;
2334300373Smav			rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2335300373Smav		}
2336300373Smav	} else if (ASIC_IS_DCE6(rdev)) {
2337300373Smav		sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
2338300373Smav		sclk |= clock_info->si.ucEngineClockHigh << 16;
2339300373Smav		mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
2340300373Smav		mclk |= clock_info->si.ucMemoryClockHigh << 16;
2341300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
2342300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2343300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
2344300373Smav			VOLTAGE_SW;
2345300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
2346300373Smav			le16_to_cpu(clock_info->si.usVDDC);
2347300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
2348300373Smav			le16_to_cpu(clock_info->si.usVDDCI);
2349300373Smav	} else if (ASIC_IS_DCE4(rdev)) {
2350300373Smav		sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
2351300373Smav		sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
2352300373Smav		mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
2353300373Smav		mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
2354300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
2355300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2356300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
2357300373Smav			VOLTAGE_SW;
2358300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
2359300373Smav			le16_to_cpu(clock_info->evergreen.usVDDC);
2360300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
2361300373Smav			le16_to_cpu(clock_info->evergreen.usVDDCI);
2362300373Smav	} else {
2363300373Smav		sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
2364300373Smav		sclk |= clock_info->r600.ucEngineClockHigh << 16;
2365300373Smav		mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow);
2366300373Smav		mclk |= clock_info->r600.ucMemoryClockHigh << 16;
2367300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
2368300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2369300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
2370300373Smav			VOLTAGE_SW;
2371300373Smav		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
2372300373Smav			le16_to_cpu(clock_info->r600.usVDDC);
2373300373Smav	}
2374300373Smav
2375300373Smav	/* patch up vddc if necessary */
2376300373Smav	switch (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage) {
2377300373Smav	case ATOM_VIRTUAL_VOLTAGE_ID0:
2378300373Smav	case ATOM_VIRTUAL_VOLTAGE_ID1:
2379300373Smav	case ATOM_VIRTUAL_VOLTAGE_ID2:
2380300373Smav	case ATOM_VIRTUAL_VOLTAGE_ID3:
2381300373Smav		if (radeon_atom_get_max_vddc(rdev, VOLTAGE_TYPE_VDDC,
2382300373Smav					     rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage,
2383300373Smav					     &vddc) == 0)
2384300373Smav			rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc;
2385300373Smav		break;
2386300373Smav	default:
2387300373Smav		break;
2388300373Smav	}
2389300373Smav
2390300373Smav	if (rdev->flags & RADEON_IS_IGP) {
2391300373Smav		/* skip invalid modes */
2392300373Smav		if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
2393304380Smav			return false;
2394300373Smav	} else {
2395300373Smav		/* skip invalid modes */
2396300373Smav		if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
2397300373Smav		    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
2398300373Smav			return false;
2399300373Smav	}
2400300373Smav	return true;
2401300373Smav}
2402300373Smav
2403300373Smavstatic int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
2404300373Smav{
2405300373Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
2406300373Smav	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
2407300373Smav	union pplib_power_state *power_state;
2408300373Smav	int i, j;
2409300373Smav	int state_index = 0, mode_index = 0;
2410300373Smav	union pplib_clock_info *clock_info;
2411300373Smav	bool valid;
2412300373Smav	union power_info *power_info;
2413304380Smav	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2414300373Smav        u16 data_offset;
2415300373Smav	u8 frev, crev;
2416300373Smav
2417300373Smav	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
2418300373Smav				   &frev, &crev, &data_offset))
2419300373Smav		return state_index;
2420300373Smav	power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset);
2421300373Smav
2422300373Smav	radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
2423300373Smav	rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) *
2424300373Smav				       power_info->pplib.ucNumStates,
2425300373Smav				       DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2426300373Smav	if (!rdev->pm.power_state)
2427300373Smav		return state_index;
2428300373Smav	/* first mode is usually default, followed by low to high */
2429300373Smav	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
2430300373Smav		mode_index = 0;
2431300373Smav		power_state = (union pplib_power_state *)
2432300373Smav			((char *)mode_info->atom_context->bios + data_offset +
2433300373Smav			 le16_to_cpu(power_info->pplib.usStateArrayOffset) +
2434300373Smav			 i * power_info->pplib.ucStateEntrySize);
2435300373Smav		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
2436300373Smav			((char *)mode_info->atom_context->bios + data_offset +
2437304380Smav			 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
2438300373Smav			 (power_state->v1.ucNonClockStateIndex *
2439300373Smav			  power_info->pplib.ucNonClockSize));
2440300373Smav		rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) *
2441300373Smav							     ((power_info->pplib.ucStateEntrySize - 1) ?
2442300373Smav							      (power_info->pplib.ucStateEntrySize - 1) : 1),
2443300373Smav							     DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2444300373Smav		if (!rdev->pm.power_state[i].clock_info)
2445300373Smav			return state_index;
2446300373Smav		if (power_info->pplib.ucStateEntrySize - 1) {
2447300373Smav			for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
2448300373Smav				clock_info = (union pplib_clock_info *)
2449300373Smav					((char *)mode_info->atom_context->bios + data_offset +
2450300373Smav					 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
2451300373Smav					 (power_state->v1.ucClockStateIndices[j] *
2452300373Smav					  power_info->pplib.ucClockInfoSize));
2453300373Smav				valid = radeon_atombios_parse_pplib_clock_info(rdev,
2454300373Smav									       state_index, mode_index,
2455250079Scarl									       clock_info);
2456250079Scarl				if (valid)
2457300373Smav					mode_index++;
2458300373Smav			}
2459250079Scarl		} else {
2460304377Smav			rdev->pm.power_state[state_index].clock_info[0].mclk =
2461300373Smav				rdev->clock.default_mclk;
2462300373Smav			rdev->pm.power_state[state_index].clock_info[0].sclk =
2463250079Scarl				rdev->clock.default_sclk;
2464300373Smav			mode_index++;
2465300373Smav		}
2466300373Smav		rdev->pm.power_state[state_index].num_clock_modes = mode_index;
2467300373Smav		if (mode_index) {
2468300373Smav			radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
2469300373Smav								   non_clock_info);
2470300373Smav			state_index++;
2471300373Smav		}
2472300373Smav	}
2473250079Scarl	/* if multiple clock modes, mark the lowest as no display */
2474250079Scarl	for (i = 0; i < state_index; i++) {
2475300373Smav		if (rdev->pm.power_state[i].num_clock_modes > 1)
2476301811Sngie			rdev->pm.power_state[i].clock_info[0].flags |=
2477250079Scarl				RADEON_PM_MODE_NO_DISPLAY;
2478304377Smav	}
2479301811Sngie	/* first mode is usually default */
2480301811Sngie	if (rdev->pm.default_power_state_index == -1) {
2481301811Sngie		rdev->pm.power_state[0].type =
2482304404Smav			POWER_STATE_TYPE_DEFAULT;
2483301811Sngie		rdev->pm.default_power_state_index = 0;
2484301811Sngie		rdev->pm.power_state[0].default_clock_mode =
2485301811Sngie			&rdev->pm.power_state[0].clock_info[0];
2486301811Sngie	}
2487301811Sngie	return state_index;
2488301811Sngie}
2489301811Sngie
2490301811Sngiestatic int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
2491301811Sngie{
2492304404Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
2493301811Sngie	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
2494301811Sngie	union pplib_power_state *power_state;
2495301811Sngie	int i, j, non_clock_array_index, clock_array_index;
2496304404Smav	int state_index = 0, mode_index = 0;
2497301811Sngie	union pplib_clock_info *clock_info;
2498304404Smav	struct _StateArray *state_array;
2499301811Sngie	struct _ClockInfoArray *clock_info_array;
2500301811Sngie	struct _NonClockInfoArray *non_clock_info_array;
2501301811Sngie	bool valid;
2502301811Sngie	union power_info *power_info;
2503301811Sngie	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2504301811Sngie        u16 data_offset;
2505304377Smav	u8 frev, crev;
2506300373Smav
2507300373Smav	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
2508300373Smav				   &frev, &crev, &data_offset))
2509300373Smav		return state_index;
2510250079Scarl	power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset);
2511300373Smav
2512300373Smav	radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
2513304404Smav	state_array = (struct _StateArray *)
2514300373Smav		((char *)mode_info->atom_context->bios + data_offset +
2515300373Smav		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
2516300373Smav	clock_info_array = (struct _ClockInfoArray *)
2517300373Smav		((char *)mode_info->atom_context->bios + data_offset +
2518300373Smav		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
2519300373Smav	non_clock_info_array = (struct _NonClockInfoArray *)
2520300373Smav		((char *)mode_info->atom_context->bios + data_offset +
2521300373Smav		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
2522300373Smav	rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) *
2523300373Smav				       state_array->ucNumEntries,
2524300373Smav				       DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2525250079Scarl	if (!rdev->pm.power_state)
2526250079Scarl		return state_index;
2527300373Smav	for (i = 0; i < state_array->ucNumEntries; i++) {
2528301811Sngie		mode_index = 0;
2529301811Sngie		power_state = (union pplib_power_state *)&state_array->states[i];
2530304377Smav		/* XXX this might be an inagua bug... */
2531301811Sngie		non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
2532301811Sngie		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
2533301811Sngie			&non_clock_info_array->nonClockInfo[non_clock_array_index];
2534304404Smav		rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) *
2535301811Sngie							     (power_state->v2.ucNumDPMLevels ?
2536301811Sngie							      power_state->v2.ucNumDPMLevels : 1),
2537301811Sngie							     DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2538301811Sngie		if (!rdev->pm.power_state[i].clock_info)
2539301811Sngie			return state_index;
2540301811Sngie		if (power_state->v2.ucNumDPMLevels) {
2541301811Sngie			for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
2542301811Sngie				clock_array_index = power_state->v2.clockInfoIndex[j];
2543300373Smav				/* XXX this might be an inagua bug... */
2544250079Scarl				if (clock_array_index >= clock_info_array->ucNumEntries)
2545300373Smav					continue;
2546300373Smav				clock_info = (union pplib_clock_info *)
2547300373Smav					&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
2548300373Smav				valid = radeon_atombios_parse_pplib_clock_info(rdev,
2549300373Smav									       state_index, mode_index,
2550300373Smav									       clock_info);
2551300373Smav				if (valid)
2552300373Smav					mode_index++;
2553300373Smav			}
2554250079Scarl		} else {
2555300373Smav			rdev->pm.power_state[state_index].clock_info[0].mclk =
2556300373Smav				rdev->clock.default_mclk;
2557300373Smav			rdev->pm.power_state[state_index].clock_info[0].sclk =
2558300373Smav				rdev->clock.default_sclk;
2559300373Smav			mode_index++;
2560250079Scarl		}
2561300373Smav		rdev->pm.power_state[state_index].num_clock_modes = mode_index;
2562250079Scarl		if (mode_index) {
2563300373Smav			radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
2564300373Smav								   non_clock_info);
2565300373Smav			state_index++;
2566300373Smav		}
2567300373Smav	}
2568300373Smav	/* if multiple clock modes, mark the lowest as no display */
2569300373Smav	for (i = 0; i < state_index; i++) {
2570300373Smav		if (rdev->pm.power_state[i].num_clock_modes > 1)
2571300373Smav			rdev->pm.power_state[i].clock_info[0].flags |=
2572300373Smav				RADEON_PM_MODE_NO_DISPLAY;
2573304404Smav	}
2574300373Smav	/* first mode is usually default */
2575300373Smav	if (rdev->pm.default_power_state_index == -1) {
2576300373Smav		rdev->pm.power_state[0].type =
2577300373Smav			POWER_STATE_TYPE_DEFAULT;
2578300373Smav		rdev->pm.default_power_state_index = 0;
2579300373Smav		rdev->pm.power_state[0].default_clock_mode =
2580304404Smav			&rdev->pm.power_state[0].clock_info[0];
2581300373Smav	}
2582300373Smav	return state_index;
2583300373Smav}
2584300373Smav
2585300373Smavvoid radeon_atombios_get_power_modes(struct radeon_device *rdev)
2586300373Smav{
2587304404Smav	struct radeon_mode_info *mode_info = &rdev->mode_info;
2588300373Smav	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2589300373Smav	u16 data_offset;
2590300373Smav	u8 frev, crev;
2591300373Smav	int state_index = 0;
2592300373Smav
2593300373Smav	rdev->pm.default_power_state_index = -1;
2594304404Smav
2595300373Smav	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
2596300373Smav				   &frev, &crev, &data_offset)) {
2597300373Smav		switch (frev) {
2598300373Smav		case 1:
2599300373Smav		case 2:
2600300373Smav		case 3:
2601300373Smav			state_index = radeon_atombios_parse_power_table_1_3(rdev);
2602300373Smav			break;
2603300373Smav		case 4:
2604300373Smav		case 5:
2605300373Smav			state_index = radeon_atombios_parse_power_table_4_5(rdev);
2606300373Smav			break;
2607300373Smav		case 6:
2608300373Smav			state_index = radeon_atombios_parse_power_table_6(rdev);
2609300373Smav			break;
2610300373Smav		default:
2611250079Scarl			break;
2612250079Scarl		}
2613300373Smav	} else {
2614304404Smav		rdev->pm.power_state = malloc(sizeof(struct radeon_power_state),
2615300373Smav		    DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2616300373Smav		if (rdev->pm.power_state) {
2617301811Sngie			rdev->pm.power_state[0].clock_info =
2618301811Sngie				malloc(sizeof(struct radeon_pm_clock_info) * 1,
2619301811Sngie				    DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
2620301811Sngie			if (rdev->pm.power_state[0].clock_info) {
2621301811Sngie				/* add the default mode */
2622301811Sngie				rdev->pm.power_state[state_index].type =
2623301811Sngie					POWER_STATE_TYPE_DEFAULT;
2624301811Sngie				rdev->pm.power_state[state_index].num_clock_modes = 1;
2625300373Smav				rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
2626300373Smav				rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
2627300373Smav				rdev->pm.power_state[state_index].default_clock_mode =
2628304410Smav					&rdev->pm.power_state[state_index].clock_info[0];
2629304409Smav				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2630304409Smav				rdev->pm.power_state[state_index].pcie_lanes = 16;
2631301811Sngie				rdev->pm.default_power_state_index = state_index;
2632304409Smav				rdev->pm.power_state[state_index].flags = 0;
2633304409Smav				state_index++;
2634304409Smav			}
2635304409Smav		}
2636304409Smav	}
2637304409Smav
2638304409Smav	rdev->pm.num_power_states = state_index;
2639304410Smav
2640304409Smav	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
2641304409Smav	rdev->pm.current_clock_mode_index = 0;
2642304404Smav	if (rdev->pm.default_power_state_index >= 0)
2643301811Sngie		rdev->pm.current_vddc =
2644301811Sngie			rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
2645301811Sngie	else
2646301811Sngie		rdev->pm.current_vddc = 0;
2647301811Sngie}
2648301811Sngie
2649301811Sngievoid radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
2650301903Smav{
2651301903Smav	DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
2652301811Sngie	int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating);
2653301811Sngie
2654301811Sngie	args.ucEnable = enable;
2655304410Smav
2656304409Smav	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2657304409Smav}
2658304409Smav
2659304410Smavuint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
2660304409Smav{
2661304404Smav	GET_ENGINE_CLOCK_PS_ALLOCATION args;
2662301811Sngie	int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
2663304404Smav
2664301811Sngie	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2665304404Smav	return le32_to_cpu(args.ulReturnEngineClock);
2666301904Smav}
2667301811Sngie
2668304404Smavuint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev)
2669301811Sngie{
2670304404Smav	GET_MEMORY_CLOCK_PS_ALLOCATION args;
2671301811Sngie	int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
2672301811Sngie
2673301811Sngie	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2674301811Sngie	return le32_to_cpu(args.ulReturnMemoryClock);
2675304404Smav}
2676304404Smav
2677301811Sngievoid radeon_atom_set_engine_clock(struct radeon_device *rdev,
2678304404Smav				  uint32_t eng_clock)
2679304404Smav{
2680301811Sngie	SET_ENGINE_CLOCK_PS_ALLOCATION args;
2681301811Sngie	int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
2682301811Sngie
2683301811Sngie	args.ulTargetEngineClock = cpu_to_le32(eng_clock);	/* 10 khz */
2684301811Sngie
2685301811Sngie	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2686304404Smav}
2687304404Smav
2688301811Sngievoid radeon_atom_set_memory_clock(struct radeon_device *rdev,
2689301811Sngie				  uint32_t mem_clock)
2690301811Sngie{
2691304406Smav	SET_MEMORY_CLOCK_PS_ALLOCATION args;
2692301811Sngie	int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);
2693301903Smav
2694301903Smav	if (rdev->flags & RADEON_IS_IGP)
2695301811Sngie		return;
2696301903Smav
2697304404Smav	args.ulTargetMemoryClock = cpu_to_le32(mem_clock);	/* 10 khz */
2698304380Smav
2699301811Sngie	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2700301811Sngie}
2701301811Sngie
2702301811Sngieunion set_voltage {
2703301903Smav	struct _SET_VOLTAGE_PS_ALLOCATION alloc;
2704301903Smav	struct _SET_VOLTAGE_PARAMETERS v1;
2705301903Smav	struct _SET_VOLTAGE_PARAMETERS_V2 v2;
2706304404Smav	struct _SET_VOLTAGE_PARAMETERS_V1_3 v3;
2707301903Smav};
2708304404Smav
2709301811Sngievoid radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type)
2710301811Sngie{
2711300373Smav	union set_voltage args;
2712300373Smav	int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
2713300373Smav	u8 frev, crev, volt_index = voltage_level;
2714300373Smav
2715304380Smav	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2716304404Smav		return;
2717250079Scarl
2718304380Smav	/* 0xff01 is a flag rather then an actual voltage */
2719250079Scarl	if (voltage_level == 0xff01)
2720300373Smav		return;
2721250079Scarl
2722250079Scarl	switch (crev) {
2723304380Smav	case 1:
2724304404Smav		args.v1.ucVoltageType = voltage_type;
2725300373Smav		args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
2726304380Smav		args.v1.ucVoltageIndex = volt_index;
2727301811Sngie		break;
2728300373Smav	case 2:
2729301811Sngie		args.v2.ucVoltageType = voltage_type;
2730300373Smav		args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
2731301811Sngie		args.v2.usVoltageLevel = cpu_to_le16(voltage_level);
2732301811Sngie		break;
2733301811Sngie	case 3:
2734301811Sngie		args.v3.ucVoltageType = voltage_type;
2735300373Smav		args.v3.ucVoltageMode = ATOM_SET_VOLTAGE;
2736300373Smav		args.v3.usVoltageLevel = cpu_to_le16(voltage_level);
2737304380Smav		break;
2738304404Smav	default:
2739250079Scarl		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
2740304380Smav		return;
2741250079Scarl	}
2742300373Smav
2743250079Scarl	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2744250079Scarl}
2745304404Smav
2746250079Scarlstatic int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type,
2747250079Scarl				    u16 voltage_id, u16 *voltage)
2748250079Scarl{
2749250079Scarl	union set_voltage args;
2750301811Sngie	int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
2751301811Sngie	u8 frev, crev;
2752301811Sngie
2753304380Smav	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2754304404Smav		return -EINVAL;
2755301811Sngie
2756304380Smav	switch (crev) {
2757301811Sngie	case 1:
2758301811Sngie		return -EINVAL;
2759301811Sngie	case 2:
2760304404Smav		args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE;
2761301811Sngie		args.v2.ucVoltageMode = 0;
2762301811Sngie		args.v2.usVoltageLevel = 0;
2763304380Smav
2764304404Smav		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2765250079Scarl
2766304380Smav		*voltage = le16_to_cpu(args.v2.usVoltageLevel);
2767250079Scarl		break;
2768300373Smav	case 3:
2769250079Scarl		args.v3.ucVoltageType = voltage_type;
2770250079Scarl		args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL;
2771304404Smav		args.v3.usVoltageLevel = cpu_to_le16(voltage_id);
2772250079Scarl
2773250079Scarl		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2774250079Scarl
2775250079Scarl		*voltage = le16_to_cpu(args.v3.usVoltageLevel);
2776304380Smav		break;
2777304404Smav	default:
2778250079Scarl		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
2779304380Smav		return -EINVAL;
2780250079Scarl	}
2781300373Smav
2782250079Scarl	return 0;
2783250079Scarl}
2784304380Smav
2785304404Smavvoid radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
2786255279Scarl{
2787304404Smav	struct radeon_device *rdev = dev->dev_private;
2788250079Scarl	uint32_t bios_2_scratch, bios_6_scratch;
2789250079Scarl
2790250079Scarl	if (rdev->family >= CHIP_R600) {
2791250079Scarl		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
2792304380Smav		bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2793304404Smav	} else {
2794250079Scarl		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
2795304380Smav		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2796250079Scarl	}
2797300373Smav
2798250079Scarl	/* let the bios control the backlight */
2799250079Scarl	bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
2800304380Smav
2801304404Smav	/* tell the bios not to handle mode switching */
2802255279Scarl	bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
2803304404Smav
2804250079Scarl	if (rdev->family >= CHIP_R600) {
2805250079Scarl		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
2806250079Scarl		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2807250079Scarl	} else {
2808304380Smav		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
2809304404Smav		WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2810300373Smav	}
2811300373Smav
2812250079Scarl}
2813304380Smav
2814300373Smavvoid radeon_save_bios_scratch_regs(struct radeon_device *rdev)
2815300373Smav{
2816300373Smav	uint32_t scratch_reg;
2817300373Smav	int i;
2818250079Scarl
2819304404Smav	if (rdev->family >= CHIP_R600)
2820300373Smav		scratch_reg = R600_BIOS_0_SCRATCH;
2821304404Smav	else
2822250079Scarl		scratch_reg = RADEON_BIOS_0_SCRATCH;
2823304404Smav
2824300373Smav	for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
2825300373Smav		rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4));
2826300373Smav}
2827300373Smav
2828300373Smavvoid radeon_restore_bios_scratch_regs(struct radeon_device *rdev)
2829300373Smav{
2830300373Smav	uint32_t scratch_reg;
2831300373Smav	int i;
2832300373Smav
2833300373Smav	if (rdev->family >= CHIP_R600)
2834300373Smav		scratch_reg = R600_BIOS_0_SCRATCH;
2835300373Smav	else
2836300373Smav		scratch_reg = RADEON_BIOS_0_SCRATCH;
2837300373Smav
2838300373Smav	for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
2839300373Smav		WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]);
2840300373Smav}
2841300373Smav
2842300373Smavvoid radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
2843300373Smav{
2844300373Smav	struct drm_device *dev = encoder->dev;
2845300373Smav	struct radeon_device *rdev = dev->dev_private;
2846300373Smav	uint32_t bios_6_scratch;
2847300373Smav
2848300373Smav	if (rdev->family >= CHIP_R600)
2849300373Smav		bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2850250079Scarl	else
2851250079Scarl		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2852304380Smav
2853304404Smav	if (lock) {
2854250079Scarl		bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
2855304380Smav		bios_6_scratch &= ~ATOM_S6_ACC_MODE;
2856300373Smav	} else {
2857300373Smav		bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
2858300373Smav		bios_6_scratch |= ATOM_S6_ACC_MODE;
2859300373Smav	}
2860300373Smav
2861250079Scarl	if (rdev->family >= CHIP_R600)
2862304404Smav		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2863300373Smav	else
2864304404Smav		WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2865250079Scarl}
2866304404Smav
2867300373Smav/* at some point we may want to break this out into individual functions */
2868300373Smavvoid
2869300373Smavradeon_atombios_connected_scratch_regs(struct drm_connector *connector,
2870300373Smav				       struct drm_encoder *encoder,
2871300373Smav				       bool connected)
2872300373Smav{
2873300373Smav	struct drm_device *dev = connector->dev;
2874300373Smav	struct radeon_device *rdev = dev->dev_private;
2875300373Smav	struct radeon_connector *radeon_connector =
2876300373Smav	    to_radeon_connector(connector);
2877300373Smav	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2878300373Smav	uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch;
2879300373Smav
2880300373Smav	if (rdev->family >= CHIP_R600) {
2881300373Smav		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2882300373Smav		bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
2883300373Smav		bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2884300373Smav	} else {
2885300373Smav		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
2886304404Smav		bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
2887300373Smav		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2888300373Smav	}
2889300373Smav
2890300373Smav	if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
2891300373Smav	    (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
2892304404Smav		if (connected) {
2893304404Smav			DRM_DEBUG_KMS("TV1 connected\n");
2894300373Smav			bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
2895304404Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_TV1;
2896300373Smav		} else {
2897300373Smav			DRM_DEBUG_KMS("TV1 disconnected\n");
2898300373Smav			bios_0_scratch &= ~ATOM_S0_TV1_MASK;
2899300373Smav			bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
2900304404Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1;
2901304404Smav		}
2902300373Smav	}
2903304404Smav	if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) &&
2904304404Smav	    (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) {
2905300373Smav		if (connected) {
2906300373Smav			DRM_DEBUG_KMS("CV connected\n");
2907300373Smav			bios_3_scratch |= ATOM_S3_CV_ACTIVE;
2908300373Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_CV;
2909300373Smav		} else {
2910300373Smav			DRM_DEBUG_KMS("CV disconnected\n");
2911300373Smav			bios_0_scratch &= ~ATOM_S0_CV_MASK;
2912300373Smav			bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
2913300373Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV;
2914300373Smav		}
2915304404Smav	}
2916300373Smav	if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
2917300373Smav	    (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
2918300373Smav		if (connected) {
2919300373Smav			DRM_DEBUG_KMS("LCD1 connected\n");
2920300373Smav			bios_0_scratch |= ATOM_S0_LCD1;
2921304404Smav			bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
2922304404Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1;
2923300373Smav		} else {
2924304404Smav			DRM_DEBUG_KMS("LCD1 disconnected\n");
2925300373Smav			bios_0_scratch &= ~ATOM_S0_LCD1;
2926300373Smav			bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
2927300373Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1;
2928300373Smav		}
2929304404Smav	}
2930304404Smav	if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
2931300373Smav	    (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
2932304404Smav		if (connected) {
2933304404Smav			DRM_DEBUG_KMS("CRT1 connected\n");
2934300373Smav			bios_0_scratch |= ATOM_S0_CRT1_COLOR;
2935300373Smav			bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
2936300373Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1;
2937300373Smav		} else {
2938250079Scarl			DRM_DEBUG_KMS("CRT1 disconnected\n");
2939250079Scarl			bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
2940304380Smav			bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
2941304404Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1;
2942250079Scarl		}
2943250079Scarl	}
2944304404Smav	if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
2945300373Smav	    (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
2946300373Smav		if (connected) {
2947304380Smav			DRM_DEBUG_KMS("CRT2 connected\n");
2948304404Smav			bios_0_scratch |= ATOM_S0_CRT2_COLOR;
2949300373Smav			bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
2950304380Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2;
2951300373Smav		} else {
2952300373Smav			DRM_DEBUG_KMS("CRT2 disconnected\n");
2953304404Smav			bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
2954300373Smav			bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
2955304404Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2;
2956300373Smav		}
2957304404Smav	}
2958300373Smav	if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
2959300373Smav	    (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
2960300373Smav		if (connected) {
2961300373Smav			DRM_DEBUG_KMS("DFP1 connected\n");
2962304380Smav			bios_0_scratch |= ATOM_S0_DFP1;
2963304404Smav			bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
2964300373Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1;
2965304380Smav		} else {
2966300373Smav			DRM_DEBUG_KMS("DFP1 disconnected\n");
2967304404Smav			bios_0_scratch &= ~ATOM_S0_DFP1;
2968300373Smav			bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
2969300373Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1;
2970304404Smav		}
2971304404Smav	}
2972300373Smav	if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
2973300373Smav	    (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
2974300373Smav		if (connected) {
2975304404Smav			DRM_DEBUG_KMS("DFP2 connected\n");
2976300373Smav			bios_0_scratch |= ATOM_S0_DFP2;
2977300373Smav			bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
2978300373Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2;
2979300373Smav		} else {
2980304404Smav			DRM_DEBUG_KMS("DFP2 disconnected\n");
2981300373Smav			bios_0_scratch &= ~ATOM_S0_DFP2;
2982250079Scarl			bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
2983250079Scarl			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2;
2984300373Smav		}
2985300373Smav	}
2986300373Smav	if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) &&
2987300373Smav	    (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) {
2988300373Smav		if (connected) {
2989250079Scarl			DRM_DEBUG_KMS("DFP3 connected\n");
2990250079Scarl			bios_0_scratch |= ATOM_S0_DFP3;
2991304380Smav			bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
2992304404Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3;
2993250079Scarl		} else {
2994304380Smav			DRM_DEBUG_KMS("DFP3 disconnected\n");
2995250079Scarl			bios_0_scratch &= ~ATOM_S0_DFP3;
2996304380Smav			bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
2997301811Sngie			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3;
2998301811Sngie		}
2999301811Sngie	}
3000301811Sngie	if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) &&
3001301811Sngie	    (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) {
3002301811Sngie		if (connected) {
3003304404Smav			DRM_DEBUG_KMS("DFP4 connected\n");
3004301811Sngie			bios_0_scratch |= ATOM_S0_DFP4;
3005301811Sngie			bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
3006301811Sngie			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4;
3007301811Sngie		} else {
3008301811Sngie			DRM_DEBUG_KMS("DFP4 disconnected\n");
3009301811Sngie			bios_0_scratch &= ~ATOM_S0_DFP4;
3010301811Sngie			bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
3011301811Sngie			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4;
3012304380Smav		}
3013304404Smav	}
3014250079Scarl	if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) &&
3015300373Smav	    (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) {
3016250079Scarl		if (connected) {
3017300373Smav			DRM_DEBUG_KMS("DFP5 connected\n");
3018300373Smav			bios_0_scratch |= ATOM_S0_DFP5;
3019300373Smav			bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
3020304380Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5;
3021304404Smav		} else {
3022300373Smav			DRM_DEBUG_KMS("DFP5 disconnected\n");
3023304380Smav			bios_0_scratch &= ~ATOM_S0_DFP5;
3024300373Smav			bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
3025300373Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
3026300373Smav		}
3027304380Smav	}
3028300373Smav	if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) &&
3029304380Smav	    (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) {
3030300373Smav		if (connected) {
3031300373Smav			DRM_DEBUG_KMS("DFP6 connected\n");
3032300373Smav			bios_0_scratch |= ATOM_S0_DFP6;
3033300373Smav			bios_3_scratch |= ATOM_S3_DFP6_ACTIVE;
3034300373Smav			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6;
3035300373Smav		} else {
3036304404Smav			DRM_DEBUG_KMS("DFP6 disconnected\n");
3037300373Smav			bios_0_scratch &= ~ATOM_S0_DFP6;
3038250079Scarl			bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE;
3039300373Smav			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6;
3040300373Smav		}
3041300373Smav	}
3042304380Smav
3043304380Smav	if (rdev->family >= CHIP_R600) {
3044304380Smav		WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
3045250079Scarl		WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
3046250079Scarl		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
3047304380Smav	} else {
3048304404Smav		WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
3049250079Scarl		WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
3050304380Smav		WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
3051250079Scarl	}
3052300373Smav}
3053250079Scarl
3054250079Scarlvoid
3055304380Smavradeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
3056304404Smav{
3057300373Smav	struct drm_device *dev = encoder->dev;
3058304380Smav	struct radeon_device *rdev = dev->dev_private;
3059300373Smav	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3060304380Smav	uint32_t bios_3_scratch;
3061304380Smav
3062304380Smav	if (ASIC_IS_DCE4(rdev))
3063304380Smav		return;
3064304404Smav
3065304380Smav	if (rdev->family >= CHIP_R600)
3066304380Smav		bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
3067304380Smav	else
3068300373Smav		bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
3069300373Smav
3070304404Smav	if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
3071300373Smav		bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
3072300373Smav		bios_3_scratch |= (crtc << 18);
3073304380Smav	}
3074304404Smav	if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
3075250079Scarl		bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
3076304380Smav		bios_3_scratch |= (crtc << 24);
3077250079Scarl	}
3078300373Smav	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
3079304404Smav		bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
3080300373Smav		bios_3_scratch |= (crtc << 16);
3081304404Smav	}
3082300373Smav	if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
3083250079Scarl		bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
3084250079Scarl		bios_3_scratch |= (crtc << 20);
3085255272Scarl	}
3086255272Scarl	if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
3087250079Scarl		bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
3088255272Scarl		bios_3_scratch |= (crtc << 17);
3089300373Smav	}
3090300373Smav	if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
3091300373Smav		bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
3092300373Smav		bios_3_scratch |= (crtc << 19);
3093300373Smav	}
3094250079Scarl	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
3095255268Scarl		bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
3096304380Smav		bios_3_scratch |= (crtc << 23);
3097304380Smav	}
3098304404Smav	if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
3099304404Smav		bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
3100304404Smav		bios_3_scratch |= (crtc << 25);
3101304380Smav	}
3102304404Smav
3103304404Smav	if (rdev->family >= CHIP_R600)
3104304404Smav		WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
3105304404Smav	else
3106304404Smav		WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
3107304404Smav}
3108304404Smav
3109304404Smavvoid
3110304404Smavradeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
3111304404Smav{
3112304404Smav	struct drm_device *dev = encoder->dev;
3113304404Smav	struct radeon_device *rdev = dev->dev_private;
3114304404Smav	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3115304404Smav	uint32_t bios_2_scratch;
3116304404Smav
3117304404Smav	if (ASIC_IS_DCE4(rdev))
3118304404Smav		return;
3119304404Smav
3120304404Smav	if (rdev->family >= CHIP_R600)
3121304404Smav		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
3122304404Smav	else
3123304404Smav		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
3124304404Smav
3125304404Smav	if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
3126304404Smav		if (on)
3127304380Smav			bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
3128304380Smav		else
3129255268Scarl			bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
3130304380Smav	}
3131304380Smav	if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
3132304380Smav		if (on)
3133304380Smav			bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
3134304380Smav		else
3135			bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
3136	}
3137	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
3138		if (on)
3139			bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
3140		else
3141			bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
3142	}
3143	if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
3144		if (on)
3145			bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
3146		else
3147			bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
3148	}
3149	if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
3150		if (on)
3151			bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
3152		else
3153			bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
3154	}
3155	if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
3156		if (on)
3157			bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
3158		else
3159			bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
3160	}
3161	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
3162		if (on)
3163			bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
3164		else
3165			bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
3166	}
3167	if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
3168		if (on)
3169			bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
3170		else
3171			bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
3172	}
3173	if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) {
3174		if (on)
3175			bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
3176		else
3177			bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
3178	}
3179	if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) {
3180		if (on)
3181			bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
3182		else
3183			bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
3184	}
3185
3186	if (rdev->family >= CHIP_R600)
3187		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
3188	else
3189		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
3190}
3191