blob: d24baf30efcb8e583ab38b0540fe508369e47423 [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
Alex Deucher5137ee92010-08-12 18:58:47 -040035radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
36 uint8_t dac);
Jerome Glisse771fe6b2009-06-05 14:42:42 +020037extern void radeon_link_encoder_connector(struct drm_device *dev);
38extern void
Alex Deucher5137ee92010-08-12 18:58:47 -040039radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
Alex Deucher36868bd2011-01-06 21:19:21 -050040 uint32_t supported_device, u16 caps);
Jerome Glisse771fe6b2009-06-05 14:42:42 +020041
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 Deucher5137ee92010-08-12 18:58:47 -040049 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
Alex Deucher5137ee92010-08-12 18:58:47 -040056radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
Jerome Glisse771fe6b2009-06-05 14:42:42 +020057 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 Deucher21240f92011-11-21 12:41:21 -050065static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev,
66 ATOM_GPIO_I2C_ASSIGMENT *gpio,
67 u8 index)
68{
69 /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */
70 if ((rdev->family == CHIP_R420) ||
71 (rdev->family == CHIP_R423) ||
72 (rdev->family == CHIP_RV410)) {
73 if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) ||
74 (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) ||
75 (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) {
76 gpio->ucClkMaskShift = 0x19;
77 gpio->ucDataMaskShift = 0x18;
78 }
79 }
80
81 /* some evergreen boards have bad data for this entry */
82 if (ASIC_IS_DCE4(rdev)) {
83 if ((index == 7) &&
84 (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
85 (gpio->sucI2cId.ucAccess == 0)) {
86 gpio->sucI2cId.ucAccess = 0x97;
87 gpio->ucDataMaskShift = 8;
88 gpio->ucDataEnShift = 8;
89 gpio->ucDataY_Shift = 8;
90 gpio->ucDataA_Shift = 8;
91 }
92 }
93
94 /* some DCE3 boards have bad data for this entry */
95 if (ASIC_IS_DCE3(rdev)) {
96 if ((index == 4) &&
97 (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
98 (gpio->sucI2cId.ucAccess == 0x94))
99 gpio->sucI2cId.ucAccess = 0x14;
100 }
101}
102
103static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
104{
105 struct radeon_i2c_bus_rec i2c;
106
107 memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
108
109 i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
110 i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
111 i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
112 i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
113 i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
114 i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
115 i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
116 i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
117 i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
118 i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
119 i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
120 i2c.en_data_mask = (1 << gpio->ucDataEnShift);
121 i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
122 i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
123 i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
124 i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
125
126 if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
127 i2c.hw_capable = true;
128 else
129 i2c.hw_capable = false;
130
131 if (gpio->sucI2cId.ucAccess == 0xa0)
132 i2c.mm_i2c = true;
133 else
134 i2c.mm_i2c = false;
135
136 i2c.i2c_id = gpio->sucI2cId.ucAccess;
137
138 if (i2c.mask_clk_reg)
139 i2c.valid = true;
140 else
141 i2c.valid = false;
142
143 return i2c;
144}
145
Andi Kleence580fa2011-10-13 16:08:47 -0700146static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
Alex Deuchereed45b32009-12-04 14:45:27 -0500147 uint8_t id)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200148{
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200149 struct atom_context *ctx = rdev->mode_info.atom_context;
Alex Deucher6a93cb22009-11-23 17:39:28 -0500150 ATOM_GPIO_I2C_ASSIGMENT *gpio;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200151 struct radeon_i2c_bus_rec i2c;
152 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
153 struct _ATOM_GPIO_I2C_INFO *i2c_info;
Alex Deucher95beb692010-04-01 19:08:47 +0000154 uint16_t data_offset, size;
155 int i, num_indices;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200156
157 memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
158 i2c.valid = false;
159
Alex Deucher95beb692010-04-01 19:08:47 +0000160 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
Alex Deuchera084e6e2010-03-18 01:04:01 -0400161 i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200162
Alex Deucher95beb692010-04-01 19:08:47 +0000163 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
164 sizeof(ATOM_GPIO_I2C_ASSIGMENT);
165
166 for (i = 0; i < num_indices; i++) {
Alex Deuchera084e6e2010-03-18 01:04:01 -0400167 gpio = &i2c_info->asGPIO_Info[i];
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200168
Alex Deucher21240f92011-11-21 12:41:21 -0500169 radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
Alex Deucher3074adc2010-11-30 00:15:10 -0500170
Alex Deuchera084e6e2010-03-18 01:04:01 -0400171 if (gpio->sucI2cId.ucAccess == id) {
Alex Deucher21240f92011-11-21 12:41:21 -0500172 i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
Alex Deuchera084e6e2010-03-18 01:04:01 -0400173 break;
174 }
Alex Deucherd3f420d2009-12-08 14:30:49 -0500175 }
176 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200177
178 return i2c;
179}
180
Alex Deucherf376b942010-08-05 21:21:16 -0400181void radeon_atombios_i2c_init(struct radeon_device *rdev)
182{
183 struct atom_context *ctx = rdev->mode_info.atom_context;
184 ATOM_GPIO_I2C_ASSIGMENT *gpio;
185 struct radeon_i2c_bus_rec i2c;
186 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
187 struct _ATOM_GPIO_I2C_INFO *i2c_info;
188 uint16_t data_offset, size;
189 int i, num_indices;
190 char stmp[32];
191
Alex Deucherf376b942010-08-05 21:21:16 -0400192 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
193 i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
194
195 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
196 sizeof(ATOM_GPIO_I2C_ASSIGMENT);
197
198 for (i = 0; i < num_indices; i++) {
199 gpio = &i2c_info->asGPIO_Info[i];
Alex Deucherea393022010-08-27 16:04:29 -0400200
Alex Deucher21240f92011-11-21 12:41:21 -0500201 radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
Alex Deucherd7245022011-11-21 12:10:14 -0500202
Alex Deucher21240f92011-11-21 12:41:21 -0500203 i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
Alex Deucherea393022010-08-27 16:04:29 -0400204
Alex Deucher21240f92011-11-21 12:41:21 -0500205 if (i2c.valid) {
Alex Deucherf376b942010-08-05 21:21:16 -0400206 sprintf(stmp, "0x%x", i2c.i2c_id);
207 rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
208 }
209 }
210 }
211}
212
Andi Kleence580fa2011-10-13 16:08:47 -0700213static struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
Alex Deuchereed45b32009-12-04 14:45:27 -0500214 u8 id)
215{
216 struct atom_context *ctx = rdev->mode_info.atom_context;
217 struct radeon_gpio_rec gpio;
218 int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
219 struct _ATOM_GPIO_PIN_LUT *gpio_info;
220 ATOM_GPIO_PIN_ASSIGNMENT *pin;
221 u16 data_offset, size;
222 int i, num_indices;
223
224 memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
225 gpio.valid = false;
226
Alex Deuchera084e6e2010-03-18 01:04:01 -0400227 if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
228 gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
Alex Deuchereed45b32009-12-04 14:45:27 -0500229
Alex Deuchera084e6e2010-03-18 01:04:01 -0400230 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
231 sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
Alex Deuchereed45b32009-12-04 14:45:27 -0500232
Alex Deuchera084e6e2010-03-18 01:04:01 -0400233 for (i = 0; i < num_indices; i++) {
234 pin = &gpio_info->asGPIO_Pin[i];
235 if (id == pin->ucGPIO_ID) {
236 gpio.id = pin->ucGPIO_ID;
Cédric Cano45894332011-02-11 19:45:37 -0500237 gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex) * 4;
Alex Deuchera084e6e2010-03-18 01:04:01 -0400238 gpio.mask = (1 << pin->ucGpioPinBitShift);
239 gpio.valid = true;
240 break;
241 }
Alex Deuchereed45b32009-12-04 14:45:27 -0500242 }
243 }
244
245 return gpio;
246}
247
248static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev,
249 struct radeon_gpio_rec *gpio)
250{
251 struct radeon_hpd hpd;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500252 u32 reg;
253
Jean Delvare1d978da2010-08-15 14:11:24 +0200254 memset(&hpd, 0, sizeof(struct radeon_hpd));
255
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500256 if (ASIC_IS_DCE4(rdev))
257 reg = EVERGREEN_DC_GPIO_HPD_A;
258 else
259 reg = AVIVO_DC_GPIO_HPD_A;
260
Alex Deuchereed45b32009-12-04 14:45:27 -0500261 hpd.gpio = *gpio;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500262 if (gpio->reg == reg) {
Alex Deuchereed45b32009-12-04 14:45:27 -0500263 switch(gpio->mask) {
264 case (1 << 0):
265 hpd.hpd = RADEON_HPD_1;
266 break;
267 case (1 << 8):
268 hpd.hpd = RADEON_HPD_2;
269 break;
270 case (1 << 16):
271 hpd.hpd = RADEON_HPD_3;
272 break;
273 case (1 << 24):
274 hpd.hpd = RADEON_HPD_4;
275 break;
276 case (1 << 26):
277 hpd.hpd = RADEON_HPD_5;
278 break;
279 case (1 << 28):
280 hpd.hpd = RADEON_HPD_6;
281 break;
282 default:
283 hpd.hpd = RADEON_HPD_NONE;
284 break;
285 }
286 } else
287 hpd.hpd = RADEON_HPD_NONE;
288 return hpd;
289}
290
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200291static bool radeon_atom_apply_quirks(struct drm_device *dev,
292 uint32_t supported_device,
293 int *connector_type,
Alex Deucher848577e2009-07-08 16:15:30 -0400294 struct radeon_i2c_bus_rec *i2c_bus,
Alex Deuchereed45b32009-12-04 14:45:27 -0500295 uint16_t *line_mux,
296 struct radeon_hpd *hpd)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200297{
298
299 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
300 if ((dev->pdev->device == 0x791e) &&
301 (dev->pdev->subsystem_vendor == 0x1043) &&
302 (dev->pdev->subsystem_device == 0x826d)) {
303 if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
304 (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
305 *connector_type = DRM_MODE_CONNECTOR_DVID;
306 }
307
Alex Deucherc86a9032010-02-18 14:14:58 -0500308 /* Asrock RS600 board lists the DVI port as HDMI */
309 if ((dev->pdev->device == 0x7941) &&
310 (dev->pdev->subsystem_vendor == 0x1849) &&
311 (dev->pdev->subsystem_device == 0x7941)) {
312 if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
313 (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
314 *connector_type = DRM_MODE_CONNECTOR_DVID;
315 }
316
Alex Deucherf36fce02010-09-27 11:33:00 -0400317 /* MSI K9A2GM V2/V3 board has no HDMI or DVI */
318 if ((dev->pdev->device == 0x796e) &&
319 (dev->pdev->subsystem_vendor == 0x1462) &&
320 (dev->pdev->subsystem_device == 0x7302)) {
321 if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) ||
322 (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
323 return false;
324 }
325
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200326 /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
327 if ((dev->pdev->device == 0x7941) &&
328 (dev->pdev->subsystem_vendor == 0x147b) &&
329 (dev->pdev->subsystem_device == 0x2412)) {
330 if (*connector_type == DRM_MODE_CONNECTOR_DVII)
331 return false;
332 }
333
334 /* Falcon NW laptop lists vga ddc line for LVDS */
335 if ((dev->pdev->device == 0x5653) &&
336 (dev->pdev->subsystem_vendor == 0x1462) &&
337 (dev->pdev->subsystem_device == 0x0291)) {
Alex Deucher848577e2009-07-08 16:15:30 -0400338 if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200339 i2c_bus->valid = false;
Alex Deucher848577e2009-07-08 16:15:30 -0400340 *line_mux = 53;
341 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200342 }
343
Alex Deucher4e3f9b782009-12-01 14:49:50 -0500344 /* HIS X1300 is DVI+VGA, not DVI+DVI */
345 if ((dev->pdev->device == 0x7146) &&
346 (dev->pdev->subsystem_vendor == 0x17af) &&
347 (dev->pdev->subsystem_device == 0x2058)) {
348 if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
349 return false;
350 }
351
Dave Airlieaa1a7502009-12-04 11:51:34 +1000352 /* Gigabyte X1300 is DVI+VGA, not DVI+DVI */
353 if ((dev->pdev->device == 0x7142) &&
354 (dev->pdev->subsystem_vendor == 0x1458) &&
355 (dev->pdev->subsystem_device == 0x2134)) {
356 if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
357 return false;
358 }
359
360
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200361 /* Funky macbooks */
362 if ((dev->pdev->device == 0x71C5) &&
363 (dev->pdev->subsystem_vendor == 0x106b) &&
364 (dev->pdev->subsystem_device == 0x0080)) {
365 if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
366 (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
367 return false;
Alex Deuchere1e8a5d2010-03-26 17:14:37 -0400368 if (supported_device == ATOM_DEVICE_CRT2_SUPPORT)
369 *line_mux = 0x90;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200370 }
371
Alex Deucherbe23da82011-01-18 18:26:11 +0000372 /* mac rv630, rv730, others */
373 if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) &&
374 (*connector_type == DRM_MODE_CONNECTOR_DVII)) {
375 *connector_type = DRM_MODE_CONNECTOR_9PinDIN;
376 *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1;
Alex Deucherf598aa72011-01-04 00:43:39 -0500377 }
378
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200379 /* ASUS HD 3600 XT board lists the DVI port as HDMI */
380 if ((dev->pdev->device == 0x9598) &&
381 (dev->pdev->subsystem_vendor == 0x1043) &&
382 (dev->pdev->subsystem_device == 0x01da)) {
Alex Deucher705af9c2009-09-10 16:31:13 -0400383 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
Alex Deucherd42571e2009-09-11 15:27:14 -0400384 *connector_type = DRM_MODE_CONNECTOR_DVII;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200385 }
386 }
387
Alex Deuchere153b702010-07-20 18:07:22 -0400388 /* ASUS HD 3600 board lists the DVI port as HDMI */
389 if ((dev->pdev->device == 0x9598) &&
390 (dev->pdev->subsystem_vendor == 0x1043) &&
391 (dev->pdev->subsystem_device == 0x01e4)) {
392 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
393 *connector_type = DRM_MODE_CONNECTOR_DVII;
394 }
395 }
396
Alex Deucher705af9c2009-09-10 16:31:13 -0400397 /* ASUS HD 3450 board lists the DVI port as HDMI */
398 if ((dev->pdev->device == 0x95C5) &&
399 (dev->pdev->subsystem_vendor == 0x1043) &&
400 (dev->pdev->subsystem_device == 0x01e2)) {
401 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
Alex Deucherd42571e2009-09-11 15:27:14 -0400402 *connector_type = DRM_MODE_CONNECTOR_DVII;
Alex Deucher705af9c2009-09-10 16:31:13 -0400403 }
404 }
405
406 /* some BIOSes seem to report DAC on HDMI - usually this is a board with
407 * HDMI + VGA reporting as HDMI
408 */
409 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
410 if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
411 *connector_type = DRM_MODE_CONNECTOR_VGA;
412 *line_mux = 0;
413 }
414 }
415
Alex Deucher4f87af42011-05-04 11:41:47 -0400416 /* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port
Alex Deucher2f299d52011-01-04 17:42:20 -0500417 * on the laptop and a DVI port on the docking station and
418 * both share the same encoder, hpd pin, and ddc line.
419 * So while the bios table is technically correct,
420 * we drop the DVI port here since xrandr has no concept of
421 * encoders and will try and drive both connectors
422 * with different crtcs which isn't possible on the hardware
423 * side and leaves no crtcs for LVDS or VGA.
424 */
Alex Deucher4f87af42011-05-04 11:41:47 -0400425 if (((dev->pdev->device == 0x95c4) || (dev->pdev->device == 0x9591)) &&
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500426 (dev->pdev->subsystem_vendor == 0x1025) &&
427 (dev->pdev->subsystem_device == 0x013c)) {
428 if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
Alex Deucher9ea2c4b2010-08-06 00:27:44 -0400429 (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
Alex Deucher2f299d52011-01-04 17:42:20 -0500430 /* actually it's a DVI-D port not DVI-I */
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500431 *connector_type = DRM_MODE_CONNECTOR_DVID;
Alex Deucher2f299d52011-01-04 17:42:20 -0500432 return false;
Alex Deucher9ea2c4b2010-08-06 00:27:44 -0400433 }
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500434 }
435
Dave Airlieefa84502010-02-09 09:06:00 +1000436 /* XFX Pine Group device rv730 reports no VGA DDC lines
437 * even though they are wired up to record 0x93
438 */
439 if ((dev->pdev->device == 0x9498) &&
440 (dev->pdev->subsystem_vendor == 0x1682) &&
441 (dev->pdev->subsystem_device == 0x2452)) {
442 struct radeon_device *rdev = dev->dev_private;
443 *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
444 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200445 return true;
446}
447
448const int supported_devices_connector_convert[] = {
449 DRM_MODE_CONNECTOR_Unknown,
450 DRM_MODE_CONNECTOR_VGA,
451 DRM_MODE_CONNECTOR_DVII,
452 DRM_MODE_CONNECTOR_DVID,
453 DRM_MODE_CONNECTOR_DVIA,
454 DRM_MODE_CONNECTOR_SVIDEO,
455 DRM_MODE_CONNECTOR_Composite,
456 DRM_MODE_CONNECTOR_LVDS,
457 DRM_MODE_CONNECTOR_Unknown,
458 DRM_MODE_CONNECTOR_Unknown,
459 DRM_MODE_CONNECTOR_HDMIA,
460 DRM_MODE_CONNECTOR_HDMIB,
461 DRM_MODE_CONNECTOR_Unknown,
462 DRM_MODE_CONNECTOR_Unknown,
463 DRM_MODE_CONNECTOR_9PinDIN,
464 DRM_MODE_CONNECTOR_DisplayPort
465};
466
Alex Deucherb75fad02009-11-05 13:16:01 -0500467const uint16_t supported_devices_connector_object_id_convert[] = {
468 CONNECTOR_OBJECT_ID_NONE,
469 CONNECTOR_OBJECT_ID_VGA,
470 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
471 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
472 CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
473 CONNECTOR_OBJECT_ID_COMPOSITE,
474 CONNECTOR_OBJECT_ID_SVIDEO,
475 CONNECTOR_OBJECT_ID_LVDS,
476 CONNECTOR_OBJECT_ID_9PIN_DIN,
477 CONNECTOR_OBJECT_ID_9PIN_DIN,
478 CONNECTOR_OBJECT_ID_DISPLAYPORT,
479 CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
480 CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
481 CONNECTOR_OBJECT_ID_SVIDEO
482};
483
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200484const int object_connector_convert[] = {
485 DRM_MODE_CONNECTOR_Unknown,
486 DRM_MODE_CONNECTOR_DVII,
487 DRM_MODE_CONNECTOR_DVII,
488 DRM_MODE_CONNECTOR_DVID,
489 DRM_MODE_CONNECTOR_DVID,
490 DRM_MODE_CONNECTOR_VGA,
491 DRM_MODE_CONNECTOR_Composite,
492 DRM_MODE_CONNECTOR_SVIDEO,
493 DRM_MODE_CONNECTOR_Unknown,
Alex Deucher705af9c2009-09-10 16:31:13 -0400494 DRM_MODE_CONNECTOR_Unknown,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200495 DRM_MODE_CONNECTOR_9PinDIN,
496 DRM_MODE_CONNECTOR_Unknown,
497 DRM_MODE_CONNECTOR_HDMIA,
498 DRM_MODE_CONNECTOR_HDMIB,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200499 DRM_MODE_CONNECTOR_LVDS,
500 DRM_MODE_CONNECTOR_9PinDIN,
501 DRM_MODE_CONNECTOR_Unknown,
502 DRM_MODE_CONNECTOR_Unknown,
503 DRM_MODE_CONNECTOR_Unknown,
Alex Deucher196c58d2010-01-07 14:22:32 -0500504 DRM_MODE_CONNECTOR_DisplayPort,
505 DRM_MODE_CONNECTOR_eDP,
506 DRM_MODE_CONNECTOR_Unknown
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200507};
508
509bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
510{
511 struct radeon_device *rdev = dev->dev_private;
512 struct radeon_mode_info *mode_info = &rdev->mode_info;
513 struct atom_context *ctx = mode_info->atom_context;
514 int index = GetIndexIntoMasterTable(DATA, Object_Header);
Alex Deuchereed45b32009-12-04 14:45:27 -0500515 u16 size, data_offset;
516 u8 frev, crev;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200517 ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
Alex Deucher36868bd2011-01-06 21:19:21 -0500518 ATOM_ENCODER_OBJECT_TABLE *enc_obj;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400519 ATOM_OBJECT_TABLE *router_obj;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200520 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
521 ATOM_OBJECT_HEADER *obj_header;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400522 int i, j, k, path_size, device_support;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200523 int connector_type;
Alex Deuchereed45b32009-12-04 14:45:27 -0500524 u16 igp_lane_info, conn_id, connector_object_id;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200525 struct radeon_i2c_bus_rec ddc_bus;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400526 struct radeon_router router;
Alex Deuchereed45b32009-12-04 14:45:27 -0500527 struct radeon_gpio_rec gpio;
528 struct radeon_hpd hpd;
529
Alex Deuchera084e6e2010-03-18 01:04:01 -0400530 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200531 return false;
532
533 if (crev < 2)
534 return false;
535
536 obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
537 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
538 (ctx->bios + data_offset +
539 le16_to_cpu(obj_header->usDisplayPathTableOffset));
540 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
541 (ctx->bios + data_offset +
542 le16_to_cpu(obj_header->usConnectorObjectTableOffset));
Alex Deucher36868bd2011-01-06 21:19:21 -0500543 enc_obj = (ATOM_ENCODER_OBJECT_TABLE *)
544 (ctx->bios + data_offset +
545 le16_to_cpu(obj_header->usEncoderObjectTableOffset));
Alex Deucher26b5bc92010-08-05 21:21:18 -0400546 router_obj = (ATOM_OBJECT_TABLE *)
547 (ctx->bios + data_offset +
548 le16_to_cpu(obj_header->usRouterObjectTableOffset));
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200549 device_support = le16_to_cpu(obj_header->usDeviceSupport);
550
551 path_size = 0;
552 for (i = 0; i < path_obj->ucNumOfDispPath; i++) {
553 uint8_t *addr = (uint8_t *) path_obj->asDispPath;
554 ATOM_DISPLAY_OBJECT_PATH *path;
555 addr += path_size;
556 path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
557 path_size += le16_to_cpu(path->usSize);
Alex Deucher5137ee92010-08-12 18:58:47 -0400558
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200559 if (device_support & le16_to_cpu(path->usDeviceTag)) {
560 uint8_t con_obj_id, con_obj_num, con_obj_type;
561
562 con_obj_id =
563 (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
564 >> OBJECT_ID_SHIFT;
565 con_obj_num =
566 (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
567 >> ENUM_ID_SHIFT;
568 con_obj_type =
569 (le16_to_cpu(path->usConnObjectId) &
570 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
571
Dave Airlie4bbd4972009-09-25 08:56:12 +1000572 /* TODO CV support */
573 if (le16_to_cpu(path->usDeviceTag) ==
574 ATOM_DEVICE_CV_SUPPORT)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200575 continue;
576
Alex Deucheree59f2b2009-11-05 13:11:46 -0500577 /* IGP chips */
578 if ((rdev->flags & RADEON_IS_IGP) &&
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200579 (con_obj_id ==
580 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
581 uint16_t igp_offset = 0;
582 ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj;
583
584 index =
585 GetIndexIntoMasterTable(DATA,
586 IntegratedSystemInfo);
587
Alex Deuchera084e6e2010-03-18 01:04:01 -0400588 if (atom_parse_data_header(ctx, index, &size, &frev,
589 &crev, &igp_offset)) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200590
Alex Deuchera084e6e2010-03-18 01:04:01 -0400591 if (crev >= 2) {
592 igp_obj =
593 (ATOM_INTEGRATED_SYSTEM_INFO_V2
594 *) (ctx->bios + igp_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200595
Alex Deuchera084e6e2010-03-18 01:04:01 -0400596 if (igp_obj) {
597 uint32_t slot_config, ct;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200598
Alex Deuchera084e6e2010-03-18 01:04:01 -0400599 if (con_obj_num == 1)
600 slot_config =
601 igp_obj->
602 ulDDISlot1Config;
603 else
604 slot_config =
605 igp_obj->
606 ulDDISlot2Config;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200607
Alex Deuchera084e6e2010-03-18 01:04:01 -0400608 ct = (slot_config >> 16) & 0xff;
609 connector_type =
610 object_connector_convert
611 [ct];
612 connector_object_id = ct;
613 igp_lane_info =
614 slot_config & 0xffff;
615 } else
616 continue;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200617 } else
618 continue;
Alex Deuchera084e6e2010-03-18 01:04:01 -0400619 } else {
620 igp_lane_info = 0;
621 connector_type =
622 object_connector_convert[con_obj_id];
623 connector_object_id = con_obj_id;
624 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200625 } else {
626 igp_lane_info = 0;
627 connector_type =
628 object_connector_convert[con_obj_id];
Alex Deucherb75fad02009-11-05 13:16:01 -0500629 connector_object_id = con_obj_id;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200630 }
631
632 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
633 continue;
634
Tyson Whiteheadbdd91b22010-11-08 16:08:30 +0000635 router.ddc_valid = false;
636 router.cd_valid = false;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400637 for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
638 uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200639
Alex Deucher26b5bc92010-08-05 21:21:18 -0400640 grph_obj_id =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200641 (le16_to_cpu(path->usGraphicObjIds[j]) &
642 OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400643 grph_obj_num =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200644 (le16_to_cpu(path->usGraphicObjIds[j]) &
645 ENUM_ID_MASK) >> ENUM_ID_SHIFT;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400646 grph_obj_type =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200647 (le16_to_cpu(path->usGraphicObjIds[j]) &
648 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
649
Alex Deucher26b5bc92010-08-05 21:21:18 -0400650 if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
Alex Deucher36868bd2011-01-06 21:19:21 -0500651 for (k = 0; k < enc_obj->ucNumberOfObjects; k++) {
652 u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID);
653 if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) {
654 ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
655 (ctx->bios + data_offset +
656 le16_to_cpu(enc_obj->asObjects[k].usRecordOffset));
657 ATOM_ENCODER_CAP_RECORD *cap_record;
658 u16 caps = 0;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200659
John Lindgren97ea5302011-03-24 23:28:31 +0000660 while (record->ucRecordSize > 0 &&
661 record->ucRecordType > 0 &&
Alex Deucher36868bd2011-01-06 21:19:21 -0500662 record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
663 switch (record->ucRecordType) {
664 case ATOM_ENCODER_CAP_RECORD_TYPE:
665 cap_record =(ATOM_ENCODER_CAP_RECORD *)
666 record;
667 caps = le16_to_cpu(cap_record->usEncoderCap);
668 break;
669 }
670 record = (ATOM_COMMON_RECORD_HEADER *)
671 ((char *)record + record->ucRecordSize);
672 }
673 radeon_add_atom_encoder(dev,
674 encoder_obj,
675 le16_to_cpu
676 (path->
677 usDeviceTag),
678 caps);
679 }
680 }
Alex Deucher26b5bc92010-08-05 21:21:18 -0400681 } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
Alex Deucher26b5bc92010-08-05 21:21:18 -0400682 for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
Tyson Whiteheadbdd91b22010-11-08 16:08:30 +0000683 u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID);
Alex Deucher26b5bc92010-08-05 21:21:18 -0400684 if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
685 ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
686 (ctx->bios + data_offset +
687 le16_to_cpu(router_obj->asObjects[k].usRecordOffset));
688 ATOM_I2C_RECORD *i2c_record;
689 ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
690 ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
Alex Deucherfb939df2010-11-08 16:08:29 +0000691 ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400692 ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
693 (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
694 (ctx->bios + data_offset +
695 le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset));
696 int enum_id;
697
698 router.router_id = router_obj_id;
699 for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst;
700 enum_id++) {
701 if (le16_to_cpu(path->usConnObjectId) ==
702 le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id]))
703 break;
704 }
705
John Lindgren97ea5302011-03-24 23:28:31 +0000706 while (record->ucRecordSize > 0 &&
707 record->ucRecordType > 0 &&
Alex Deucher26b5bc92010-08-05 21:21:18 -0400708 record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
709 switch (record->ucRecordType) {
710 case ATOM_I2C_RECORD_TYPE:
711 i2c_record =
712 (ATOM_I2C_RECORD *)
713 record;
714 i2c_config =
715 (ATOM_I2C_ID_CONFIG_ACCESS *)
716 &i2c_record->sucI2cId;
717 router.i2c_info =
718 radeon_lookup_i2c_gpio(rdev,
719 i2c_config->
720 ucAccess);
721 router.i2c_addr = i2c_record->ucI2CAddr >> 1;
722 break;
723 case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
724 ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
725 record;
Alex Deucherfb939df2010-11-08 16:08:29 +0000726 router.ddc_valid = true;
727 router.ddc_mux_type = ddc_path->ucMuxType;
728 router.ddc_mux_control_pin = ddc_path->ucMuxControlPin;
729 router.ddc_mux_state = ddc_path->ucMuxState[enum_id];
730 break;
731 case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE:
732 cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *)
733 record;
734 router.cd_valid = true;
735 router.cd_mux_type = cd_path->ucMuxType;
736 router.cd_mux_control_pin = cd_path->ucMuxControlPin;
737 router.cd_mux_state = cd_path->ucMuxState[enum_id];
Alex Deucher26b5bc92010-08-05 21:21:18 -0400738 break;
739 }
740 record = (ATOM_COMMON_RECORD_HEADER *)
741 ((char *)record + record->ucRecordSize);
742 }
743 }
744 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200745 }
746 }
747
Alex Deuchereed45b32009-12-04 14:45:27 -0500748 /* look up gpio for ddc, hpd */
Alex Deucher2bfcc0f2010-05-18 19:26:46 -0400749 ddc_bus.valid = false;
750 hpd.hpd = RADEON_HPD_NONE;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200751 if ((le16_to_cpu(path->usDeviceTag) &
Alex Deuchereed45b32009-12-04 14:45:27 -0500752 (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200753 for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
754 if (le16_to_cpu(path->usConnObjectId) ==
755 le16_to_cpu(con_obj->asObjects[j].
756 usObjectID)) {
757 ATOM_COMMON_RECORD_HEADER
758 *record =
759 (ATOM_COMMON_RECORD_HEADER
760 *)
761 (ctx->bios + data_offset +
762 le16_to_cpu(con_obj->
763 asObjects[j].
764 usRecordOffset));
765 ATOM_I2C_RECORD *i2c_record;
Alex Deuchereed45b32009-12-04 14:45:27 -0500766 ATOM_HPD_INT_RECORD *hpd_record;
Alex Deucherd3f420d2009-12-08 14:30:49 -0500767 ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
Alex Deucher6a93cb22009-11-23 17:39:28 -0500768
John Lindgren97ea5302011-03-24 23:28:31 +0000769 while (record->ucRecordSize > 0 &&
770 record->ucRecordType > 0 &&
771 record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
Alex Deuchereed45b32009-12-04 14:45:27 -0500772 switch (record->ucRecordType) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200773 case ATOM_I2C_RECORD_TYPE:
774 i2c_record =
Alex Deuchereed45b32009-12-04 14:45:27 -0500775 (ATOM_I2C_RECORD *)
776 record;
Alex Deucherd3f420d2009-12-08 14:30:49 -0500777 i2c_config =
778 (ATOM_I2C_ID_CONFIG_ACCESS *)
779 &i2c_record->sucI2cId;
Alex Deuchereed45b32009-12-04 14:45:27 -0500780 ddc_bus = radeon_lookup_i2c_gpio(rdev,
Alex Deucherd3f420d2009-12-08 14:30:49 -0500781 i2c_config->
782 ucAccess);
Alex Deuchereed45b32009-12-04 14:45:27 -0500783 break;
784 case ATOM_HPD_INT_RECORD_TYPE:
785 hpd_record =
786 (ATOM_HPD_INT_RECORD *)
787 record;
788 gpio = radeon_lookup_gpio(rdev,
789 hpd_record->ucHPDIntGPIOID);
790 hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
791 hpd.plugged_state = hpd_record->ucPlugged_PinState;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200792 break;
793 }
794 record =
795 (ATOM_COMMON_RECORD_HEADER
796 *) ((char *)record
797 +
798 record->
799 ucRecordSize);
800 }
801 break;
802 }
803 }
Alex Deuchereed45b32009-12-04 14:45:27 -0500804 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200805
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500806 /* needed for aux chan transactions */
Alex Deucher8e36ed02010-05-18 19:26:47 -0400807 ddc_bus.hpd = hpd.hpd;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -0500808
Alex Deucher705af9c2009-09-10 16:31:13 -0400809 conn_id = le16_to_cpu(path->usConnObjectId);
810
811 if (!radeon_atom_apply_quirks
812 (dev, le16_to_cpu(path->usDeviceTag), &connector_type,
Alex Deuchereed45b32009-12-04 14:45:27 -0500813 &ddc_bus, &conn_id, &hpd))
Alex Deucher705af9c2009-09-10 16:31:13 -0400814 continue;
815
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200816 radeon_add_atom_connector(dev,
Alex Deucher705af9c2009-09-10 16:31:13 -0400817 conn_id,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200818 le16_to_cpu(path->
819 usDeviceTag),
820 connector_type, &ddc_bus,
Alex Deucher5137ee92010-08-12 18:58:47 -0400821 igp_lane_info,
Alex Deuchereed45b32009-12-04 14:45:27 -0500822 connector_object_id,
Alex Deucher26b5bc92010-08-05 21:21:18 -0400823 &hpd,
824 &router);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200825
826 }
827 }
828
829 radeon_link_encoder_connector(dev);
830
831 return true;
832}
833
Alex Deucherb75fad02009-11-05 13:16:01 -0500834static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
835 int connector_type,
836 uint16_t devices)
837{
838 struct radeon_device *rdev = dev->dev_private;
839
840 if (rdev->flags & RADEON_IS_IGP) {
841 return supported_devices_connector_object_id_convert
842 [connector_type];
843 } else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
844 (connector_type == DRM_MODE_CONNECTOR_DVID)) &&
845 (devices & ATOM_DEVICE_DFP2_SUPPORT)) {
846 struct radeon_mode_info *mode_info = &rdev->mode_info;
847 struct atom_context *ctx = mode_info->atom_context;
848 int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
849 uint16_t size, data_offset;
850 uint8_t frev, crev;
851 ATOM_XTMDS_INFO *xtmds;
852
Alex Deuchera084e6e2010-03-18 01:04:01 -0400853 if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
854 xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
Alex Deucherb75fad02009-11-05 13:16:01 -0500855
Alex Deuchera084e6e2010-03-18 01:04:01 -0400856 if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
857 if (connector_type == DRM_MODE_CONNECTOR_DVII)
858 return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
859 else
860 return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
861 } else {
862 if (connector_type == DRM_MODE_CONNECTOR_DVII)
863 return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
864 else
865 return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
866 }
867 } else
868 return supported_devices_connector_object_id_convert
869 [connector_type];
Alex Deucherb75fad02009-11-05 13:16:01 -0500870 } else {
871 return supported_devices_connector_object_id_convert
872 [connector_type];
873 }
874}
875
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200876struct bios_connector {
877 bool valid;
Alex Deucher705af9c2009-09-10 16:31:13 -0400878 uint16_t line_mux;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200879 uint16_t devices;
880 int connector_type;
881 struct radeon_i2c_bus_rec ddc_bus;
Alex Deuchereed45b32009-12-04 14:45:27 -0500882 struct radeon_hpd hpd;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200883};
884
885bool radeon_get_atom_connector_info_from_supported_devices_table(struct
886 drm_device
887 *dev)
888{
889 struct radeon_device *rdev = dev->dev_private;
890 struct radeon_mode_info *mode_info = &rdev->mode_info;
891 struct atom_context *ctx = mode_info->atom_context;
892 int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo);
893 uint16_t size, data_offset;
894 uint8_t frev, crev;
895 uint16_t device_support;
896 uint8_t dac;
897 union atom_supported_devices *supported_devices;
Alex Deuchereed45b32009-12-04 14:45:27 -0500898 int i, j, max_device;
Prarit Bhargavaf49d2732010-05-24 10:24:07 +1000899 struct bios_connector *bios_connectors;
900 size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
Alex Deucher26b5bc92010-08-05 21:21:18 -0400901 struct radeon_router router;
902
Alex Deucherfb939df2010-11-08 16:08:29 +0000903 router.ddc_valid = false;
904 router.cd_valid = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200905
Prarit Bhargavaf49d2732010-05-24 10:24:07 +1000906 bios_connectors = kzalloc(bc_size, GFP_KERNEL);
907 if (!bios_connectors)
Alex Deuchera084e6e2010-03-18 01:04:01 -0400908 return false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200909
Prarit Bhargavaf49d2732010-05-24 10:24:07 +1000910 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev,
911 &data_offset)) {
912 kfree(bios_connectors);
913 return false;
914 }
915
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200916 supported_devices =
917 (union atom_supported_devices *)(ctx->bios + data_offset);
918
919 device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
920
Alex Deuchereed45b32009-12-04 14:45:27 -0500921 if (frev > 1)
922 max_device = ATOM_MAX_SUPPORTED_DEVICE;
923 else
924 max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
925
926 for (i = 0; i < max_device; i++) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200927 ATOM_CONNECTOR_INFO_I2C ci =
928 supported_devices->info.asConnInfo[i];
929
930 bios_connectors[i].valid = false;
931
932 if (!(device_support & (1 << i))) {
933 continue;
934 }
935
936 if (i == ATOM_DEVICE_CV_INDEX) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000937 DRM_DEBUG_KMS("Skipping Component Video\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200938 continue;
939 }
940
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200941 bios_connectors[i].connector_type =
942 supported_devices_connector_convert[ci.sucConnectorInfo.
943 sbfAccess.
944 bfConnectorType];
945
946 if (bios_connectors[i].connector_type ==
947 DRM_MODE_CONNECTOR_Unknown)
948 continue;
949
950 dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
951
Alex Deucherd3f420d2009-12-08 14:30:49 -0500952 bios_connectors[i].line_mux =
953 ci.sucI2cId.ucAccess;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200954
955 /* give tv unique connector ids */
956 if (i == ATOM_DEVICE_TV1_INDEX) {
957 bios_connectors[i].ddc_bus.valid = false;
958 bios_connectors[i].line_mux = 50;
959 } else if (i == ATOM_DEVICE_TV2_INDEX) {
960 bios_connectors[i].ddc_bus.valid = false;
961 bios_connectors[i].line_mux = 51;
962 } else if (i == ATOM_DEVICE_CV_INDEX) {
963 bios_connectors[i].ddc_bus.valid = false;
964 bios_connectors[i].line_mux = 52;
965 } else
966 bios_connectors[i].ddc_bus =
Alex Deuchereed45b32009-12-04 14:45:27 -0500967 radeon_lookup_i2c_gpio(rdev,
968 bios_connectors[i].line_mux);
969
970 if ((crev > 1) && (frev > 1)) {
971 u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap;
972 switch (isb) {
973 case 0x4:
974 bios_connectors[i].hpd.hpd = RADEON_HPD_1;
975 break;
976 case 0xa:
977 bios_connectors[i].hpd.hpd = RADEON_HPD_2;
978 break;
979 default:
980 bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
981 break;
982 }
983 } else {
984 if (i == ATOM_DEVICE_DFP1_INDEX)
985 bios_connectors[i].hpd.hpd = RADEON_HPD_1;
986 else if (i == ATOM_DEVICE_DFP2_INDEX)
987 bios_connectors[i].hpd.hpd = RADEON_HPD_2;
988 else
989 bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
990 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200991
992 /* Always set the connector type to VGA for CRT1/CRT2. if they are
993 * shared with a DVI port, we'll pick up the DVI connector when we
994 * merge the outputs. Some bioses incorrectly list VGA ports as DVI.
995 */
996 if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX)
997 bios_connectors[i].connector_type =
998 DRM_MODE_CONNECTOR_VGA;
999
1000 if (!radeon_atom_apply_quirks
1001 (dev, (1 << i), &bios_connectors[i].connector_type,
Alex Deuchereed45b32009-12-04 14:45:27 -05001002 &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux,
1003 &bios_connectors[i].hpd))
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001004 continue;
1005
1006 bios_connectors[i].valid = true;
1007 bios_connectors[i].devices = (1 << i);
1008
1009 if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)
1010 radeon_add_atom_encoder(dev,
Alex Deucher5137ee92010-08-12 18:58:47 -04001011 radeon_get_encoder_enum(dev,
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001012 (1 << i),
1013 dac),
Alex Deucher36868bd2011-01-06 21:19:21 -05001014 (1 << i),
1015 0);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001016 else
1017 radeon_add_legacy_encoder(dev,
Alex Deucher5137ee92010-08-12 18:58:47 -04001018 radeon_get_encoder_enum(dev,
Alex Deucherf56cd642009-12-18 11:28:22 -05001019 (1 << i),
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001020 dac),
1021 (1 << i));
1022 }
1023
1024 /* combine shared connectors */
Alex Deuchereed45b32009-12-04 14:45:27 -05001025 for (i = 0; i < max_device; i++) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001026 if (bios_connectors[i].valid) {
Alex Deuchereed45b32009-12-04 14:45:27 -05001027 for (j = 0; j < max_device; j++) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001028 if (bios_connectors[j].valid && (i != j)) {
1029 if (bios_connectors[i].line_mux ==
1030 bios_connectors[j].line_mux) {
Alex Deucherf56cd642009-12-18 11:28:22 -05001031 /* make sure not to combine LVDS */
1032 if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1033 bios_connectors[i].line_mux = 53;
1034 bios_connectors[i].ddc_bus.valid = false;
1035 continue;
1036 }
1037 if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1038 bios_connectors[j].line_mux = 53;
1039 bios_connectors[j].ddc_bus.valid = false;
1040 continue;
1041 }
1042 /* combine analog and digital for DVI-I */
1043 if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
1044 (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) ||
1045 ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
1046 (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) {
1047 bios_connectors[i].devices |=
1048 bios_connectors[j].devices;
1049 bios_connectors[i].connector_type =
1050 DRM_MODE_CONNECTOR_DVII;
1051 if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT))
Alex Deuchereed45b32009-12-04 14:45:27 -05001052 bios_connectors[i].hpd =
1053 bios_connectors[j].hpd;
Alex Deucherf56cd642009-12-18 11:28:22 -05001054 bios_connectors[j].valid = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001055 }
1056 }
1057 }
1058 }
1059 }
1060 }
1061
1062 /* add the connectors */
Alex Deuchereed45b32009-12-04 14:45:27 -05001063 for (i = 0; i < max_device; i++) {
Alex Deucherb75fad02009-11-05 13:16:01 -05001064 if (bios_connectors[i].valid) {
1065 uint16_t connector_object_id =
1066 atombios_get_connector_object_id(dev,
1067 bios_connectors[i].connector_type,
1068 bios_connectors[i].devices);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001069 radeon_add_atom_connector(dev,
1070 bios_connectors[i].line_mux,
1071 bios_connectors[i].devices,
1072 bios_connectors[i].
1073 connector_type,
1074 &bios_connectors[i].ddc_bus,
Alex Deucher5137ee92010-08-12 18:58:47 -04001075 0,
Alex Deuchereed45b32009-12-04 14:45:27 -05001076 connector_object_id,
Alex Deucher26b5bc92010-08-05 21:21:18 -04001077 &bios_connectors[i].hpd,
1078 &router);
Alex Deucherb75fad02009-11-05 13:16:01 -05001079 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001080 }
1081
1082 radeon_link_encoder_connector(dev);
1083
Prarit Bhargavaf49d2732010-05-24 10:24:07 +10001084 kfree(bios_connectors);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001085 return true;
1086}
1087
1088union firmware_info {
1089 ATOM_FIRMWARE_INFO info;
1090 ATOM_FIRMWARE_INFO_V1_2 info_12;
1091 ATOM_FIRMWARE_INFO_V1_3 info_13;
1092 ATOM_FIRMWARE_INFO_V1_4 info_14;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001093 ATOM_FIRMWARE_INFO_V2_1 info_21;
Alex Deucherf82b3dd2011-01-06 21:19:15 -05001094 ATOM_FIRMWARE_INFO_V2_2 info_22;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001095};
1096
1097bool radeon_atom_get_clock_info(struct drm_device *dev)
1098{
1099 struct radeon_device *rdev = dev->dev_private;
1100 struct radeon_mode_info *mode_info = &rdev->mode_info;
1101 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
1102 union firmware_info *firmware_info;
1103 uint8_t frev, crev;
1104 struct radeon_pll *p1pll = &rdev->clock.p1pll;
1105 struct radeon_pll *p2pll = &rdev->clock.p2pll;
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001106 struct radeon_pll *dcpll = &rdev->clock.dcpll;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001107 struct radeon_pll *spll = &rdev->clock.spll;
1108 struct radeon_pll *mpll = &rdev->clock.mpll;
1109 uint16_t data_offset;
1110
Alex Deuchera084e6e2010-03-18 01:04:01 -04001111 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1112 &frev, &crev, &data_offset)) {
1113 firmware_info =
1114 (union firmware_info *)(mode_info->atom_context->bios +
1115 data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001116 /* pixel clocks */
1117 p1pll->reference_freq =
1118 le16_to_cpu(firmware_info->info.usReferenceClock);
1119 p1pll->reference_div = 0;
1120
Mathias Fröhlichbc293e52009-10-19 17:49:49 -04001121 if (crev < 2)
1122 p1pll->pll_out_min =
1123 le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
1124 else
1125 p1pll->pll_out_min =
1126 le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001127 p1pll->pll_out_max =
1128 le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
1129
Alex Deucher86cb2bb2010-03-08 12:55:16 -05001130 if (crev >= 4) {
1131 p1pll->lcd_pll_out_min =
1132 le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
1133 if (p1pll->lcd_pll_out_min == 0)
1134 p1pll->lcd_pll_out_min = p1pll->pll_out_min;
1135 p1pll->lcd_pll_out_max =
1136 le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
1137 if (p1pll->lcd_pll_out_max == 0)
1138 p1pll->lcd_pll_out_max = p1pll->pll_out_max;
1139 } else {
1140 p1pll->lcd_pll_out_min = p1pll->pll_out_min;
1141 p1pll->lcd_pll_out_max = p1pll->pll_out_max;
1142 }
1143
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001144 if (p1pll->pll_out_min == 0) {
1145 if (ASIC_IS_AVIVO(rdev))
1146 p1pll->pll_out_min = 64800;
1147 else
1148 p1pll->pll_out_min = 20000;
1149 }
1150
1151 p1pll->pll_in_min =
1152 le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
1153 p1pll->pll_in_max =
1154 le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);
1155
1156 *p2pll = *p1pll;
1157
1158 /* system clock */
Alex Deucherf82b3dd2011-01-06 21:19:15 -05001159 if (ASIC_IS_DCE4(rdev))
1160 spll->reference_freq =
1161 le16_to_cpu(firmware_info->info_21.usCoreReferenceClock);
1162 else
1163 spll->reference_freq =
1164 le16_to_cpu(firmware_info->info.usReferenceClock);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001165 spll->reference_div = 0;
1166
1167 spll->pll_out_min =
1168 le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output);
1169 spll->pll_out_max =
1170 le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output);
1171
1172 /* ??? */
1173 if (spll->pll_out_min == 0) {
1174 if (ASIC_IS_AVIVO(rdev))
1175 spll->pll_out_min = 64800;
1176 else
1177 spll->pll_out_min = 20000;
1178 }
1179
1180 spll->pll_in_min =
1181 le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input);
1182 spll->pll_in_max =
1183 le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);
1184
1185 /* memory clock */
Alex Deucherf82b3dd2011-01-06 21:19:15 -05001186 if (ASIC_IS_DCE4(rdev))
1187 mpll->reference_freq =
1188 le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock);
1189 else
1190 mpll->reference_freq =
1191 le16_to_cpu(firmware_info->info.usReferenceClock);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001192 mpll->reference_div = 0;
1193
1194 mpll->pll_out_min =
1195 le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output);
1196 mpll->pll_out_max =
1197 le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output);
1198
1199 /* ??? */
1200 if (mpll->pll_out_min == 0) {
1201 if (ASIC_IS_AVIVO(rdev))
1202 mpll->pll_out_min = 64800;
1203 else
1204 mpll->pll_out_min = 20000;
1205 }
1206
1207 mpll->pll_in_min =
1208 le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input);
1209 mpll->pll_in_max =
1210 le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input);
1211
1212 rdev->clock.default_sclk =
1213 le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
1214 rdev->clock.default_mclk =
1215 le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
1216
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001217 if (ASIC_IS_DCE4(rdev)) {
1218 rdev->clock.default_dispclk =
1219 le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
Alex Deucherf82b3dd2011-01-06 21:19:15 -05001220 if (rdev->clock.default_dispclk == 0) {
1221 if (ASIC_IS_DCE5(rdev))
1222 rdev->clock.default_dispclk = 54000; /* 540 Mhz */
1223 else
1224 rdev->clock.default_dispclk = 60000; /* 600 Mhz */
1225 }
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001226 rdev->clock.dp_extclk =
1227 le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
1228 }
1229 *dcpll = *p1pll;
1230
Alex Deucherb20f9be2011-06-08 13:01:11 -04001231 rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock);
1232 if (rdev->clock.max_pixel_clock == 0)
1233 rdev->clock.max_pixel_clock = 40000;
1234
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001235 return true;
1236 }
Alex Deucherbcc1c2a2010-01-12 17:54:34 -05001237
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001238 return false;
1239}
1240
Alex Deucher06b64762010-01-05 11:27:29 -05001241union igp_info {
1242 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1243 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1244};
1245
1246bool radeon_atombios_sideport_present(struct radeon_device *rdev)
1247{
1248 struct radeon_mode_info *mode_info = &rdev->mode_info;
1249 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1250 union igp_info *igp_info;
1251 u8 frev, crev;
1252 u16 data_offset;
1253
Alex Deucher4c70b2e2010-08-02 19:39:15 -04001254 /* sideport is AMD only */
1255 if (rdev->family == CHIP_RS600)
1256 return false;
1257
Alex Deuchera084e6e2010-03-18 01:04:01 -04001258 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1259 &frev, &crev, &data_offset)) {
1260 igp_info = (union igp_info *)(mode_info->atom_context->bios +
Alex Deucher06b64762010-01-05 11:27:29 -05001261 data_offset);
Alex Deucher06b64762010-01-05 11:27:29 -05001262 switch (crev) {
1263 case 1:
Cédric Cano45894332011-02-11 19:45:37 -05001264 if (le32_to_cpu(igp_info->info.ulBootUpMemoryClock))
Alex Deucher4c70b2e2010-08-02 19:39:15 -04001265 return true;
Alex Deucher06b64762010-01-05 11:27:29 -05001266 break;
1267 case 2:
Cédric Cano45894332011-02-11 19:45:37 -05001268 if (le32_to_cpu(igp_info->info_2.ulBootUpSidePortClock))
Alex Deucher06b64762010-01-05 11:27:29 -05001269 return true;
1270 break;
1271 default:
1272 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1273 break;
1274 }
1275 }
1276 return false;
1277}
1278
Dave Airlie445282d2009-09-09 17:40:54 +10001279bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
1280 struct radeon_encoder_int_tmds *tmds)
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001281{
1282 struct drm_device *dev = encoder->base.dev;
1283 struct radeon_device *rdev = dev->dev_private;
1284 struct radeon_mode_info *mode_info = &rdev->mode_info;
1285 int index = GetIndexIntoMasterTable(DATA, TMDS_Info);
1286 uint16_t data_offset;
1287 struct _ATOM_TMDS_INFO *tmds_info;
1288 uint8_t frev, crev;
1289 uint16_t maxfreq;
1290 int i;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001291
Alex Deuchera084e6e2010-03-18 01:04:01 -04001292 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1293 &frev, &crev, &data_offset)) {
1294 tmds_info =
1295 (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
1296 data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001297
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001298 maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
1299 for (i = 0; i < 4; i++) {
1300 tmds->tmds_pll[i].freq =
1301 le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency);
1302 tmds->tmds_pll[i].value =
1303 tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f;
1304 tmds->tmds_pll[i].value |=
1305 (tmds_info->asMiscInfo[i].
1306 ucPLL_VCO_Gain & 0x3f) << 6;
1307 tmds->tmds_pll[i].value |=
1308 (tmds_info->asMiscInfo[i].
1309 ucPLL_DutyCycle & 0xf) << 12;
1310 tmds->tmds_pll[i].value |=
1311 (tmds_info->asMiscInfo[i].
1312 ucPLL_VoltageSwing & 0xf) << 16;
1313
Dave Airlied9fdaaf2010-08-02 10:42:55 +10001314 DRM_DEBUG_KMS("TMDS PLL From ATOMBIOS %u %x\n",
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001315 tmds->tmds_pll[i].freq,
1316 tmds->tmds_pll[i].value);
1317
1318 if (maxfreq == tmds->tmds_pll[i].freq) {
1319 tmds->tmds_pll[i].freq = 0xffffffff;
1320 break;
1321 }
1322 }
Dave Airlie445282d2009-09-09 17:40:54 +10001323 return true;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001324 }
Dave Airlie445282d2009-09-09 17:40:54 +10001325 return false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001326}
1327
Alex Deucherba032a52010-10-04 17:13:01 -04001328bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev,
1329 struct radeon_atom_ss *ss,
1330 int id)
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001331{
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001332 struct radeon_mode_info *mode_info = &rdev->mode_info;
1333 int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
Alex Deucherba032a52010-10-04 17:13:01 -04001334 uint16_t data_offset, size;
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001335 struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
1336 uint8_t frev, crev;
Alex Deucherba032a52010-10-04 17:13:01 -04001337 int i, num_indices;
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001338
Alex Deucherba032a52010-10-04 17:13:01 -04001339 memset(ss, 0, sizeof(struct radeon_atom_ss));
1340 if (atom_parse_data_header(mode_info->atom_context, index, &size,
Alex Deuchera084e6e2010-03-18 01:04:01 -04001341 &frev, &crev, &data_offset)) {
1342 ss_info =
1343 (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001344
Alex Deucherba032a52010-10-04 17:13:01 -04001345 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1346 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001347
Alex Deucherba032a52010-10-04 17:13:01 -04001348 for (i = 0; i < num_indices; i++) {
Alex Deucher279b2152009-12-08 14:07:03 -05001349 if (ss_info->asSS_Info[i].ucSS_Id == id) {
1350 ss->percentage =
1351 le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage);
1352 ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType;
1353 ss->step = ss_info->asSS_Info[i].ucSS_Step;
1354 ss->delay = ss_info->asSS_Info[i].ucSS_Delay;
1355 ss->range = ss_info->asSS_Info[i].ucSS_Range;
1356 ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div;
Alex Deucherba032a52010-10-04 17:13:01 -04001357 return true;
Alex Deucher279b2152009-12-08 14:07:03 -05001358 }
1359 }
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001360 }
Alex Deucherba032a52010-10-04 17:13:01 -04001361 return false;
1362}
1363
Alex Deucher4339c442010-11-22 17:56:25 -05001364static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev,
1365 struct radeon_atom_ss *ss,
1366 int id)
1367{
1368 struct radeon_mode_info *mode_info = &rdev->mode_info;
1369 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1370 u16 data_offset, size;
1371 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info;
1372 u8 frev, crev;
1373 u16 percentage = 0, rate = 0;
1374
1375 /* get any igp specific overrides */
1376 if (atom_parse_data_header(mode_info->atom_context, index, &size,
1377 &frev, &crev, &data_offset)) {
1378 igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *)
1379 (mode_info->atom_context->bios + data_offset);
1380 switch (id) {
1381 case ASIC_INTERNAL_SS_ON_TMDS:
1382 percentage = le16_to_cpu(igp_info->usDVISSPercentage);
1383 rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz);
1384 break;
1385 case ASIC_INTERNAL_SS_ON_HDMI:
1386 percentage = le16_to_cpu(igp_info->usHDMISSPercentage);
1387 rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz);
1388 break;
1389 case ASIC_INTERNAL_SS_ON_LVDS:
1390 percentage = le16_to_cpu(igp_info->usLvdsSSPercentage);
1391 rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz);
1392 break;
1393 }
1394 if (percentage)
1395 ss->percentage = percentage;
1396 if (rate)
1397 ss->rate = rate;
1398 }
1399}
1400
Alex Deucherba032a52010-10-04 17:13:01 -04001401union asic_ss_info {
1402 struct _ATOM_ASIC_INTERNAL_SS_INFO info;
1403 struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2;
1404 struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3;
1405};
1406
1407bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
1408 struct radeon_atom_ss *ss,
1409 int id, u32 clock)
1410{
1411 struct radeon_mode_info *mode_info = &rdev->mode_info;
1412 int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
1413 uint16_t data_offset, size;
1414 union asic_ss_info *ss_info;
1415 uint8_t frev, crev;
1416 int i, num_indices;
1417
1418 memset(ss, 0, sizeof(struct radeon_atom_ss));
1419 if (atom_parse_data_header(mode_info->atom_context, index, &size,
1420 &frev, &crev, &data_offset)) {
1421
1422 ss_info =
1423 (union asic_ss_info *)(mode_info->atom_context->bios + data_offset);
1424
1425 switch (frev) {
1426 case 1:
1427 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1428 sizeof(ATOM_ASIC_SS_ASSIGNMENT);
1429
1430 for (i = 0; i < num_indices; i++) {
1431 if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) &&
Cédric Cano45894332011-02-11 19:45:37 -05001432 (clock <= le32_to_cpu(ss_info->info.asSpreadSpectrum[i].ulTargetClockRange))) {
Alex Deucherba032a52010-10-04 17:13:01 -04001433 ss->percentage =
1434 le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
1435 ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode;
1436 ss->rate = le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz);
1437 return true;
1438 }
1439 }
1440 break;
1441 case 2:
1442 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1443 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1444 for (i = 0; i < num_indices; i++) {
1445 if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) &&
Cédric Cano45894332011-02-11 19:45:37 -05001446 (clock <= le32_to_cpu(ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange))) {
Alex Deucherba032a52010-10-04 17:13:01 -04001447 ss->percentage =
1448 le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
1449 ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode;
1450 ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz);
1451 return true;
1452 }
1453 }
1454 break;
1455 case 3:
1456 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
1457 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
1458 for (i = 0; i < num_indices; i++) {
1459 if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) &&
Cédric Cano45894332011-02-11 19:45:37 -05001460 (clock <= le32_to_cpu(ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange))) {
Alex Deucherba032a52010-10-04 17:13:01 -04001461 ss->percentage =
1462 le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
1463 ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode;
1464 ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz);
Alex Deucher4339c442010-11-22 17:56:25 -05001465 if (rdev->flags & RADEON_IS_IGP)
1466 radeon_atombios_get_igp_ss_overrides(rdev, ss, id);
Alex Deucherba032a52010-10-04 17:13:01 -04001467 return true;
1468 }
1469 }
1470 break;
1471 default:
1472 DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev);
1473 break;
1474 }
1475
1476 }
1477 return false;
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001478}
1479
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001480union lvds_info {
1481 struct _ATOM_LVDS_INFO info;
1482 struct _ATOM_LVDS_INFO_V12 info_12;
1483};
1484
1485struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
1486 radeon_encoder
1487 *encoder)
1488{
1489 struct drm_device *dev = encoder->base.dev;
1490 struct radeon_device *rdev = dev->dev_private;
1491 struct radeon_mode_info *mode_info = &rdev->mode_info;
1492 int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
Alex Deucher7dde8a192009-11-30 01:40:24 -05001493 uint16_t data_offset, misc;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001494 union lvds_info *lvds_info;
1495 uint8_t frev, crev;
1496 struct radeon_encoder_atom_dig *lvds = NULL;
Alex Deucher5137ee92010-08-12 18:58:47 -04001497 int encoder_enum = (encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001498
Alex Deuchera084e6e2010-03-18 01:04:01 -04001499 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1500 &frev, &crev, &data_offset)) {
1501 lvds_info =
1502 (union lvds_info *)(mode_info->atom_context->bios + data_offset);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001503 lvds =
1504 kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
1505
1506 if (!lvds)
1507 return NULL;
1508
Alex Deucherde2103e2009-10-09 15:14:30 -04001509 lvds->native_mode.clock =
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001510 le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
Alex Deucherde2103e2009-10-09 15:14:30 -04001511 lvds->native_mode.hdisplay =
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001512 le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
Alex Deucherde2103e2009-10-09 15:14:30 -04001513 lvds->native_mode.vdisplay =
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001514 le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
Alex Deucherde2103e2009-10-09 15:14:30 -04001515 lvds->native_mode.htotal = lvds->native_mode.hdisplay +
1516 le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
1517 lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
1518 le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
1519 lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
1520 le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
1521 lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
1522 le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
1523 lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
Alex Deucher1ff26a32010-05-18 00:23:15 -04001524 le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
Alex Deucherde2103e2009-10-09 15:14:30 -04001525 lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
1526 le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001527 lvds->panel_pwr_delay =
1528 le16_to_cpu(lvds_info->info.usOffDelayInMs);
Alex Deucherba032a52010-10-04 17:13:01 -04001529 lvds->lcd_misc = lvds_info->info.ucLVDS_Misc;
Alex Deucher7dde8a192009-11-30 01:40:24 -05001530
1531 misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess);
1532 if (misc & ATOM_VSYNC_POLARITY)
1533 lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC;
1534 if (misc & ATOM_HSYNC_POLARITY)
1535 lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC;
1536 if (misc & ATOM_COMPOSITESYNC)
1537 lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC;
1538 if (misc & ATOM_INTERLACE)
1539 lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE;
1540 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1541 lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;
1542
Cédric Cano45894332011-02-11 19:45:37 -05001543 lvds->native_mode.width_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageHSize);
1544 lvds->native_mode.height_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageVSize);
Alex Deucher7a868e12010-12-08 22:13:05 -05001545
Alex Deucherde2103e2009-10-09 15:14:30 -04001546 /* set crtc values */
1547 drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001548
Alex Deucherba032a52010-10-04 17:13:01 -04001549 lvds->lcd_ss_id = lvds_info->info.ucSS_Id;
Alex Deucherebbe1cb2009-10-16 11:15:25 -04001550
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001551 encoder->native_mode = lvds->native_mode;
Alex Deucher5137ee92010-08-12 18:58:47 -04001552
1553 if (encoder_enum == 2)
1554 lvds->linkb = true;
1555 else
1556 lvds->linkb = false;
1557
Alex Deucherc324acd2010-12-08 22:13:06 -05001558 /* parse the lcd record table */
Cédric Cano45894332011-02-11 19:45:37 -05001559 if (le16_to_cpu(lvds_info->info.usModePatchTableOffset)) {
Alex Deucherc324acd2010-12-08 22:13:06 -05001560 ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
1561 ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
1562 bool bad_record = false;
Alex Deucher05fa7ea2011-05-11 14:02:07 -04001563 u8 *record;
1564
1565 if ((frev == 1) && (crev < 2))
1566 /* absolute */
1567 record = (u8 *)(mode_info->atom_context->bios +
1568 le16_to_cpu(lvds_info->info.usModePatchTableOffset));
1569 else
1570 /* relative */
1571 record = (u8 *)(mode_info->atom_context->bios +
1572 data_offset +
1573 le16_to_cpu(lvds_info->info.usModePatchTableOffset));
Alex Deucherc324acd2010-12-08 22:13:06 -05001574 while (*record != ATOM_RECORD_END_TYPE) {
1575 switch (*record) {
1576 case LCD_MODE_PATCH_RECORD_MODE_TYPE:
1577 record += sizeof(ATOM_PATCH_RECORD_MODE);
1578 break;
1579 case LCD_RTS_RECORD_TYPE:
1580 record += sizeof(ATOM_LCD_RTS_RECORD);
1581 break;
1582 case LCD_CAP_RECORD_TYPE:
1583 record += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
1584 break;
1585 case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
1586 fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
1587 if (fake_edid_record->ucFakeEDIDLength) {
1588 struct edid *edid;
1589 int edid_size =
1590 max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
1591 edid = kmalloc(edid_size, GFP_KERNEL);
1592 if (edid) {
1593 memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
1594 fake_edid_record->ucFakeEDIDLength);
1595
Dave Airlieeaa4f5e2011-05-01 20:16:30 +10001596 if (drm_edid_is_valid(edid)) {
Alex Deucherc324acd2010-12-08 22:13:06 -05001597 rdev->mode_info.bios_hardcoded_edid = edid;
Dave Airlieeaa4f5e2011-05-01 20:16:30 +10001598 rdev->mode_info.bios_hardcoded_edid_size = edid_size;
1599 } else
Alex Deucherc324acd2010-12-08 22:13:06 -05001600 kfree(edid);
1601 }
1602 }
1603 record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
1604 break;
1605 case LCD_PANEL_RESOLUTION_RECORD_TYPE:
1606 panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
1607 lvds->native_mode.width_mm = panel_res_record->usHSize;
1608 lvds->native_mode.height_mm = panel_res_record->usVSize;
1609 record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
1610 break;
1611 default:
1612 DRM_ERROR("Bad LCD record %d\n", *record);
1613 bad_record = true;
1614 break;
1615 }
1616 if (bad_record)
1617 break;
1618 }
1619 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001620 }
1621 return lvds;
1622}
1623
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001624struct radeon_encoder_primary_dac *
1625radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
1626{
1627 struct drm_device *dev = encoder->base.dev;
1628 struct radeon_device *rdev = dev->dev_private;
1629 struct radeon_mode_info *mode_info = &rdev->mode_info;
1630 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1631 uint16_t data_offset;
1632 struct _COMPASSIONATE_DATA *dac_info;
1633 uint8_t frev, crev;
1634 uint8_t bg, dac;
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001635 struct radeon_encoder_primary_dac *p_dac = NULL;
1636
Alex Deuchera084e6e2010-03-18 01:04:01 -04001637 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1638 &frev, &crev, &data_offset)) {
1639 dac_info = (struct _COMPASSIONATE_DATA *)
1640 (mode_info->atom_context->bios + data_offset);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001641
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001642 p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
1643
1644 if (!p_dac)
1645 return NULL;
1646
1647 bg = dac_info->ucDAC1_BG_Adjustment;
1648 dac = dac_info->ucDAC1_DAC_Adjustment;
1649 p_dac->ps2_pdac_adj = (bg << 8) | (dac);
1650
1651 }
1652 return p_dac;
1653}
1654
Dave Airlie4ce001a2009-08-13 16:32:14 +10001655bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001656 struct drm_display_mode *mode)
Dave Airlie4ce001a2009-08-13 16:32:14 +10001657{
1658 struct radeon_mode_info *mode_info = &rdev->mode_info;
1659 ATOM_ANALOG_TV_INFO *tv_info;
1660 ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
1661 ATOM_DTD_FORMAT *dtd_timings;
1662 int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
1663 u8 frev, crev;
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001664 u16 data_offset, misc;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001665
Alex Deuchera084e6e2010-03-18 01:04:01 -04001666 if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
1667 &frev, &crev, &data_offset))
1668 return false;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001669
1670 switch (crev) {
1671 case 1:
1672 tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
Dan Carpenter0031c412010-04-27 14:11:04 -07001673 if (index >= MAX_SUPPORTED_TV_TIMING)
Dave Airlie4ce001a2009-08-13 16:32:14 +10001674 return false;
1675
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001676 mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
1677 mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
1678 mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
1679 mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
1680 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001681
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001682 mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
1683 mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
1684 mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
1685 mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
1686 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001687
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001688 mode->flags = 0;
1689 misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
1690 if (misc & ATOM_VSYNC_POLARITY)
1691 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1692 if (misc & ATOM_HSYNC_POLARITY)
1693 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1694 if (misc & ATOM_COMPOSITESYNC)
1695 mode->flags |= DRM_MODE_FLAG_CSYNC;
1696 if (misc & ATOM_INTERLACE)
1697 mode->flags |= DRM_MODE_FLAG_INTERLACE;
1698 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1699 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001700
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001701 mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001702
1703 if (index == 1) {
1704 /* PAL timings appear to have wrong values for totals */
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001705 mode->crtc_htotal -= 1;
1706 mode->crtc_vtotal -= 1;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001707 }
1708 break;
1709 case 2:
1710 tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
Dan Carpenter0031c412010-04-27 14:11:04 -07001711 if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)
Dave Airlie4ce001a2009-08-13 16:32:14 +10001712 return false;
1713
1714 dtd_timings = &tv_info_v1_2->aModeTimings[index];
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001715 mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
1716 le16_to_cpu(dtd_timings->usHBlanking_Time);
1717 mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive);
1718 mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) +
1719 le16_to_cpu(dtd_timings->usHSyncOffset);
1720 mode->crtc_hsync_end = mode->crtc_hsync_start +
1721 le16_to_cpu(dtd_timings->usHSyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001722
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001723 mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) +
1724 le16_to_cpu(dtd_timings->usVBlanking_Time);
1725 mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive);
1726 mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) +
1727 le16_to_cpu(dtd_timings->usVSyncOffset);
1728 mode->crtc_vsync_end = mode->crtc_vsync_start +
1729 le16_to_cpu(dtd_timings->usVSyncWidth);
1730
1731 mode->flags = 0;
1732 misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
1733 if (misc & ATOM_VSYNC_POLARITY)
1734 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1735 if (misc & ATOM_HSYNC_POLARITY)
1736 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1737 if (misc & ATOM_COMPOSITESYNC)
1738 mode->flags |= DRM_MODE_FLAG_CSYNC;
1739 if (misc & ATOM_INTERLACE)
1740 mode->flags |= DRM_MODE_FLAG_INTERLACE;
1741 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1742 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
1743
1744 mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001745 break;
1746 }
1747 return true;
1748}
1749
Alex Deucherd79766f2009-12-17 19:00:29 -05001750enum radeon_tv_std
1751radeon_atombios_get_tv_info(struct radeon_device *rdev)
1752{
1753 struct radeon_mode_info *mode_info = &rdev->mode_info;
1754 int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
1755 uint16_t data_offset;
1756 uint8_t frev, crev;
1757 struct _ATOM_ANALOG_TV_INFO *tv_info;
1758 enum radeon_tv_std tv_std = TV_STD_NTSC;
1759
Alex Deuchera084e6e2010-03-18 01:04:01 -04001760 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1761 &frev, &crev, &data_offset)) {
Alex Deucherd79766f2009-12-17 19:00:29 -05001762
Alex Deuchera084e6e2010-03-18 01:04:01 -04001763 tv_info = (struct _ATOM_ANALOG_TV_INFO *)
1764 (mode_info->atom_context->bios + data_offset);
Alex Deucherd79766f2009-12-17 19:00:29 -05001765
Alex Deuchera084e6e2010-03-18 01:04:01 -04001766 switch (tv_info->ucTV_BootUpDefaultStandard) {
1767 case ATOM_TV_NTSC:
1768 tv_std = TV_STD_NTSC;
Alex Deucher40f76d82010-10-07 22:38:42 -04001769 DRM_DEBUG_KMS("Default TV standard: NTSC\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001770 break;
1771 case ATOM_TV_NTSCJ:
1772 tv_std = TV_STD_NTSC_J;
Alex Deucher40f76d82010-10-07 22:38:42 -04001773 DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001774 break;
1775 case ATOM_TV_PAL:
1776 tv_std = TV_STD_PAL;
Alex Deucher40f76d82010-10-07 22:38:42 -04001777 DRM_DEBUG_KMS("Default TV standard: PAL\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001778 break;
1779 case ATOM_TV_PALM:
1780 tv_std = TV_STD_PAL_M;
Alex Deucher40f76d82010-10-07 22:38:42 -04001781 DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001782 break;
1783 case ATOM_TV_PALN:
1784 tv_std = TV_STD_PAL_N;
Alex Deucher40f76d82010-10-07 22:38:42 -04001785 DRM_DEBUG_KMS("Default TV standard: PAL-N\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001786 break;
1787 case ATOM_TV_PALCN:
1788 tv_std = TV_STD_PAL_CN;
Alex Deucher40f76d82010-10-07 22:38:42 -04001789 DRM_DEBUG_KMS("Default TV standard: PAL-CN\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001790 break;
1791 case ATOM_TV_PAL60:
1792 tv_std = TV_STD_PAL_60;
Alex Deucher40f76d82010-10-07 22:38:42 -04001793 DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001794 break;
1795 case ATOM_TV_SECAM:
1796 tv_std = TV_STD_SECAM;
Alex Deucher40f76d82010-10-07 22:38:42 -04001797 DRM_DEBUG_KMS("Default TV standard: SECAM\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001798 break;
1799 default:
1800 tv_std = TV_STD_NTSC;
Alex Deucher40f76d82010-10-07 22:38:42 -04001801 DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n");
Alex Deuchera084e6e2010-03-18 01:04:01 -04001802 break;
1803 }
Alex Deucherd79766f2009-12-17 19:00:29 -05001804 }
1805 return tv_std;
1806}
1807
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001808struct radeon_encoder_tv_dac *
1809radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
1810{
1811 struct drm_device *dev = encoder->base.dev;
1812 struct radeon_device *rdev = dev->dev_private;
1813 struct radeon_mode_info *mode_info = &rdev->mode_info;
1814 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1815 uint16_t data_offset;
1816 struct _COMPASSIONATE_DATA *dac_info;
1817 uint8_t frev, crev;
1818 uint8_t bg, dac;
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001819 struct radeon_encoder_tv_dac *tv_dac = NULL;
1820
Alex Deuchera084e6e2010-03-18 01:04:01 -04001821 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1822 &frev, &crev, &data_offset)) {
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001823
Alex Deuchera084e6e2010-03-18 01:04:01 -04001824 dac_info = (struct _COMPASSIONATE_DATA *)
1825 (mode_info->atom_context->bios + data_offset);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001826
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001827 tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
1828
1829 if (!tv_dac)
1830 return NULL;
1831
1832 bg = dac_info->ucDAC2_CRT2_BG_Adjustment;
1833 dac = dac_info->ucDAC2_CRT2_DAC_Adjustment;
1834 tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
1835
1836 bg = dac_info->ucDAC2_PAL_BG_Adjustment;
1837 dac = dac_info->ucDAC2_PAL_DAC_Adjustment;
1838 tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
1839
1840 bg = dac_info->ucDAC2_NTSC_BG_Adjustment;
1841 dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
1842 tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
1843
Alex Deucherd79766f2009-12-17 19:00:29 -05001844 tv_dac->tv_std = radeon_atombios_get_tv_info(rdev);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001845 }
1846 return tv_dac;
1847}
1848
Alex Deucher29fb52c2010-03-11 10:01:17 -05001849static const char *thermal_controller_names[] = {
1850 "NONE",
Alex Deucher678e7df2010-04-22 14:17:56 -04001851 "lm63",
1852 "adm1032",
1853 "adm1030",
1854 "max6649",
1855 "lm64",
1856 "f75375",
1857 "asc7xxx",
Alex Deucher29fb52c2010-03-11 10:01:17 -05001858};
1859
1860static const char *pp_lib_thermal_controller_names[] = {
1861 "NONE",
Alex Deucher678e7df2010-04-22 14:17:56 -04001862 "lm63",
1863 "adm1032",
1864 "adm1030",
1865 "max6649",
1866 "lm64",
1867 "f75375",
Alex Deucher29fb52c2010-03-11 10:01:17 -05001868 "RV6xx",
1869 "RV770",
Alex Deucher678e7df2010-04-22 14:17:56 -04001870 "adt7473",
Alex Deucher560154e2010-11-22 17:56:34 -05001871 "NONE",
Alex Deucher49f65982010-03-24 16:39:45 -04001872 "External GPIO",
1873 "Evergreen",
Alex Deucherb0e66412010-11-22 17:56:35 -05001874 "emc2103",
1875 "Sumo",
Alex Deucher4fddba12011-01-06 21:19:22 -05001876 "Northern Islands",
Alex Deucher29fb52c2010-03-11 10:01:17 -05001877};
1878
Alex Deucher56278a82009-12-28 13:58:44 -05001879union power_info {
1880 struct _ATOM_POWERPLAY_INFO info;
1881 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1882 struct _ATOM_POWERPLAY_INFO_V3 info_3;
Alex Deucher560154e2010-11-22 17:56:34 -05001883 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
Alex Deucherb0e66412010-11-22 17:56:35 -05001884 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1885 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
Alex Deucher56278a82009-12-28 13:58:44 -05001886};
1887
Alex Deucher560154e2010-11-22 17:56:34 -05001888union pplib_clock_info {
1889 struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1890 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1891 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
Alex Deucherb0e66412010-11-22 17:56:35 -05001892 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
Alex Deucher560154e2010-11-22 17:56:34 -05001893};
1894
1895union pplib_power_state {
1896 struct _ATOM_PPLIB_STATE v1;
1897 struct _ATOM_PPLIB_STATE_V2 v2;
1898};
1899
1900static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev,
1901 int state_index,
1902 u32 misc, u32 misc2)
1903{
1904 rdev->pm.power_state[state_index].misc = misc;
1905 rdev->pm.power_state[state_index].misc2 = misc2;
1906 /* order matters! */
1907 if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
1908 rdev->pm.power_state[state_index].type =
1909 POWER_STATE_TYPE_POWERSAVE;
1910 if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
1911 rdev->pm.power_state[state_index].type =
1912 POWER_STATE_TYPE_BATTERY;
1913 if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
1914 rdev->pm.power_state[state_index].type =
1915 POWER_STATE_TYPE_BATTERY;
1916 if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
1917 rdev->pm.power_state[state_index].type =
1918 POWER_STATE_TYPE_BALANCED;
1919 if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
1920 rdev->pm.power_state[state_index].type =
1921 POWER_STATE_TYPE_PERFORMANCE;
1922 rdev->pm.power_state[state_index].flags &=
1923 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
1924 }
1925 if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
1926 rdev->pm.power_state[state_index].type =
1927 POWER_STATE_TYPE_BALANCED;
1928 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
1929 rdev->pm.power_state[state_index].type =
1930 POWER_STATE_TYPE_DEFAULT;
1931 rdev->pm.default_power_state_index = state_index;
1932 rdev->pm.power_state[state_index].default_clock_mode =
1933 &rdev->pm.power_state[state_index].clock_info[0];
1934 } else if (state_index == 0) {
1935 rdev->pm.power_state[state_index].clock_info[0].flags |=
1936 RADEON_PM_MODE_NO_DISPLAY;
1937 }
1938}
1939
1940static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
1941{
1942 struct radeon_mode_info *mode_info = &rdev->mode_info;
1943 u32 misc, misc2 = 0;
1944 int num_modes = 0, i;
1945 int state_index = 0;
1946 struct radeon_i2c_bus_rec i2c_bus;
1947 union power_info *power_info;
1948 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1949 u16 data_offset;
1950 u8 frev, crev;
1951
1952 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1953 &frev, &crev, &data_offset))
1954 return state_index;
1955 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1956
1957 /* add the i2c bus for thermal/fan chip */
1958 if (power_info->info.ucOverdriveThermalController > 0) {
1959 DRM_INFO("Possible %s thermal controller at 0x%02x\n",
1960 thermal_controller_names[power_info->info.ucOverdriveThermalController],
1961 power_info->info.ucOverdriveControllerAddress >> 1);
1962 i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
1963 rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
1964 if (rdev->pm.i2c_bus) {
1965 struct i2c_board_info info = { };
1966 const char *name = thermal_controller_names[power_info->info.
1967 ucOverdriveThermalController];
1968 info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
1969 strlcpy(info.type, name, sizeof(info.type));
1970 i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
1971 }
1972 }
1973 num_modes = power_info->info.ucNumOfPowerModeEntries;
1974 if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
1975 num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
Alex Deucher0975b162011-02-02 18:42:03 -05001976 rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL);
1977 if (!rdev->pm.power_state)
1978 return state_index;
Alex Deucher560154e2010-11-22 17:56:34 -05001979 /* last mode is usually default, array is low to high */
1980 for (i = 0; i < num_modes; i++) {
Alex Deucher6991b8f2011-11-14 17:52:51 -05001981 rdev->pm.power_state[state_index].clock_info =
1982 kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
1983 if (!rdev->pm.power_state[state_index].clock_info)
1984 return state_index;
1985 rdev->pm.power_state[state_index].num_clock_modes = 1;
Alex Deucher560154e2010-11-22 17:56:34 -05001986 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
1987 switch (frev) {
1988 case 1:
Alex Deucher560154e2010-11-22 17:56:34 -05001989 rdev->pm.power_state[state_index].clock_info[0].mclk =
1990 le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
1991 rdev->pm.power_state[state_index].clock_info[0].sclk =
1992 le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
1993 /* skip invalid modes */
1994 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
1995 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
1996 continue;
1997 rdev->pm.power_state[state_index].pcie_lanes =
1998 power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
1999 misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
2000 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
2001 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
2002 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2003 VOLTAGE_GPIO;
2004 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
2005 radeon_lookup_gpio(rdev,
2006 power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
2007 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
2008 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2009 true;
2010 else
2011 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2012 false;
2013 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
2014 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2015 VOLTAGE_VDDC;
2016 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
2017 power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
2018 }
2019 rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2020 radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0);
2021 state_index++;
2022 break;
2023 case 2:
Alex Deucher560154e2010-11-22 17:56:34 -05002024 rdev->pm.power_state[state_index].clock_info[0].mclk =
2025 le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
2026 rdev->pm.power_state[state_index].clock_info[0].sclk =
2027 le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
2028 /* skip invalid modes */
2029 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
2030 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
2031 continue;
2032 rdev->pm.power_state[state_index].pcie_lanes =
2033 power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
2034 misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
2035 misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
2036 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
2037 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
2038 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2039 VOLTAGE_GPIO;
2040 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
2041 radeon_lookup_gpio(rdev,
2042 power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
2043 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
2044 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2045 true;
2046 else
2047 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2048 false;
2049 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
2050 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2051 VOLTAGE_VDDC;
2052 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
2053 power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
2054 }
2055 rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2056 radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
2057 state_index++;
2058 break;
2059 case 3:
Alex Deucher560154e2010-11-22 17:56:34 -05002060 rdev->pm.power_state[state_index].clock_info[0].mclk =
2061 le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
2062 rdev->pm.power_state[state_index].clock_info[0].sclk =
2063 le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
2064 /* skip invalid modes */
2065 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
2066 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
2067 continue;
2068 rdev->pm.power_state[state_index].pcie_lanes =
2069 power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
2070 misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
2071 misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
2072 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
2073 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
2074 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2075 VOLTAGE_GPIO;
2076 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
2077 radeon_lookup_gpio(rdev,
2078 power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
2079 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
2080 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2081 true;
2082 else
2083 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2084 false;
2085 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
2086 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
2087 VOLTAGE_VDDC;
2088 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
2089 power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
2090 if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
2091 rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
2092 true;
2093 rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
2094 power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
2095 }
2096 }
2097 rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2098 radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
2099 state_index++;
2100 break;
2101 }
2102 }
2103 /* last mode is usually default */
2104 if (rdev->pm.default_power_state_index == -1) {
2105 rdev->pm.power_state[state_index - 1].type =
2106 POWER_STATE_TYPE_DEFAULT;
2107 rdev->pm.default_power_state_index = state_index - 1;
2108 rdev->pm.power_state[state_index - 1].default_clock_mode =
2109 &rdev->pm.power_state[state_index - 1].clock_info[0];
2110 rdev->pm.power_state[state_index].flags &=
2111 ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2112 rdev->pm.power_state[state_index].misc = 0;
2113 rdev->pm.power_state[state_index].misc2 = 0;
2114 }
2115 return state_index;
2116}
2117
2118static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev,
2119 ATOM_PPLIB_THERMALCONTROLLER *controller)
2120{
2121 struct radeon_i2c_bus_rec i2c_bus;
2122
2123 /* add the i2c bus for thermal/fan chip */
2124 if (controller->ucType > 0) {
2125 if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
2126 DRM_INFO("Internal thermal controller %s fan control\n",
2127 (controller->ucFanParameters &
2128 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2129 rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
2130 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
2131 DRM_INFO("Internal thermal controller %s fan control\n",
2132 (controller->ucFanParameters &
2133 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2134 rdev->pm.int_thermal_type = THERMAL_TYPE_RV770;
2135 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
2136 DRM_INFO("Internal thermal controller %s fan control\n",
2137 (controller->ucFanParameters &
2138 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2139 rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
Alex Deucherb0e66412010-11-22 17:56:35 -05002140 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
2141 DRM_INFO("Internal thermal controller %s fan control\n",
2142 (controller->ucFanParameters &
2143 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2144 rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
Alex Deucher4fddba12011-01-06 21:19:22 -05002145 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
2146 DRM_INFO("Internal thermal controller %s fan control\n",
2147 (controller->ucFanParameters &
2148 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2149 rdev->pm.int_thermal_type = THERMAL_TYPE_NI;
Alex Deucher560154e2010-11-22 17:56:34 -05002150 } else if ((controller->ucType ==
2151 ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
2152 (controller->ucType ==
Alex Deucherb0e66412010-11-22 17:56:35 -05002153 ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) ||
2154 (controller->ucType ==
2155 ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) {
Alex Deucher560154e2010-11-22 17:56:34 -05002156 DRM_INFO("Special thermal controller config\n");
2157 } else {
2158 DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
2159 pp_lib_thermal_controller_names[controller->ucType],
2160 controller->ucI2cAddress >> 1,
2161 (controller->ucFanParameters &
2162 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
2163 i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
2164 rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
2165 if (rdev->pm.i2c_bus) {
2166 struct i2c_board_info info = { };
2167 const char *name = pp_lib_thermal_controller_names[controller->ucType];
2168 info.addr = controller->ucI2cAddress >> 1;
2169 strlcpy(info.type, name, sizeof(info.type));
2170 i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
2171 }
2172 }
2173 }
2174}
2175
Alex Deucher2feea492011-04-12 14:49:24 -04002176static void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
2177 u16 *vddc, u16 *vddci)
Alex Deucher560154e2010-11-22 17:56:34 -05002178{
2179 struct radeon_mode_info *mode_info = &rdev->mode_info;
2180 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
2181 u8 frev, crev;
2182 u16 data_offset;
2183 union firmware_info *firmware_info;
Alex Deucher2feea492011-04-12 14:49:24 -04002184
2185 *vddc = 0;
2186 *vddci = 0;
Alex Deucher560154e2010-11-22 17:56:34 -05002187
2188 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
2189 &frev, &crev, &data_offset)) {
2190 firmware_info =
2191 (union firmware_info *)(mode_info->atom_context->bios +
2192 data_offset);
Alex Deucher2feea492011-04-12 14:49:24 -04002193 *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
2194 if ((frev == 2) && (crev >= 2))
2195 *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
Alex Deucher560154e2010-11-22 17:56:34 -05002196 }
Alex Deucher560154e2010-11-22 17:56:34 -05002197}
2198
2199static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
2200 int state_index, int mode_index,
2201 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info)
2202{
2203 int j;
2204 u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
2205 u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
Alex Deucher2feea492011-04-12 14:49:24 -04002206 u16 vddc, vddci;
2207
2208 radeon_atombios_get_default_voltages(rdev, &vddc, &vddci);
Alex Deucher560154e2010-11-22 17:56:34 -05002209
2210 rdev->pm.power_state[state_index].misc = misc;
2211 rdev->pm.power_state[state_index].misc2 = misc2;
2212 rdev->pm.power_state[state_index].pcie_lanes =
2213 ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
2214 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
2215 switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
2216 case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
2217 rdev->pm.power_state[state_index].type =
2218 POWER_STATE_TYPE_BATTERY;
2219 break;
2220 case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
2221 rdev->pm.power_state[state_index].type =
2222 POWER_STATE_TYPE_BALANCED;
2223 break;
2224 case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
2225 rdev->pm.power_state[state_index].type =
2226 POWER_STATE_TYPE_PERFORMANCE;
2227 break;
2228 case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
2229 if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
2230 rdev->pm.power_state[state_index].type =
2231 POWER_STATE_TYPE_PERFORMANCE;
2232 break;
2233 }
2234 rdev->pm.power_state[state_index].flags = 0;
2235 if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
2236 rdev->pm.power_state[state_index].flags |=
2237 RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
2238 if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
2239 rdev->pm.power_state[state_index].type =
2240 POWER_STATE_TYPE_DEFAULT;
2241 rdev->pm.default_power_state_index = state_index;
2242 rdev->pm.power_state[state_index].default_clock_mode =
2243 &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
Alex Deucher8f3f1c92011-11-04 10:09:43 -04002244 if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
Alex Deucher9ace9f72011-01-06 21:19:26 -05002245 /* NI chips post without MC ucode, so default clocks are strobe mode only */
2246 rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
2247 rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
2248 rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage;
Alex Deucher2feea492011-04-12 14:49:24 -04002249 rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci;
Alex Deucher9ace9f72011-01-06 21:19:26 -05002250 } else {
2251 /* patch the table values with the default slck/mclk from firmware info */
2252 for (j = 0; j < mode_index; j++) {
2253 rdev->pm.power_state[state_index].clock_info[j].mclk =
2254 rdev->clock.default_mclk;
2255 rdev->pm.power_state[state_index].clock_info[j].sclk =
2256 rdev->clock.default_sclk;
2257 if (vddc)
2258 rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
2259 vddc;
2260 }
Alex Deucher560154e2010-11-22 17:56:34 -05002261 }
2262 }
2263}
2264
2265static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,
2266 int state_index, int mode_index,
2267 union pplib_clock_info *clock_info)
2268{
2269 u32 sclk, mclk;
2270
2271 if (rdev->flags & RADEON_IS_IGP) {
Alex Deucherb0e66412010-11-22 17:56:35 -05002272 if (rdev->family >= CHIP_PALM) {
2273 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
2274 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
2275 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2276 } else {
2277 sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow);
2278 sclk |= clock_info->rs780.ucLowEngineClockHigh << 16;
2279 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2280 }
Alex Deucher560154e2010-11-22 17:56:34 -05002281 } else if (ASIC_IS_DCE4(rdev)) {
2282 sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
2283 sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
2284 mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
2285 mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
2286 rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
2287 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2288 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
2289 VOLTAGE_SW;
2290 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
Cédric Cano45894332011-02-11 19:45:37 -05002291 le16_to_cpu(clock_info->evergreen.usVDDC);
Alex Deucher2feea492011-04-12 14:49:24 -04002292 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
2293 le16_to_cpu(clock_info->evergreen.usVDDCI);
Alex Deucher560154e2010-11-22 17:56:34 -05002294 } else {
2295 sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
2296 sclk |= clock_info->r600.ucEngineClockHigh << 16;
2297 mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow);
2298 mclk |= clock_info->r600.ucMemoryClockHigh << 16;
2299 rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
2300 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
2301 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
2302 VOLTAGE_SW;
2303 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
Cédric Cano45894332011-02-11 19:45:37 -05002304 le16_to_cpu(clock_info->r600.usVDDC);
Alex Deucher560154e2010-11-22 17:56:34 -05002305 }
2306
Alex Deucheree4017f2011-06-23 12:19:32 -04002307 /* patch up vddc if necessary */
2308 if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) {
2309 u16 vddc;
2310
2311 if (radeon_atom_get_max_vddc(rdev, &vddc) == 0)
2312 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc;
2313 }
2314
Alex Deucher560154e2010-11-22 17:56:34 -05002315 if (rdev->flags & RADEON_IS_IGP) {
2316 /* skip invalid modes */
2317 if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
2318 return false;
2319 } else {
2320 /* skip invalid modes */
2321 if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
2322 (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
2323 return false;
2324 }
2325 return true;
2326}
2327
2328static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
2329{
2330 struct radeon_mode_info *mode_info = &rdev->mode_info;
2331 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
2332 union pplib_power_state *power_state;
2333 int i, j;
2334 int state_index = 0, mode_index = 0;
2335 union pplib_clock_info *clock_info;
2336 bool valid;
2337 union power_info *power_info;
2338 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2339 u16 data_offset;
2340 u8 frev, crev;
2341
2342 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
2343 &frev, &crev, &data_offset))
2344 return state_index;
2345 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
2346
2347 radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
Alex Deucher0975b162011-02-02 18:42:03 -05002348 rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
2349 power_info->pplib.ucNumStates, GFP_KERNEL);
2350 if (!rdev->pm.power_state)
2351 return state_index;
Alex Deucher560154e2010-11-22 17:56:34 -05002352 /* first mode is usually default, followed by low to high */
2353 for (i = 0; i < power_info->pplib.ucNumStates; i++) {
2354 mode_index = 0;
2355 power_state = (union pplib_power_state *)
2356 (mode_info->atom_context->bios + data_offset +
2357 le16_to_cpu(power_info->pplib.usStateArrayOffset) +
2358 i * power_info->pplib.ucStateEntrySize);
2359 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
2360 (mode_info->atom_context->bios + data_offset +
2361 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
2362 (power_state->v1.ucNonClockStateIndex *
2363 power_info->pplib.ucNonClockSize));
Alex Deucher8f3f1c92011-11-04 10:09:43 -04002364 rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
2365 ((power_info->pplib.ucStateEntrySize - 1) ?
2366 (power_info->pplib.ucStateEntrySize - 1) : 1),
2367 GFP_KERNEL);
2368 if (!rdev->pm.power_state[i].clock_info)
2369 return state_index;
2370 if (power_info->pplib.ucStateEntrySize - 1) {
2371 for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
2372 clock_info = (union pplib_clock_info *)
2373 (mode_info->atom_context->bios + data_offset +
2374 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
2375 (power_state->v1.ucClockStateIndices[j] *
2376 power_info->pplib.ucClockInfoSize));
2377 valid = radeon_atombios_parse_pplib_clock_info(rdev,
2378 state_index, mode_index,
2379 clock_info);
2380 if (valid)
2381 mode_index++;
2382 }
2383 } else {
2384 rdev->pm.power_state[state_index].clock_info[0].mclk =
2385 rdev->clock.default_mclk;
2386 rdev->pm.power_state[state_index].clock_info[0].sclk =
2387 rdev->clock.default_sclk;
2388 mode_index++;
Alex Deucher560154e2010-11-22 17:56:34 -05002389 }
2390 rdev->pm.power_state[state_index].num_clock_modes = mode_index;
2391 if (mode_index) {
2392 radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
2393 non_clock_info);
2394 state_index++;
2395 }
2396 }
2397 /* if multiple clock modes, mark the lowest as no display */
2398 for (i = 0; i < state_index; i++) {
2399 if (rdev->pm.power_state[i].num_clock_modes > 1)
2400 rdev->pm.power_state[i].clock_info[0].flags |=
2401 RADEON_PM_MODE_NO_DISPLAY;
2402 }
2403 /* first mode is usually default */
2404 if (rdev->pm.default_power_state_index == -1) {
2405 rdev->pm.power_state[0].type =
2406 POWER_STATE_TYPE_DEFAULT;
2407 rdev->pm.default_power_state_index = 0;
2408 rdev->pm.power_state[0].default_clock_mode =
2409 &rdev->pm.power_state[0].clock_info[0];
2410 }
2411 return state_index;
2412}
2413
Alex Deucherb0e66412010-11-22 17:56:35 -05002414static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
2415{
2416 struct radeon_mode_info *mode_info = &rdev->mode_info;
2417 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
2418 union pplib_power_state *power_state;
2419 int i, j, non_clock_array_index, clock_array_index;
2420 int state_index = 0, mode_index = 0;
2421 union pplib_clock_info *clock_info;
2422 struct StateArray *state_array;
2423 struct ClockInfoArray *clock_info_array;
2424 struct NonClockInfoArray *non_clock_info_array;
2425 bool valid;
2426 union power_info *power_info;
2427 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2428 u16 data_offset;
2429 u8 frev, crev;
2430
2431 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
2432 &frev, &crev, &data_offset))
2433 return state_index;
2434 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
2435
2436 radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
2437 state_array = (struct StateArray *)
2438 (mode_info->atom_context->bios + data_offset +
Cédric Cano45894332011-02-11 19:45:37 -05002439 le16_to_cpu(power_info->pplib.usStateArrayOffset));
Alex Deucherb0e66412010-11-22 17:56:35 -05002440 clock_info_array = (struct ClockInfoArray *)
2441 (mode_info->atom_context->bios + data_offset +
Cédric Cano45894332011-02-11 19:45:37 -05002442 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
Alex Deucherb0e66412010-11-22 17:56:35 -05002443 non_clock_info_array = (struct NonClockInfoArray *)
2444 (mode_info->atom_context->bios + data_offset +
Cédric Cano45894332011-02-11 19:45:37 -05002445 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
Alex Deucher0975b162011-02-02 18:42:03 -05002446 rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
2447 state_array->ucNumEntries, GFP_KERNEL);
2448 if (!rdev->pm.power_state)
2449 return state_index;
Alex Deucherb0e66412010-11-22 17:56:35 -05002450 for (i = 0; i < state_array->ucNumEntries; i++) {
2451 mode_index = 0;
2452 power_state = (union pplib_power_state *)&state_array->states[i];
2453 /* XXX this might be an inagua bug... */
2454 non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
2455 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
2456 &non_clock_info_array->nonClockInfo[non_clock_array_index];
Alex Deucher8f3f1c92011-11-04 10:09:43 -04002457 rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
2458 (power_state->v2.ucNumDPMLevels ?
2459 power_state->v2.ucNumDPMLevels : 1),
2460 GFP_KERNEL);
2461 if (!rdev->pm.power_state[i].clock_info)
2462 return state_index;
2463 if (power_state->v2.ucNumDPMLevels) {
2464 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
2465 clock_array_index = power_state->v2.clockInfoIndex[j];
2466 /* XXX this might be an inagua bug... */
2467 if (clock_array_index >= clock_info_array->ucNumEntries)
2468 continue;
2469 clock_info = (union pplib_clock_info *)
2470 &clock_info_array->clockInfo[clock_array_index];
2471 valid = radeon_atombios_parse_pplib_clock_info(rdev,
2472 state_index, mode_index,
2473 clock_info);
2474 if (valid)
2475 mode_index++;
2476 }
2477 } else {
2478 rdev->pm.power_state[state_index].clock_info[0].mclk =
2479 rdev->clock.default_mclk;
2480 rdev->pm.power_state[state_index].clock_info[0].sclk =
2481 rdev->clock.default_sclk;
2482 mode_index++;
Alex Deucherb0e66412010-11-22 17:56:35 -05002483 }
2484 rdev->pm.power_state[state_index].num_clock_modes = mode_index;
2485 if (mode_index) {
2486 radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
2487 non_clock_info);
2488 state_index++;
2489 }
2490 }
2491 /* if multiple clock modes, mark the lowest as no display */
2492 for (i = 0; i < state_index; i++) {
2493 if (rdev->pm.power_state[i].num_clock_modes > 1)
2494 rdev->pm.power_state[i].clock_info[0].flags |=
2495 RADEON_PM_MODE_NO_DISPLAY;
2496 }
2497 /* first mode is usually default */
2498 if (rdev->pm.default_power_state_index == -1) {
2499 rdev->pm.power_state[0].type =
2500 POWER_STATE_TYPE_DEFAULT;
2501 rdev->pm.default_power_state_index = 0;
2502 rdev->pm.power_state[0].default_clock_mode =
2503 &rdev->pm.power_state[0].clock_info[0];
2504 }
2505 return state_index;
2506}
2507
Alex Deucher56278a82009-12-28 13:58:44 -05002508void radeon_atombios_get_power_modes(struct radeon_device *rdev)
2509{
2510 struct radeon_mode_info *mode_info = &rdev->mode_info;
2511 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2512 u16 data_offset;
2513 u8 frev, crev;
Alex Deucher560154e2010-11-22 17:56:34 -05002514 int state_index = 0;
Alex Deucher56278a82009-12-28 13:58:44 -05002515
Alex Deuchera48b9b42010-04-22 14:03:55 -04002516 rdev->pm.default_power_state_index = -1;
Alex Deucher56278a82009-12-28 13:58:44 -05002517
Alex Deuchera084e6e2010-03-18 01:04:01 -04002518 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
2519 &frev, &crev, &data_offset)) {
Alex Deucher560154e2010-11-22 17:56:34 -05002520 switch (frev) {
2521 case 1:
2522 case 2:
2523 case 3:
2524 state_index = radeon_atombios_parse_power_table_1_3(rdev);
2525 break;
2526 case 4:
2527 case 5:
2528 state_index = radeon_atombios_parse_power_table_4_5(rdev);
2529 break;
Alex Deucherb0e66412010-11-22 17:56:35 -05002530 case 6:
2531 state_index = radeon_atombios_parse_power_table_6(rdev);
2532 break;
Alex Deucher560154e2010-11-22 17:56:34 -05002533 default:
2534 break;
Alex Deucher56278a82009-12-28 13:58:44 -05002535 }
2536 } else {
Alex Deucher0975b162011-02-02 18:42:03 -05002537 rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
2538 if (rdev->pm.power_state) {
Alex Deucher8f3f1c92011-11-04 10:09:43 -04002539 rdev->pm.power_state[0].clock_info =
2540 kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
2541 if (rdev->pm.power_state[0].clock_info) {
2542 /* add the default mode */
2543 rdev->pm.power_state[state_index].type =
2544 POWER_STATE_TYPE_DEFAULT;
2545 rdev->pm.power_state[state_index].num_clock_modes = 1;
2546 rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
2547 rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
2548 rdev->pm.power_state[state_index].default_clock_mode =
2549 &rdev->pm.power_state[state_index].clock_info[0];
2550 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2551 rdev->pm.power_state[state_index].pcie_lanes = 16;
2552 rdev->pm.default_power_state_index = state_index;
2553 rdev->pm.power_state[state_index].flags = 0;
2554 state_index++;
2555 }
Alex Deucher0975b162011-02-02 18:42:03 -05002556 }
Alex Deucher56278a82009-12-28 13:58:44 -05002557 }
Alex Deucher02b17cc2010-04-22 13:25:06 -04002558
Alex Deucher56278a82009-12-28 13:58:44 -05002559 rdev->pm.num_power_states = state_index;
Rafał Miłecki9038dfd2010-02-20 23:15:04 +00002560
Alex Deuchera48b9b42010-04-22 14:03:55 -04002561 rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
2562 rdev->pm.current_clock_mode_index = 0;
Alex Deucher4d601732010-06-07 18:15:18 -04002563 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 -05002564}
2565
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002566void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
2567{
2568 DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
2569 int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating);
2570
2571 args.ucEnable = enable;
2572
2573 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2574}
2575
Rafał Miłecki74338742009-11-03 00:53:02 +01002576uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
2577{
2578 GET_ENGINE_CLOCK_PS_ALLOCATION args;
2579 int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
2580
2581 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
Cédric Cano45894332011-02-11 19:45:37 -05002582 return le32_to_cpu(args.ulReturnEngineClock);
Rafał Miłecki74338742009-11-03 00:53:02 +01002583}
2584
2585uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev)
2586{
2587 GET_MEMORY_CLOCK_PS_ALLOCATION args;
2588 int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
2589
2590 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
Cédric Cano45894332011-02-11 19:45:37 -05002591 return le32_to_cpu(args.ulReturnMemoryClock);
Rafał Miłecki74338742009-11-03 00:53:02 +01002592}
2593
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002594void radeon_atom_set_engine_clock(struct radeon_device *rdev,
2595 uint32_t eng_clock)
2596{
2597 SET_ENGINE_CLOCK_PS_ALLOCATION args;
2598 int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
2599
Cédric Cano45894332011-02-11 19:45:37 -05002600 args.ulTargetEngineClock = cpu_to_le32(eng_clock); /* 10 khz */
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002601
2602 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2603}
2604
2605void radeon_atom_set_memory_clock(struct radeon_device *rdev,
2606 uint32_t mem_clock)
2607{
2608 SET_MEMORY_CLOCK_PS_ALLOCATION args;
2609 int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);
2610
2611 if (rdev->flags & RADEON_IS_IGP)
2612 return;
2613
Cédric Cano45894332011-02-11 19:45:37 -05002614 args.ulTargetMemoryClock = cpu_to_le32(mem_clock); /* 10 khz */
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002615
2616 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2617}
2618
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002619union set_voltage {
2620 struct _SET_VOLTAGE_PS_ALLOCATION alloc;
2621 struct _SET_VOLTAGE_PARAMETERS v1;
2622 struct _SET_VOLTAGE_PARAMETERS_V2 v2;
2623};
2624
Alex Deucher8a83ec52011-04-12 14:49:23 -04002625void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type)
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002626{
2627 union set_voltage args;
2628 int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
Alex Deucher8a83ec52011-04-12 14:49:23 -04002629 u8 frev, crev, volt_index = voltage_level;
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002630
2631 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2632 return;
2633
Alex Deuchera377e182011-06-20 13:00:31 -04002634 /* 0xff01 is a flag rather then an actual voltage */
2635 if (voltage_level == 0xff01)
2636 return;
2637
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002638 switch (crev) {
2639 case 1:
Alex Deucher8a83ec52011-04-12 14:49:23 -04002640 args.v1.ucVoltageType = voltage_type;
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002641 args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
2642 args.v1.ucVoltageIndex = volt_index;
2643 break;
2644 case 2:
Alex Deucher8a83ec52011-04-12 14:49:23 -04002645 args.v2.ucVoltageType = voltage_type;
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002646 args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
Alex Deucher8a83ec52011-04-12 14:49:23 -04002647 args.v2.usVoltageLevel = cpu_to_le16(voltage_level);
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002648 break;
2649 default:
2650 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
2651 return;
2652 }
2653
2654 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2655}
2656
Alex Deucheree4017f2011-06-23 12:19:32 -04002657int radeon_atom_get_max_vddc(struct radeon_device *rdev,
2658 u16 *voltage)
2659{
2660 union set_voltage args;
2661 int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
2662 u8 frev, crev;
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002663
Alex Deucheree4017f2011-06-23 12:19:32 -04002664 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2665 return -EINVAL;
2666
2667 switch (crev) {
2668 case 1:
2669 return -EINVAL;
2670 case 2:
2671 args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE;
2672 args.v2.ucVoltageMode = 0;
2673 args.v2.usVoltageLevel = 0;
2674
2675 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2676
2677 *voltage = le16_to_cpu(args.v2.usVoltageLevel);
2678 break;
2679 default:
2680 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
2681 return -EINVAL;
2682 }
2683
2684 return 0;
2685}
Alex Deucher7ac9aa52010-05-27 19:25:54 -04002686
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002687void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
2688{
2689 struct radeon_device *rdev = dev->dev_private;
2690 uint32_t bios_2_scratch, bios_6_scratch;
2691
2692 if (rdev->family >= CHIP_R600) {
Dave Airlie4ce001a2009-08-13 16:32:14 +10002693 bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002694 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2695 } else {
Dave Airlie4ce001a2009-08-13 16:32:14 +10002696 bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002697 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2698 }
2699
2700 /* let the bios control the backlight */
2701 bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
2702
2703 /* tell the bios not to handle mode switching */
Alex Deucher87364762011-02-02 19:46:06 -05002704 bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002705
2706 if (rdev->family >= CHIP_R600) {
2707 WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
2708 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2709 } else {
2710 WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
2711 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2712 }
2713
2714}
2715
Yang Zhaof657c2a2009-09-15 12:21:01 +10002716void radeon_save_bios_scratch_regs(struct radeon_device *rdev)
2717{
2718 uint32_t scratch_reg;
2719 int i;
2720
2721 if (rdev->family >= CHIP_R600)
2722 scratch_reg = R600_BIOS_0_SCRATCH;
2723 else
2724 scratch_reg = RADEON_BIOS_0_SCRATCH;
2725
2726 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
2727 rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4));
2728}
2729
2730void radeon_restore_bios_scratch_regs(struct radeon_device *rdev)
2731{
2732 uint32_t scratch_reg;
2733 int i;
2734
2735 if (rdev->family >= CHIP_R600)
2736 scratch_reg = R600_BIOS_0_SCRATCH;
2737 else
2738 scratch_reg = RADEON_BIOS_0_SCRATCH;
2739
2740 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
2741 WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]);
2742}
2743
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002744void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
2745{
2746 struct drm_device *dev = encoder->dev;
2747 struct radeon_device *rdev = dev->dev_private;
2748 uint32_t bios_6_scratch;
2749
2750 if (rdev->family >= CHIP_R600)
2751 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2752 else
2753 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2754
Alex Deucher87364762011-02-02 19:46:06 -05002755 if (lock) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002756 bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
Alex Deucher87364762011-02-02 19:46:06 -05002757 bios_6_scratch &= ~ATOM_S6_ACC_MODE;
2758 } else {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002759 bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
Alex Deucher87364762011-02-02 19:46:06 -05002760 bios_6_scratch |= ATOM_S6_ACC_MODE;
2761 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002762
2763 if (rdev->family >= CHIP_R600)
2764 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2765 else
2766 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2767}
2768
2769/* at some point we may want to break this out into individual functions */
2770void
2771radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
2772 struct drm_encoder *encoder,
2773 bool connected)
2774{
2775 struct drm_device *dev = connector->dev;
2776 struct radeon_device *rdev = dev->dev_private;
2777 struct radeon_connector *radeon_connector =
2778 to_radeon_connector(connector);
2779 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2780 uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch;
2781
2782 if (rdev->family >= CHIP_R600) {
2783 bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
2784 bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
2785 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
2786 } else {
2787 bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
2788 bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
2789 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
2790 }
2791
2792 if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
2793 (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
2794 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002795 DRM_DEBUG_KMS("TV1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002796 bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
2797 bios_6_scratch |= ATOM_S6_ACC_REQ_TV1;
2798 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002799 DRM_DEBUG_KMS("TV1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002800 bios_0_scratch &= ~ATOM_S0_TV1_MASK;
2801 bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
2802 bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1;
2803 }
2804 }
2805 if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) &&
2806 (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) {
2807 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002808 DRM_DEBUG_KMS("CV connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002809 bios_3_scratch |= ATOM_S3_CV_ACTIVE;
2810 bios_6_scratch |= ATOM_S6_ACC_REQ_CV;
2811 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002812 DRM_DEBUG_KMS("CV disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002813 bios_0_scratch &= ~ATOM_S0_CV_MASK;
2814 bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
2815 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV;
2816 }
2817 }
2818 if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
2819 (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
2820 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002821 DRM_DEBUG_KMS("LCD1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002822 bios_0_scratch |= ATOM_S0_LCD1;
2823 bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
2824 bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1;
2825 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002826 DRM_DEBUG_KMS("LCD1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002827 bios_0_scratch &= ~ATOM_S0_LCD1;
2828 bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
2829 bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1;
2830 }
2831 }
2832 if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
2833 (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
2834 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002835 DRM_DEBUG_KMS("CRT1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002836 bios_0_scratch |= ATOM_S0_CRT1_COLOR;
2837 bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
2838 bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1;
2839 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002840 DRM_DEBUG_KMS("CRT1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002841 bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
2842 bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
2843 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1;
2844 }
2845 }
2846 if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
2847 (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
2848 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002849 DRM_DEBUG_KMS("CRT2 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002850 bios_0_scratch |= ATOM_S0_CRT2_COLOR;
2851 bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
2852 bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2;
2853 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002854 DRM_DEBUG_KMS("CRT2 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002855 bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
2856 bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
2857 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2;
2858 }
2859 }
2860 if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
2861 (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
2862 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002863 DRM_DEBUG_KMS("DFP1 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002864 bios_0_scratch |= ATOM_S0_DFP1;
2865 bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
2866 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1;
2867 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002868 DRM_DEBUG_KMS("DFP1 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002869 bios_0_scratch &= ~ATOM_S0_DFP1;
2870 bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
2871 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1;
2872 }
2873 }
2874 if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
2875 (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
2876 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002877 DRM_DEBUG_KMS("DFP2 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002878 bios_0_scratch |= ATOM_S0_DFP2;
2879 bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
2880 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2;
2881 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002882 DRM_DEBUG_KMS("DFP2 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002883 bios_0_scratch &= ~ATOM_S0_DFP2;
2884 bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
2885 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2;
2886 }
2887 }
2888 if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) &&
2889 (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) {
2890 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002891 DRM_DEBUG_KMS("DFP3 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002892 bios_0_scratch |= ATOM_S0_DFP3;
2893 bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
2894 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3;
2895 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002896 DRM_DEBUG_KMS("DFP3 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002897 bios_0_scratch &= ~ATOM_S0_DFP3;
2898 bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
2899 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3;
2900 }
2901 }
2902 if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) &&
2903 (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) {
2904 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002905 DRM_DEBUG_KMS("DFP4 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002906 bios_0_scratch |= ATOM_S0_DFP4;
2907 bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
2908 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4;
2909 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002910 DRM_DEBUG_KMS("DFP4 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002911 bios_0_scratch &= ~ATOM_S0_DFP4;
2912 bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
2913 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4;
2914 }
2915 }
2916 if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) &&
2917 (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) {
2918 if (connected) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002919 DRM_DEBUG_KMS("DFP5 connected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002920 bios_0_scratch |= ATOM_S0_DFP5;
2921 bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
2922 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5;
2923 } else {
Dave Airlied9fdaaf2010-08-02 10:42:55 +10002924 DRM_DEBUG_KMS("DFP5 disconnected\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +02002925 bios_0_scratch &= ~ATOM_S0_DFP5;
2926 bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
2927 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
2928 }
2929 }
2930
2931 if (rdev->family >= CHIP_R600) {
2932 WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
2933 WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
2934 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
2935 } else {
2936 WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
2937 WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
2938 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
2939 }
2940}
2941
2942void
2943radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
2944{
2945 struct drm_device *dev = encoder->dev;
2946 struct radeon_device *rdev = dev->dev_private;
2947 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
2948 uint32_t bios_3_scratch;
2949
2950 if (rdev->family >= CHIP_R600)
2951 bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
2952 else
2953 bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
2954
2955 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
2956 bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
2957 bios_3_scratch |= (crtc << 18);
2958 }
2959 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
2960 bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
2961 bios_3_scratch |= (crtc << 24);
2962 }
2963 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
2964 bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
2965 bios_3_scratch |= (crtc << 16);
2966 }
2967 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
2968 bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
2969 bios_3_scratch |= (crtc << 20);
2970 }
2971 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
2972 bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
2973 bios_3_scratch |= (crtc << 17);
2974 }
2975 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
2976 bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
2977 bios_3_scratch |= (crtc << 19);
2978 }
2979 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
2980 bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
2981 bios_3_scratch |= (crtc << 23);
2982 }
2983 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
2984 bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
2985 bios_3_scratch |= (crtc << 25);
2986 }
2987
2988 if (rdev->family >= CHIP_R600)
2989 WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
2990 else
2991 WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
2992}
2993
2994void
2995radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
2996{
2997 struct drm_device *dev = encoder->dev;
2998 struct radeon_device *rdev = dev->dev_private;
2999 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
3000 uint32_t bios_2_scratch;
3001
3002 if (rdev->family >= CHIP_R600)
3003 bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
3004 else
3005 bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
3006
3007 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
3008 if (on)
3009 bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
3010 else
3011 bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
3012 }
3013 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
3014 if (on)
3015 bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
3016 else
3017 bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
3018 }
3019 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
3020 if (on)
3021 bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
3022 else
3023 bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
3024 }
3025 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
3026 if (on)
3027 bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
3028 else
3029 bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
3030 }
3031 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
3032 if (on)
3033 bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
3034 else
3035 bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
3036 }
3037 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
3038 if (on)
3039 bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
3040 else
3041 bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
3042 }
3043 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
3044 if (on)
3045 bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
3046 else
3047 bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
3048 }
3049 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
3050 if (on)
3051 bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
3052 else
3053 bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
3054 }
3055 if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) {
3056 if (on)
3057 bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
3058 else
3059 bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
3060 }
3061 if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) {
3062 if (on)
3063 bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
3064 else
3065 bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
3066 }
3067
3068 if (rdev->family >= CHIP_R600)
3069 WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
3070 else
3071 WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
3072}