blob: de05ac9764725b175d3da128e965a3318aa554fe [file] [log] [blame]
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001/*
2 * Copyright 2007-8 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Dave Airlie
24 * Alex Deucher
25 */
26#include "drmP.h"
27#include "radeon_drm.h"
28#include "radeon.h"
29
30#include "atom.h"
31#include "atom-bits.h"
32
33/* from radeon_encoder.c */
34extern uint32_t
35radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device,
36 uint8_t dac);
37extern void radeon_link_encoder_connector(struct drm_device *dev);
38extern void
39radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id,
40 uint32_t supported_device);
41
42/* from radeon_connector.c */
43extern void
44radeon_add_atom_connector(struct drm_device *dev,
45 uint32_t connector_id,
46 uint32_t supported_device,
47 int connector_type,
48 struct radeon_i2c_bus_rec *i2c_bus,
Alex Deucherb75fad02009-11-05 13:16:01 -050049 bool linkb, uint32_t igp_lane_info,
Dave Airlie746c1aa2009-12-08 07:07:28 +100050 uint16_t connector_object_id, uint8_t uc_i2c_id);
Jerome Glisse771fe6b2009-06-05 14:42:42 +020051
52/* from radeon_legacy_encoder.c */
53extern void
54radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id,
55 uint32_t supported_device);
56
57union atom_supported_devices {
58 struct _ATOM_SUPPORTED_DEVICES_INFO info;
59 struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2;
60 struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
61};
62
Dave Airlie746c1aa2009-12-08 07:07:28 +100063static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *dev,
64 uint8_t id)
Jerome Glisse771fe6b2009-06-05 14:42:42 +020065{
66 struct radeon_device *rdev = dev->dev_private;
67 struct atom_context *ctx = rdev->mode_info.atom_context;
68 ATOM_GPIO_I2C_ASSIGMENT gpio;
69 struct radeon_i2c_bus_rec i2c;
70 int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
71 struct _ATOM_GPIO_I2C_INFO *i2c_info;
72 uint16_t data_offset;
73
74 memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
75 i2c.valid = false;
76
77 atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
78
79 i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
80
81 gpio = i2c_info->asGPIO_Info[id];
82
83 i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4;
84 i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4;
Alex Deucher9b9fe722009-11-10 15:59:44 -050085 i2c.en_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
86 i2c.en_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
87 i2c.y_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
88 i2c.y_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
Jerome Glisse771fe6b2009-06-05 14:42:42 +020089 i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4;
90 i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4;
91 i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
92 i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
Alex Deucher9b9fe722009-11-10 15:59:44 -050093 i2c.en_clk_mask = (1 << gpio.ucClkEnShift);
94 i2c.en_data_mask = (1 << gpio.ucDataEnShift);
95 i2c.y_clk_mask = (1 << gpio.ucClkY_Shift);
96 i2c.y_data_mask = (1 << gpio.ucDataY_Shift);
Jerome Glisse771fe6b2009-06-05 14:42:42 +020097 i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
98 i2c.a_data_mask = (1 << gpio.ucDataA_Shift);
99 i2c.valid = true;
100
101 return i2c;
102}
103
104static bool radeon_atom_apply_quirks(struct drm_device *dev,
105 uint32_t supported_device,
106 int *connector_type,
Alex Deucher848577e2009-07-08 16:15:30 -0400107 struct radeon_i2c_bus_rec *i2c_bus,
Alex Deucher705af9c2009-09-10 16:31:13 -0400108 uint16_t *line_mux)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200109{
110
111 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
112 if ((dev->pdev->device == 0x791e) &&
113 (dev->pdev->subsystem_vendor == 0x1043) &&
114 (dev->pdev->subsystem_device == 0x826d)) {
115 if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
116 (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
117 *connector_type = DRM_MODE_CONNECTOR_DVID;
118 }
119
120 /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
121 if ((dev->pdev->device == 0x7941) &&
122 (dev->pdev->subsystem_vendor == 0x147b) &&
123 (dev->pdev->subsystem_device == 0x2412)) {
124 if (*connector_type == DRM_MODE_CONNECTOR_DVII)
125 return false;
126 }
127
128 /* Falcon NW laptop lists vga ddc line for LVDS */
129 if ((dev->pdev->device == 0x5653) &&
130 (dev->pdev->subsystem_vendor == 0x1462) &&
131 (dev->pdev->subsystem_device == 0x0291)) {
Alex Deucher848577e2009-07-08 16:15:30 -0400132 if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200133 i2c_bus->valid = false;
Alex Deucher848577e2009-07-08 16:15:30 -0400134 *line_mux = 53;
135 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200136 }
137
Alex Deucher4e3f9b72009-12-01 14:49:50 -0500138 /* HIS X1300 is DVI+VGA, not DVI+DVI */
139 if ((dev->pdev->device == 0x7146) &&
140 (dev->pdev->subsystem_vendor == 0x17af) &&
141 (dev->pdev->subsystem_device == 0x2058)) {
142 if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
143 return false;
144 }
145
Dave Airlieaa1a7502009-12-04 11:51:34 +1000146 /* Gigabyte X1300 is DVI+VGA, not DVI+DVI */
147 if ((dev->pdev->device == 0x7142) &&
148 (dev->pdev->subsystem_vendor == 0x1458) &&
149 (dev->pdev->subsystem_device == 0x2134)) {
150 if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
151 return false;
152 }
153
154
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200155 /* Funky macbooks */
156 if ((dev->pdev->device == 0x71C5) &&
157 (dev->pdev->subsystem_vendor == 0x106b) &&
158 (dev->pdev->subsystem_device == 0x0080)) {
159 if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
160 (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
161 return false;
162 }
163
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200164 /* ASUS HD 3600 XT board lists the DVI port as HDMI */
165 if ((dev->pdev->device == 0x9598) &&
166 (dev->pdev->subsystem_vendor == 0x1043) &&
167 (dev->pdev->subsystem_device == 0x01da)) {
Alex Deucher705af9c2009-09-10 16:31:13 -0400168 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
Alex Deucherd42571e2009-09-11 15:27:14 -0400169 *connector_type = DRM_MODE_CONNECTOR_DVII;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200170 }
171 }
172
Alex Deucher705af9c2009-09-10 16:31:13 -0400173 /* ASUS HD 3450 board lists the DVI port as HDMI */
174 if ((dev->pdev->device == 0x95C5) &&
175 (dev->pdev->subsystem_vendor == 0x1043) &&
176 (dev->pdev->subsystem_device == 0x01e2)) {
177 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
Alex Deucherd42571e2009-09-11 15:27:14 -0400178 *connector_type = DRM_MODE_CONNECTOR_DVII;
Alex Deucher705af9c2009-09-10 16:31:13 -0400179 }
180 }
181
182 /* some BIOSes seem to report DAC on HDMI - usually this is a board with
183 * HDMI + VGA reporting as HDMI
184 */
185 if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
186 if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
187 *connector_type = DRM_MODE_CONNECTOR_VGA;
188 *line_mux = 0;
189 }
190 }
191
Alex Deucher3e5f8ff2009-11-17 17:12:10 -0500192 /* Acer laptop reports DVI-D as DVI-I */
193 if ((dev->pdev->device == 0x95c4) &&
194 (dev->pdev->subsystem_vendor == 0x1025) &&
195 (dev->pdev->subsystem_device == 0x013c)) {
196 if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
197 (supported_device == ATOM_DEVICE_DFP1_SUPPORT))
198 *connector_type = DRM_MODE_CONNECTOR_DVID;
199 }
200
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200201 return true;
202}
203
204const int supported_devices_connector_convert[] = {
205 DRM_MODE_CONNECTOR_Unknown,
206 DRM_MODE_CONNECTOR_VGA,
207 DRM_MODE_CONNECTOR_DVII,
208 DRM_MODE_CONNECTOR_DVID,
209 DRM_MODE_CONNECTOR_DVIA,
210 DRM_MODE_CONNECTOR_SVIDEO,
211 DRM_MODE_CONNECTOR_Composite,
212 DRM_MODE_CONNECTOR_LVDS,
213 DRM_MODE_CONNECTOR_Unknown,
214 DRM_MODE_CONNECTOR_Unknown,
215 DRM_MODE_CONNECTOR_HDMIA,
216 DRM_MODE_CONNECTOR_HDMIB,
217 DRM_MODE_CONNECTOR_Unknown,
218 DRM_MODE_CONNECTOR_Unknown,
219 DRM_MODE_CONNECTOR_9PinDIN,
220 DRM_MODE_CONNECTOR_DisplayPort
221};
222
Alex Deucherb75fad02009-11-05 13:16:01 -0500223const uint16_t supported_devices_connector_object_id_convert[] = {
224 CONNECTOR_OBJECT_ID_NONE,
225 CONNECTOR_OBJECT_ID_VGA,
226 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
227 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
228 CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
229 CONNECTOR_OBJECT_ID_COMPOSITE,
230 CONNECTOR_OBJECT_ID_SVIDEO,
231 CONNECTOR_OBJECT_ID_LVDS,
232 CONNECTOR_OBJECT_ID_9PIN_DIN,
233 CONNECTOR_OBJECT_ID_9PIN_DIN,
234 CONNECTOR_OBJECT_ID_DISPLAYPORT,
235 CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
236 CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
237 CONNECTOR_OBJECT_ID_SVIDEO
238};
239
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200240const int object_connector_convert[] = {
241 DRM_MODE_CONNECTOR_Unknown,
242 DRM_MODE_CONNECTOR_DVII,
243 DRM_MODE_CONNECTOR_DVII,
244 DRM_MODE_CONNECTOR_DVID,
245 DRM_MODE_CONNECTOR_DVID,
246 DRM_MODE_CONNECTOR_VGA,
247 DRM_MODE_CONNECTOR_Composite,
248 DRM_MODE_CONNECTOR_SVIDEO,
249 DRM_MODE_CONNECTOR_Unknown,
Alex Deucher705af9c2009-09-10 16:31:13 -0400250 DRM_MODE_CONNECTOR_Unknown,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200251 DRM_MODE_CONNECTOR_9PinDIN,
252 DRM_MODE_CONNECTOR_Unknown,
253 DRM_MODE_CONNECTOR_HDMIA,
254 DRM_MODE_CONNECTOR_HDMIB,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200255 DRM_MODE_CONNECTOR_LVDS,
256 DRM_MODE_CONNECTOR_9PinDIN,
257 DRM_MODE_CONNECTOR_Unknown,
258 DRM_MODE_CONNECTOR_Unknown,
259 DRM_MODE_CONNECTOR_Unknown,
260 DRM_MODE_CONNECTOR_DisplayPort
261};
262
263bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
264{
265 struct radeon_device *rdev = dev->dev_private;
266 struct radeon_mode_info *mode_info = &rdev->mode_info;
267 struct atom_context *ctx = mode_info->atom_context;
268 int index = GetIndexIntoMasterTable(DATA, Object_Header);
269 uint16_t size, data_offset;
270 uint8_t frev, crev, line_mux = 0;
271 ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
272 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
273 ATOM_OBJECT_HEADER *obj_header;
274 int i, j, path_size, device_support;
275 int connector_type;
Alex Deucherb75fad02009-11-05 13:16:01 -0500276 uint16_t igp_lane_info, conn_id, connector_object_id;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200277 bool linkb;
278 struct radeon_i2c_bus_rec ddc_bus;
Dave Airlie746c1aa2009-12-08 07:07:28 +1000279 ATOM_I2C_ID_CONFIG_ACCESS i2c_id;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200280 atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
281
282 if (data_offset == 0)
283 return false;
284
285 if (crev < 2)
286 return false;
287
288 obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
289 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
290 (ctx->bios + data_offset +
291 le16_to_cpu(obj_header->usDisplayPathTableOffset));
292 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
293 (ctx->bios + data_offset +
294 le16_to_cpu(obj_header->usConnectorObjectTableOffset));
295 device_support = le16_to_cpu(obj_header->usDeviceSupport);
296
297 path_size = 0;
298 for (i = 0; i < path_obj->ucNumOfDispPath; i++) {
299 uint8_t *addr = (uint8_t *) path_obj->asDispPath;
300 ATOM_DISPLAY_OBJECT_PATH *path;
301 addr += path_size;
302 path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
303 path_size += le16_to_cpu(path->usSize);
304 linkb = false;
Dave Airlie746c1aa2009-12-08 07:07:28 +1000305 i2c_id.ucAccess = 0;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200306 if (device_support & le16_to_cpu(path->usDeviceTag)) {
307 uint8_t con_obj_id, con_obj_num, con_obj_type;
308
309 con_obj_id =
310 (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
311 >> OBJECT_ID_SHIFT;
312 con_obj_num =
313 (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
314 >> ENUM_ID_SHIFT;
315 con_obj_type =
316 (le16_to_cpu(path->usConnObjectId) &
317 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
318
Dave Airlie4bbd4972009-09-25 08:56:12 +1000319 /* TODO CV support */
320 if (le16_to_cpu(path->usDeviceTag) ==
321 ATOM_DEVICE_CV_SUPPORT)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200322 continue;
323
Alex Deucheree59f2b2009-11-05 13:11:46 -0500324 /* IGP chips */
325 if ((rdev->flags & RADEON_IS_IGP) &&
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200326 (con_obj_id ==
327 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
328 uint16_t igp_offset = 0;
329 ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj;
330
331 index =
332 GetIndexIntoMasterTable(DATA,
333 IntegratedSystemInfo);
334
335 atom_parse_data_header(ctx, index, &size, &frev,
336 &crev, &igp_offset);
337
338 if (crev >= 2) {
339 igp_obj =
340 (ATOM_INTEGRATED_SYSTEM_INFO_V2
341 *) (ctx->bios + igp_offset);
342
343 if (igp_obj) {
344 uint32_t slot_config, ct;
345
346 if (con_obj_num == 1)
347 slot_config =
348 igp_obj->
349 ulDDISlot1Config;
350 else
351 slot_config =
352 igp_obj->
353 ulDDISlot2Config;
354
355 ct = (slot_config >> 16) & 0xff;
356 connector_type =
357 object_connector_convert
358 [ct];
Alex Deucherb75fad02009-11-05 13:16:01 -0500359 connector_object_id = ct;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200360 igp_lane_info =
361 slot_config & 0xffff;
362 } else
363 continue;
364 } else
365 continue;
366 } else {
367 igp_lane_info = 0;
368 connector_type =
369 object_connector_convert[con_obj_id];
Alex Deucherb75fad02009-11-05 13:16:01 -0500370 connector_object_id = con_obj_id;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200371 }
372
373 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
374 continue;
375
376 for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2);
377 j++) {
378 uint8_t enc_obj_id, enc_obj_num, enc_obj_type;
379
380 enc_obj_id =
381 (le16_to_cpu(path->usGraphicObjIds[j]) &
382 OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
383 enc_obj_num =
384 (le16_to_cpu(path->usGraphicObjIds[j]) &
385 ENUM_ID_MASK) >> ENUM_ID_SHIFT;
386 enc_obj_type =
387 (le16_to_cpu(path->usGraphicObjIds[j]) &
388 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
389
390 /* FIXME: add support for router objects */
391 if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
392 if (enc_obj_num == 2)
393 linkb = true;
394 else
395 linkb = false;
396
397 radeon_add_atom_encoder(dev,
398 enc_obj_id,
399 le16_to_cpu
400 (path->
401 usDeviceTag));
402
403 }
404 }
405
406 /* look up gpio for ddc */
407 if ((le16_to_cpu(path->usDeviceTag) &
408 (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
409 == 0) {
410 for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
411 if (le16_to_cpu(path->usConnObjectId) ==
412 le16_to_cpu(con_obj->asObjects[j].
413 usObjectID)) {
414 ATOM_COMMON_RECORD_HEADER
415 *record =
416 (ATOM_COMMON_RECORD_HEADER
417 *)
418 (ctx->bios + data_offset +
419 le16_to_cpu(con_obj->
420 asObjects[j].
421 usRecordOffset));
422 ATOM_I2C_RECORD *i2c_record;
Dave Airlie746c1aa2009-12-08 07:07:28 +1000423
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200424 while (record->ucRecordType > 0
425 && record->
426 ucRecordType <=
427 ATOM_MAX_OBJECT_RECORD_NUMBER) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200428 switch (record->
429 ucRecordType) {
430 case ATOM_I2C_RECORD_TYPE:
431 i2c_record =
432 (ATOM_I2C_RECORD
433 *) record;
Dave Airlie746c1aa2009-12-08 07:07:28 +1000434 i2c_id.sbfAccess = i2c_record->sucI2cId;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200435 line_mux =
436 i2c_record->
437 sucI2cId.
438 bfI2C_LineMux;
439 break;
440 }
441 record =
442 (ATOM_COMMON_RECORD_HEADER
443 *) ((char *)record
444 +
445 record->
446 ucRecordSize);
447 }
448 break;
449 }
450 }
451 } else
452 line_mux = 0;
453
454 if ((le16_to_cpu(path->usDeviceTag) ==
455 ATOM_DEVICE_TV1_SUPPORT)
456 || (le16_to_cpu(path->usDeviceTag) ==
457 ATOM_DEVICE_TV2_SUPPORT)
458 || (le16_to_cpu(path->usDeviceTag) ==
459 ATOM_DEVICE_CV_SUPPORT))
460 ddc_bus.valid = false;
461 else
462 ddc_bus = radeon_lookup_gpio(dev, line_mux);
463
Alex Deucher705af9c2009-09-10 16:31:13 -0400464 conn_id = le16_to_cpu(path->usConnObjectId);
465
466 if (!radeon_atom_apply_quirks
467 (dev, le16_to_cpu(path->usDeviceTag), &connector_type,
468 &ddc_bus, &conn_id))
469 continue;
470
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200471 radeon_add_atom_connector(dev,
Alex Deucher705af9c2009-09-10 16:31:13 -0400472 conn_id,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200473 le16_to_cpu(path->
474 usDeviceTag),
475 connector_type, &ddc_bus,
Alex Deucherb75fad02009-11-05 13:16:01 -0500476 linkb, igp_lane_info,
Dave Airlie746c1aa2009-12-08 07:07:28 +1000477 connector_object_id, i2c_id.ucAccess);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200478
479 }
480 }
481
482 radeon_link_encoder_connector(dev);
483
484 return true;
485}
486
Alex Deucherb75fad02009-11-05 13:16:01 -0500487static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
488 int connector_type,
489 uint16_t devices)
490{
491 struct radeon_device *rdev = dev->dev_private;
492
493 if (rdev->flags & RADEON_IS_IGP) {
494 return supported_devices_connector_object_id_convert
495 [connector_type];
496 } else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
497 (connector_type == DRM_MODE_CONNECTOR_DVID)) &&
498 (devices & ATOM_DEVICE_DFP2_SUPPORT)) {
499 struct radeon_mode_info *mode_info = &rdev->mode_info;
500 struct atom_context *ctx = mode_info->atom_context;
501 int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
502 uint16_t size, data_offset;
503 uint8_t frev, crev;
504 ATOM_XTMDS_INFO *xtmds;
505
506 atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
507 xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
508
509 if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
510 if (connector_type == DRM_MODE_CONNECTOR_DVII)
511 return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
512 else
513 return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
514 } else {
515 if (connector_type == DRM_MODE_CONNECTOR_DVII)
516 return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
517 else
518 return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
519 }
520 } else {
521 return supported_devices_connector_object_id_convert
522 [connector_type];
523 }
524}
525
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200526struct bios_connector {
527 bool valid;
Alex Deucher705af9c2009-09-10 16:31:13 -0400528 uint16_t line_mux;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200529 uint16_t devices;
530 int connector_type;
531 struct radeon_i2c_bus_rec ddc_bus;
532};
533
534bool radeon_get_atom_connector_info_from_supported_devices_table(struct
535 drm_device
536 *dev)
537{
538 struct radeon_device *rdev = dev->dev_private;
539 struct radeon_mode_info *mode_info = &rdev->mode_info;
540 struct atom_context *ctx = mode_info->atom_context;
541 int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo);
542 uint16_t size, data_offset;
543 uint8_t frev, crev;
544 uint16_t device_support;
545 uint8_t dac;
546 union atom_supported_devices *supported_devices;
547 int i, j;
548 struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
549
550 atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
551
552 supported_devices =
553 (union atom_supported_devices *)(ctx->bios + data_offset);
554
555 device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
556
557 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
558 ATOM_CONNECTOR_INFO_I2C ci =
559 supported_devices->info.asConnInfo[i];
560
561 bios_connectors[i].valid = false;
562
563 if (!(device_support & (1 << i))) {
564 continue;
565 }
566
567 if (i == ATOM_DEVICE_CV_INDEX) {
568 DRM_DEBUG("Skipping Component Video\n");
569 continue;
570 }
571
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200572 bios_connectors[i].connector_type =
573 supported_devices_connector_convert[ci.sucConnectorInfo.
574 sbfAccess.
575 bfConnectorType];
576
577 if (bios_connectors[i].connector_type ==
578 DRM_MODE_CONNECTOR_Unknown)
579 continue;
580
581 dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
582
583 if ((rdev->family == CHIP_RS690) ||
584 (rdev->family == CHIP_RS740)) {
585 if ((i == ATOM_DEVICE_DFP2_INDEX)
586 && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 2))
587 bios_connectors[i].line_mux =
588 ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1;
589 else if ((i == ATOM_DEVICE_DFP3_INDEX)
590 && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 1))
591 bios_connectors[i].line_mux =
592 ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1;
593 else
594 bios_connectors[i].line_mux =
595 ci.sucI2cId.sbfAccess.bfI2C_LineMux;
596 } else
597 bios_connectors[i].line_mux =
598 ci.sucI2cId.sbfAccess.bfI2C_LineMux;
599
600 /* give tv unique connector ids */
601 if (i == ATOM_DEVICE_TV1_INDEX) {
602 bios_connectors[i].ddc_bus.valid = false;
603 bios_connectors[i].line_mux = 50;
604 } else if (i == ATOM_DEVICE_TV2_INDEX) {
605 bios_connectors[i].ddc_bus.valid = false;
606 bios_connectors[i].line_mux = 51;
607 } else if (i == ATOM_DEVICE_CV_INDEX) {
608 bios_connectors[i].ddc_bus.valid = false;
609 bios_connectors[i].line_mux = 52;
610 } else
611 bios_connectors[i].ddc_bus =
612 radeon_lookup_gpio(dev,
613 bios_connectors[i].line_mux);
614
615 /* Always set the connector type to VGA for CRT1/CRT2. if they are
616 * shared with a DVI port, we'll pick up the DVI connector when we
617 * merge the outputs. Some bioses incorrectly list VGA ports as DVI.
618 */
619 if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX)
620 bios_connectors[i].connector_type =
621 DRM_MODE_CONNECTOR_VGA;
622
623 if (!radeon_atom_apply_quirks
624 (dev, (1 << i), &bios_connectors[i].connector_type,
Alex Deucher848577e2009-07-08 16:15:30 -0400625 &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200626 continue;
627
628 bios_connectors[i].valid = true;
629 bios_connectors[i].devices = (1 << i);
630
631 if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)
632 radeon_add_atom_encoder(dev,
633 radeon_get_encoder_id(dev,
634 (1 << i),
635 dac),
636 (1 << i));
637 else
638 radeon_add_legacy_encoder(dev,
639 radeon_get_encoder_id(dev,
640 (1 <<
641 i),
642 dac),
643 (1 << i));
644 }
645
646 /* combine shared connectors */
647 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
648 if (bios_connectors[i].valid) {
649 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) {
650 if (bios_connectors[j].valid && (i != j)) {
651 if (bios_connectors[i].line_mux ==
652 bios_connectors[j].line_mux) {
653 if (((bios_connectors[i].
654 devices &
655 (ATOM_DEVICE_DFP_SUPPORT))
656 && (bios_connectors[j].
657 devices &
658 (ATOM_DEVICE_CRT_SUPPORT)))
659 ||
660 ((bios_connectors[j].
661 devices &
662 (ATOM_DEVICE_DFP_SUPPORT))
663 && (bios_connectors[i].
664 devices &
665 (ATOM_DEVICE_CRT_SUPPORT)))) {
666 bios_connectors[i].
667 devices |=
668 bios_connectors[j].
669 devices;
670 bios_connectors[i].
671 connector_type =
672 DRM_MODE_CONNECTOR_DVII;
673 bios_connectors[j].
674 valid = false;
675 }
676 }
677 }
678 }
679 }
680 }
681
682 /* add the connectors */
683 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
Alex Deucherb75fad02009-11-05 13:16:01 -0500684 if (bios_connectors[i].valid) {
685 uint16_t connector_object_id =
686 atombios_get_connector_object_id(dev,
687 bios_connectors[i].connector_type,
688 bios_connectors[i].devices);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200689 radeon_add_atom_connector(dev,
690 bios_connectors[i].line_mux,
691 bios_connectors[i].devices,
692 bios_connectors[i].
693 connector_type,
694 &bios_connectors[i].ddc_bus,
Alex Deucherb75fad02009-11-05 13:16:01 -0500695 false, 0,
Dave Airlie746c1aa2009-12-08 07:07:28 +1000696 connector_object_id, 0);
Alex Deucherb75fad02009-11-05 13:16:01 -0500697 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200698 }
699
700 radeon_link_encoder_connector(dev);
701
702 return true;
703}
704
705union firmware_info {
706 ATOM_FIRMWARE_INFO info;
707 ATOM_FIRMWARE_INFO_V1_2 info_12;
708 ATOM_FIRMWARE_INFO_V1_3 info_13;
709 ATOM_FIRMWARE_INFO_V1_4 info_14;
710};
711
712bool radeon_atom_get_clock_info(struct drm_device *dev)
713{
714 struct radeon_device *rdev = dev->dev_private;
715 struct radeon_mode_info *mode_info = &rdev->mode_info;
716 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
717 union firmware_info *firmware_info;
718 uint8_t frev, crev;
719 struct radeon_pll *p1pll = &rdev->clock.p1pll;
720 struct radeon_pll *p2pll = &rdev->clock.p2pll;
721 struct radeon_pll *spll = &rdev->clock.spll;
722 struct radeon_pll *mpll = &rdev->clock.mpll;
723 uint16_t data_offset;
724
725 atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
726 &crev, &data_offset);
727
728 firmware_info =
729 (union firmware_info *)(mode_info->atom_context->bios +
730 data_offset);
731
732 if (firmware_info) {
733 /* pixel clocks */
734 p1pll->reference_freq =
735 le16_to_cpu(firmware_info->info.usReferenceClock);
736 p1pll->reference_div = 0;
737
Mathias Fröhlichbc293e52009-10-19 17:49:49 -0400738 if (crev < 2)
739 p1pll->pll_out_min =
740 le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
741 else
742 p1pll->pll_out_min =
743 le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200744 p1pll->pll_out_max =
745 le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
746
747 if (p1pll->pll_out_min == 0) {
748 if (ASIC_IS_AVIVO(rdev))
749 p1pll->pll_out_min = 64800;
750 else
751 p1pll->pll_out_min = 20000;
Alex Deucher8f552a62009-10-27 11:16:09 -0400752 } else if (p1pll->pll_out_min > 64800) {
753 /* Limiting the pll output range is a good thing generally as
754 * it limits the number of possible pll combinations for a given
755 * frequency presumably to the ones that work best on each card.
756 * However, certain duallink DVI monitors seem to like
757 * pll combinations that would be limited by this at least on
758 * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per
759 * family.
760 */
761 p1pll->pll_out_min = 64800;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200762 }
763
764 p1pll->pll_in_min =
765 le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
766 p1pll->pll_in_max =
767 le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);
768
769 *p2pll = *p1pll;
770
771 /* system clock */
772 spll->reference_freq =
773 le16_to_cpu(firmware_info->info.usReferenceClock);
774 spll->reference_div = 0;
775
776 spll->pll_out_min =
777 le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output);
778 spll->pll_out_max =
779 le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output);
780
781 /* ??? */
782 if (spll->pll_out_min == 0) {
783 if (ASIC_IS_AVIVO(rdev))
784 spll->pll_out_min = 64800;
785 else
786 spll->pll_out_min = 20000;
787 }
788
789 spll->pll_in_min =
790 le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input);
791 spll->pll_in_max =
792 le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);
793
794 /* memory clock */
795 mpll->reference_freq =
796 le16_to_cpu(firmware_info->info.usReferenceClock);
797 mpll->reference_div = 0;
798
799 mpll->pll_out_min =
800 le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output);
801 mpll->pll_out_max =
802 le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output);
803
804 /* ??? */
805 if (mpll->pll_out_min == 0) {
806 if (ASIC_IS_AVIVO(rdev))
807 mpll->pll_out_min = 64800;
808 else
809 mpll->pll_out_min = 20000;
810 }
811
812 mpll->pll_in_min =
813 le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input);
814 mpll->pll_in_max =
815 le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input);
816
817 rdev->clock.default_sclk =
818 le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
819 rdev->clock.default_mclk =
820 le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
821
822 return true;
823 }
824 return false;
825}
826
Dave Airlie445282d2009-09-09 17:40:54 +1000827bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
828 struct radeon_encoder_int_tmds *tmds)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200829{
830 struct drm_device *dev = encoder->base.dev;
831 struct radeon_device *rdev = dev->dev_private;
832 struct radeon_mode_info *mode_info = &rdev->mode_info;
833 int index = GetIndexIntoMasterTable(DATA, TMDS_Info);
834 uint16_t data_offset;
835 struct _ATOM_TMDS_INFO *tmds_info;
836 uint8_t frev, crev;
837 uint16_t maxfreq;
838 int i;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200839
840 atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
841 &crev, &data_offset);
842
843 tmds_info =
844 (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
845 data_offset);
846
847 if (tmds_info) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200848 maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
849 for (i = 0; i < 4; i++) {
850 tmds->tmds_pll[i].freq =
851 le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency);
852 tmds->tmds_pll[i].value =
853 tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f;
854 tmds->tmds_pll[i].value |=
855 (tmds_info->asMiscInfo[i].
856 ucPLL_VCO_Gain & 0x3f) << 6;
857 tmds->tmds_pll[i].value |=
858 (tmds_info->asMiscInfo[i].
859 ucPLL_DutyCycle & 0xf) << 12;
860 tmds->tmds_pll[i].value |=
861 (tmds_info->asMiscInfo[i].
862 ucPLL_VoltageSwing & 0xf) << 16;
863
864 DRM_DEBUG("TMDS PLL From ATOMBIOS %u %x\n",
865 tmds->tmds_pll[i].freq,
866 tmds->tmds_pll[i].value);
867
868 if (maxfreq == tmds->tmds_pll[i].freq) {
869 tmds->tmds_pll[i].freq = 0xffffffff;
870 break;
871 }
872 }
Dave Airlie445282d2009-09-09 17:40:54 +1000873 return true;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200874 }
Dave Airlie445282d2009-09-09 17:40:54 +1000875 return false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200876}
877
Alex Deucherebbe1cb2009-10-16 11:15:25 -0400878static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
879 radeon_encoder
880 *encoder,
881 int id)
882{
883 struct drm_device *dev = encoder->base.dev;
884 struct radeon_device *rdev = dev->dev_private;
885 struct radeon_mode_info *mode_info = &rdev->mode_info;
886 int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
887 uint16_t data_offset;
888 struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
889 uint8_t frev, crev;
890 struct radeon_atom_ss *ss = NULL;
891
892 if (id > ATOM_MAX_SS_ENTRY)
893 return NULL;
894
895 atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
896 &crev, &data_offset);
897
898 ss_info =
899 (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
900
901 if (ss_info) {
902 ss =
903 kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
904
905 if (!ss)
906 return NULL;
907
908 ss->percentage = le16_to_cpu(ss_info->asSS_Info[id].usSpreadSpectrumPercentage);
909 ss->type = ss_info->asSS_Info[id].ucSpreadSpectrumType;
910 ss->step = ss_info->asSS_Info[id].ucSS_Step;
911 ss->delay = ss_info->asSS_Info[id].ucSS_Delay;
912 ss->range = ss_info->asSS_Info[id].ucSS_Range;
913 ss->refdiv = ss_info->asSS_Info[id].ucRecommendedRef_Div;
914 }
915 return ss;
916}
917
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200918union lvds_info {
919 struct _ATOM_LVDS_INFO info;
920 struct _ATOM_LVDS_INFO_V12 info_12;
921};
922
923struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
924 radeon_encoder
925 *encoder)
926{
927 struct drm_device *dev = encoder->base.dev;
928 struct radeon_device *rdev = dev->dev_private;
929 struct radeon_mode_info *mode_info = &rdev->mode_info;
930 int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
Alex Deucher7dde8a12009-11-30 01:40:24 -0500931 uint16_t data_offset, misc;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200932 union lvds_info *lvds_info;
933 uint8_t frev, crev;
934 struct radeon_encoder_atom_dig *lvds = NULL;
935
936 atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
937 &crev, &data_offset);
938
939 lvds_info =
940 (union lvds_info *)(mode_info->atom_context->bios + data_offset);
941
942 if (lvds_info) {
943 lvds =
944 kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
945
946 if (!lvds)
947 return NULL;
948
Alex Deucherde2103e2009-10-09 15:14:30 -0400949 lvds->native_mode.clock =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200950 le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
Alex Deucherde2103e2009-10-09 15:14:30 -0400951 lvds->native_mode.hdisplay =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200952 le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
Alex Deucherde2103e2009-10-09 15:14:30 -0400953 lvds->native_mode.vdisplay =
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200954 le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
Alex Deucherde2103e2009-10-09 15:14:30 -0400955 lvds->native_mode.htotal = lvds->native_mode.hdisplay +
956 le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
957 lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
958 le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
959 lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
960 le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
961 lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
962 le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
963 lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
964 le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
965 lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
966 le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200967 lvds->panel_pwr_delay =
968 le16_to_cpu(lvds_info->info.usOffDelayInMs);
969 lvds->lvds_misc = lvds_info->info.ucLVDS_Misc;
Alex Deucher7dde8a12009-11-30 01:40:24 -0500970
971 misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess);
972 if (misc & ATOM_VSYNC_POLARITY)
973 lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC;
974 if (misc & ATOM_HSYNC_POLARITY)
975 lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC;
976 if (misc & ATOM_COMPOSITESYNC)
977 lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC;
978 if (misc & ATOM_INTERLACE)
979 lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE;
980 if (misc & ATOM_DOUBLE_CLOCK_MODE)
981 lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;
982
Alex Deucherde2103e2009-10-09 15:14:30 -0400983 /* set crtc values */
984 drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200985
Alex Deucherebbe1cb2009-10-16 11:15:25 -0400986 lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id);
987
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200988 encoder->native_mode = lvds->native_mode;
989 }
990 return lvds;
991}
992
Alex Deucher6fe7ac32009-06-12 17:26:08 +0000993struct radeon_encoder_primary_dac *
994radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
995{
996 struct drm_device *dev = encoder->base.dev;
997 struct radeon_device *rdev = dev->dev_private;
998 struct radeon_mode_info *mode_info = &rdev->mode_info;
999 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1000 uint16_t data_offset;
1001 struct _COMPASSIONATE_DATA *dac_info;
1002 uint8_t frev, crev;
1003 uint8_t bg, dac;
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001004 struct radeon_encoder_primary_dac *p_dac = NULL;
1005
1006 atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
1007
1008 dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
1009
1010 if (dac_info) {
1011 p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
1012
1013 if (!p_dac)
1014 return NULL;
1015
1016 bg = dac_info->ucDAC1_BG_Adjustment;
1017 dac = dac_info->ucDAC1_DAC_Adjustment;
1018 p_dac->ps2_pdac_adj = (bg << 8) | (dac);
1019
1020 }
1021 return p_dac;
1022}
1023
Dave Airlie4ce001a2009-08-13 16:32:14 +10001024bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001025 struct drm_display_mode *mode)
Dave Airlie4ce001a2009-08-13 16:32:14 +10001026{
1027 struct radeon_mode_info *mode_info = &rdev->mode_info;
1028 ATOM_ANALOG_TV_INFO *tv_info;
1029 ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
1030 ATOM_DTD_FORMAT *dtd_timings;
1031 int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
1032 u8 frev, crev;
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001033 u16 data_offset, misc;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001034
1035 atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
1036
1037 switch (crev) {
1038 case 1:
1039 tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
1040 if (index > MAX_SUPPORTED_TV_TIMING)
1041 return false;
1042
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001043 mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
1044 mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
1045 mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
1046 mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
1047 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001048
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001049 mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
1050 mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
1051 mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
1052 mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
1053 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001054
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001055 mode->flags = 0;
1056 misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
1057 if (misc & ATOM_VSYNC_POLARITY)
1058 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1059 if (misc & ATOM_HSYNC_POLARITY)
1060 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1061 if (misc & ATOM_COMPOSITESYNC)
1062 mode->flags |= DRM_MODE_FLAG_CSYNC;
1063 if (misc & ATOM_INTERLACE)
1064 mode->flags |= DRM_MODE_FLAG_INTERLACE;
1065 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1066 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001067
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001068 mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001069
1070 if (index == 1) {
1071 /* PAL timings appear to have wrong values for totals */
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001072 mode->crtc_htotal -= 1;
1073 mode->crtc_vtotal -= 1;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001074 }
1075 break;
1076 case 2:
1077 tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
1078 if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
1079 return false;
1080
1081 dtd_timings = &tv_info_v1_2->aModeTimings[index];
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001082 mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
1083 le16_to_cpu(dtd_timings->usHBlanking_Time);
1084 mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive);
1085 mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) +
1086 le16_to_cpu(dtd_timings->usHSyncOffset);
1087 mode->crtc_hsync_end = mode->crtc_hsync_start +
1088 le16_to_cpu(dtd_timings->usHSyncWidth);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001089
Alex Deucher5a9bcac2009-10-08 15:09:31 -04001090 mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) +
1091 le16_to_cpu(dtd_timings->usVBlanking_Time);
1092 mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive);
1093 mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) +
1094 le16_to_cpu(dtd_timings->usVSyncOffset);
1095 mode->crtc_vsync_end = mode->crtc_vsync_start +
1096 le16_to_cpu(dtd_timings->usVSyncWidth);
1097
1098 mode->flags = 0;
1099 misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
1100 if (misc & ATOM_VSYNC_POLARITY)
1101 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1102 if (misc & ATOM_HSYNC_POLARITY)
1103 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1104 if (misc & ATOM_COMPOSITESYNC)
1105 mode->flags |= DRM_MODE_FLAG_CSYNC;
1106 if (misc & ATOM_INTERLACE)
1107 mode->flags |= DRM_MODE_FLAG_INTERLACE;
1108 if (misc & ATOM_DOUBLE_CLOCK_MODE)
1109 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
1110
1111 mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001112 break;
1113 }
1114 return true;
1115}
1116
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001117struct radeon_encoder_tv_dac *
1118radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
1119{
1120 struct drm_device *dev = encoder->base.dev;
1121 struct radeon_device *rdev = dev->dev_private;
1122 struct radeon_mode_info *mode_info = &rdev->mode_info;
1123 int index = GetIndexIntoMasterTable(DATA, CompassionateData);
1124 uint16_t data_offset;
1125 struct _COMPASSIONATE_DATA *dac_info;
1126 uint8_t frev, crev;
1127 uint8_t bg, dac;
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001128 struct radeon_encoder_tv_dac *tv_dac = NULL;
1129
1130 atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
1131
1132 dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
1133
1134 if (dac_info) {
1135 tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
1136
1137 if (!tv_dac)
1138 return NULL;
1139
1140 bg = dac_info->ucDAC2_CRT2_BG_Adjustment;
1141 dac = dac_info->ucDAC2_CRT2_DAC_Adjustment;
1142 tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
1143
1144 bg = dac_info->ucDAC2_PAL_BG_Adjustment;
1145 dac = dac_info->ucDAC2_PAL_DAC_Adjustment;
1146 tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
1147
1148 bg = dac_info->ucDAC2_NTSC_BG_Adjustment;
1149 dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
1150 tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
1151
1152 }
1153 return tv_dac;
1154}
1155
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001156void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
1157{
1158 DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
1159 int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating);
1160
1161 args.ucEnable = enable;
1162
1163 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1164}
1165
1166void radeon_atom_static_pwrmgt_setup(struct radeon_device *rdev, int enable)
1167{
1168 ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION args;
1169 int index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt);
1170
1171 args.ucEnable = enable;
1172
1173 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1174}
1175
Rafał Miłecki74338742009-11-03 00:53:02 +01001176uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
1177{
1178 GET_ENGINE_CLOCK_PS_ALLOCATION args;
1179 int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
1180
1181 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1182 return args.ulReturnEngineClock;
1183}
1184
1185uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev)
1186{
1187 GET_MEMORY_CLOCK_PS_ALLOCATION args;
1188 int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
1189
1190 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1191 return args.ulReturnMemoryClock;
1192}
1193
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001194void radeon_atom_set_engine_clock(struct radeon_device *rdev,
1195 uint32_t eng_clock)
1196{
1197 SET_ENGINE_CLOCK_PS_ALLOCATION args;
1198 int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
1199
1200 args.ulTargetEngineClock = eng_clock; /* 10 khz */
1201
1202 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1203}
1204
1205void radeon_atom_set_memory_clock(struct radeon_device *rdev,
1206 uint32_t mem_clock)
1207{
1208 SET_MEMORY_CLOCK_PS_ALLOCATION args;
1209 int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);
1210
1211 if (rdev->flags & RADEON_IS_IGP)
1212 return;
1213
1214 args.ulTargetMemoryClock = mem_clock; /* 10 khz */
1215
1216 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1217}
1218
1219void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
1220{
1221 struct radeon_device *rdev = dev->dev_private;
1222 uint32_t bios_2_scratch, bios_6_scratch;
1223
1224 if (rdev->family >= CHIP_R600) {
Dave Airlie4ce001a2009-08-13 16:32:14 +10001225 bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001226 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
1227 } else {
Dave Airlie4ce001a2009-08-13 16:32:14 +10001228 bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001229 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
1230 }
1231
1232 /* let the bios control the backlight */
1233 bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
1234
1235 /* tell the bios not to handle mode switching */
1236 bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE);
1237
1238 if (rdev->family >= CHIP_R600) {
1239 WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
1240 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
1241 } else {
1242 WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
1243 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
1244 }
1245
1246}
1247
Yang Zhaof657c2a2009-09-15 12:21:01 +10001248void radeon_save_bios_scratch_regs(struct radeon_device *rdev)
1249{
1250 uint32_t scratch_reg;
1251 int i;
1252
1253 if (rdev->family >= CHIP_R600)
1254 scratch_reg = R600_BIOS_0_SCRATCH;
1255 else
1256 scratch_reg = RADEON_BIOS_0_SCRATCH;
1257
1258 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
1259 rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4));
1260}
1261
1262void radeon_restore_bios_scratch_regs(struct radeon_device *rdev)
1263{
1264 uint32_t scratch_reg;
1265 int i;
1266
1267 if (rdev->family >= CHIP_R600)
1268 scratch_reg = R600_BIOS_0_SCRATCH;
1269 else
1270 scratch_reg = RADEON_BIOS_0_SCRATCH;
1271
1272 for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
1273 WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]);
1274}
1275
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001276void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
1277{
1278 struct drm_device *dev = encoder->dev;
1279 struct radeon_device *rdev = dev->dev_private;
1280 uint32_t bios_6_scratch;
1281
1282 if (rdev->family >= CHIP_R600)
1283 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
1284 else
1285 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
1286
1287 if (lock)
1288 bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
1289 else
1290 bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
1291
1292 if (rdev->family >= CHIP_R600)
1293 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
1294 else
1295 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
1296}
1297
1298/* at some point we may want to break this out into individual functions */
1299void
1300radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
1301 struct drm_encoder *encoder,
1302 bool connected)
1303{
1304 struct drm_device *dev = connector->dev;
1305 struct radeon_device *rdev = dev->dev_private;
1306 struct radeon_connector *radeon_connector =
1307 to_radeon_connector(connector);
1308 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1309 uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch;
1310
1311 if (rdev->family >= CHIP_R600) {
1312 bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
1313 bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
1314 bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
1315 } else {
1316 bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
1317 bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
1318 bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
1319 }
1320
1321 if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
1322 (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
1323 if (connected) {
1324 DRM_DEBUG("TV1 connected\n");
1325 bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
1326 bios_6_scratch |= ATOM_S6_ACC_REQ_TV1;
1327 } else {
1328 DRM_DEBUG("TV1 disconnected\n");
1329 bios_0_scratch &= ~ATOM_S0_TV1_MASK;
1330 bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
1331 bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1;
1332 }
1333 }
1334 if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) &&
1335 (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) {
1336 if (connected) {
1337 DRM_DEBUG("CV connected\n");
1338 bios_3_scratch |= ATOM_S3_CV_ACTIVE;
1339 bios_6_scratch |= ATOM_S6_ACC_REQ_CV;
1340 } else {
1341 DRM_DEBUG("CV disconnected\n");
1342 bios_0_scratch &= ~ATOM_S0_CV_MASK;
1343 bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
1344 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV;
1345 }
1346 }
1347 if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
1348 (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
1349 if (connected) {
1350 DRM_DEBUG("LCD1 connected\n");
1351 bios_0_scratch |= ATOM_S0_LCD1;
1352 bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
1353 bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1;
1354 } else {
1355 DRM_DEBUG("LCD1 disconnected\n");
1356 bios_0_scratch &= ~ATOM_S0_LCD1;
1357 bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
1358 bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1;
1359 }
1360 }
1361 if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
1362 (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
1363 if (connected) {
1364 DRM_DEBUG("CRT1 connected\n");
1365 bios_0_scratch |= ATOM_S0_CRT1_COLOR;
1366 bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
1367 bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1;
1368 } else {
1369 DRM_DEBUG("CRT1 disconnected\n");
1370 bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
1371 bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
1372 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1;
1373 }
1374 }
1375 if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
1376 (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
1377 if (connected) {
1378 DRM_DEBUG("CRT2 connected\n");
1379 bios_0_scratch |= ATOM_S0_CRT2_COLOR;
1380 bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
1381 bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2;
1382 } else {
1383 DRM_DEBUG("CRT2 disconnected\n");
1384 bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
1385 bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
1386 bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2;
1387 }
1388 }
1389 if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
1390 (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
1391 if (connected) {
1392 DRM_DEBUG("DFP1 connected\n");
1393 bios_0_scratch |= ATOM_S0_DFP1;
1394 bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
1395 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1;
1396 } else {
1397 DRM_DEBUG("DFP1 disconnected\n");
1398 bios_0_scratch &= ~ATOM_S0_DFP1;
1399 bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
1400 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1;
1401 }
1402 }
1403 if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
1404 (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
1405 if (connected) {
1406 DRM_DEBUG("DFP2 connected\n");
1407 bios_0_scratch |= ATOM_S0_DFP2;
1408 bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
1409 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2;
1410 } else {
1411 DRM_DEBUG("DFP2 disconnected\n");
1412 bios_0_scratch &= ~ATOM_S0_DFP2;
1413 bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
1414 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2;
1415 }
1416 }
1417 if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) &&
1418 (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) {
1419 if (connected) {
1420 DRM_DEBUG("DFP3 connected\n");
1421 bios_0_scratch |= ATOM_S0_DFP3;
1422 bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
1423 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3;
1424 } else {
1425 DRM_DEBUG("DFP3 disconnected\n");
1426 bios_0_scratch &= ~ATOM_S0_DFP3;
1427 bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
1428 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3;
1429 }
1430 }
1431 if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) &&
1432 (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) {
1433 if (connected) {
1434 DRM_DEBUG("DFP4 connected\n");
1435 bios_0_scratch |= ATOM_S0_DFP4;
1436 bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
1437 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4;
1438 } else {
1439 DRM_DEBUG("DFP4 disconnected\n");
1440 bios_0_scratch &= ~ATOM_S0_DFP4;
1441 bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
1442 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4;
1443 }
1444 }
1445 if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) &&
1446 (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) {
1447 if (connected) {
1448 DRM_DEBUG("DFP5 connected\n");
1449 bios_0_scratch |= ATOM_S0_DFP5;
1450 bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
1451 bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5;
1452 } else {
1453 DRM_DEBUG("DFP5 disconnected\n");
1454 bios_0_scratch &= ~ATOM_S0_DFP5;
1455 bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
1456 bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
1457 }
1458 }
1459
1460 if (rdev->family >= CHIP_R600) {
1461 WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
1462 WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
1463 WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
1464 } else {
1465 WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
1466 WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
1467 WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
1468 }
1469}
1470
1471void
1472radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
1473{
1474 struct drm_device *dev = encoder->dev;
1475 struct radeon_device *rdev = dev->dev_private;
1476 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1477 uint32_t bios_3_scratch;
1478
1479 if (rdev->family >= CHIP_R600)
1480 bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
1481 else
1482 bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
1483
1484 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
1485 bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
1486 bios_3_scratch |= (crtc << 18);
1487 }
1488 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
1489 bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
1490 bios_3_scratch |= (crtc << 24);
1491 }
1492 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
1493 bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
1494 bios_3_scratch |= (crtc << 16);
1495 }
1496 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
1497 bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
1498 bios_3_scratch |= (crtc << 20);
1499 }
1500 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1501 bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
1502 bios_3_scratch |= (crtc << 17);
1503 }
1504 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
1505 bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
1506 bios_3_scratch |= (crtc << 19);
1507 }
1508 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
1509 bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
1510 bios_3_scratch |= (crtc << 23);
1511 }
1512 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
1513 bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
1514 bios_3_scratch |= (crtc << 25);
1515 }
1516
1517 if (rdev->family >= CHIP_R600)
1518 WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
1519 else
1520 WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
1521}
1522
1523void
1524radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
1525{
1526 struct drm_device *dev = encoder->dev;
1527 struct radeon_device *rdev = dev->dev_private;
1528 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1529 uint32_t bios_2_scratch;
1530
1531 if (rdev->family >= CHIP_R600)
1532 bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
1533 else
1534 bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
1535
1536 if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
1537 if (on)
1538 bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
1539 else
1540 bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
1541 }
1542 if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
1543 if (on)
1544 bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
1545 else
1546 bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
1547 }
1548 if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
1549 if (on)
1550 bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
1551 else
1552 bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
1553 }
1554 if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
1555 if (on)
1556 bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
1557 else
1558 bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
1559 }
1560 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1561 if (on)
1562 bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
1563 else
1564 bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
1565 }
1566 if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
1567 if (on)
1568 bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
1569 else
1570 bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
1571 }
1572 if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
1573 if (on)
1574 bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
1575 else
1576 bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
1577 }
1578 if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
1579 if (on)
1580 bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
1581 else
1582 bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
1583 }
1584 if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) {
1585 if (on)
1586 bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
1587 else
1588 bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
1589 }
1590 if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) {
1591 if (on)
1592 bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
1593 else
1594 bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
1595 }
1596
1597 if (rdev->family >= CHIP_R600)
1598 WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
1599 else
1600 WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
1601}