blob: 6d30868744eeed8e1890a13532dd77a36161fa4b [file] [log] [blame]
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001/*
2 * Copyright 2007-8 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Dave Airlie
24 * Alex Deucher
25 */
26#include "drmP.h"
27#include "radeon_drm.h"
28#include "radeon.h"
29
30#include "atom.h"
31#include "atom-bits.h"
32
33/* from radeon_encoder.c */
34extern uint32_t
35radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device,
36 uint8_t dac);
37extern void radeon_link_encoder_connector(struct drm_device *dev);
38extern void
39radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id,
40 uint32_t supported_device);
41
42/* from radeon_connector.c */
43extern void
44radeon_add_atom_connector(struct drm_device *dev,
45 uint32_t connector_id,
46 uint32_t supported_device,
47 int connector_type,
48 struct radeon_i2c_bus_rec *i2c_bus,
Alex Deucherb75fad02009-11-05 13:16:01 -050049 bool linkb, uint32_t igp_lane_info,
Alex Deuchereed45b32009-12-04 14:45:27 -050050 uint16_t connector_object_id,
Alex Deucher26b5bc92010-08-05 21:21:18 -040051 struct radeon_hpd *hpd,
52 struct radeon_router *router);
Jerome Glisse771fe6b2009-06-05 14:42:42 +020053
54/* from radeon_legacy_encoder.c */
55extern void
56radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id,
57 uint32_t supported_device);
58
59union atom_supported_devices {
60 struct _ATOM_SUPPORTED_DEVICES_INFO info;
61 struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2;
62 struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
63};
64
Alex Deuchereed45b32009-12-04 14:45:27 -050065static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
66 uint8_t id)
Jerome Glisse771fe6b2009-06-05 14:42:42 +020067{
Jerome Glisse771fe6b2009-06-05 14:42:42 +020068 struct atom_context *ctx = rdev->mode_info.atom_context;
Alex Deucher6a93cb22009-11-23 17:39:28 -050069 ATOM_GPIO_I2C_ASSIGMENT *gpio;
Jerome Glisse771fe6b2009-06-05 14:42:42 +020070 struct radeon_i2c_bus_rec i2c;
71 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
72 struct _ATOM_GPIO_I2C_INFO *i2c_info;
Alex Deucher95beb692010-04-01 19:08:47 +000073 uint16_t data_offset, size;
74 int i, num_indices;
Jerome Glisse771fe6b2009-06-05 14:42:42 +020075
76 memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
77 i2c.valid = false;
78
Alex Deucher95beb692010-04-01 19:08:47 +000079 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
Alex Deuchera084e6e2010-03-18 01:04:01 -040080 i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +020081
Alex Deucher95beb692010-04-01 19:08:47 +000082 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
83 sizeof(ATOM_GPIO_I2C_ASSIGMENT);
84
85 for (i = 0; i < num_indices; i++) {
Alex Deuchera084e6e2010-03-18 01:04:01 -040086 gpio = &i2c_info->asGPIO_Info[i];
Jerome Glisse771fe6b2009-06-05 14:42:42 +020087
Alex Deuchera084e6e2010-03-18 01:04:01 -040088 if (gpio->sucI2cId.ucAccess == id) {
89 i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
90 i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
91 i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
92 i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
93 i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
94 i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
95 i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
96 i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
97 i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
98 i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
99 i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
100 i2c.en_data_mask = (1 << gpio->ucDataEnShift);
101 i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
102 i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
103 i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
104 i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200105
Alex Deuchera084e6e2010-03-18 01:04:01 -0400106 if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
107 i2c.hw_capable = true;
108 else
109 i2c.hw_capable = false;
Alex Deucher6a93cb22009-11-23 17:39:28 -0500110
Alex Deuchera084e6e2010-03-18 01:04:01 -0400111 if (gpio->sucI2cId.ucAccess == 0xa0)
112 i2c.mm_i2c = true;
113 else
114 i2c.mm_i2c = false;
Alex Deucher6a93cb22009-11-23 17:39:28 -0500115
Alex Deuchera084e6e2010-03-18 01:04:01 -0400116 i2c.i2c_id = gpio->sucI2cId.ucAccess;
Alex Deucher6a93cb22009-11-23 17:39:28 -0500117
Alex Deucherf376b942010-08-05 21:21:16 -0400118 if (i2c.mask_clk_reg)
119 i2c.valid = true;
Alex Deuchera084e6e2010-03-18 01:04:01 -0400120 break;
121 }
Alex Deucherd3f420d2009-12-08 14:30:49 -0500122 }
123 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200124
125 return i2c;
126}
127
Alex Deucherf376b942010-08-05 21:21:16 -0400128void radeon_atombios_i2c_init(struct radeon_device *rdev)
129{
130 struct atom_context *ctx = rdev->mode_info.atom_context;
131 ATOM_GPIO_I2C_ASSIGMENT *gpio;
132 struct radeon_i2c_bus_rec i2c;
133 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
134 struct _ATOM_GPIO_I2C_INFO *i2c_info;
135 uint16_t data_offset, size;
136 int i, num_indices;
137 char stmp[32];
138
139 memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
140
141 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
142 i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
143
144 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
145 sizeof(ATOM_GPIO_I2C_ASSIGMENT);
146
147 for (i = 0; i < num_indices; i++) {
148 gpio = &i2c_info->asGPIO_Info[i];
149 i2c.valid = false;
150 i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
151 i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
152 i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
153 i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
154 i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
155 i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
156 i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
157 i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
158 i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
159 i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
160 i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
161 i2c.en_data_mask = (1 << gpio->ucDataEnShift);
162 i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
163 i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
164 i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
165 i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
166
167 if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
168 i2c.hw_capable = true;
169 else
170 i2c.hw_capable = false;
171
172 if (gpio->sucI2cId.ucAccess == 0xa0)
173 i2c.mm_i2c = true;
174 else
175 i2c.mm_i2c = false;
176
177 i2c.i2c_id = gpio->sucI2cId.ucAccess;
178
179 if (i2c.mask_clk_reg) {
180 i2c.valid = true;
181 sprintf(stmp, "0x%x", i2c.i2c_id);
182 rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
183 }
184 }
185 }
186}
187
Alex Deuchereed45b32009-12-04 14:45:27 -0500188static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
189 u8 id)
190{
191 struct atom_context *ctx = rdev->mode_info.atom_context;
192 struct radeon_gpio_rec gpio;
193 int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
194 struct _ATOM_GPIO_PIN_LUT *gpio_info;
195 ATOM_GPIO_PIN_ASSIGNMENT *pin;
196 u16 data_offset, size;
197 int i, num_indices;
198
199 memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
200 gpio.valid = false;
201
Alex Deuchera084e6e2010-03-18 01:04:01 -0400202 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
203 gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
Alex Deuchereed45b32009-12-04 14:45:27 -0500204
Alex Deuchera084e6e2010-03-18 01:04:01 -0400205 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
206 sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
Alex Deuchereed45b32009-12-04 14:45:27 -0500207
Alex Deuchera084e6e2010-03-18 01:04:01 -0400208 for (i = 0; i < num_indices; i++) {
209 pin = &gpio_info->asGPIO_Pin[i];
210 if (id == pin->ucGPIO_ID) {
211 gpio.id = pin->ucGPIO_ID;
212 gpio.reg = pin->usGpioPin_AIndex * 4;
213 gpio.mask = (1 << pin->ucGpioPinBitShift);
214 gpio.valid = true;
215 break;
216 }
Alex Deuchereed45b32009-12-04 14:45:27 -0500217 }
218 }
219
220 return gpio;
221}
222
223static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev,
224 struct radeon_gpio_rec *gpio)
225{
226 struct radeon_hpd hpd;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500227 u32 reg;
228
229 if (ASIC_IS_DCE4(rdev))
230 reg = EVERGREEN_DC_GPIO_HPD_A;
231 else
232 reg = AVIVO_DC_GPIO_HPD_A;
233
Alex Deuchereed45b32009-12-04 14:45:27 -0500234 hpd.gpio = *gpio;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500235 if (gpio->reg == reg) {
Alex Deuchereed45b32009-12-04 14:45:27 -0500236 switch(gpio->mask) {
237 case (1 << 0):
238 hpd.hpd = RADEON_HPD_1;
239 break;
240 case (1 << 8):
241 hpd.hpd = RADEON_HPD_2;
242 break;
243 case (1 << 16):
244 hpd.hpd = RADEON_HPD_3;
245 break;
246 case (1 << 24):
247 hpd.hpd = RADEON_HPD_4;
248 break;
249 case (1 << 26):
250 hpd.hpd = RADEON_HPD_5;
251 break;
252 case (1 << 28):
253 hpd.hpd = RADEON_HPD_6;
254 break;
255 default:
256 hpd.hpd = RADEON_HPD_NONE;
257 break;
258 }
259 } else
260 hpd.hpd = RADEON_HPD_NONE;
261 return hpd;
262}
263
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200264static bool radeon_atom_apply_quirks(struct drm_device *dev,
265 uint32_t supported_device,
266 int *connector_type,
Alex Deucher848577e2009-07-08 16:15:30 -0400267 struct radeon_i2c_bus_rec *i2c_bus,
Alex Deuchereed45b32009-12-04 14:45:27 -0500268 uint16_t *line_mux,
269 struct radeon_hpd *hpd)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200270{
Alex Deucher9ea2c4b2010-08-06 00:27:44 -0400271 struct radeon_device *rdev = dev->dev_private;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200272
273 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
274 if ((dev->pdev->device == 0x791e) &&
275 (dev->pdev->subsystem_vendor == 0x1043) &&
276 (dev->pdev->subsystem_device == 0x826d)) {
277 if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
278 (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
279 *connector_type = DRM_MODE_CONNECTOR_DVID;
280 }
281
Alex Deucherc86a9032010-02-18 14:14:58 -0500282 /* Asrock RS600 board lists the DVI port as HDMI */
283 if ((dev->pdev->device == 0x7941) &&
284 (dev->pdev->subsystem_vendor == 0x1849) &&
285 (dev->pdev->subsystem_device == 0x7941)) {
286 if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
287 (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
288 *connector_type = DRM_MODE_CONNECTOR_DVID;
289 }
290
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200291 /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
292 if ((dev->pdev->device == 0x7941) &&
293 (dev->pdev->subsystem_vendor == 0x147b) &&
294 (dev->pdev->subsystem_device == 0x2412)) {
295 if (*connector_type == DRM_MODE_CONNECTOR_DVII)
296 return false;
297 }
298
299 /* Falcon NW laptop lists vga ddc line for LVDS */
300 if ((dev->pdev->device == 0x5653) &&
301 (dev->pdev->subsystem_vendor == 0x1462) &&
302 (dev->pdev->subsystem_device == 0x0291)) {
Alex Deucher848577e2009-07-08 16:15:30 -0400303 if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200304 i2c_bus->valid = false;
Alex Deucher848577e2009-07-08 16:15:30 -0400305 *line_mux = 53;
306 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200307 }
308
Alex Deucher4e3f9b72009-12-01 14:49:50 -0500309 /* HIS X1300 is DVI+VGA, not DVI+DVI */
310 if ((dev->pdev->device == 0x7146) &&
311 (dev->pdev->subsystem_vendor == 0x17af) &&
312 (dev->pdev->subsystem_device == 0x2058)) {
313 if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
314 return false;
315 }
316
Dave Airlieaa1a7502009-12-04 11:51:34 +1000317 /* Gigabyte X1300 is DVI+VGA, not DVI+DVI */
318 if ((dev->pdev->device == 0x7142) &&
319 (dev->pdev->subsystem_vendor == 0x1458) &&
320 (dev->pdev->subsystem_device == 0x2134)) {
321 if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
322 return false;
323 }
324
325
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200326 /* Funky macbooks */
327 if ((dev->pdev->device == 0x71C5) &&
328 (dev->pdev->subsystem_vendor == 0x106b) &&
329 (dev->pdev->subsystem_device == 0x0080)) {
330 if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
331 (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
332 return false;
Alex Deuchere1e8a5d2010-03-26 17:14:37 -0400333 if (supported_device == ATOM_DEVICE_CRT2_SUPPORT)
334 *line_mux = 0x90;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200335 }
336
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200337 /* ASUS HD 3600 XT board lists the DVI port as HDMI */
338 if ((dev->pdev->device == 0x9598) &&
339 (dev->pdev->subsystem_vendor == 0x1043) &&
340 (dev->pdev->subsystem_device == 0x01da)) {
Alex Deucher705af9c2009-09-10 16:31:13 -0400341 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
Alex Deucherd42571e2009-09-11 15:27:14 -0400342 *connector_type = DRM_MODE_CONNECTOR_DVII;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200343 }
344 }
345
Alex Deuchere153b702010-07-20 18:07:22 -0400346 /* ASUS HD 3600 board lists the DVI port as HDMI */
347 if ((dev->pdev->device == 0x9598) &&
348 (dev->pdev->subsystem_vendor == 0x1043) &&
349 (dev->pdev->subsystem_device == 0x01e4)) {
350 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
351 *connector_type = DRM_MODE_CONNECTOR_DVII;
352 }
353 }
354
Alex Deucher705af9c2009-09-10 16:31:13 -0400355 /* ASUS HD 3450 board lists the DVI port as HDMI */
356 if ((dev->pdev->device == 0x95C5) &&
357 (dev->pdev->subsystem_vendor == 0x1043) &&
358 (dev->pdev->subsystem_device == 0x01e2)) {
359 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
Alex Deucherd42571e2009-09-11 15:27:14 -0400360 *connector_type = DRM_MODE_CONNECTOR_DVII;
Alex Deucher705af9c2009-09-10 16:31:13 -0400361 }
362 }
363
364 /* some BIOSes seem to report DAC on HDMI - usually this is a board with
365 * HDMI + VGA reporting as HDMI
366 */
367 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
368 if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
369 *connector_type = DRM_MODE_CONNECTOR_VGA;
370 *line_mux = 0;
371 }
372 }
373
Alex Deucher9ea2c4b2010-08-06 00:27:44 -0400374 /* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500375 if ((dev->pdev->device == 0x95c4) &&
376 (dev->pdev->subsystem_vendor == 0x1025) &&
377 (dev->pdev->subsystem_device == 0x013c)) {
Alex Deucher9ea2c4b2010-08-06 00:27:44 -0400378 struct radeon_gpio_rec gpio;
379
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500380 if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
Alex Deucher9ea2c4b2010-08-06 00:27:44 -0400381 (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
382 gpio = radeon_lookup_gpio(rdev, 6);
383 *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500384 *connector_type = DRM_MODE_CONNECTOR_DVID;
Alex Deucher9ea2c4b2010-08-06 00:27:44 -0400385 } else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
386 (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
387 gpio = radeon_lookup_gpio(rdev, 7);
388 *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
389 }
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500390 }
391
Dave Airlieefa84502010-02-09 09:06:00 +1000392 /* XFX Pine Group device rv730 reports no VGA DDC lines
393 * even though they are wired up to record 0x93
394 */
395 if ((dev->pdev->device == 0x9498) &&
396 (dev->pdev->subsystem_vendor == 0x1682) &&
397 (dev->pdev->subsystem_device == 0x2452)) {
398 struct radeon_device *rdev = dev->dev_private;
399 *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
400 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200401 return true;
402}
403
404const int supported_devices_connector_convert[] = {
405 DRM_MODE_CONNECTOR_Unknown,
406 DRM_MODE_CONNECTOR_VGA,
407 DRM_MODE_CONNECTOR_DVII,
408 DRM_MODE_CONNECTOR_DVID,
409 DRM_MODE_CONNECTOR_DVIA,
410 DRM_MODE_CONNECTOR_SVIDEO,
411 DRM_MODE_CONNECTOR_Composite,
412 DRM_MODE_CONNECTOR_LVDS,
413 DRM_MODE_CONNECTOR_Unknown,
414 DRM_MODE_CONNECTOR_Unknown,
415 DRM_MODE_CONNECTOR_HDMIA,
416 DRM_MODE_CONNECTOR_HDMIB,
417 DRM_MODE_CONNECTOR_Unknown,
418 DRM_MODE_CONNECTOR_Unknown,
419 DRM_MODE_CONNECTOR_9PinDIN,
420 DRM_MODE_CONNECTOR_DisplayPort
421};
422
Alex Deucherb75fad02009-11-05 13:16:01 -0500423const uint16_t supported_devices_connector_object_id_convert[] = {
424 CONNECTOR_OBJECT_ID_NONE,
425 CONNECTOR_OBJECT_ID_VGA,
426 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
427 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
428 CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
429 CONNECTOR_OBJECT_ID_COMPOSITE,
430 CONNECTOR_OBJECT_ID_SVIDEO,
431 CONNECTOR_OBJECT_ID_LVDS,
432 CONNECTOR_OBJECT_ID_9PIN_DIN,
433 CONNECTOR_OBJECT_ID_9PIN_DIN,
434 CONNECTOR_OBJECT_ID_DISPLAYPORT,
435 CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
436 CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
437 CONNECTOR_OBJECT_ID_SVIDEO
438};
439
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200440const int object_connector_convert[] = {
441 DRM_MODE_CONNECTOR_Unknown,
442 DRM_MODE_CONNECTOR_DVII,
443 DRM_MODE_CONNECTOR_DVII,
444 DRM_MODE_CONNECTOR_DVID,
445 DRM_MODE_CONNECTOR_DVID,
446 DRM_MODE_CONNECTOR_VGA,
447 DRM_MODE_CONNECTOR_Composite,
448 DRM_MODE_CONNECTOR_SVIDEO,
449 DRM_MODE_CONNECTOR_Unknown,
Alex Deucher705af9c2009-09-10 16:31:13 -0400450 DRM_MODE_CONNECTOR_Unknown,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200451 DRM_MODE_CONNECTOR_9PinDIN,
452 DRM_MODE_CONNECTOR_Unknown,
453 DRM_MODE_CONNECTOR_HDMIA,
454 DRM_MODE_CONNECTOR_HDMIB,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200455 DRM_MODE_CONNECTOR_LVDS,
456 DRM_MODE_CONNECTOR_9PinDIN,
457 DRM_MODE_CONNECTOR_Unknown,
458 DRM_MODE_CONNECTOR_Unknown,
459 DRM_MODE_CONNECTOR_Unknown,
Alex Deucher196c58d2010-01-07 14:22:32 -0500460 DRM_MODE_CONNECTOR_DisplayPort,
461 DRM_MODE_CONNECTOR_eDP,
462 DRM_MODE_CONNECTOR_Unknown
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200463};
464
465bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
466{
467 struct radeon_device *rdev = dev->dev_private;
468 struct radeon_mode_info *mode_info = &rdev->mode_info;
469 struct atom_context *ctx = mode_info->atom_context;
470 int index = GetIndexIntoMasterTable(DATA, Object_Header);
Alex Deuchereed45b32009-12-04 14:45:27 -0500471 u16 size, data_offset;
472 u8 frev, crev;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200473 ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400474 ATOM_OBJECT_TABLE *router_obj;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200475 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
476 ATOM_OBJECT_HEADER *obj_header;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400477 int i, j, k, path_size, device_support;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200478 int connector_type;
Alex Deuchereed45b32009-12-04 14:45:27 -0500479 u16 igp_lane_info, conn_id, connector_object_id;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200480 bool linkb;
481 struct radeon_i2c_bus_rec ddc_bus;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400482 struct radeon_router router;
Alex Deuchereed45b32009-12-04 14:45:27 -0500483 struct radeon_gpio_rec gpio;
484 struct radeon_hpd hpd;
485
Alex Deuchera084e6e2010-03-18 01:04:01 -0400486 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200487 return false;
488
489 if (crev < 2)
490 return false;
491
Alex Deucher26b5bc92010-08-05 21:21:18 -0400492 router.valid = false;
493
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200494 obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
495 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
496 (ctx->bios + data_offset +
497 le16_to_cpu(obj_header->usDisplayPathTableOffset));
498 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
499 (ctx->bios + data_offset +
500 le16_to_cpu(obj_header->usConnectorObjectTableOffset));
Alex Deucher26b5bc92010-08-05 21:21:18 -0400501 router_obj = (ATOM_OBJECT_TABLE *)
502 (ctx->bios + data_offset +
503 le16_to_cpu(obj_header->usRouterObjectTableOffset));
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200504 device_support = le16_to_cpu(obj_header->usDeviceSupport);
505
506 path_size = 0;
507 for (i = 0; i < path_obj->ucNumOfDispPath; i++) {
508 uint8_t *addr = (uint8_t *) path_obj->asDispPath;
509 ATOM_DISPLAY_OBJECT_PATH *path;
510 addr += path_size;
511 path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
512 path_size += le16_to_cpu(path->usSize);
513 linkb = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200514 if (device_support & le16_to_cpu(path->usDeviceTag)) {
515 uint8_t con_obj_id, con_obj_num, con_obj_type;
516
517 con_obj_id =
518 (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
519 >> OBJECT_ID_SHIFT;
520 con_obj_num =
521 (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
522 >> ENUM_ID_SHIFT;
523 con_obj_type =
524 (le16_to_cpu(path->usConnObjectId) &
525 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
526
Dave Airlie4bbd4972009-09-25 08:56:12 +1000527 /* TODO CV support */
528 if (le16_to_cpu(path->usDeviceTag) ==
529 ATOM_DEVICE_CV_SUPPORT)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200530 continue;
531
Alex Deucheree59f2b2009-11-05 13:11:46 -0500532 /* IGP chips */
533 if ((rdev->flags & RADEON_IS_IGP) &&
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200534 (con_obj_id ==
535 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
536 uint16_t igp_offset = 0;
537 ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj;
538
539 index =
540 GetIndexIntoMasterTable(DATA,
541 IntegratedSystemInfo);
542
Alex Deuchera084e6e2010-03-18 01:04:01 -0400543 if (atom_parse_data_header(ctx, index, &size, &frev,
544 &crev, &igp_offset)) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200545
Alex Deuchera084e6e2010-03-18 01:04:01 -0400546 if (crev >= 2) {
547 igp_obj =
548 (ATOM_INTEGRATED_SYSTEM_INFO_V2
549 *) (ctx->bios + igp_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200550
Alex Deuchera084e6e2010-03-18 01:04:01 -0400551 if (igp_obj) {
552 uint32_t slot_config, ct;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200553
Alex Deuchera084e6e2010-03-18 01:04:01 -0400554 if (con_obj_num == 1)
555 slot_config =
556 igp_obj->
557 ulDDISlot1Config;
558 else
559 slot_config =
560 igp_obj->
561 ulDDISlot2Config;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200562
Alex Deuchera084e6e2010-03-18 01:04:01 -0400563 ct = (slot_config >> 16) & 0xff;
564 connector_type =
565 object_connector_convert
566 [ct];
567 connector_object_id = ct;
568 igp_lane_info =
569 slot_config & 0xffff;
570 } else
571 continue;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200572 } else
573 continue;
Alex Deuchera084e6e2010-03-18 01:04:01 -0400574 } else {
575 igp_lane_info = 0;
576 connector_type =
577 object_connector_convert[con_obj_id];
578 connector_object_id = con_obj_id;
579 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200580 } else {
581 igp_lane_info = 0;
582 connector_type =
583 object_connector_convert[con_obj_id];
Alex Deucherb75fad02009-11-05 13:16:01 -0500584 connector_object_id = con_obj_id;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200585 }
586
587 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
588 continue;
589
Alex Deucher26b5bc92010-08-05 21:21:18 -0400590 for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
591 uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200592
Alex Deucher26b5bc92010-08-05 21:21:18 -0400593 grph_obj_id =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200594 (le16_to_cpu(path->usGraphicObjIds[j]) &
595 OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400596 grph_obj_num =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200597 (le16_to_cpu(path->usGraphicObjIds[j]) &
598 ENUM_ID_MASK) >> ENUM_ID_SHIFT;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400599 grph_obj_type =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200600 (le16_to_cpu(path->usGraphicObjIds[j]) &
601 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
602
Alex Deucher26b5bc92010-08-05 21:21:18 -0400603 if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
604 if (grph_obj_num == 2)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200605 linkb = true;
606 else
607 linkb = false;
608
609 radeon_add_atom_encoder(dev,
Alex Deucher26b5bc92010-08-05 21:21:18 -0400610 grph_obj_id,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200611 le16_to_cpu
612 (path->
613 usDeviceTag));
614
Alex Deucher26b5bc92010-08-05 21:21:18 -0400615 } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
616 router.valid = false;
617 for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
618 u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID);
619 if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
620 ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
621 (ctx->bios + data_offset +
622 le16_to_cpu(router_obj->asObjects[k].usRecordOffset));
623 ATOM_I2C_RECORD *i2c_record;
624 ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
625 ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
626 ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
627 (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
628 (ctx->bios + data_offset +
629 le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset));
630 int enum_id;
631
632 router.router_id = router_obj_id;
633 for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst;
634 enum_id++) {
635 if (le16_to_cpu(path->usConnObjectId) ==
636 le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id]))
637 break;
638 }
639
640 while (record->ucRecordType > 0 &&
641 record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
642 switch (record->ucRecordType) {
643 case ATOM_I2C_RECORD_TYPE:
644 i2c_record =
645 (ATOM_I2C_RECORD *)
646 record;
647 i2c_config =
648 (ATOM_I2C_ID_CONFIG_ACCESS *)
649 &i2c_record->sucI2cId;
650 router.i2c_info =
651 radeon_lookup_i2c_gpio(rdev,
652 i2c_config->
653 ucAccess);
654 router.i2c_addr = i2c_record->ucI2CAddr >> 1;
655 break;
656 case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
657 ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
658 record;
659 router.valid = true;
660 router.mux_type = ddc_path->ucMuxType;
661 router.mux_control_pin = ddc_path->ucMuxControlPin;
662 router.mux_state = ddc_path->ucMuxState[enum_id];
663 break;
664 }
665 record = (ATOM_COMMON_RECORD_HEADER *)
666 ((char *)record + record->ucRecordSize);
667 }
668 }
669 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200670 }
671 }
672
Alex Deuchereed45b32009-12-04 14:45:27 -0500673 /* look up gpio for ddc, hpd */
Alex Deucher2bfcc0f2010-05-18 19:26:46 -0400674 ddc_bus.valid = false;
675 hpd.hpd = RADEON_HPD_NONE;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200676 if ((le16_to_cpu(path->usDeviceTag) &
Alex Deuchereed45b32009-12-04 14:45:27 -0500677 (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200678 for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
679 if (le16_to_cpu(path->usConnObjectId) ==
680 le16_to_cpu(con_obj->asObjects[j].
681 usObjectID)) {
682 ATOM_COMMON_RECORD_HEADER
683 *record =
684 (ATOM_COMMON_RECORD_HEADER
685 *)
686 (ctx->bios + data_offset +
687 le16_to_cpu(con_obj->
688 asObjects[j].
689 usRecordOffset));
690 ATOM_I2C_RECORD *i2c_record;
Alex Deuchereed45b32009-12-04 14:45:27 -0500691 ATOM_HPD_INT_RECORD *hpd_record;
Alex Deucherd3f420d2009-12-08 14:30:49 -0500692 ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
Alex Deucher6a93cb22009-11-23 17:39:28 -0500693
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200694 while (record->ucRecordType > 0
695 && record->
696 ucRecordType <=
697 ATOM_MAX_OBJECT_RECORD_NUMBER) {
Alex Deuchereed45b32009-12-04 14:45:27 -0500698 switch (record->ucRecordType) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200699 case ATOM_I2C_RECORD_TYPE:
700 i2c_record =
Alex Deuchereed45b32009-12-04 14:45:27 -0500701 (ATOM_I2C_RECORD *)
702 record;
Alex Deucherd3f420d2009-12-08 14:30:49 -0500703 i2c_config =
704 (ATOM_I2C_ID_CONFIG_ACCESS *)
705 &i2c_record->sucI2cId;
Alex Deuchereed45b32009-12-04 14:45:27 -0500706 ddc_bus = radeon_lookup_i2c_gpio(rdev,
Alex Deucherd3f420d2009-12-08 14:30:49 -0500707 i2c_config->
708 ucAccess);
Alex Deuchereed45b32009-12-04 14:45:27 -0500709 break;
710 case ATOM_HPD_INT_RECORD_TYPE:
711 hpd_record =
712 (ATOM_HPD_INT_RECORD *)
713 record;
714 gpio = radeon_lookup_gpio(rdev,
715 hpd_record->ucHPDIntGPIOID);
716 hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
717 hpd.plugged_state = hpd_record->ucPlugged_PinState;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200718 break;
719 }
720 record =
721 (ATOM_COMMON_RECORD_HEADER
722 *) ((char *)record
723 +
724 record->
725 ucRecordSize);
726 }
727 break;
728 }
729 }
Alex Deuchereed45b32009-12-04 14:45:27 -0500730 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200731
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500732 /* needed for aux chan transactions */
Alex Deucher8e36ed02010-05-18 19:26:47 -0400733 ddc_bus.hpd = hpd.hpd;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500734
Alex Deucher705af9c2009-09-10 16:31:13 -0400735 conn_id = le16_to_cpu(path->usConnObjectId);
736
737 if (!radeon_atom_apply_quirks
738 (dev, le16_to_cpu(path->usDeviceTag), &connector_type,
Alex Deuchereed45b32009-12-04 14:45:27 -0500739 &ddc_bus, &conn_id, &hpd))
Alex Deucher705af9c2009-09-10 16:31:13 -0400740 continue;
741
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200742 radeon_add_atom_connector(dev,
Alex Deucher705af9c2009-09-10 16:31:13 -0400743 conn_id,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200744 le16_to_cpu(path->
745 usDeviceTag),
746 connector_type, &ddc_bus,
Alex Deucherb75fad02009-11-05 13:16:01 -0500747 linkb, igp_lane_info,
Alex Deuchereed45b32009-12-04 14:45:27 -0500748 connector_object_id,
Alex Deucher26b5bc92010-08-05 21:21:18 -0400749 &hpd,
750 &router);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200751
752 }
753 }
754
755 radeon_link_encoder_connector(dev);
756
757 return true;
758}
759
Alex Deucherb75fad02009-11-05 13:16:01 -0500760static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
761 int connector_type,
762 uint16_t devices)
763{
764 struct radeon_device *rdev = dev->dev_private;
765
766 if (rdev->flags & RADEON_IS_IGP) {
767 return supported_devices_connector_object_id_convert
768 [connector_type];
769 } else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
770 (connector_type == DRM_MODE_CONNECTOR_DVID)) &&
771 (devices & ATOM_DEVICE_DFP2_SUPPORT)) {
772 struct radeon_mode_info *mode_info = &rdev->mode_info;
773 struct atom_context *ctx = mode_info->atom_context;
774 int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
775 uint16_t size, data_offset;
776 uint8_t frev, crev;
777 ATOM_XTMDS_INFO *xtmds;
778
Alex Deuchera084e6e2010-03-18 01:04:01 -0400779 if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
780 xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
Alex Deucherb75fad02009-11-05 13:16:01 -0500781
Alex Deuchera084e6e2010-03-18 01:04:01 -0400782 if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
783 if (connector_type == DRM_MODE_CONNECTOR_DVII)
784 return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
785 else
786 return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
787 } else {
788 if (connector_type == DRM_MODE_CONNECTOR_DVII)
789 return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
790 else
791 return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
792 }
793 } else
794 return supported_devices_connector_object_id_convert
795 [connector_type];
Alex Deucherb75fad02009-11-05 13:16:01 -0500796 } else {
797 return supported_devices_connector_object_id_convert
798 [connector_type];
799 }
800}
801
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200802struct bios_connector {
803 bool valid;
Alex Deucher705af9c2009-09-10 16:31:13 -0400804 uint16_t line_mux;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200805 uint16_t devices;
806 int connector_type;
807 struct radeon_i2c_bus_rec ddc_bus;
Alex Deuchereed45b32009-12-04 14:45:27 -0500808 struct radeon_hpd hpd;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200809};
810
811bool radeon_get_atom_connector_info_from_supported_devices_table(struct
812 drm_device
813 *dev)
814{
815 struct radeon_device *rdev = dev->dev_private;
816 struct radeon_mode_info *mode_info = &rdev->mode_info;
817 struct atom_context *ctx = mode_info->atom_context;
818 int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo);
819 uint16_t size, data_offset;
820 uint8_t frev, crev;
821 uint16_t device_support;
822 uint8_t dac;
823 union atom_supported_devices *supported_devices;
Alex Deuchereed45b32009-12-04 14:45:27 -0500824 int i, j, max_device;
Prarit Bhargavaf49d2732010-05-24 10:24:07 +1000825 struct bios_connector *bios_connectors;
826 size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400827 struct radeon_router router;
828
829 router.valid = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200830
Prarit Bhargavaf49d2732010-05-24 10:24:07 +1000831 bios_connectors = kzalloc(bc_size, GFP_KERNEL);
832 if (!bios_connectors)
Alex Deuchera084e6e2010-03-18 01:04:01 -0400833 return false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200834
Prarit Bhargavaf49d2732010-05-24 10:24:07 +1000835 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev,
836 &data_offset)) {
837 kfree(bios_connectors);
838 return false;
839 }
840
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200841 supported_devices =
842 (union atom_supported_devices *)(ctx->bios + data_offset);
843
844 device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
845
Alex Deuchereed45b32009-12-04 14:45:27 -0500846 if (frev > 1)
847 max_device = ATOM_MAX_SUPPORTED_DEVICE;
848 else
849 max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
850
851 for (i = 0; i < max_device; i++) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200852 ATOM_CONNECTOR_INFO_I2C ci =
853 supported_devices->info.asConnInfo[i];
854
855 bios_connectors[i].valid = false;
856
857 if (!(device_support & (1 << i))) {
858 continue;
859 }
860
861 if (i == ATOM_DEVICE_CV_INDEX) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000862 DRM_DEBUG_KMS("Skipping Component Video\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200863 continue;
864 }
865
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200866 bios_connectors[i].connector_type =
867 supported_devices_connector_convert[ci.sucConnectorInfo.
868 sbfAccess.
869 bfConnectorType];
870
871 if (bios_connectors[i].connector_type ==
872 DRM_MODE_CONNECTOR_Unknown)
873 continue;
874
875 dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
876
Alex Deucherd3f420d2009-12-08 14:30:49 -0500877 bios_connectors[i].line_mux =
878 ci.sucI2cId.ucAccess;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200879
880 /* give tv unique connector ids */
881 if (i == ATOM_DEVICE_TV1_INDEX) {
882 bios_connectors[i].ddc_bus.valid = false;
883 bios_connectors[i].line_mux = 50;
884 } else if (i == ATOM_DEVICE_TV2_INDEX) {
885 bios_connectors[i].ddc_bus.valid = false;
886 bios_connectors[i].line_mux = 51;
887 } else if (i == ATOM_DEVICE_CV_INDEX) {
888 bios_connectors[i].ddc_bus.valid = false;
889 bios_connectors[i].line_mux = 52;
890 } else
891 bios_connectors[i].ddc_bus =
Alex Deuchereed45b32009-12-04 14:45:27 -0500892 radeon_lookup_i2c_gpio(rdev,
893 bios_connectors[i].line_mux);
894
895 if ((crev > 1) && (frev > 1)) {
896 u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap;
897 switch (isb) {
898 case 0x4:
899 bios_connectors[i].hpd.hpd = RADEON_HPD_1;
900 break;
901 case 0xa:
902 bios_connectors[i].hpd.hpd = RADEON_HPD_2;
903 break;
904 default:
905 bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
906 break;
907 }
908 } else {
909 if (i == ATOM_DEVICE_DFP1_INDEX)
910 bios_connectors[i].hpd.hpd = RADEON_HPD_1;
911 else if (i == ATOM_DEVICE_DFP2_INDEX)
912 bios_connectors[i].hpd.hpd = RADEON_HPD_2;
913 else
914 bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
915 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200916
917 /* Always set the connector type to VGA for CRT1/CRT2. if they are
918 * shared with a DVI port, we'll pick up the DVI connector when we
919 * merge the outputs. Some bioses incorrectly list VGA ports as DVI.
920 */
921 if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX)
922 bios_connectors[i].connector_type =
923 DRM_MODE_CONNECTOR_VGA;
924
925 if (!radeon_atom_apply_quirks
926 (dev, (1 << i), &bios_connectors[i].connector_type,
Alex Deuchereed45b32009-12-04 14:45:27 -0500927 &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux,
928 &bios_connectors[i].hpd))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200929 continue;
930
931 bios_connectors[i].valid = true;
932 bios_connectors[i].devices = (1 << i);
933
934 if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)
935 radeon_add_atom_encoder(dev,
936 radeon_get_encoder_id(dev,
937 (1 << i),
938 dac),
939 (1 << i));
940 else
941 radeon_add_legacy_encoder(dev,
942 radeon_get_encoder_id(dev,
Alex Deucherf56cd642009-12-18 11:28:22 -0500943 (1 << i),
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200944 dac),
945 (1 << i));
946 }
947
948 /* combine shared connectors */
Alex Deuchereed45b32009-12-04 14:45:27 -0500949 for (i = 0; i < max_device; i++) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200950 if (bios_connectors[i].valid) {
Alex Deuchereed45b32009-12-04 14:45:27 -0500951 for (j = 0; j < max_device; j++) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200952 if (bios_connectors[j].valid && (i != j)) {
953 if (bios_connectors[i].line_mux ==
954 bios_connectors[j].line_mux) {
Alex Deucherf56cd642009-12-18 11:28:22 -0500955 /* make sure not to combine LVDS */
956 if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
957 bios_connectors[i].line_mux = 53;
958 bios_connectors[i].ddc_bus.valid = false;
959 continue;
960 }
961 if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
962 bios_connectors[j].line_mux = 53;
963 bios_connectors[j].ddc_bus.valid = false;
964 continue;
965 }
966 /* combine analog and digital for DVI-I */
967 if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
968 (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) ||
969 ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
970 (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) {
971 bios_connectors[i].devices |=
972 bios_connectors[j].devices;
973 bios_connectors[i].connector_type =
974 DRM_MODE_CONNECTOR_DVII;
975 if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT))
Alex Deuchereed45b32009-12-04 14:45:27 -0500976 bios_connectors[i].hpd =
977 bios_connectors[j].hpd;
Alex Deucherf56cd642009-12-18 11:28:22 -0500978 bios_connectors[j].valid = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200979 }
980 }
981 }
982 }
983 }
984 }
985
986 /* add the connectors */
Alex Deuchereed45b32009-12-04 14:45:27 -0500987 for (i = 0; i < max_device; i++) {
Alex Deucherb75fad02009-11-05 13:16:01 -0500988 if (bios_connectors[i].valid) {
989 uint16_t connector_object_id =
990 atombios_get_connector_object_id(dev,
991 bios_connectors[i].connector_type,
992 bios_connectors[i].devices);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200993 radeon_add_atom_connector(dev,
994 bios_connectors[i].line_mux,
995 bios_connectors[i].devices,
996 bios_connectors[i].
997 connector_type,
998 &bios_connectors[i].ddc_bus,
Alex Deucherb75fad02009-11-05 13:16:01 -0500999 false, 0,
Alex Deuchereed45b32009-12-04 14:45:27 -05001000 connector_object_id,
Alex Deucher26b5bc92010-08-05 21:21:18 -04001001 &bios_connectors[i].hpd,
1002 &router);
Alex Deucherb75fad02009-11-05 13:16:01 -05001003 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001004 }
1005
1006 radeon_link_encoder_connector(dev);
1007
Prarit Bhargavaf49d2732010-05-24 10:24:07 +10001008 kfree(bios_connectors);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001009 return true;
1010}
1011
1012union firmware_info {
1013 ATOM_FIRMWARE_INFO info;
1014 ATOM_FIRMWARE_INFO_V1_2 info_12;
1015 ATOM_FIRMWARE_INFO_V1_3 info_13;
1016 ATOM_FIRMWARE_INFO_V1_4 info_14;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001017 ATOM_FIRMWARE_INFO_V2_1 info_21;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001018};
1019
1020bool radeon_atom_get_clock_info(struct drm_device *dev)
1021{
1022 struct radeon_device *rdev = dev->dev_private;
1023 struct radeon_mode_info *mode_info = &rdev->mode_info;
1024 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
1025 union firmware_info *firmware_info;
1026 uint8_t frev, crev;
1027 struct radeon_pll *p1pll = &rdev->clock.p1pll;
1028 struct radeon_pll *p2pll = &rdev->clock.p2pll;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001029 struct radeon_pll *dcpll = &rdev->clock.dcpll;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001030 struct radeon_pll *spll = &rdev->clock.spll;
1031 struct radeon_pll *mpll = &rdev->clock.mpll;
1032 uint16_t data_offset;
1033
Alex Deuchera084e6e2010-03-18 01:04:01 -04001034 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1035 &frev, &crev, &data_offset)) {
1036 firmware_info =
1037 (union firmware_info *)(mode_info->atom_context->bios +
1038 data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001039 /* pixel clocks */
1040 p1pll->reference_freq =
1041 le16_to_cpu(firmware_info->info.usReferenceClock);
1042 p1pll->reference_div = 0;
1043
Mathias Fröhlichbc293e52009-10-19 17:49:49 -04001044 if (crev < 2)
1045 p1pll->pll_out_min =
1046 le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
1047 else
1048 p1pll->pll_out_min =
1049 le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001050 p1pll->pll_out_max =
1051 le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
1052
Alex Deucher86cb2bb2010-03-08 12:55:16 -05001053 if (crev >= 4) {
1054 p1pll->lcd_pll_out_min =
1055 le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
1056 if (p1pll->lcd_pll_out_min == 0)
1057 p1pll->lcd_pll_out_min = p1pll->pll_out_min;
1058 p1pll->lcd_pll_out_max =
1059 le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
1060 if (p1pll->lcd_pll_out_max == 0)
1061 p1pll->lcd_pll_out_max = p1pll->pll_out_max;
1062 } else {
1063 p1pll->lcd_pll_out_min = p1pll->pll_out_min;
1064 p1pll->lcd_pll_out_max = p1pll->pll_out_max;
1065 }
1066
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001067 if (p1pll->pll_out_min == 0) {
1068 if (ASIC_IS_AVIVO(rdev))
1069 p1pll->pll_out_min = 64800;
1070 else
1071 p1pll->pll_out_min = 20000;
Alex Deucher8f552a62009-10-27 11:16:09 -04001072 } else if (p1pll->pll_out_min > 64800) {
1073 /* Limiting the pll output range is a good thing generally as
1074 * it limits the number of possible pll combinations for a given
1075 * frequency presumably to the ones that work best on each card.
1076 * However, certain duallink DVI monitors seem to like
1077 * pll combinations that would be limited by this at least on
1078 * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per
1079 * family.
1080 */
Alex Deucherb27b6372009-12-09 17:44:25 -05001081 if (!radeon_new_pll)
1082 p1pll->pll_out_min = 64800;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001083 }
1084
1085 p1pll->pll_in_min =
1086 le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
1087 p1pll->pll_in_max =
1088 le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);
1089
1090 *p2pll = *p1pll;
1091
1092 /* system clock */
1093 spll->reference_freq =
1094 le16_to_cpu(firmware_info->info.usReferenceClock);
1095 spll->reference_div = 0;
1096
1097 spll->pll_out_min =
1098 le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output);
1099 spll->pll_out_max =
1100 le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output);
1101
1102 /* ??? */
1103 if (spll->pll_out_min == 0) {
1104 if (ASIC_IS_AVIVO(rdev))
1105 spll->pll_out_min = 64800;
1106 else
1107 spll->pll_out_min = 20000;
1108 }
1109
1110 spll->pll_in_min =
1111 le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input);
1112 spll->pll_in_max =
1113 le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);
1114
1115 /* memory clock */
1116 mpll->reference_freq =
1117 le16_to_cpu(firmware_info->info.usReferenceClock);
1118 mpll->reference_div = 0;
1119
1120 mpll->pll_out_min =
1121 le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output);
1122 mpll->pll_out_max =
1123 le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output);
1124
1125 /* ??? */
1126 if (mpll->pll_out_min == 0) {
1127 if (ASIC_IS_AVIVO(rdev))
1128 mpll->pll_out_min = 64800;
1129 else
1130 mpll->pll_out_min = 20000;
1131 }
1132
1133 mpll->pll_in_min =
1134 le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input);
1135 mpll->pll_in_max =
1136 le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input);
1137
1138 rdev->clock.default_sclk =
1139 le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
1140 rdev->clock.default_mclk =
1141 le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
1142
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001143 if (ASIC_IS_DCE4(rdev)) {
1144 rdev->clock.default_dispclk =
1145 le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
1146 if (rdev->clock.default_dispclk == 0)
1147 rdev->clock.default_dispclk = 60000; /* 600 Mhz */
1148 rdev->clock.dp_extclk =
1149 le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
1150 }
1151 *dcpll = *p1pll;
1152
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001153 return true;
1154 }
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001155
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001156 return false;
1157}
1158
Alex Deucher06b64762010-01-05 11:27:29 -05001159union igp_info {
1160 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1161 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1162};
1163
1164bool radeon_atombios_sideport_present(struct radeon_device *rdev)
1165{
1166 struct radeon_mode_info *mode_info = &rdev->mode_info;
1167 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1168 union igp_info *igp_info;
1169 u8 frev, crev;
1170 u16 data_offset;
1171
Alex Deucher4c70b2e2010-08-02 19:39:15 -04001172 /* sideport is AMD only */
1173 if (rdev->family == CHIP_RS600)
1174 return false;
1175
Alex Deuchera084e6e2010-03-18 01:04:01 -04001176 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1177 &frev, &crev, &data_offset)) {
1178 igp_info = (union igp_info *)(mode_info->atom_context->bios +
Alex Deucher06b64762010-01-05 11:27:29 -05001179 data_offset);
Alex Deucher06b64762010-01-05 11:27:29 -05001180 switch (crev) {
1181 case 1:
Alex Deucher4c70b2e2010-08-02 19:39:15 -04001182 if (igp_info->info.ulBootUpMemoryClock)
1183 return true;
Alex Deucher06b64762010-01-05 11:27:29 -05001184 break;
1185 case 2:
1186 if (igp_info->info_2.ucMemoryType & 0x0f)
1187 return true;
1188 break;
1189 default:
1190 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1191 break;
1192 }
1193 }
1194 return false;
1195}
1196
Dave Airlie445282d2009-09-09 17:40:54 +10001197bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
1198 struct radeon_encoder_int_tmds *tmds)
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001199{
1200 struct drm_device *dev = encoder->base.dev;
1201 struct radeon_device *rdev = dev->dev_private;
1202 struct radeon_mode_info *mode_info = &rdev->mode_info;
1203 int index = GetIndexIntoMasterTable(DATA, TMDS_Info);
1204 uint16_t data_offset;
1205 struct _ATOM_TMDS_INFO *tmds_info;
1206 uint8_t frev, crev;
1207 uint16_t maxfreq;
1208 int i;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001209
Alex Deuchera084e6e2010-03-18 01:04:01 -04001210 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1211 &frev, &crev, &data_offset)) {
1212 tmds_info =
1213 (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
1214 data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001215
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001216 maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
1217 for (i = 0; i < 4; i++) {
1218 tmds->tmds_pll[i].freq =
1219 le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency);
1220 tmds->tmds_pll[i].value =
1221 tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f;
1222 tmds->tmds_pll[i].value |=
1223 (tmds_info->asMiscInfo[i].
1224 ucPLL_VCO_Gain & 0x3f) << 6;
1225 tmds->tmds_pll[i].value |=
1226 (tmds_info->asMiscInfo[i].
1227 ucPLL_DutyCycle & 0xf) << 12;
1228 tmds->tmds_pll[i].value |=
1229 (tmds_info->asMiscInfo[i].
1230 ucPLL_VoltageSwing & 0xf) << 16;
1231
Dave Airlied9fdaaf2010-08-02 10:42:55 +10001232 DRM_DEBUG_KMS("TMDS PLL From ATOMBIOS %u %x\n",
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001233 tmds->tmds_pll[i].freq,
1234 tmds->tmds_pll[i].value);
1235
1236 if (maxfreq == tmds->tmds_pll[i].freq) {
1237 tmds->tmds_pll[i].freq = 0xffffffff;
1238 break;
1239 }
1240 }
Dave Airlie445282d2009-09-09 17:40:54 +10001241 return true;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001242 }
Dave Airlie445282d2009-09-09 17:40:54 +10001243 return false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001244}
1245
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001246static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
1247 radeon_encoder
1248 *encoder,
1249 int id)
1250{
1251 struct drm_device *dev = encoder->base.dev;
1252 struct radeon_device *rdev = dev->dev_private;
1253 struct radeon_mode_info *mode_info = &rdev->mode_info;
1254 int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
1255 uint16_t data_offset;
1256 struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
1257 uint8_t frev, crev;
1258 struct radeon_atom_ss *ss = NULL;
Alex Deucher279b2152009-12-08 14:07:03 -05001259 int i;
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001260
1261 if (id > ATOM_MAX_SS_ENTRY)
1262 return NULL;
1263
Alex Deuchera084e6e2010-03-18 01:04:01 -04001264 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1265 &frev, &crev, &data_offset)) {
1266 ss_info =
1267 (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001268
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001269 ss =
1270 kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
1271
1272 if (!ss)
1273 return NULL;
1274
Alex Deucher279b2152009-12-08 14:07:03 -05001275 for (i = 0; i < ATOM_MAX_SS_ENTRY; i++) {
1276 if (ss_info->asSS_Info[i].ucSS_Id == id) {
1277 ss->percentage =
1278 le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage);
1279 ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType;
1280 ss->step = ss_info->asSS_Info[i].ucSS_Step;
1281 ss->delay = ss_info->asSS_Info[i].ucSS_Delay;
1282 ss->range = ss_info->asSS_Info[i].ucSS_Range;
1283 ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div;
Alex Deucher1d3d51b2009-12-28 13:45:23 -05001284 break;
Alex Deucher279b2152009-12-08 14:07:03 -05001285 }
1286 }
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001287 }
1288 return ss;
1289}
1290
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001291union lvds_info {
1292 struct _ATOM_LVDS_INFO info;
1293 struct _ATOM_LVDS_INFO_V12 info_12;
1294};
1295
1296struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
1297 radeon_encoder
1298 *encoder)
1299{
1300 struct drm_device *dev = encoder->base.dev;
1301 struct radeon_device *rdev = dev->dev_private;
1302 struct radeon_mode_info *mode_info = &rdev->mode_info;
1303 int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
Alex Deucher7dde8a12009-11-30 01:40:24 -05001304 uint16_t data_offset, misc;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001305 union lvds_info *lvds_info;
1306 uint8_t frev, crev;
1307 struct radeon_encoder_atom_dig *lvds = NULL;
1308
Alex Deuchera084e6e2010-03-18 01:04:01 -04001309 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1310 &frev, &crev, &data_offset)) {
1311 lvds_info =
1312 (union lvds_info *)(mode_info->atom_context->bios + data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001313 lvds =
1314 kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
1315
1316 if (!lvds)
1317 return NULL;
1318
Alex Deucherde2103e2009-10-09 15:14:30 -04001319 lvds->native_mode.clock =
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001320 le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
Alex Deucherde2103e2009-10-09 15:14:30 -04001321 lvds->native_mode.hdisplay =
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001322 le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
Alex Deucherde2103e2009-10-09 15:14:30 -04001323 lvds->native_mode.vdisplay =
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001324 le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
Alex Deucherde2103e2009-10-09 15:14:30 -04001325 lvds->native_mode.htotal = lvds->native_mode.hdisplay +
1326 le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
1327 lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
1328 le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
1329 lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
1330 le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
1331 lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
1332 le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
1333 lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
Alex Deucher1ff26a32010-05-18 00:23:15 -04001334 le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
Alex Deucherde2103e2009-10-09 15:14:30 -04001335 lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
1336 le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001337 lvds->panel_pwr_delay =
1338 le16_to_cpu(lvds_info->info.usOffDelayInMs);
1339 lvds->lvds_misc = lvds_info->info.ucLVDS_Misc;
Alex Deucher7dde8a12009-11-30 01:40:24 -05001340
1341 misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess);
1342 if (misc & ATOM_VSYNC_POLARITY)
1343 lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC;
1344 if (misc & ATOM_HSYNC_POLARITY)
1345 lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC;
1346 if (misc & ATOM_COMPOSITESYNC)
1347 lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC;
1348 if (misc & ATOM_INTERLACE)
1349 lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE;
1350 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1351 lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;
1352
Alex Deucherde2103e2009-10-09 15:14:30 -04001353 /* set crtc values */
1354 drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001355
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001356 lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id);
1357
Alex Deucher7c27f872010-02-02 12:05:01 -05001358 if (ASIC_IS_AVIVO(rdev)) {
Alex Deucher383be5d2010-02-23 03:24:38 -05001359 if (radeon_new_pll == 0)
1360 lvds->pll_algo = PLL_ALGO_LEGACY;
1361 else
1362 lvds->pll_algo = PLL_ALGO_NEW;
1363 } else {
1364 if (radeon_new_pll == 1)
1365 lvds->pll_algo = PLL_ALGO_NEW;
Alex Deucher7c27f872010-02-02 12:05:01 -05001366 else
1367 lvds->pll_algo = PLL_ALGO_LEGACY;
Alex Deucher383be5d2010-02-23 03:24:38 -05001368 }
Alex Deucher7c27f872010-02-02 12:05:01 -05001369
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001370 encoder->native_mode = lvds->native_mode;
1371 }
1372 return lvds;
1373}
1374
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001375struct radeon_encoder_primary_dac *
1376radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
1377{
1378 struct drm_device *dev = encoder->base.dev;
1379 struct radeon_device *rdev = dev->dev_private;
1380 struct radeon_mode_info *mode_info = &rdev->mode_info;
1381 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1382 uint16_t data_offset;
1383 struct _COMPASSIONATE_DATA *dac_info;
1384 uint8_t frev, crev;
1385 uint8_t bg, dac;
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001386 struct radeon_encoder_primary_dac *p_dac = NULL;
1387
Alex Deuchera084e6e2010-03-18 01:04:01 -04001388 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1389 &frev, &crev, &data_offset)) {
1390 dac_info = (struct _COMPASSIONATE_DATA *)
1391 (mode_info->atom_context->bios + data_offset);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001392
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001393 p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
1394
1395 if (!p_dac)
1396 return NULL;
1397
1398 bg = dac_info->ucDAC1_BG_Adjustment;
1399 dac = dac_info->ucDAC1_DAC_Adjustment;
1400 p_dac->ps2_pdac_adj = (bg << 8) | (dac);
1401
1402 }
1403 return p_dac;
1404}
1405
Dave Airlie4ce001a2009-08-13 16:32:14 +10001406bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001407 struct drm_display_mode *mode)
Dave Airlie4ce001a2009-08-13 16:32:14 +10001408{
1409 struct radeon_mode_info *mode_info = &rdev->mode_info;
1410 ATOM_ANALOG_TV_INFO *tv_info;
1411 ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
1412 ATOM_DTD_FORMAT *dtd_timings;
1413 int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
1414 u8 frev, crev;
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001415 u16 data_offset, misc;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001416
Alex Deuchera084e6e2010-03-18 01:04:01 -04001417 if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
1418 &frev, &crev, &data_offset))
1419 return false;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001420
1421 switch (crev) {
1422 case 1:
1423 tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
Dan Carpenter0031c412010-04-27 14:11:04 -07001424 if (index >= MAX_SUPPORTED_TV_TIMING)
Dave Airlie4ce001a2009-08-13 16:32:14 +10001425 return false;
1426
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001427 mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
1428 mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
1429 mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
1430 mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
1431 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001432
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001433 mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
1434 mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
1435 mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
1436 mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
1437 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001438
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001439 mode->flags = 0;
1440 misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
1441 if (misc & ATOM_VSYNC_POLARITY)
1442 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1443 if (misc & ATOM_HSYNC_POLARITY)
1444 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1445 if (misc & ATOM_COMPOSITESYNC)
1446 mode->flags |= DRM_MODE_FLAG_CSYNC;
1447 if (misc & ATOM_INTERLACE)
1448 mode->flags |= DRM_MODE_FLAG_INTERLACE;
1449 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1450 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001451
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001452 mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001453
1454 if (index == 1) {
1455 /* PAL timings appear to have wrong values for totals */
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001456 mode->crtc_htotal -= 1;
1457 mode->crtc_vtotal -= 1;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001458 }
1459 break;
1460 case 2:
1461 tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
Dan Carpenter0031c412010-04-27 14:11:04 -07001462 if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)
Dave Airlie4ce001a2009-08-13 16:32:14 +10001463 return false;
1464
1465 dtd_timings = &tv_info_v1_2->aModeTimings[index];
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001466 mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
1467 le16_to_cpu(dtd_timings->usHBlanking_Time);
1468 mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive);
1469 mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) +
1470 le16_to_cpu(dtd_timings->usHSyncOffset);
1471 mode->crtc_hsync_end = mode->crtc_hsync_start +
1472 le16_to_cpu(dtd_timings->usHSyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001473
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001474 mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) +
1475 le16_to_cpu(dtd_timings->usVBlanking_Time);
1476 mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive);
1477 mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) +
1478 le16_to_cpu(dtd_timings->usVSyncOffset);
1479 mode->crtc_vsync_end = mode->crtc_vsync_start +
1480 le16_to_cpu(dtd_timings->usVSyncWidth);
1481
1482 mode->flags = 0;
1483 misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
1484 if (misc & ATOM_VSYNC_POLARITY)
1485 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1486 if (misc & ATOM_HSYNC_POLARITY)
1487 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1488 if (misc & ATOM_COMPOSITESYNC)
1489 mode->flags |= DRM_MODE_FLAG_CSYNC;
1490 if (misc & ATOM_INTERLACE)
1491 mode->flags |= DRM_MODE_FLAG_INTERLACE;
1492 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1493 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
1494
1495 mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001496 break;
1497 }
1498 return true;
1499}
1500
Alex Deucherd79766f2009-12-17 19:00:29 -05001501enum radeon_tv_std
1502radeon_atombios_get_tv_info(struct radeon_device *rdev)
1503{
1504 struct radeon_mode_info *mode_info = &rdev->mode_info;
1505 int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
1506 uint16_t data_offset;
1507 uint8_t frev, crev;
1508 struct _ATOM_ANALOG_TV_INFO *tv_info;
1509 enum radeon_tv_std tv_std = TV_STD_NTSC;
1510
Alex Deuchera084e6e2010-03-18 01:04:01 -04001511 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1512 &frev, &crev, &data_offset)) {
Alex Deucherd79766f2009-12-17 19:00:29 -05001513
Alex Deuchera084e6e2010-03-18 01:04:01 -04001514 tv_info = (struct _ATOM_ANALOG_TV_INFO *)
1515 (mode_info->atom_context->bios + data_offset);
Alex Deucherd79766f2009-12-17 19:00:29 -05001516
Alex Deuchera084e6e2010-03-18 01:04:01 -04001517 switch (tv_info->ucTV_BootUpDefaultStandard) {
1518 case ATOM_TV_NTSC:
1519 tv_std = TV_STD_NTSC;
1520 DRM_INFO("Default TV standard: NTSC\n");
1521 break;
1522 case ATOM_TV_NTSCJ:
1523 tv_std = TV_STD_NTSC_J;
1524 DRM_INFO("Default TV standard: NTSC-J\n");
1525 break;
1526 case ATOM_TV_PAL:
1527 tv_std = TV_STD_PAL;
1528 DRM_INFO("Default TV standard: PAL\n");
1529 break;
1530 case ATOM_TV_PALM:
1531 tv_std = TV_STD_PAL_M;
1532 DRM_INFO("Default TV standard: PAL-M\n");
1533 break;
1534 case ATOM_TV_PALN:
1535 tv_std = TV_STD_PAL_N;
1536 DRM_INFO("Default TV standard: PAL-N\n");
1537 break;
1538 case ATOM_TV_PALCN:
1539 tv_std = TV_STD_PAL_CN;
1540 DRM_INFO("Default TV standard: PAL-CN\n");
1541 break;
1542 case ATOM_TV_PAL60:
1543 tv_std = TV_STD_PAL_60;
1544 DRM_INFO("Default TV standard: PAL-60\n");
1545 break;
1546 case ATOM_TV_SECAM:
1547 tv_std = TV_STD_SECAM;
1548 DRM_INFO("Default TV standard: SECAM\n");
1549 break;
1550 default:
1551 tv_std = TV_STD_NTSC;
1552 DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
1553 break;
1554 }
Alex Deucherd79766f2009-12-17 19:00:29 -05001555 }
1556 return tv_std;
1557}
1558
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001559struct radeon_encoder_tv_dac *
1560radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
1561{
1562 struct drm_device *dev = encoder->base.dev;
1563 struct radeon_device *rdev = dev->dev_private;
1564 struct radeon_mode_info *mode_info = &rdev->mode_info;
1565 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1566 uint16_t data_offset;
1567 struct _COMPASSIONATE_DATA *dac_info;
1568 uint8_t frev, crev;
1569 uint8_t bg, dac;
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001570 struct radeon_encoder_tv_dac *tv_dac = NULL;
1571
Alex Deuchera084e6e2010-03-18 01:04:01 -04001572 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1573 &frev, &crev, &data_offset)) {
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001574
Alex Deuchera084e6e2010-03-18 01:04:01 -04001575 dac_info = (struct _COMPASSIONATE_DATA *)
1576 (mode_info->atom_context->bios + data_offset);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001577
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001578 tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
1579
1580 if (!tv_dac)
1581 return NULL;
1582
1583 bg = dac_info->ucDAC2_CRT2_BG_Adjustment;
1584 dac = dac_info->ucDAC2_CRT2_DAC_Adjustment;
1585 tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
1586
1587 bg = dac_info->ucDAC2_PAL_BG_Adjustment;
1588 dac = dac_info->ucDAC2_PAL_DAC_Adjustment;
1589 tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
1590
1591 bg = dac_info->ucDAC2_NTSC_BG_Adjustment;
1592 dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
1593 tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
1594
Alex Deucherd79766f2009-12-17 19:00:29 -05001595 tv_dac->tv_std = radeon_atombios_get_tv_info(rdev);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001596 }
1597 return tv_dac;
1598}
1599
Alex Deucher29fb52c2010-03-11 10:01:17 -05001600static const char *thermal_controller_names[] = {
1601 "NONE",
Alex Deucher678e7df2010-04-22 14:17:56 -04001602 "lm63",
1603 "adm1032",
1604 "adm1030",
1605 "max6649",
1606 "lm64",
1607 "f75375",
1608 "asc7xxx",
Alex Deucher29fb52c2010-03-11 10:01:17 -05001609};
1610
1611static const char *pp_lib_thermal_controller_names[] = {
1612 "NONE",
Alex Deucher678e7df2010-04-22 14:17:56 -04001613 "lm63",
1614 "adm1032",
1615 "adm1030",
1616 "max6649",
1617 "lm64",
1618 "f75375",
Alex Deucher29fb52c2010-03-11 10:01:17 -05001619 "RV6xx",
1620 "RV770",
Alex Deucher678e7df2010-04-22 14:17:56 -04001621 "adt7473",
Alex Deucher49f65982010-03-24 16:39:45 -04001622 "External GPIO",
1623 "Evergreen",
Alex Deucher678e7df2010-04-22 14:17:56 -04001624 "adt7473 with internal",
Alex Deucher49f65982010-03-24 16:39:45 -04001625
Alex Deucher29fb52c2010-03-11 10:01:17 -05001626};
1627
Alex Deucher56278a82009-12-28 13:58:44 -05001628union power_info {
1629 struct _ATOM_POWERPLAY_INFO info;
1630 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1631 struct _ATOM_POWERPLAY_INFO_V3 info_3;
1632 struct _ATOM_PPLIB_POWERPLAYTABLE info_4;
1633};
1634
1635void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1636{
1637 struct radeon_mode_info *mode_info = &rdev->mode_info;
1638 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1639 u16 data_offset;
1640 u8 frev, crev;
1641 u32 misc, misc2 = 0, sclk, mclk;
1642 union power_info *power_info;
1643 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1644 struct _ATOM_PPLIB_STATE *power_state;
1645 int num_modes = 0, i, j;
1646 int state_index = 0, mode_index = 0;
Alex Deucher29fb52c2010-03-11 10:01:17 -05001647 struct radeon_i2c_bus_rec i2c_bus;
Alex Deucher56278a82009-12-28 13:58:44 -05001648
Alex Deuchera48b9b42010-04-22 14:03:55 -04001649 rdev->pm.default_power_state_index = -1;
Alex Deucher56278a82009-12-28 13:58:44 -05001650
Alex Deuchera084e6e2010-03-18 01:04:01 -04001651 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1652 &frev, &crev, &data_offset)) {
1653 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
Alex Deucher56278a82009-12-28 13:58:44 -05001654 if (frev < 4) {
Alex Deucher29fb52c2010-03-11 10:01:17 -05001655 /* add the i2c bus for thermal/fan chip */
1656 if (power_info->info.ucOverdriveThermalController > 0) {
1657 DRM_INFO("Possible %s thermal controller at 0x%02x\n",
1658 thermal_controller_names[power_info->info.ucOverdriveThermalController],
1659 power_info->info.ucOverdriveControllerAddress >> 1);
1660 i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
Alex Deucherf376b942010-08-05 21:21:16 -04001661 rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
Alex Deucher678e7df2010-04-22 14:17:56 -04001662 if (rdev->pm.i2c_bus) {
1663 struct i2c_board_info info = { };
1664 const char *name = thermal_controller_names[power_info->info.
1665 ucOverdriveThermalController];
1666 info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
1667 strlcpy(info.type, name, sizeof(info.type));
1668 i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
1669 }
Alex Deucher29fb52c2010-03-11 10:01:17 -05001670 }
Alex Deucher56278a82009-12-28 13:58:44 -05001671 num_modes = power_info->info.ucNumOfPowerModeEntries;
1672 if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
1673 num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
Alex Deucher02b17cc2010-04-22 13:25:06 -04001674 /* last mode is usually default, array is low to high */
Alex Deucher56278a82009-12-28 13:58:44 -05001675 for (i = 0; i < num_modes; i++) {
1676 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
1677 switch (frev) {
1678 case 1:
1679 rdev->pm.power_state[state_index].num_clock_modes = 1;
1680 rdev->pm.power_state[state_index].clock_info[0].mclk =
1681 le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
1682 rdev->pm.power_state[state_index].clock_info[0].sclk =
1683 le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
1684 /* skip invalid modes */
1685 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
1686 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
1687 continue;
Alex Deucher79daedc2010-04-22 14:25:19 -04001688 rdev->pm.power_state[state_index].pcie_lanes =
Alex Deucher56278a82009-12-28 13:58:44 -05001689 power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
1690 misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
Alex Deucher84d88f42010-05-27 17:01:42 -04001691 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
1692 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
Alex Deucher56278a82009-12-28 13:58:44 -05001693 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1694 VOLTAGE_GPIO;
1695 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
1696 radeon_lookup_gpio(rdev,
1697 power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
1698 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
1699 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1700 true;
1701 else
1702 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1703 false;
1704 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
1705 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1706 VOLTAGE_VDDC;
1707 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
1708 power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
1709 }
Alex Deucherd7311172010-05-03 01:13:14 -04001710 rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deucher79daedc2010-04-22 14:25:19 -04001711 rdev->pm.power_state[state_index].misc = misc;
Alex Deucher0ec0e742009-12-23 13:21:58 -05001712 /* order matters! */
1713 if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
1714 rdev->pm.power_state[state_index].type =
1715 POWER_STATE_TYPE_POWERSAVE;
1716 if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
1717 rdev->pm.power_state[state_index].type =
1718 POWER_STATE_TYPE_BATTERY;
1719 if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
1720 rdev->pm.power_state[state_index].type =
1721 POWER_STATE_TYPE_BATTERY;
1722 if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
1723 rdev->pm.power_state[state_index].type =
1724 POWER_STATE_TYPE_BALANCED;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001725 if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
Alex Deucher0ec0e742009-12-23 13:21:58 -05001726 rdev->pm.power_state[state_index].type =
1727 POWER_STATE_TYPE_PERFORMANCE;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001728 rdev->pm.power_state[state_index].flags &=
Alex Deucherd7311172010-05-03 01:13:14 -04001729 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001730 }
Alex Deucher56278a82009-12-28 13:58:44 -05001731 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
Alex Deucher0ec0e742009-12-23 13:21:58 -05001732 rdev->pm.power_state[state_index].type =
1733 POWER_STATE_TYPE_DEFAULT;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001734 rdev->pm.default_power_state_index = state_index;
Alex Deucher56278a82009-12-28 13:58:44 -05001735 rdev->pm.power_state[state_index].default_clock_mode =
1736 &rdev->pm.power_state[state_index].clock_info[0];
Alex Deuchera48b9b42010-04-22 14:03:55 -04001737 rdev->pm.power_state[state_index].flags &=
Alex Deucherd7311172010-05-03 01:13:14 -04001738 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
1739 } else if (state_index == 0) {
1740 rdev->pm.power_state[state_index].clock_info[0].flags |=
1741 RADEON_PM_MODE_NO_DISPLAY;
Alex Deucher56278a82009-12-28 13:58:44 -05001742 }
1743 state_index++;
1744 break;
1745 case 2:
1746 rdev->pm.power_state[state_index].num_clock_modes = 1;
1747 rdev->pm.power_state[state_index].clock_info[0].mclk =
1748 le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
1749 rdev->pm.power_state[state_index].clock_info[0].sclk =
1750 le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
1751 /* skip invalid modes */
1752 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
1753 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
1754 continue;
Alex Deucher79daedc2010-04-22 14:25:19 -04001755 rdev->pm.power_state[state_index].pcie_lanes =
Alex Deucher56278a82009-12-28 13:58:44 -05001756 power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
1757 misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
1758 misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
Alex Deucher84d88f42010-05-27 17:01:42 -04001759 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
1760 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
Alex Deucher56278a82009-12-28 13:58:44 -05001761 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1762 VOLTAGE_GPIO;
1763 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
1764 radeon_lookup_gpio(rdev,
1765 power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
1766 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
1767 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1768 true;
1769 else
1770 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1771 false;
1772 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
1773 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1774 VOLTAGE_VDDC;
1775 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
1776 power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
1777 }
Alex Deucherd7311172010-05-03 01:13:14 -04001778 rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deucher79daedc2010-04-22 14:25:19 -04001779 rdev->pm.power_state[state_index].misc = misc;
1780 rdev->pm.power_state[state_index].misc2 = misc2;
Alex Deucher0ec0e742009-12-23 13:21:58 -05001781 /* order matters! */
1782 if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
1783 rdev->pm.power_state[state_index].type =
1784 POWER_STATE_TYPE_POWERSAVE;
1785 if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
1786 rdev->pm.power_state[state_index].type =
1787 POWER_STATE_TYPE_BATTERY;
1788 if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
1789 rdev->pm.power_state[state_index].type =
1790 POWER_STATE_TYPE_BATTERY;
1791 if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
1792 rdev->pm.power_state[state_index].type =
1793 POWER_STATE_TYPE_BALANCED;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001794 if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
Alex Deucher0ec0e742009-12-23 13:21:58 -05001795 rdev->pm.power_state[state_index].type =
1796 POWER_STATE_TYPE_PERFORMANCE;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001797 rdev->pm.power_state[state_index].flags &=
Alex Deucherd7311172010-05-03 01:13:14 -04001798 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001799 }
Alex Deucher0ec0e742009-12-23 13:21:58 -05001800 if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
1801 rdev->pm.power_state[state_index].type =
1802 POWER_STATE_TYPE_BALANCED;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001803 if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT)
1804 rdev->pm.power_state[state_index].flags &=
Alex Deucherd7311172010-05-03 01:13:14 -04001805 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deucher56278a82009-12-28 13:58:44 -05001806 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
Alex Deucher0ec0e742009-12-23 13:21:58 -05001807 rdev->pm.power_state[state_index].type =
1808 POWER_STATE_TYPE_DEFAULT;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001809 rdev->pm.default_power_state_index = state_index;
Alex Deucher56278a82009-12-28 13:58:44 -05001810 rdev->pm.power_state[state_index].default_clock_mode =
1811 &rdev->pm.power_state[state_index].clock_info[0];
Alex Deuchera48b9b42010-04-22 14:03:55 -04001812 rdev->pm.power_state[state_index].flags &=
Alex Deucherd7311172010-05-03 01:13:14 -04001813 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
1814 } else if (state_index == 0) {
1815 rdev->pm.power_state[state_index].clock_info[0].flags |=
1816 RADEON_PM_MODE_NO_DISPLAY;
Alex Deucher56278a82009-12-28 13:58:44 -05001817 }
1818 state_index++;
1819 break;
1820 case 3:
1821 rdev->pm.power_state[state_index].num_clock_modes = 1;
1822 rdev->pm.power_state[state_index].clock_info[0].mclk =
1823 le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
1824 rdev->pm.power_state[state_index].clock_info[0].sclk =
1825 le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
1826 /* skip invalid modes */
1827 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
1828 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
1829 continue;
Alex Deucher79daedc2010-04-22 14:25:19 -04001830 rdev->pm.power_state[state_index].pcie_lanes =
Alex Deucher56278a82009-12-28 13:58:44 -05001831 power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
1832 misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
1833 misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
Alex Deucher84d88f42010-05-27 17:01:42 -04001834 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
1835 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
Alex Deucher56278a82009-12-28 13:58:44 -05001836 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1837 VOLTAGE_GPIO;
1838 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
1839 radeon_lookup_gpio(rdev,
1840 power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
1841 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
1842 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1843 true;
1844 else
1845 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1846 false;
1847 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
1848 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1849 VOLTAGE_VDDC;
1850 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
1851 power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
1852 if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
1853 rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
1854 true;
1855 rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
1856 power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
1857 }
1858 }
Alex Deucherd7311172010-05-03 01:13:14 -04001859 rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deucher79daedc2010-04-22 14:25:19 -04001860 rdev->pm.power_state[state_index].misc = misc;
1861 rdev->pm.power_state[state_index].misc2 = misc2;
Alex Deucher0ec0e742009-12-23 13:21:58 -05001862 /* order matters! */
1863 if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
1864 rdev->pm.power_state[state_index].type =
1865 POWER_STATE_TYPE_POWERSAVE;
1866 if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
1867 rdev->pm.power_state[state_index].type =
1868 POWER_STATE_TYPE_BATTERY;
1869 if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
1870 rdev->pm.power_state[state_index].type =
1871 POWER_STATE_TYPE_BATTERY;
1872 if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
1873 rdev->pm.power_state[state_index].type =
1874 POWER_STATE_TYPE_BALANCED;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001875 if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
Alex Deucher0ec0e742009-12-23 13:21:58 -05001876 rdev->pm.power_state[state_index].type =
1877 POWER_STATE_TYPE_PERFORMANCE;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001878 rdev->pm.power_state[state_index].flags &=
Alex Deucherd7311172010-05-03 01:13:14 -04001879 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001880 }
Alex Deucher0ec0e742009-12-23 13:21:58 -05001881 if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
1882 rdev->pm.power_state[state_index].type =
1883 POWER_STATE_TYPE_BALANCED;
Alex Deucher56278a82009-12-28 13:58:44 -05001884 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
Alex Deucher0ec0e742009-12-23 13:21:58 -05001885 rdev->pm.power_state[state_index].type =
1886 POWER_STATE_TYPE_DEFAULT;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001887 rdev->pm.default_power_state_index = state_index;
Alex Deucher56278a82009-12-28 13:58:44 -05001888 rdev->pm.power_state[state_index].default_clock_mode =
1889 &rdev->pm.power_state[state_index].clock_info[0];
Alex Deucherd7311172010-05-03 01:13:14 -04001890 } else if (state_index == 0) {
1891 rdev->pm.power_state[state_index].clock_info[0].flags |=
1892 RADEON_PM_MODE_NO_DISPLAY;
Alex Deucher56278a82009-12-28 13:58:44 -05001893 }
1894 state_index++;
1895 break;
1896 }
1897 }
Alex Deucher02b17cc2010-04-22 13:25:06 -04001898 /* last mode is usually default */
Alex Deuchera48b9b42010-04-22 14:03:55 -04001899 if (rdev->pm.default_power_state_index == -1) {
Alex Deucher02b17cc2010-04-22 13:25:06 -04001900 rdev->pm.power_state[state_index - 1].type =
1901 POWER_STATE_TYPE_DEFAULT;
Alex Deuchera48b9b42010-04-22 14:03:55 -04001902 rdev->pm.default_power_state_index = state_index - 1;
Alex Deucher02b17cc2010-04-22 13:25:06 -04001903 rdev->pm.power_state[state_index - 1].default_clock_mode =
1904 &rdev->pm.power_state[state_index - 1].clock_info[0];
Alex Deuchera48b9b42010-04-22 14:03:55 -04001905 rdev->pm.power_state[state_index].flags &=
Alex Deucherd7311172010-05-03 01:13:14 -04001906 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deucher79daedc2010-04-22 14:25:19 -04001907 rdev->pm.power_state[state_index].misc = 0;
1908 rdev->pm.power_state[state_index].misc2 = 0;
Alex Deucher02b17cc2010-04-22 13:25:06 -04001909 }
Alex Deucher49f65982010-03-24 16:39:45 -04001910 } else {
Alex Deucherc5e8ce62010-05-27 17:01:40 -04001911 int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
1912 uint8_t fw_frev, fw_crev;
1913 uint16_t fw_data_offset, vddc = 0;
1914 union firmware_info *firmware_info;
1915 ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
1916
1917 if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
1918 &fw_frev, &fw_crev, &fw_data_offset)) {
1919 firmware_info =
1920 (union firmware_info *)(mode_info->atom_context->bios +
1921 fw_data_offset);
1922 vddc = firmware_info->info_14.usBootUpVDDCVoltage;
1923 }
1924
Alex Deucher29fb52c2010-03-11 10:01:17 -05001925 /* add the i2c bus for thermal/fan chip */
Alex Deucher678e7df2010-04-22 14:17:56 -04001926 if (controller->ucType > 0) {
Alex Deucher21a81222010-07-02 12:58:16 -04001927 if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
Alex Deucher29fb52c2010-03-11 10:01:17 -05001928 DRM_INFO("Internal thermal controller %s fan control\n",
Alex Deucher678e7df2010-04-22 14:17:56 -04001929 (controller->ucFanParameters &
Alex Deucher29fb52c2010-03-11 10:01:17 -05001930 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
Alex Deucher21a81222010-07-02 12:58:16 -04001931 rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
1932 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
1933 DRM_INFO("Internal thermal controller %s fan control\n",
1934 (controller->ucFanParameters &
1935 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
1936 rdev->pm.int_thermal_type = THERMAL_TYPE_RV770;
1937 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
1938 DRM_INFO("Internal thermal controller %s fan control\n",
1939 (controller->ucFanParameters &
1940 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
1941 rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
Alex Deucher678e7df2010-04-22 14:17:56 -04001942 } else if ((controller->ucType ==
Alex Deucher49f65982010-03-24 16:39:45 -04001943 ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
Alex Deucher678e7df2010-04-22 14:17:56 -04001944 (controller->ucType ==
Alex Deucher49f65982010-03-24 16:39:45 -04001945 ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL)) {
1946 DRM_INFO("Special thermal controller config\n");
Alex Deucher29fb52c2010-03-11 10:01:17 -05001947 } else {
1948 DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
Alex Deucher678e7df2010-04-22 14:17:56 -04001949 pp_lib_thermal_controller_names[controller->ucType],
1950 controller->ucI2cAddress >> 1,
1951 (controller->ucFanParameters &
Alex Deucher29fb52c2010-03-11 10:01:17 -05001952 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
Alex Deucher678e7df2010-04-22 14:17:56 -04001953 i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
Alex Deucherf376b942010-08-05 21:21:16 -04001954 rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
Alex Deucher678e7df2010-04-22 14:17:56 -04001955 if (rdev->pm.i2c_bus) {
1956 struct i2c_board_info info = { };
1957 const char *name = pp_lib_thermal_controller_names[controller->ucType];
1958 info.addr = controller->ucI2cAddress >> 1;
1959 strlcpy(info.type, name, sizeof(info.type));
1960 i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
1961 }
1962
Alex Deucher29fb52c2010-03-11 10:01:17 -05001963 }
1964 }
Alex Deucher02b17cc2010-04-22 13:25:06 -04001965 /* first mode is usually default, followed by low to high */
Alex Deucher56278a82009-12-28 13:58:44 -05001966 for (i = 0; i < power_info->info_4.ucNumStates; i++) {
1967 mode_index = 0;
1968 power_state = (struct _ATOM_PPLIB_STATE *)
1969 (mode_info->atom_context->bios +
1970 data_offset +
1971 le16_to_cpu(power_info->info_4.usStateArrayOffset) +
1972 i * power_info->info_4.ucStateEntrySize);
1973 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1974 (mode_info->atom_context->bios +
1975 data_offset +
1976 le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) +
1977 (power_state->ucNonClockStateIndex *
1978 power_info->info_4.ucNonClockSize));
Alex Deucher56278a82009-12-28 13:58:44 -05001979 for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) {
1980 if (rdev->flags & RADEON_IS_IGP) {
1981 struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info =
1982 (struct _ATOM_PPLIB_RS780_CLOCK_INFO *)
1983 (mode_info->atom_context->bios +
1984 data_offset +
1985 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
1986 (power_state->ucClockStateIndices[j] *
1987 power_info->info_4.ucClockInfoSize));
1988 sclk = le16_to_cpu(clock_info->usLowEngineClockLow);
1989 sclk |= clock_info->ucLowEngineClockHigh << 16;
1990 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
1991 /* skip invalid modes */
1992 if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
1993 continue;
Alex Deucheraa1df0f2010-06-07 11:35:53 -04001994 /* voltage works differently on IGPs */
Alex Deucher56278a82009-12-28 13:58:44 -05001995 mode_index++;
Alex Deucher49f65982010-03-24 16:39:45 -04001996 } else if (ASIC_IS_DCE4(rdev)) {
1997 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
1998 (struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *)
1999 (mode_info->atom_context->bios +
2000 data_offset +
2001 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
2002 (power_state->ucClockStateIndices[j] *
2003 power_info->info_4.ucClockInfoSize));
2004 sclk = le16_to_cpu(clock_info->usEngineClockLow);
2005 sclk |= clock_info->ucEngineClockHigh << 16;
2006 mclk = le16_to_cpu(clock_info->usMemoryClockLow);
2007 mclk |= clock_info->ucMemoryClockHigh << 16;
2008 rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
2009 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2010 /* skip invalid modes */
2011 if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
2012 (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
2013 continue;
Alex Deucher49f65982010-03-24 16:39:45 -04002014 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
2015 VOLTAGE_SW;
2016 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
2017 clock_info->usVDDC;
2018 /* XXX usVDDCI */
2019 mode_index++;
Alex Deucher56278a82009-12-28 13:58:44 -05002020 } else {
2021 struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info =
2022 (struct _ATOM_PPLIB_R600_CLOCK_INFO *)
2023 (mode_info->atom_context->bios +
2024 data_offset +
2025 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
2026 (power_state->ucClockStateIndices[j] *
2027 power_info->info_4.ucClockInfoSize));
2028 sclk = le16_to_cpu(clock_info->usEngineClockLow);
2029 sclk |= clock_info->ucEngineClockHigh << 16;
2030 mclk = le16_to_cpu(clock_info->usMemoryClockLow);
2031 mclk |= clock_info->ucMemoryClockHigh << 16;
2032 rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
2033 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2034 /* skip invalid modes */
2035 if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
2036 (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
2037 continue;
Alex Deucher56278a82009-12-28 13:58:44 -05002038 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
2039 VOLTAGE_SW;
2040 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
2041 clock_info->usVDDC;
2042 mode_index++;
2043 }
2044 }
2045 rdev->pm.power_state[state_index].num_clock_modes = mode_index;
2046 if (mode_index) {
Rafał Miłecki845db702009-12-23 00:42:43 +01002047 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
Alex Deucher56278a82009-12-28 13:58:44 -05002048 misc2 = le16_to_cpu(non_clock_info->usClassification);
Alex Deucher79daedc2010-04-22 14:25:19 -04002049 rdev->pm.power_state[state_index].misc = misc;
2050 rdev->pm.power_state[state_index].misc2 = misc2;
2051 rdev->pm.power_state[state_index].pcie_lanes =
Rafał Miłecki845db702009-12-23 00:42:43 +01002052 ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
2053 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
Alex Deucher0ec0e742009-12-23 13:21:58 -05002054 switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
2055 case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
2056 rdev->pm.power_state[state_index].type =
2057 POWER_STATE_TYPE_BATTERY;
2058 break;
2059 case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
2060 rdev->pm.power_state[state_index].type =
2061 POWER_STATE_TYPE_BALANCED;
2062 break;
2063 case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
2064 rdev->pm.power_state[state_index].type =
2065 POWER_STATE_TYPE_PERFORMANCE;
2066 break;
Alex Deuchera44d2f32010-08-04 11:10:26 -04002067 case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
2068 if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
2069 rdev->pm.power_state[state_index].type =
2070 POWER_STATE_TYPE_PERFORMANCE;
2071 break;
Alex Deucher0ec0e742009-12-23 13:21:58 -05002072 }
Alex Deuchera48b9b42010-04-22 14:03:55 -04002073 rdev->pm.power_state[state_index].flags = 0;
2074 if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
2075 rdev->pm.power_state[state_index].flags |=
Alex Deucherd7311172010-05-03 01:13:14 -04002076 RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
Alex Deucher56278a82009-12-28 13:58:44 -05002077 if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
Alex Deucher0ec0e742009-12-23 13:21:58 -05002078 rdev->pm.power_state[state_index].type =
2079 POWER_STATE_TYPE_DEFAULT;
Alex Deuchera48b9b42010-04-22 14:03:55 -04002080 rdev->pm.default_power_state_index = state_index;
Alex Deucher56278a82009-12-28 13:58:44 -05002081 rdev->pm.power_state[state_index].default_clock_mode =
2082 &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
Alex Deucherc5e8ce62010-05-27 17:01:40 -04002083 /* patch the table values with the default slck/mclk from firmware info */
2084 for (j = 0; j < mode_index; j++) {
2085 rdev->pm.power_state[state_index].clock_info[j].mclk =
2086 rdev->clock.default_mclk;
2087 rdev->pm.power_state[state_index].clock_info[j].sclk =
2088 rdev->clock.default_sclk;
2089 if (vddc)
2090 rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
2091 vddc;
2092 }
Alex Deucher56278a82009-12-28 13:58:44 -05002093 }
2094 state_index++;
2095 }
2096 }
Alex Deucherd7311172010-05-03 01:13:14 -04002097 /* if multiple clock modes, mark the lowest as no display */
2098 for (i = 0; i < state_index; i++) {
2099 if (rdev->pm.power_state[i].num_clock_modes > 1)
2100 rdev->pm.power_state[i].clock_info[0].flags |=
2101 RADEON_PM_MODE_NO_DISPLAY;
2102 }
Alex Deucher02b17cc2010-04-22 13:25:06 -04002103 /* first mode is usually default */
Alex Deuchera48b9b42010-04-22 14:03:55 -04002104 if (rdev->pm.default_power_state_index == -1) {
Alex Deucher02b17cc2010-04-22 13:25:06 -04002105 rdev->pm.power_state[0].type =
2106 POWER_STATE_TYPE_DEFAULT;
Alex Deuchera48b9b42010-04-22 14:03:55 -04002107 rdev->pm.default_power_state_index = 0;
Alex Deucher02b17cc2010-04-22 13:25:06 -04002108 rdev->pm.power_state[0].default_clock_mode =
2109 &rdev->pm.power_state[0].clock_info[0];
2110 }
Alex Deucher56278a82009-12-28 13:58:44 -05002111 }
2112 } else {
Alex Deucher56278a82009-12-28 13:58:44 -05002113 /* add the default mode */
Alex Deucher0ec0e742009-12-23 13:21:58 -05002114 rdev->pm.power_state[state_index].type =
2115 POWER_STATE_TYPE_DEFAULT;
Alex Deucher56278a82009-12-28 13:58:44 -05002116 rdev->pm.power_state[state_index].num_clock_modes = 1;
2117 rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
2118 rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
2119 rdev->pm.power_state[state_index].default_clock_mode =
2120 &rdev->pm.power_state[state_index].clock_info[0];
Alex Deucher56278a82009-12-28 13:58:44 -05002121 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
Alex Deucher79daedc2010-04-22 14:25:19 -04002122 rdev->pm.power_state[state_index].pcie_lanes = 16;
Alex Deuchera48b9b42010-04-22 14:03:55 -04002123 rdev->pm.default_power_state_index = state_index;
2124 rdev->pm.power_state[state_index].flags = 0;
Alex Deucher56278a82009-12-28 13:58:44 -05002125 state_index++;
2126 }
Alex Deucher02b17cc2010-04-22 13:25:06 -04002127
Alex Deucher56278a82009-12-28 13:58:44 -05002128 rdev->pm.num_power_states = state_index;
Rafał Miłecki9038dfd2010-02-20 23:15:04 +00002129
Alex Deuchera48b9b42010-04-22 14:03:55 -04002130 rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
2131 rdev->pm.current_clock_mode_index = 0;
Alex Deucher4d601732010-06-07 18:15:18 -04002132 rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
Alex Deucher56278a82009-12-28 13:58:44 -05002133}
2134
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002135void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
2136{
2137 DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
2138 int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating);
2139
2140 args.ucEnable = enable;
2141
2142 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2143}
2144
Rafał Miłecki74338742009-11-03 00:53:02 +01002145uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
2146{
2147 GET_ENGINE_CLOCK_PS_ALLOCATION args;
2148 int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
2149
2150 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2151 return args.ulReturnEngineClock;
2152}
2153
2154uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev)
2155{
2156 GET_MEMORY_CLOCK_PS_ALLOCATION args;
2157 int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
2158
2159 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2160 return args.ulReturnMemoryClock;
2161}
2162
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002163void radeon_atom_set_engine_clock(struct radeon_device *rdev,
2164 uint32_t eng_clock)
2165{
2166 SET_ENGINE_CLOCK_PS_ALLOCATION args;
2167 int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
2168
2169 args.ulTargetEngineClock = eng_clock; /* 10 khz */
2170
2171 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2172}
2173
2174void radeon_atom_set_memory_clock(struct radeon_device *rdev,
2175 uint32_t mem_clock)
2176{
2177 SET_MEMORY_CLOCK_PS_ALLOCATION args;
2178 int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);
2179
2180 if (rdev->flags & RADEON_IS_IGP)
2181 return;
2182
2183 args.ulTargetMemoryClock = mem_clock; /* 10 khz */
2184
2185 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2186}
2187
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002188union set_voltage {
2189 struct _SET_VOLTAGE_PS_ALLOCATION alloc;
2190 struct _SET_VOLTAGE_PARAMETERS v1;
2191 struct _SET_VOLTAGE_PARAMETERS_V2 v2;
2192};
2193
2194void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
2195{
2196 union set_voltage args;
2197 int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
2198 u8 frev, crev, volt_index = level;
2199
2200 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2201 return;
2202
2203 switch (crev) {
2204 case 1:
2205 args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
2206 args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
2207 args.v1.ucVoltageIndex = volt_index;
2208 break;
2209 case 2:
2210 args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
2211 args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
2212 args.v2.usVoltageLevel = cpu_to_le16(level);
2213 break;
2214 default:
2215 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
2216 return;
2217 }
2218
2219 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2220}
2221
2222
2223
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002224void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
2225{
2226 struct radeon_device *rdev = dev->dev_private;
2227 uint32_t bios_2_scratch, bios_6_scratch;
2228
2229 if (rdev->family >= CHIP_R600) {
Dave Airlie4ce001a2009-08-13 16:32:14 +10002230 bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002231 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2232 } else {
Dave Airlie4ce001a2009-08-13 16:32:14 +10002233 bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002234 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2235 }
2236
2237 /* let the bios control the backlight */
2238 bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
2239
2240 /* tell the bios not to handle mode switching */
2241 bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE);
2242
2243 if (rdev->family >= CHIP_R600) {
2244 WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
2245 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2246 } else {
2247 WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
2248 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2249 }
2250
2251}
2252
Yang Zhaof657c2a2009-09-15 12:21:01 +10002253void radeon_save_bios_scratch_regs(struct radeon_device *rdev)
2254{
2255 uint32_t scratch_reg;
2256 int i;
2257
2258 if (rdev->family >= CHIP_R600)
2259 scratch_reg = R600_BIOS_0_SCRATCH;
2260 else
2261 scratch_reg = RADEON_BIOS_0_SCRATCH;
2262
2263 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
2264 rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4));
2265}
2266
2267void radeon_restore_bios_scratch_regs(struct radeon_device *rdev)
2268{
2269 uint32_t scratch_reg;
2270 int i;
2271
2272 if (rdev->family >= CHIP_R600)
2273 scratch_reg = R600_BIOS_0_SCRATCH;
2274 else
2275 scratch_reg = RADEON_BIOS_0_SCRATCH;
2276
2277 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
2278 WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]);
2279}
2280
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002281void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
2282{
2283 struct drm_device *dev = encoder->dev;
2284 struct radeon_device *rdev = dev->dev_private;
2285 uint32_t bios_6_scratch;
2286
2287 if (rdev->family >= CHIP_R600)
2288 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2289 else
2290 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2291
2292 if (lock)
2293 bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
2294 else
2295 bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
2296
2297 if (rdev->family >= CHIP_R600)
2298 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2299 else
2300 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2301}
2302
2303/* at some point we may want to break this out into individual functions */
2304void
2305radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
2306 struct drm_encoder *encoder,
2307 bool connected)
2308{
2309 struct drm_device *dev = connector->dev;
2310 struct radeon_device *rdev = dev->dev_private;
2311 struct radeon_connector *radeon_connector =
2312 to_radeon_connector(connector);
2313 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2314 uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch;
2315
2316 if (rdev->family >= CHIP_R600) {
2317 bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2318 bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
2319 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2320 } else {
2321 bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
2322 bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
2323 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2324 }
2325
2326 if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
2327 (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
2328 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002329 DRM_DEBUG_KMS("TV1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002330 bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
2331 bios_6_scratch |= ATOM_S6_ACC_REQ_TV1;
2332 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002333 DRM_DEBUG_KMS("TV1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002334 bios_0_scratch &= ~ATOM_S0_TV1_MASK;
2335 bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
2336 bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1;
2337 }
2338 }
2339 if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) &&
2340 (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) {
2341 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002342 DRM_DEBUG_KMS("CV connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002343 bios_3_scratch |= ATOM_S3_CV_ACTIVE;
2344 bios_6_scratch |= ATOM_S6_ACC_REQ_CV;
2345 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002346 DRM_DEBUG_KMS("CV disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002347 bios_0_scratch &= ~ATOM_S0_CV_MASK;
2348 bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
2349 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV;
2350 }
2351 }
2352 if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
2353 (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
2354 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002355 DRM_DEBUG_KMS("LCD1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002356 bios_0_scratch |= ATOM_S0_LCD1;
2357 bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
2358 bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1;
2359 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002360 DRM_DEBUG_KMS("LCD1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002361 bios_0_scratch &= ~ATOM_S0_LCD1;
2362 bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
2363 bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1;
2364 }
2365 }
2366 if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
2367 (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
2368 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002369 DRM_DEBUG_KMS("CRT1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002370 bios_0_scratch |= ATOM_S0_CRT1_COLOR;
2371 bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
2372 bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1;
2373 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002374 DRM_DEBUG_KMS("CRT1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002375 bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
2376 bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
2377 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1;
2378 }
2379 }
2380 if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
2381 (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
2382 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002383 DRM_DEBUG_KMS("CRT2 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002384 bios_0_scratch |= ATOM_S0_CRT2_COLOR;
2385 bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
2386 bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2;
2387 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002388 DRM_DEBUG_KMS("CRT2 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002389 bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
2390 bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
2391 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2;
2392 }
2393 }
2394 if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
2395 (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
2396 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002397 DRM_DEBUG_KMS("DFP1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002398 bios_0_scratch |= ATOM_S0_DFP1;
2399 bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
2400 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1;
2401 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002402 DRM_DEBUG_KMS("DFP1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002403 bios_0_scratch &= ~ATOM_S0_DFP1;
2404 bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
2405 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1;
2406 }
2407 }
2408 if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
2409 (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
2410 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002411 DRM_DEBUG_KMS("DFP2 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002412 bios_0_scratch |= ATOM_S0_DFP2;
2413 bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
2414 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2;
2415 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002416 DRM_DEBUG_KMS("DFP2 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002417 bios_0_scratch &= ~ATOM_S0_DFP2;
2418 bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
2419 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2;
2420 }
2421 }
2422 if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) &&
2423 (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) {
2424 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002425 DRM_DEBUG_KMS("DFP3 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002426 bios_0_scratch |= ATOM_S0_DFP3;
2427 bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
2428 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3;
2429 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002430 DRM_DEBUG_KMS("DFP3 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002431 bios_0_scratch &= ~ATOM_S0_DFP3;
2432 bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
2433 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3;
2434 }
2435 }
2436 if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) &&
2437 (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) {
2438 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002439 DRM_DEBUG_KMS("DFP4 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002440 bios_0_scratch |= ATOM_S0_DFP4;
2441 bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
2442 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4;
2443 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002444 DRM_DEBUG_KMS("DFP4 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002445 bios_0_scratch &= ~ATOM_S0_DFP4;
2446 bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
2447 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4;
2448 }
2449 }
2450 if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) &&
2451 (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) {
2452 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002453 DRM_DEBUG_KMS("DFP5 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002454 bios_0_scratch |= ATOM_S0_DFP5;
2455 bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
2456 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5;
2457 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002458 DRM_DEBUG_KMS("DFP5 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002459 bios_0_scratch &= ~ATOM_S0_DFP5;
2460 bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
2461 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
2462 }
2463 }
2464
2465 if (rdev->family >= CHIP_R600) {
2466 WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
2467 WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
2468 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2469 } else {
2470 WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
2471 WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
2472 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2473 }
2474}
2475
2476void
2477radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
2478{
2479 struct drm_device *dev = encoder->dev;
2480 struct radeon_device *rdev = dev->dev_private;
2481 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2482 uint32_t bios_3_scratch;
2483
2484 if (rdev->family >= CHIP_R600)
2485 bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
2486 else
2487 bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
2488
2489 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
2490 bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
2491 bios_3_scratch |= (crtc << 18);
2492 }
2493 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
2494 bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
2495 bios_3_scratch |= (crtc << 24);
2496 }
2497 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2498 bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
2499 bios_3_scratch |= (crtc << 16);
2500 }
2501 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2502 bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
2503 bios_3_scratch |= (crtc << 20);
2504 }
2505 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
2506 bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
2507 bios_3_scratch |= (crtc << 17);
2508 }
2509 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
2510 bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
2511 bios_3_scratch |= (crtc << 19);
2512 }
2513 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
2514 bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
2515 bios_3_scratch |= (crtc << 23);
2516 }
2517 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
2518 bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
2519 bios_3_scratch |= (crtc << 25);
2520 }
2521
2522 if (rdev->family >= CHIP_R600)
2523 WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
2524 else
2525 WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
2526}
2527
2528void
2529radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
2530{
2531 struct drm_device *dev = encoder->dev;
2532 struct radeon_device *rdev = dev->dev_private;
2533 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2534 uint32_t bios_2_scratch;
2535
2536 if (rdev->family >= CHIP_R600)
2537 bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
2538 else
2539 bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
2540
2541 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
2542 if (on)
2543 bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
2544 else
2545 bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
2546 }
2547 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
2548 if (on)
2549 bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
2550 else
2551 bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
2552 }
2553 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2554 if (on)
2555 bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
2556 else
2557 bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
2558 }
2559 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2560 if (on)
2561 bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
2562 else
2563 bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
2564 }
2565 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
2566 if (on)
2567 bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
2568 else
2569 bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
2570 }
2571 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
2572 if (on)
2573 bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
2574 else
2575 bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
2576 }
2577 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
2578 if (on)
2579 bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
2580 else
2581 bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
2582 }
2583 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
2584 if (on)
2585 bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
2586 else
2587 bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
2588 }
2589 if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) {
2590 if (on)
2591 bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
2592 else
2593 bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
2594 }
2595 if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) {
2596 if (on)
2597 bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
2598 else
2599 bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
2600 }
2601
2602 if (rdev->family >= CHIP_R600)
2603 WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
2604 else
2605 WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
2606}