1 /*
2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Alexander von Gluck, kallisti5@unixzen.com
7 */
8
9
10 #include "encoder.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <math.h>
16
17 #include "accelerant.h"
18 #include "accelerant_protos.h"
19 #include "atombios-obsolete.h"
20 #include "bios.h"
21 #include "connector.h"
22 #include "display.h"
23 #include "displayport.h"
24 #include "utility.h"
25
26
27 #define TRACE_ENCODER
28 #ifdef TRACE_ENCODER
29 extern "C" void _sPrintf(const char* format, ...);
30 # define TRACE(x...) _sPrintf("radeon_hd: " x)
31 #else
32 # define TRACE(x...) ;
33 #endif
34
35 #define ERROR(x...) _sPrintf("radeon_hd: " x)
36
37
38 static uint32
encoder_get_bpc()39 encoder_get_bpc()
40 {
41 /*
42 switch (8) {
43 case 0:
44 return PANEL_BPC_UNDEFINE;
45 case 6:
46 return PANEL_6BIT_PER_COLOR;
47 case 8:
48 return PANEL_8BIT_PER_COLOR;
49 case 10:
50 return PANEL_10BIT_PER_COLOR;
51 case 12:
52 return PANEL_12BIT_PER_COLOR;
53 case 16:
54 return PANEL_16BIT_PER_COLOR;
55 }
56 */
57 return PANEL_8BIT_PER_COLOR;
58 }
59
60
61 void
encoder_init()62 encoder_init()
63 {
64 TRACE("%s: called\n", __func__);
65 radeon_shared_info &info = *gInfo->shared_info;
66
67 for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) {
68 if (gConnector[id]->valid == false)
69 continue;
70
71 switch (gConnector[id]->encoder.objectID) {
72 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
73 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
74 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
75 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
76 transmitter_dig_setup(id, 0, 0, 0,
77 ATOM_TRANSMITTER_ACTION_INIT);
78 break;
79 default:
80 break;
81 }
82
83 if ((info.chipsetFlags & CHIP_APU) != 0) {
84 if (gConnector[id]->encoderExternal.valid == true) {
85 encoder_external_setup(id,
86 EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
87 }
88 }
89 }
90 }
91
92
93 void
encoder_assign_crtc(uint8 crtcID)94 encoder_assign_crtc(uint8 crtcID)
95 {
96 TRACE("%s\n", __func__);
97
98 int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
99
100 // Table version
101 uint8 tableMajor;
102 uint8 tableMinor;
103 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
104 != B_OK)
105 return;
106
107 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
108 tableMajor, tableMinor);
109
110 uint16 connectorIndex = gDisplay[crtcID]->connectorIndex;
111 uint16 connectorFlags = gConnector[connectorIndex]->flags;
112 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
113
114 // Prepare AtomBIOS command arguments
115 union crtcSourceParam {
116 SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
117 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
118 SELECT_CRTC_SOURCE_PARAMETERS_V3 v3;
119 };
120 union crtcSourceParam args;
121 memset(&args, 0, sizeof(args));
122
123 switch (tableMajor) {
124 case 1:
125 switch (tableMinor) {
126 case 1:
127 default:
128 args.v1.ucCRTC = crtcID;
129 switch (encoderID) {
130 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
131 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
132 args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
133 break;
134 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
135 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
136 if ((gConnector[connectorIndex]->flags
137 & ATOM_DEVICE_LCD1_SUPPORT) != 0)
138 args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
139 else
140 args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
141 break;
142 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
143 case ENCODER_OBJECT_ID_INTERNAL_DDI:
144 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
145 args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
146 break;
147 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
148 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
149 if ((connectorFlags
150 & ATOM_DEVICE_TV_SUPPORT) != 0) {
151 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
152 } else if ((connectorFlags
153 & ATOM_DEVICE_CV_SUPPORT) != 0) {
154 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
155 } else
156 args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
157 break;
158 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
159 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
160 if ((connectorFlags
161 & ATOM_DEVICE_TV_SUPPORT) != 0) {
162 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
163 } else if ((connectorFlags
164 & ATOM_DEVICE_CV_SUPPORT) != 0) {
165 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
166 } else
167 args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
168 break;
169 }
170 break;
171 case 2:
172 args.v2.ucCRTC = crtcID;
173 args.v2.ucEncodeMode
174 = display_get_encoder_mode(connectorIndex);
175 switch (encoderID) {
176 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
177 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
178 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
179 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
180 switch (encoder_pick_dig(connectorIndex)) {
181 case 0:
182 args.v2.ucEncoderID
183 = ASIC_INT_DIG1_ENCODER_ID;
184 break;
185 case 1:
186 args.v2.ucEncoderID
187 = ASIC_INT_DIG2_ENCODER_ID;
188 break;
189 case 2:
190 args.v2.ucEncoderID
191 = ASIC_INT_DIG3_ENCODER_ID;
192 break;
193 case 3:
194 args.v2.ucEncoderID
195 = ASIC_INT_DIG4_ENCODER_ID;
196 break;
197 case 4:
198 args.v2.ucEncoderID
199 = ASIC_INT_DIG5_ENCODER_ID;
200 break;
201 case 5:
202 args.v2.ucEncoderID
203 = ASIC_INT_DIG6_ENCODER_ID;
204 break;
205 }
206 break;
207 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
208 args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
209 break;
210 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
211 if ((connectorFlags
212 & ATOM_DEVICE_TV_SUPPORT) != 0) {
213 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
214 } else if ((connectorFlags
215 & ATOM_DEVICE_CV_SUPPORT) != 0) {
216 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
217 } else
218 args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
219 break;
220 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
221 if ((connectorFlags
222 & ATOM_DEVICE_TV_SUPPORT) != 0) {
223 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
224 } else if ((connectorFlags
225 & ATOM_DEVICE_CV_SUPPORT) != 0) {
226 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
227 } else
228 args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
229 break;
230 }
231 break;
232 case 3:
233 args.v3.ucCRTC = crtcID;
234 // TODO: Better bridge logic
235 args.v2.ucEncodeMode
236 = display_get_encoder_mode(connectorIndex);
237 args.v3.ucDstBpc = encoder_get_bpc();
238 switch (encoderID) {
239 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
240 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
241 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
242 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
243 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
244 switch (encoder_pick_dig(connectorIndex)) {
245 case 0:
246 args.v3.ucEncoderID
247 = ASIC_INT_DIG1_ENCODER_ID;
248 break;
249 case 1:
250 args.v3.ucEncoderID
251 = ASIC_INT_DIG2_ENCODER_ID;
252 break;
253 case 2:
254 args.v3.ucEncoderID
255 = ASIC_INT_DIG3_ENCODER_ID;
256 break;
257 case 3:
258 args.v3.ucEncoderID
259 = ASIC_INT_DIG4_ENCODER_ID;
260 break;
261 case 4:
262 args.v3.ucEncoderID
263 = ASIC_INT_DIG5_ENCODER_ID;
264 break;
265 case 5:
266 args.v3.ucEncoderID
267 = ASIC_INT_DIG6_ENCODER_ID;
268 break;
269 case 6:
270 args.v3.ucEncoderID
271 = ASIC_INT_DIG7_ENCODER_ID;
272 break;
273 }
274 break;
275 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
276 args.v3.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
277 break;
278 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
279 if ((connectorFlags
280 & ATOM_DEVICE_TV_SUPPORT) != 0) {
281 args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
282 } else if ((connectorFlags
283 & ATOM_DEVICE_CV_SUPPORT) != 0) {
284 args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
285 } else
286 args.v3.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
287 break;
288 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
289 if ((connectorFlags
290 & ATOM_DEVICE_TV_SUPPORT) != 0) {
291 args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
292 } else if ((connectorFlags
293 & ATOM_DEVICE_CV_SUPPORT) != 0) {
294 args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
295 } else
296 args.v3.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
297 break;
298 }
299 break;
300 }
301 break;
302 default:
303 ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
304 __func__, tableMajor, tableMinor);
305 return;
306 }
307
308 atom_execute_table(gAtomContext, index, (uint32*)&args);
309
310 // update crtc encoder scratch register @ scratch 3
311 encoder_crtc_scratch(crtcID);
312 }
313
314
315 uint32
encoder_pick_dig(uint32 connectorIndex)316 encoder_pick_dig(uint32 connectorIndex)
317 {
318 TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
319 radeon_shared_info &info = *gInfo->shared_info;
320 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
321
322 // obtain assigned CRT
323 uint32 crtcID;
324 for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) {
325 if (gDisplay[crtcID]->attached != true)
326 continue;
327 if (gDisplay[crtcID]->connectorIndex == connectorIndex)
328 break;
329 }
330
331 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
332 == GRAPH_OBJECT_ENUM_ID2 ? true : false;
333
334 uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor;
335
336 if (dceVersion >= 400) {
337 // APU
338 switch (info.chipsetID) {
339 case RADEON_PALM:
340 return linkB ? 1 : 0;
341 case RADEON_SUMO:
342 case RADEON_SUMO2:
343 return crtcID;
344 }
345
346 switch (encoderID) {
347 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
348 return linkB ? 1 : 0;
349 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
350 return linkB ? 3 : 2;
351 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
352 return linkB ? 5 : 4;
353 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
354 return 6;
355 }
356 }
357
358 if (dceVersion >= 302)
359 return crtcID;
360
361 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA)
362 return 1;
363
364 return 0;
365 }
366
367
368 void
encoder_apply_quirks(uint8 crtcID)369 encoder_apply_quirks(uint8 crtcID)
370 {
371 TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
372 radeon_shared_info &info = *gInfo->shared_info;
373 register_info* regs = gDisplay[crtcID]->regs;
374 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
375 uint16 connectorFlags = gConnector[connectorIndex]->flags;
376
377 // Setting the scaler clears this on some chips...
378 if (info.dceMajor >= 3
379 && (connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0) {
380 // TODO: assume non interleave mode for now
381 // en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN
382 Write32(OUT, regs->modeDataFormat, 0);
383 }
384 }
385
386
387 void
encoder_mode_set(uint8 crtcID)388 encoder_mode_set(uint8 crtcID)
389 {
390 TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
391 radeon_shared_info &info = *gInfo->shared_info;
392 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
393 uint16 connectorFlags = gConnector[connectorIndex]->flags;
394 pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
395
396 // TODO: Should this be the adjusted pll or the original?
397 uint32 pixelClock = pll->pixelClock;
398
399 switch (gConnector[connectorIndex]->encoder.objectID) {
400 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
401 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
402 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
403 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
404 encoder_analog_setup(connectorIndex, pixelClock, ATOM_ENABLE);
405 if (info.dceMajor < 5) {
406 // TV encoder was dropped in DCE 5
407 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0
408 || (connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
409 encoder_tv_setup(connectorIndex, pixelClock, ATOM_ENABLE);
410 } else {
411 encoder_tv_setup(connectorIndex, pixelClock, ATOM_DISABLE);
412 }
413 }
414 break;
415 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
416 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
417 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
418 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
419 encoder_digital_setup(connectorIndex, pixelClock,
420 PANEL_ENCODER_ACTION_ENABLE);
421 break;
422 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
423 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
424 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
425 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
426 if ((info.chipsetFlags & CHIP_APU) != 0
427 || info.dceMajor >= 5) {
428 // Setup DIG encoder
429 encoder_dig_setup(connectorIndex, pixelClock,
430 ATOM_ENCODER_CMD_SETUP);
431 encoder_dig_setup(connectorIndex, pixelClock,
432 ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
433 } else if (info.dceMajor >= 4) {
434 // Disable DIG transmitter
435 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
436 ATOM_TRANSMITTER_ACTION_DISABLE);
437 // Setup DIG encoder
438 encoder_dig_setup(connectorIndex, pixelClock,
439 ATOM_ENCODER_CMD_SETUP);
440 // Enable DIG transmitter
441 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
442 ATOM_TRANSMITTER_ACTION_ENABLE);
443 } else {
444 // Disable DIG transmitter
445 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
446 ATOM_TRANSMITTER_ACTION_DISABLE);
447 // Disable DIG encoder
448 encoder_dig_setup(connectorIndex, pixelClock, ATOM_DISABLE);
449 // Enable the DIG encoder
450 encoder_dig_setup(connectorIndex, pixelClock, ATOM_ENABLE);
451
452 // Setup and enable DIG transmitter
453 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
454 ATOM_TRANSMITTER_ACTION_SETUP);
455 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
456 ATOM_TRANSMITTER_ACTION_ENABLE);
457 }
458 break;
459 case ENCODER_OBJECT_ID_INTERNAL_DDI:
460 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
461 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
462 TRACE("%s: TODO for DVO encoder setup\n", __func__);
463 break;
464 }
465
466 if (gConnector[connectorIndex]->encoderExternal.valid == true) {
467 if ((info.chipsetFlags & CHIP_APU) != 0) {
468 // aka DCE 4.1
469 encoder_external_setup(connectorIndex,
470 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
471 } else
472 encoder_external_setup(connectorIndex, ATOM_ENABLE);
473
474 }
475
476 encoder_apply_quirks(crtcID);
477 }
478
479
480 status_t
encoder_tv_setup(uint32 connectorIndex,uint32 pixelClock,int command)481 encoder_tv_setup(uint32 connectorIndex, uint32 pixelClock, int command)
482 {
483 TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
484 connectorIndex, pixelClock);
485
486 uint16 connectorFlags = gConnector[connectorIndex]->flags;
487
488 TV_ENCODER_CONTROL_PS_ALLOCATION args;
489 memset(&args, 0, sizeof(args));
490
491 int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
492
493 args.sTVEncoder.ucAction = command;
494
495 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
496 args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
497 else {
498 // TODO: we assume NTSC for now
499 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
500 }
501
502 args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
503
504 return atom_execute_table(gAtomContext, index, (uint32*)&args);
505 }
506
507
508 status_t
encoder_digital_setup(uint32 connectorIndex,uint32 pixelClock,int command)509 encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command)
510 {
511 TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
512 connectorIndex, pixelClock);
513
514 int index = 0;
515 uint16 connectorFlags = gConnector[connectorIndex]->flags;
516
517 switch (gConnector[connectorIndex]->encoder.objectID) {
518 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
519 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
520 break;
521 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
522 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
523 index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
524 break;
525 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
526 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
527 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
528 else
529 index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
530 break;
531 }
532
533 // Table verson
534 uint8 tableMajor;
535 uint8 tableMinor;
536
537 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
538 != B_OK) {
539 ERROR("%s: cannot parse command table\n", __func__);
540 return B_ERROR;
541 }
542
543 uint32 lvdsFlags = gConnector[connectorIndex]->lvdsFlags;
544
545 bool isHdmi = false;
546 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIA
547 || gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIB) {
548 isHdmi = true;
549 }
550
551 // Prepare AtomBIOS command arguments
552 union lvdsEncoderControl {
553 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1;
554 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
555 };
556 union lvdsEncoderControl args;
557 memset(&args, 0, sizeof(args));
558
559 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
560 tableMajor, tableMinor);
561
562 switch (tableMajor) {
563 case 1:
564 case 2:
565 switch (tableMinor) {
566 case 1:
567 args.v1.ucMisc = 0;
568 args.v1.ucAction = command;
569 if (isHdmi)
570 args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
571 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
572
573 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
574 if ((lvdsFlags & ATOM_PANEL_MISC_DUAL) != 0)
575 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
576 if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0)
577 args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
578 } else {
579 //if (dig->linkb)
580 // args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
581 if (pixelClock > 165000)
582 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
583 /*if (pScrn->rgbBits == 8) */
584 args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
585 }
586 break;
587 case 2:
588 case 3:
589 args.v2.ucMisc = 0;
590 args.v2.ucAction = command;
591 if (tableMinor == 3) {
592 //if (dig->coherent_mode)
593 // args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
594 }
595 if (isHdmi)
596 args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
597 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
598 args.v2.ucTruncate = 0;
599 args.v2.ucSpatial = 0;
600 args.v2.ucTemporal = 0;
601 args.v2.ucFRC = 0;
602 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
603 if ((lvdsFlags & ATOM_PANEL_MISC_DUAL) != 0)
604 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
605 if ((lvdsFlags & ATOM_PANEL_MISC_SPATIAL) != 0) {
606 args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
607 if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0) {
608 args.v2.ucSpatial
609 |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
610 }
611 }
612
613 if ((lvdsFlags & ATOM_PANEL_MISC_TEMPORAL) != 0) {
614 args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
615 if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0) {
616 args.v2.ucTemporal
617 |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
618 }
619 if (((lvdsFlags >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT)
620 & 0x3) == 2) {
621 args.v2.ucTemporal
622 |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
623 }
624 }
625 } else {
626 //if (dig->linkb)
627 // args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
628 if (pixelClock > 165000)
629 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
630 }
631 break;
632 default:
633 ERROR("%s: Unknown minor table version: %"
634 B_PRIu8 ".%" B_PRIu8 "\n", __func__,
635 tableMajor, tableMinor);
636 return B_ERROR;
637 }
638 break;
639 default:
640 ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
641 __func__, tableMajor, tableMinor);
642 return B_ERROR;
643 }
644 return atom_execute_table(gAtomContext, index, (uint32*)&args);
645 }
646
647
648 status_t
encoder_dig_setup(uint32 connectorIndex,uint32 pixelClock,int command)649 encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command)
650 {
651 TRACE("%s\n", __func__);
652
653 radeon_shared_info &info = *gInfo->shared_info;
654 connector_info* connector = gConnector[connectorIndex];
655
656 int index = 0;
657 if (info.dceMajor >= 4)
658 index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
659 else {
660 if (encoder_pick_dig(connectorIndex))
661 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
662 else
663 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
664 }
665
666 // Table verson
667 uint8 tableMajor;
668 uint8 tableMinor;
669
670 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
671 != B_OK) {
672 ERROR("%s: cannot parse command table\n", __func__);
673 return B_ERROR;
674 }
675
676 // Prepare AtomBIOS command arguments
677 union digEncoderControl {
678 DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
679 DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
680 DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
681 DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
682 DIG_ENCODER_CONTROL_PARAMETERS_V5 v5;
683 };
684 union digEncoderControl args;
685 memset(&args, 0, sizeof(args));
686
687 bool isDPBridge = connector->encoderExternal.isDPBridge;
688 bool linkB = connector->encoder.linkEnumeration
689 == GRAPH_OBJECT_ENUM_ID2 ? true : false;
690 uint32 digEncoderID = encoder_pick_dig(connectorIndex);
691
692 uint32 panelMode = 0;
693 // determine DP panel mode if doing panel mode setup
694 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) {
695 if (info.dceMajor >= 4 && isDPBridge) {
696 if (connector->encoderExternal.objectID == ENCODER_OBJECT_ID_NUTMEG)
697 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
698 else if (connector->encoderExternal.objectID
699 == ENCODER_OBJECT_ID_TRAVIS) {
700 dp_info* dp = &gConnector[connectorIndex]->dpInfo;
701 uint8 id[6];
702 int bit;
703 for (bit = 0; bit < 6; bit++)
704 id[bit] = dpcd_reg_read(dp->auxPin, 0x503 + bit);
705 if (id[0] == 0x73 && id[1] == 0x69 && id[2] == 0x76
706 && id[3] == 0x61 && id[4] == 0x72 && id[5] == 0x54) {
707 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
708 } else {
709 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
710 }
711 } else {
712 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
713 }
714 } else
715 panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
716 }
717
718 #if 0
719 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
720 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) {
721 uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP);
722 if ((temp & 1) != 0)
723 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
724 }
725 #endif
726
727 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
728 tableMajor, tableMinor);
729
730 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
731 uint32 dpClock = 0;
732 if (dpInfo->valid == true)
733 dpClock = dpInfo->linkRate;
734
735 bool dualLink = false;
736 if (connector->type == VIDEO_CONNECTOR_DVID
737 && pixelClock > 165000) {
738 // TODO: Expand on this duallink code
739 dualLink = true;
740 }
741
742 uint32 encoderMode = display_get_encoder_mode(connectorIndex);
743
744 // Careful! The mapping of ucHPD_ID differs between atombios calls
745 uint16 hpdID = connector_pick_atom_hpdid(connectorIndex);
746
747 if (tableMajor != 1) {
748 ERROR("%s: Unknown table major!\n", __func__);
749 }
750
751 switch (tableMinor) {
752 case 1:
753 args.v1.ucAction = command;
754 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
755
756 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
757 args.v3.ucPanelMode = panelMode;
758 else {
759 args.v1.ucEncoderMode = encoderMode;
760 }
761
762 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
763 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
764 args.v1.ucLaneNum = dpInfo->laneCount;
765 } else if (dualLink)
766 args.v1.ucLaneNum = 8;
767 else
768 args.v1.ucLaneNum = 4;
769
770 if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
771 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
772 && dpClock == 270000) {
773 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
774 }
775
776 switch (connector->encoder.objectID) {
777 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
778 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
779 break;
780 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
781 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
782 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
783 break;
784 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
785 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
786 break;
787 }
788
789 if (linkB)
790 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
791 else
792 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
793 break;
794 case 2:
795 case 3:
796 args.v3.ucAction = command;
797 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
798
799 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
800 args.v3.ucPanelMode = panelMode;
801 else
802 args.v3.ucEncoderMode = encoderMode;
803
804 if (args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
805 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
806 args.v3.ucLaneNum = dpInfo->laneCount;
807 } else if (dualLink)
808 args.v3.ucLaneNum = 8;
809 else
810 args.v3.ucLaneNum = 4;
811
812 if ((args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
813 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
814 && dpClock == 270000) {
815 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
816 }
817
818 args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex);
819 args.v3.ucBitPerColor = encoder_get_bpc();
820 break;
821 case 4:
822 args.v4.ucAction = command;
823 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
824
825 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
826 args.v4.ucPanelMode = panelMode;
827 else
828 args.v4.ucEncoderMode = encoderMode;
829
830 if (args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP
831 || args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
832 // Is DP?
833 args.v4.ucLaneNum = dpInfo->laneCount;
834 if (dpClock == 270000) {
835 args.v4.ucConfig
836 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
837 } else if (dpClock == 540000) {
838 args.v4.ucConfig
839 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
840 }
841 } else if (dualLink) {
842 // DualLink, double the lane numbers
843 args.v4.ucLaneNum = 8;
844 } else {
845 args.v4.ucLaneNum = 4;
846 }
847 args.v4.acConfig.ucDigSel = digEncoderID;
848 args.v4.ucBitPerColor = encoder_get_bpc();
849
850 if (hpdID == 0xff)
851 args.v4.ucHPD_ID = 0;
852 else
853 args.v4.ucHPD_ID = hpdID + 1;
854 break;
855 case 5:
856 switch(command) {
857 case ATOM_ENCODER_CMD_SETUP_PANEL_MODE:
858 args.v5.asDPPanelModeParam.ucAction = command;
859 args.v5.asDPPanelModeParam.ucPanelMode = panelMode;
860 args.v5.asDPPanelModeParam.ucDigId = digEncoderID;
861 break;
862 case ATOM_ENCODER_CMD_STREAM_SETUP:
863 args.v5.asStreamParam.ucAction = command;
864 args.v5.asStreamParam.ucDigId = digEncoderID;
865 args.v5.asStreamParam.ucDigMode = encoderMode;
866 if (encoderMode == ATOM_ENCODER_MODE_DP
867 || encoderMode == ATOM_ENCODER_MODE_DP_MST) {
868 args.v5.asStreamParam.ucLaneNum = dpInfo->laneCount;
869 } else if (dualLink)
870 args.v5.asStreamParam.ucLaneNum = 8;
871 else
872 args.v5.asStreamParam.ucLaneNum = 4;
873 args.v5.asStreamParam.ulPixelClock
874 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
875 args.v5.asStreamParam.ucBitPerColor = encoder_get_bpc();
876 args.v5.asStreamParam.ucLinkRateIn270Mhz = dpClock / 27000;
877 break;
878 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_START:
879 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1:
880 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2:
881 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3:
882 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN4:
883 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE:
884 case ATOM_ENCODER_CMD_DP_VIDEO_OFF:
885 case ATOM_ENCODER_CMD_DP_VIDEO_ON:
886 args.v5.asCmdParam.ucAction = command;
887 args.v5.asCmdParam.ucDigId = digEncoderID;
888 break;
889 default:
890 ERROR("%s: Unknown command: 0x%X\n", __func__, command);
891 }
892 break;
893 default:
894 ERROR("%s: unknown tableMinor!\n", __func__);
895 return B_ERROR;
896 }
897
898 status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
899
900 #if 0
901 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP
902 && panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) {
903 dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1);
904 }
905 #endif
906
907 return result;
908 }
909
910
911 status_t
encoder_external_setup(uint32 connectorIndex,int command)912 encoder_external_setup(uint32 connectorIndex, int command)
913 {
914 TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
915
916 encoder_info* encoder
917 = &gConnector[connectorIndex]->encoder;
918 encoder_info* extEncoder
919 = &gConnector[connectorIndex]->encoderExternal;
920 uint32 connectorFlags = gConnector[connectorIndex]->flags;
921
922 dp_info* dpInfo
923 = &gConnector[connectorIndex]->dpInfo;
924
925 if (extEncoder->valid != true) {
926 ERROR("%s: connector %" B_PRIu32 " doesn't have a valid "
927 "external encoder!", __func__, connectorIndex);
928 return B_ERROR;
929 }
930
931 uint8 tableMajor;
932 uint8 tableMinor;
933
934 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
935 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
936 != B_OK) {
937 ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__);
938 return B_ERROR;
939 }
940
941 // Prepare AtomBIOS command arguments
942 union externalEncoderControl {
943 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
944 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
945 };
946 union externalEncoderControl args;
947 memset(&args, 0, sizeof(args));
948
949 int connectorObjectID
950 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
951 >> OBJECT_ID_SHIFT;
952
953 uint32 pixelClock = encoder->pll.pixelClock;
954
955 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
956 tableMajor, tableMinor);
957 switch (tableMajor) {
958 case 1:
959 // no options needed on table 1.x
960 break;
961 case 2:
962 switch (tableMinor) {
963 case 1:
964 case 2:
965 args.v1.sDigEncoder.ucAction = command;
966 args.v1.sDigEncoder.usPixelClock
967 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
968 args.v1.sDigEncoder.ucEncoderMode
969 = display_get_encoder_mode(connectorIndex);
970
971 if (connector_is_dp(connectorIndex)) {
972 if (dpInfo->linkRate == 270000) {
973 args.v1.sDigEncoder.ucConfig
974 |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
975 }
976 args.v1.sDigEncoder.ucLaneNum
977 = dpInfo->laneCount;
978 } else if (pixelClock > 165000) {
979 args.v1.sDigEncoder.ucLaneNum = 8;
980 } else {
981 args.v1.sDigEncoder.ucLaneNum = 4;
982 }
983 break;
984 case 3:
985 {
986 args.v3.sExtEncoder.ucAction = command;
987 if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) {
988 args.v3.sExtEncoder.usConnectorId
989 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
990 } else {
991 args.v3.sExtEncoder.usPixelClock
992 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
993 }
994
995 args.v3.sExtEncoder.ucEncoderMode
996 = display_get_encoder_mode(connectorIndex);
997
998 if (connector_is_dp(connectorIndex)) {
999 if (dpInfo->linkRate == 270000) {
1000 args.v3.sExtEncoder.ucConfig
1001 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1002 } else if (dpInfo->linkRate == 540000) {
1003 args.v3.sExtEncoder.ucConfig
1004 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1005 }
1006 args.v1.sDigEncoder.ucLaneNum
1007 = dpInfo->laneCount;
1008 } else if (pixelClock > 165000) {
1009 args.v3.sExtEncoder.ucLaneNum = 8;
1010 } else {
1011 args.v3.sExtEncoder.ucLaneNum = 4;
1012 }
1013
1014 switch ((connectorFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) {
1015 case GRAPH_OBJECT_ENUM_ID1:
1016 TRACE("%s: external encoder 1\n", __func__);
1017 args.v3.sExtEncoder.ucConfig
1018 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1019 break;
1020 case GRAPH_OBJECT_ENUM_ID2:
1021 TRACE("%s: external encoder 2\n", __func__);
1022 args.v3.sExtEncoder.ucConfig
1023 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1024 break;
1025 case GRAPH_OBJECT_ENUM_ID3:
1026 TRACE("%s: external encoder 3\n", __func__);
1027 args.v3.sExtEncoder.ucConfig
1028 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1029 break;
1030 }
1031
1032 // TODO: don't set statically
1033 uint32 bitsPerColor = 8;
1034 switch (bitsPerColor) {
1035 case 0:
1036 args.v3.sExtEncoder.ucBitPerColor
1037 = PANEL_BPC_UNDEFINE;
1038 break;
1039 case 6:
1040 args.v3.sExtEncoder.ucBitPerColor
1041 = PANEL_6BIT_PER_COLOR;
1042 break;
1043 case 8:
1044 default:
1045 args.v3.sExtEncoder.ucBitPerColor
1046 = PANEL_8BIT_PER_COLOR;
1047 break;
1048 case 10:
1049 args.v3.sExtEncoder.ucBitPerColor
1050 = PANEL_10BIT_PER_COLOR;
1051 break;
1052 case 12:
1053 args.v3.sExtEncoder.ucBitPerColor
1054 = PANEL_12BIT_PER_COLOR;
1055 break;
1056 case 16:
1057 args.v3.sExtEncoder.ucBitPerColor
1058 = PANEL_16BIT_PER_COLOR;
1059 break;
1060 }
1061 break;
1062 }
1063 default:
1064 ERROR("%s: Unknown table minor version: "
1065 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1066 tableMajor, tableMinor);
1067 return B_ERROR;
1068 }
1069 break;
1070 default:
1071 ERROR("%s: Unknown table major version: "
1072 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1073 tableMajor, tableMinor);
1074 return B_ERROR;
1075 }
1076
1077 return atom_execute_table(gAtomContext, index, (uint32*)&args);
1078 }
1079
1080
1081 status_t
encoder_analog_setup(uint32 connectorIndex,uint32 pixelClock,int command)1082 encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command)
1083 {
1084 TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
1085 connectorIndex, pixelClock);
1086
1087 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1088
1089 int index = 0;
1090 DAC_ENCODER_CONTROL_PS_ALLOCATION args;
1091 memset(&args, 0, sizeof(args));
1092
1093 switch (gConnector[connectorIndex]->encoder.objectID) {
1094 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1095 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1096 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
1097 break;
1098 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1099 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1100 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
1101 break;
1102 }
1103
1104 args.ucAction = command;
1105
1106 if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
1107 args.ucDacStandard = ATOM_DAC1_PS2;
1108 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1109 args.ucDacStandard = ATOM_DAC1_CV;
1110 else {
1111 TRACE("%s: TODO, hardcoded NTSC TV support\n", __func__);
1112 if (1) {
1113 // NTSC, NTSC_J, PAL 60
1114 args.ucDacStandard = ATOM_DAC1_NTSC;
1115 } else {
1116 // PAL, SCART. SECAM, PAL_CN
1117 args.ucDacStandard = ATOM_DAC1_PAL;
1118 }
1119 }
1120
1121 args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1122
1123 return atom_execute_table(gAtomContext, index, (uint32*)&args);
1124 }
1125
1126
1127 bool
encoder_analog_load_detect(uint32 connectorIndex)1128 encoder_analog_load_detect(uint32 connectorIndex)
1129 {
1130 TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
1131
1132 if (gConnector[connectorIndex]->encoderExternal.valid == true)
1133 return encoder_dig_load_detect(connectorIndex);
1134
1135 return encoder_dac_load_detect(connectorIndex);
1136 }
1137
1138
1139 bool
encoder_dac_load_detect(uint32 connectorIndex)1140 encoder_dac_load_detect(uint32 connectorIndex)
1141 {
1142 TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
1143
1144 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1145 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
1146
1147 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0
1148 && (connectorFlags & ATOM_DEVICE_CV_SUPPORT) == 0
1149 && (connectorFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) {
1150 ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n",
1151 __func__, connectorIndex);
1152 return false;
1153 }
1154
1155 // *** tell the card we want to do a DAC detection
1156
1157 DAC_LOAD_DETECTION_PS_ALLOCATION args;
1158 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1159 uint8 tableMajor;
1160 uint8 tableMinor;
1161
1162 memset(&args, 0, sizeof(args));
1163
1164 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1165 != B_OK) {
1166 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n",
1167 __func__);
1168 return false;
1169 }
1170
1171 args.sDacload.ucMisc = 0;
1172
1173 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1
1174 || encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) {
1175 args.sDacload.ucDacType = ATOM_DAC_A;
1176 } else {
1177 args.sDacload.ucDacType = ATOM_DAC_B;
1178 }
1179
1180 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1181 args.sDacload.usDeviceID
1182 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT);
1183 atom_execute_table(gAtomContext, index, (uint32*)&args);
1184
1185 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1186
1187 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1188 return true;
1189
1190 } else if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1191 args.sDacload.usDeviceID
1192 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT);
1193 atom_execute_table(gAtomContext, index, (uint32*)&args);
1194
1195 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1196
1197 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1198 return true;
1199
1200 } else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1201 args.sDacload.usDeviceID
1202 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT);
1203 if (tableMinor >= 3)
1204 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1205 atom_execute_table(gAtomContext, index, (uint32*)&args);
1206
1207 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1208
1209 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1210 return true;
1211
1212 } else if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1213 args.sDacload.usDeviceID
1214 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT);
1215 if (tableMinor >= 3)
1216 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1217 atom_execute_table(gAtomContext, index, (uint32*)&args);
1218
1219 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1220
1221 if ((biosScratch0
1222 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) {
1223 return true; /* Composite connected */
1224 } else if ((biosScratch0
1225 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) {
1226 return true; /* S-Video connected */
1227 }
1228
1229 }
1230 return false;
1231 }
1232
1233
1234 bool
encoder_dig_load_detect(uint32 connectorIndex)1235 encoder_dig_load_detect(uint32 connectorIndex)
1236 {
1237 TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
1238 radeon_shared_info &info = *gInfo->shared_info;
1239
1240 if (info.dceMajor < 4) {
1241 ERROR("%s: Strange: External DIG encoder on DCE < 4?\n", __func__);
1242 return false;
1243 }
1244
1245 encoder_external_setup(connectorIndex,
1246 EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
1247
1248 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1249
1250 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1251
1252 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0)
1253 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1254 return true;
1255 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0)
1256 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1257 return true;
1258 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1259 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1260 return true;
1261 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1262 if ((biosScratch0
1263 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0)
1264 return true; /* Composite connected */
1265 else if ((biosScratch0
1266 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0)
1267 return true; /* S-Video connected */
1268 }
1269
1270 return false;
1271 }
1272
1273
1274 status_t
transmitter_dig_setup(uint32 connectorIndex,uint32 pixelClock,uint8 laneNumber,uint8 laneSet,int command)1275 transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
1276 uint8 laneNumber, uint8 laneSet, int command)
1277 {
1278 TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
1279 connectorIndex, pixelClock);
1280
1281 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1282 int index;
1283 switch (encoderID) {
1284 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1285 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1286 break;
1287 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1288 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1289 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1290 index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1291 break;
1292 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1293 index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
1294 break;
1295 default:
1296 ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__);
1297 return B_ERROR;
1298 }
1299
1300 if (index < 0) {
1301 ERROR("%s: GetIndexIntoMasterTable failed!\n", __func__);
1302 return B_ERROR;
1303 }
1304
1305 uint8 tableMajor;
1306 uint8 tableMinor;
1307
1308 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1309 != B_OK)
1310 return B_ERROR;
1311
1312 // Prepare AtomBIOS arguments
1313 union digTransmitterControl {
1314 DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
1315 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
1316 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
1317 DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
1318 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
1319 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 v6;
1320 };
1321 union digTransmitterControl args;
1322 memset(&args, 0, sizeof(args));
1323
1324 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1325 tableMajor, tableMinor);
1326
1327 int connectorObjectID
1328 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
1329 >> OBJECT_ID_SHIFT;
1330 uint32 encoderObjectID = gConnector[connectorIndex]->encoder.objectID;
1331 uint32 digEncoderID = encoder_pick_dig(connectorIndex);
1332
1333 pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
1334
1335 // Careful! The mapping of ucHPD_ID differs between atombios calls
1336 uint16 hpdID = connector_pick_atom_hpdid(connectorIndex);
1337
1338 bool isDP = connector_is_dp(connectorIndex);
1339 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
1340 == GRAPH_OBJECT_ENUM_ID2 ? true : false;
1341
1342 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
1343
1344 uint32 dpClock = 0;
1345 int dpLaneCount = 0;
1346 if (dpInfo->valid == true) {
1347 dpClock = dpInfo->linkRate;
1348 dpLaneCount = dpInfo->laneCount;
1349 }
1350
1351 switch (tableMajor) {
1352 case 1:
1353 switch (tableMinor) {
1354 case 1:
1355 args.v1.ucAction = command;
1356 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1357 args.v1.usInitInfo
1358 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1359 } else if (command
1360 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1361 args.v1.asMode.ucLaneSel = laneNumber;
1362 args.v1.asMode.ucLaneSet = laneSet;
1363 } else {
1364 if (isDP) {
1365 args.v1.usPixelClock
1366 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1367 } else if (pixelClock > 165000) {
1368 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1369 (pixelClock / 2) / 10);
1370 } else {
1371 args.v1.usPixelClock
1372 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1373 }
1374 }
1375
1376 args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1377
1378 if (digEncoderID > 0) {
1379 args.v1.ucConfig
1380 |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
1381 } else {
1382 args.v1.ucConfig
1383 |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1384 }
1385
1386 // TODO: IGP DIG Transmitter setup
1387 #if 0
1388 if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID
1389 == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1390 if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
1391 if (igp_lane_info & 0x1)
1392 args.v1.ucConfig
1393 |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
1394 else if (igp_lane_info & 0x2)
1395 args.v1.ucConfig
1396 |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
1397 else if (igp_lane_info & 0x4)
1398 args.v1.ucConfig
1399 |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
1400 else if (igp_lane_info & 0x8)
1401 args.v1.ucConfig
1402 |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1403 } else {
1404 if (igp_lane_info & 0x3)
1405 args.v1.ucConfig
1406 |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
1407 else if (igp_lane_info & 0xc)
1408 args.v1.ucConfig
1409 |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1410 }
1411 }
1412 #endif
1413
1414 if (linkB == true)
1415 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
1416 else
1417 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
1418
1419 if (isDP)
1420 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1421 else if ((gConnector[connectorIndex]->flags
1422 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1423 if (1) {
1424 // if coherentMode, i've only ever seen it true
1425 args.v1.ucConfig
1426 |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1427 }
1428 if (pixelClock > 165000) {
1429 args.v1.ucConfig
1430 |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1431 }
1432 }
1433 break;
1434 case 2:
1435 args.v2.ucAction = command;
1436 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1437 args.v2.usInitInfo
1438 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1439 } else if (command
1440 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1441 args.v2.asMode.ucLaneSel = laneNumber;
1442 args.v2.asMode.ucLaneSet = laneSet;
1443 } else {
1444 if (isDP) {
1445 args.v2.usPixelClock
1446 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1447 } else if (pixelClock > 165000) {
1448 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1449 (pixelClock / 2) / 10);
1450 } else {
1451 args.v2.usPixelClock
1452 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1453 }
1454 }
1455 args.v2.acConfig.ucEncoderSel = digEncoderID;
1456 if (linkB)
1457 args.v2.acConfig.ucLinkSel = 1;
1458
1459 switch (encoderObjectID) {
1460 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1461 args.v2.acConfig.ucTransmitterSel = 0;
1462 break;
1463 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1464 args.v2.acConfig.ucTransmitterSel = 1;
1465 break;
1466 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1467 args.v2.acConfig.ucTransmitterSel = 2;
1468 break;
1469 }
1470
1471 if (isDP) {
1472 args.v2.acConfig.fCoherentMode = 1;
1473 args.v2.acConfig.fDPConnector = 1;
1474 } else if ((gConnector[connectorIndex]->flags
1475 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1476 if (1) {
1477 // if coherentMode, i've only ever seen it true
1478 args.v2.acConfig.fCoherentMode = 1;
1479 }
1480
1481 if (pixelClock > 165000)
1482 args.v2.acConfig.fDualLinkConnector = 1;
1483 }
1484 break;
1485 case 3:
1486 args.v3.ucAction = command;
1487 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1488 args.v3.usInitInfo
1489 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1490 } else if (command
1491 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1492 args.v3.asMode.ucLaneSel = laneNumber;
1493 args.v3.asMode.ucLaneSet = laneSet;
1494 } else {
1495 if (isDP) {
1496 args.v3.usPixelClock
1497 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1498 } else if (pixelClock > 165000) {
1499 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1500 (pixelClock / 2) / 10);
1501 } else {
1502 args.v3.usPixelClock
1503 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1504 }
1505 }
1506
1507 if (isDP)
1508 args.v3.ucLaneNum = dpLaneCount;
1509 else if (pixelClock > 165000)
1510 args.v3.ucLaneNum = 8;
1511 else
1512 args.v3.ucLaneNum = 4;
1513
1514 if (linkB == true)
1515 args.v3.acConfig.ucLinkSel = 1;
1516 if (digEncoderID & 1)
1517 args.v3.acConfig.ucEncoderSel = 1;
1518
1519 // Select the PLL for the PHY
1520 // DP PHY to be clocked from external src if possible
1521
1522 // DCE4 has external DCPLL clock for DP
1523 if (isDP && gInfo->dpExternalClock) {
1524 // use external clock source (id'ed to 2 on DCE4)
1525 args.v3.acConfig.ucRefClkSource = 2; // EXT clock
1526 } else
1527 args.v3.acConfig.ucRefClkSource = pll->id;
1528
1529 switch (encoderObjectID) {
1530 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1531 args.v3.acConfig.ucTransmitterSel = 0;
1532 break;
1533 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1534 args.v3.acConfig.ucTransmitterSel = 1;
1535 break;
1536 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1537 args.v3.acConfig.ucTransmitterSel = 2;
1538 break;
1539 }
1540
1541 if (isDP)
1542 args.v3.acConfig.fCoherentMode = 1;
1543 else if ((gConnector[connectorIndex]->flags
1544 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1545 if (1) {
1546 // if coherentMode, i've only ever seen it true
1547 args.v3.acConfig.fCoherentMode = 1;
1548 }
1549 if (pixelClock > 165000)
1550 args.v3.acConfig.fDualLinkConnector = 1;
1551 }
1552 break;
1553 case 4:
1554 args.v4.ucAction = command;
1555 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1556 args.v4.usInitInfo
1557 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1558 } else if (command
1559 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1560 args.v4.asMode.ucLaneSel = laneNumber;
1561 args.v4.asMode.ucLaneSet = laneSet;
1562 } else {
1563 if (isDP) {
1564 args.v4.usPixelClock
1565 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1566 } else if (pixelClock > 165000) {
1567 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1568 (pixelClock / 2) / 10);
1569 } else {
1570 args.v4.usPixelClock
1571 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1572 }
1573 }
1574
1575 if (isDP)
1576 args.v4.ucLaneNum = dpLaneCount;
1577 else if (pixelClock > 165000)
1578 args.v4.ucLaneNum = 8;
1579 else
1580 args.v4.ucLaneNum = 4;
1581
1582 if (linkB == true)
1583 args.v4.acConfig.ucLinkSel = 1;
1584 if (digEncoderID & 1)
1585 args.v4.acConfig.ucEncoderSel = 1;
1586
1587 // Select the PLL for the PHY
1588 // DP PHY to be clocked from external src if possible
1589 // DCE5, DCPLL usually generates the DP ref clock
1590 if (isDP) {
1591 if (gInfo->dpExternalClock > 0) {
1592 args.v4.acConfig.ucRefClkSource
1593 = ENCODER_REFCLK_SRC_EXTCLK;
1594 } else {
1595 args.v4.acConfig.ucRefClkSource
1596 = ENCODER_REFCLK_SRC_DCPLL;
1597 }
1598 } else
1599 args.v4.acConfig.ucRefClkSource = pll->id;
1600
1601 switch (encoderObjectID) {
1602 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1603 args.v4.acConfig.ucTransmitterSel = 0;
1604 break;
1605 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1606 args.v4.acConfig.ucTransmitterSel = 1;
1607 break;
1608 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1609 args.v4.acConfig.ucTransmitterSel = 2;
1610 break;
1611 }
1612
1613 if (isDP)
1614 args.v4.acConfig.fCoherentMode = 1;
1615 else if ((gConnector[connectorIndex]->flags
1616 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1617 if (1) {
1618 // if coherentMode, i've only ever seen it true
1619 args.v4.acConfig.fCoherentMode = 1;
1620 }
1621 if (pixelClock > 165000)
1622 args.v4.acConfig.fDualLinkConnector = 1;
1623 }
1624 break;
1625 case 5:
1626 args.v5.ucAction = command;
1627
1628 if (isDP) {
1629 args.v5.usSymClock
1630 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1631 } else {
1632 args.v5.usSymClock
1633 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1634 }
1635 switch (encoderObjectID) {
1636 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1637 if (linkB)
1638 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1639 else
1640 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1641 break;
1642 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1643 if (linkB)
1644 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1645 else
1646 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1647 break;
1648 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1649 if (linkB)
1650 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1651 else
1652 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1653 break;
1654 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1655 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG;
1656 }
1657 if (isDP) {
1658 args.v5.ucLaneNum = dpLaneCount;
1659 } else if (pixelClock >= 165000) {
1660 args.v5.ucLaneNum = 8;
1661 } else {
1662 args.v5.ucLaneNum = 4;
1663 }
1664
1665 args.v5.ucConnObjId = connectorObjectID;
1666
1667 if (command != ATOM_TRANSMITTER_ACTION_INIT) {
1668 // not used on INIT and display_get_encoder_mode
1669 // unavailable until displays are probed.
1670 args.v5.ucDigMode
1671 = display_get_encoder_mode(connectorIndex);
1672 }
1673
1674 if (isDP && gInfo->dpExternalClock) {
1675 args.v5.asConfig.ucPhyClkSrcId
1676 = ENCODER_REFCLK_SRC_EXTCLK;
1677 } else {
1678 args.v5.asConfig.ucPhyClkSrcId = pll->id;
1679 }
1680
1681 if (isDP) {
1682 args.v5.asConfig.ucCoherentMode = 1;
1683 // DP always coherent
1684 } else if ((gConnector[connectorIndex]->flags
1685 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1686 // TODO: dig coherent mode? VVV
1687 args.v5.asConfig.ucCoherentMode = 1;
1688 }
1689
1690 if (hpdID == 0xff)
1691 args.v5.asConfig.ucHPDSel = 0;
1692 else
1693 args.v5.asConfig.ucHPDSel = hpdID + 1;
1694
1695 args.v5.ucDigEncoderSel = 1 << digEncoderID;
1696 args.v5.ucDPLaneSet = laneSet;
1697 break;
1698 case 6:
1699 args.v6.ucAction = command;
1700 if (isDP) {
1701 args.v6.ulSymClock
1702 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1703 } else {
1704 args.v6.ulSymClock
1705 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1706 }
1707 switch (encoderObjectID) {
1708 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1709 if (linkB)
1710 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1711 else
1712 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1713 break;
1714 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1715 if (linkB)
1716 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1717 else
1718 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1719 break;
1720 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1721 if (linkB)
1722 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1723 else
1724 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1725 break;
1726 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1727 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYG;
1728 break;
1729 }
1730 if (isDP)
1731 args.v6.ucLaneNum = dpLaneCount;
1732 else if (pixelClock > 165000)
1733 args.v6.ucLaneNum = 8;
1734 else
1735 args.v6.ucLaneNum = 4;
1736
1737 args.v6.ucConnObjId = connectorObjectID;
1738
1739 if (command == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH)
1740 args.v6.ucDPLaneSet = laneSet;
1741 else if (command != ATOM_TRANSMITTER_ACTION_INIT) {
1742 // not used on INIT and display_get_encoder_mode
1743 // unavailable until displays are probed.
1744 args.v6.ucDigMode
1745 = display_get_encoder_mode(connectorIndex);
1746 }
1747
1748 if (hpdID == 0xff)
1749 args.v6.ucHPDSel = 0;
1750 else
1751 args.v6.ucHPDSel = hpdID + 1;
1752
1753 args.v6.ucDigEncoderSel = 1 << digEncoderID;
1754 break;
1755 default:
1756 ERROR("%s: unknown table version\n", __func__);
1757 }
1758 break;
1759 default:
1760 ERROR("%s: unknown table version\n", __func__);
1761 }
1762
1763 return atom_execute_table(gAtomContext, index, (uint32*)&args);
1764 }
1765
1766
1767 void
encoder_crtc_scratch(uint8 crtcID)1768 encoder_crtc_scratch(uint8 crtcID)
1769 {
1770 TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
1771
1772 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1773 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1774
1775 // TODO: r500
1776 uint32 biosScratch3 = Read32(OUT, R600_SCRATCH_REG3);
1777
1778 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1779 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE;
1780 biosScratch3 |= (crtcID << 18);
1781 }
1782 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1783 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE;
1784 biosScratch3 |= (crtcID << 24);
1785 }
1786 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1787 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
1788 biosScratch3 |= (crtcID << 16);
1789 }
1790 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1791 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
1792 biosScratch3 |= (crtcID << 20);
1793 }
1794 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1795 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
1796 biosScratch3 |= (crtcID << 17);
1797 }
1798 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1799 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
1800 biosScratch3 |= (crtcID << 19);
1801 }
1802 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1803 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
1804 biosScratch3 |= (crtcID << 23);
1805 }
1806 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1807 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
1808 biosScratch3 |= (crtcID << 25);
1809 }
1810
1811 // TODO: r500
1812 Write32(OUT, R600_SCRATCH_REG3, biosScratch3);
1813 }
1814
1815
1816 void
encoder_dpms_scratch(uint8 crtcID,bool power)1817 encoder_dpms_scratch(uint8 crtcID, bool power)
1818 {
1819 TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
1820
1821 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1822 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1823
1824 // TODO: r500
1825 uint32 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2);
1826
1827 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1828 if (power == true)
1829 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE;
1830 else
1831 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE;
1832 }
1833 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1834 if (power == true)
1835 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE;
1836 else
1837 biosScratch2 |= ATOM_S2_CV_DPMS_STATE;
1838 }
1839 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1840 if (power == true)
1841 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE;
1842 else
1843 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE;
1844 }
1845 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1846 if (power == true)
1847 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE;
1848 else
1849 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE;
1850 }
1851 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1852 if (power == true)
1853 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE;
1854 else
1855 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE;
1856 }
1857 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1858 if (power == true)
1859 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE;
1860 else
1861 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE;
1862 }
1863 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1864 if (power == true)
1865 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE;
1866 else
1867 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE;
1868 }
1869 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1870 if (power == true)
1871 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE;
1872 else
1873 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE;
1874 }
1875 if ((connectorFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) {
1876 if (power == true)
1877 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE;
1878 else
1879 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE;
1880 }
1881 if ((connectorFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) {
1882 if (power == true)
1883 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE;
1884 else
1885 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE;
1886 }
1887 Write32(OUT, R600_SCRATCH_REG2, biosScratch2);
1888 }
1889
1890
1891 void
encoder_dpms_set(uint8 crtcID,int mode)1892 encoder_dpms_set(uint8 crtcID, int mode)
1893 {
1894 TRACE("%s: display %" B_PRIu8 ", power: %s\n", __func__, crtcID,
1895 mode == B_DPMS_ON ? "true" : "false");
1896
1897 int index = -1;
1898 radeon_shared_info &info = *gInfo->shared_info;
1899
1900 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1901 memset(&args, 0, sizeof(args));
1902
1903 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1904 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1905 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1906
1907 switch (encoderID) {
1908 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1909 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1910 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1911 break;
1912 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1913 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1914 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1915 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1916 encoder_dpms_set_dig(crtcID, mode);
1917 break;
1918 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1919 case ENCODER_OBJECT_ID_INTERNAL_DDI:
1920 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1921 break;
1922 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1923 if (info.dceMajor >= 5)
1924 encoder_dpms_set_dvo(crtcID, mode);
1925 else if (info.dceMajor >= 3)
1926 encoder_dpms_set_dig(crtcID, mode);
1927 else
1928 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1929 break;
1930 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1931 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1932 break;
1933 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1934 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1935 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1936 else
1937 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1938 break;
1939 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1940 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1941 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1942 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1943 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1944 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1945 else
1946 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1947 break;
1948 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1949 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1950 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1951 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1952 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1953 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1954 else
1955 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1956 break;
1957 // default, none on purpose
1958 }
1959
1960 // If we have an index, we need to execute a table.
1961 if (index >= 0) {
1962 switch (mode) {
1963 case B_DPMS_ON:
1964 args.ucAction = ATOM_ENABLE;
1965 break;
1966 case B_DPMS_STAND_BY:
1967 case B_DPMS_SUSPEND:
1968 case B_DPMS_OFF:
1969 args.ucAction = ATOM_DISABLE;
1970 break;
1971 }
1972
1973 atom_execute_table(gAtomContext, index, (uint32*)&args);
1974 if (info.dceMajor < 5) {
1975 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1976 args.ucAction = args.ucAction == ATOM_DISABLE
1977 ? ATOM_LCD_BLOFF : ATOM_LCD_BLON;
1978 atom_execute_table(gAtomContext, index, (uint32*)&args);
1979 }
1980 }
1981 if (info.dceMajor < 4)
1982 encoder_dpms_scratch(crtcID, true);
1983 }
1984 }
1985
1986
1987 void
encoder_dpms_set_dig(uint8 crtcID,int mode)1988 encoder_dpms_set_dig(uint8 crtcID, int mode)
1989 {
1990 TRACE("%s: display %" B_PRIu8 ", power: %s\n", __func__, crtcID,
1991 mode == B_DPMS_ON ? "true" : "false");
1992
1993 radeon_shared_info &info = *gInfo->shared_info;
1994 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1995 connector_info* connector = gConnector[connectorIndex];
1996 uint32 connectorFlags = connector->flags;
1997 pll_info* pll = &connector->encoder.pll;
1998 bool hasExternal = connector->encoderExternal.valid;
1999 bool travisQuirk = info.dceMajor < 5
2000 && (connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0
2001 && connector->encoderExternal.objectID == ENCODER_OBJECT_ID_TRAVIS;
2002
2003 switch (mode) {
2004 case B_DPMS_ON:
2005 if ((info.dceMajor == 4 && info.dceMinor == 1)
2006 || info.dceMajor >= 5) {
2007 // Setup encoder
2008 encoder_dig_setup(connectorIndex, pll->pixelClock,
2009 ATOM_ENCODER_CMD_SETUP);
2010 encoder_dig_setup(connectorIndex, pll->pixelClock,
2011 ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
2012 } else if (info.dceMajor >= 4) {
2013 // Setup encoder
2014 encoder_dig_setup(connectorIndex, pll->pixelClock,
2015 ATOM_ENCODER_CMD_SETUP);
2016 } else {
2017 // Setup encoder and transmitter
2018 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE);
2019 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2020 ATOM_TRANSMITTER_ACTION_SETUP);
2021 }
2022
2023 if (connector->type == VIDEO_CONNECTOR_EDP) {
2024 // TODO: If VIDEO_CONNECTOR_EDP, ATOM_TRANSMITTER_ACTION_POWER_ON
2025 ERROR("%s: TODO, edp_panel_power!\n",
2026 __func__);
2027 }
2028
2029 // Enable transmitter
2030 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2031 ATOM_TRANSMITTER_ACTION_ENABLE);
2032
2033 if (connector_is_dp(connectorIndex)) {
2034 if (info.dceMajor >= 4) {
2035 encoder_dig_setup(connectorIndex, pll->pixelClock,
2036 ATOM_ENCODER_CMD_DP_VIDEO_OFF);
2037 }
2038 // dp link train
2039 dp_link_train(crtcID);
2040 if (info.dceMajor >= 4) {
2041 encoder_dig_setup(connectorIndex, pll->pixelClock,
2042 ATOM_ENCODER_CMD_DP_VIDEO_ON);
2043 }
2044 // not sure what AtomBIOS table/command sets this
2045 // register, but it's required to get the video output
2046 Write32(OUT, AVIVO_DP_VID_STREAM_CNTL, 0x201);
2047 }
2048 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
2049 transmitter_dig_setup(connectorIndex, pll->pixelClock,
2050 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON);
2051 }
2052 if (hasExternal)
2053 encoder_external_setup(connectorIndex, ATOM_ENABLE);
2054 break;
2055 case B_DPMS_STAND_BY:
2056 case B_DPMS_SUSPEND:
2057 case B_DPMS_OFF:
2058 if (connector_is_dp(connectorIndex)) {
2059 if (info.dceMajor >= 4) {
2060 encoder_dig_setup(connectorIndex, pll->pixelClock,
2061 ATOM_ENCODER_CMD_DP_VIDEO_OFF);
2062 }
2063 }
2064 if (hasExternal)
2065 encoder_external_setup(connectorIndex, ATOM_DISABLE);
2066 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
2067 transmitter_dig_setup(connectorIndex, pll->pixelClock,
2068 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF);
2069 }
2070 if (connector_is_dp(connectorIndex) && !travisQuirk) {
2071 // If not TRAVIS on < DCE 5, set_rx_power_state D3
2072 ERROR("%s: TODO: dpms off set_rx_power_state D3\n", __func__);
2073 }
2074 if (info.dceMajor >= 4) {
2075 // Disable transmitter
2076 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2077 ATOM_TRANSMITTER_ACTION_DISABLE);
2078 } else {
2079 // Disable transmitter and encoder
2080 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2081 ATOM_TRANSMITTER_ACTION_DISABLE);
2082 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE);
2083 }
2084
2085 if (connector_is_dp(connectorIndex)) {
2086 if (travisQuirk) {
2087 ERROR("%s: TODO: dpms off set_rx_power_state D3\n",
2088 __func__);
2089 }
2090 if (connector->type == VIDEO_CONNECTOR_EDP) {
2091 // TODO: ATOM_TRANSMITTER_ACTION_POWER_OFF
2092 ERROR("%s: TODO, edp_panel_power!\n", __func__);
2093 }
2094 }
2095 break;
2096 }
2097 }
2098
2099
2100 void
encoder_dpms_set_dvo(uint8 crtcID,int mode)2101 encoder_dpms_set_dvo(uint8 crtcID, int mode)
2102 {
2103 ERROR("%s: TODO, dvo encoder dpms stub\n", __func__);
2104 }
2105
2106
2107 void
encoder_output_lock(bool lock)2108 encoder_output_lock(bool lock)
2109 {
2110 TRACE("%s: %s\n", __func__, lock ? "true" : "false");
2111 uint32 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6);
2112
2113 if (lock) {
2114 biosScratch6 |= ATOM_S6_CRITICAL_STATE;
2115 biosScratch6 &= ~ATOM_S6_ACC_MODE;
2116 } else {
2117 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE;
2118 biosScratch6 |= ATOM_S6_ACC_MODE;
2119 }
2120
2121 Write32(OUT, R600_SCRATCH_REG6, biosScratch6);
2122 }
2123
2124 static const char* encoder_name_matrix[] = {
2125 "NONE",
2126 "Internal Radeon LVDS",
2127 "Internal Radeon TMDS1",
2128 "Internal Radeon TMDS2",
2129 "Internal Radeon DAC1",
2130 "Internal Radeon DAC2 (TV)",
2131 "Internal Radeon SDVOA",
2132 "Internal Radeon SDVOB",
2133 "External 3rd party SI170B",
2134 "External 3rd party CH7303",
2135 "External 3rd party CH7301",
2136 "Internal Radeon DVO1",
2137 "External 3rd party SDVOA",
2138 "External 3rd party SDVOB",
2139 "External 3rd party TITFP513",
2140 "Internal LVTM1",
2141 "External 3rd party VT1623",
2142 "External HDMI SI1930",
2143 "Internal HDMI",
2144 "Internal Kaleidoscope TMDS1",
2145 "Internal Kaleidoscope DVO1",
2146 "Internal Kaleidoscope DAC1",
2147 "Internal Kaleidoscope DAC2",
2148 "External Kaleidoscope SI178",
2149 "MVPU FPGA",
2150 "Internal Kaleidoscope DDI",
2151 "External Kaleidoscope VT1625",
2152 "External Kaleidoscope HDMI SI1932",
2153 "External Kaleidoscope DP AN9801",
2154 "External Kaleidoscope DP DP501",
2155 "Internal Kaleidoscope UNIPHY",
2156 "Internal Kaleidoscope LVTMA",
2157 "Internal Kaleidoscope UNIPHY1",
2158 "Internal Kaleidoscope UNIPHY2",
2159 "External Nutmeg Bridge",
2160 "External Travis Bridge",
2161 "Internal Kaleidoscope VCE"
2162 };
2163
2164
2165 const char*
encoder_name_lookup(uint32 encoderID)2166 encoder_name_lookup(uint32 encoderID) {
2167 if (encoderID < B_COUNT_OF(encoder_name_matrix))
2168 return encoder_name_matrix[encoderID];
2169 else
2170 return "Unknown";
2171 }
2172
2173
2174 uint32
encoder_object_lookup(uint32 connectorFlags,uint8 dacID)2175 encoder_object_lookup(uint32 connectorFlags, uint8 dacID)
2176 {
2177 // used on older cards to take a guess at the encoder
2178 // object
2179
2180 radeon_shared_info &info = *gInfo->shared_info;
2181
2182 uint32 ret = 0;
2183
2184 switch (connectorFlags) {
2185 case ATOM_DEVICE_CRT1_SUPPORT:
2186 case ATOM_DEVICE_TV1_SUPPORT:
2187 case ATOM_DEVICE_TV2_SUPPORT:
2188 case ATOM_DEVICE_CRT2_SUPPORT:
2189 case ATOM_DEVICE_CV_SUPPORT:
2190 switch (dacID) {
2191 case 1:
2192 if ((info.chipsetID == RADEON_RS400)
2193 || (info.chipsetID == RADEON_RS480))
2194 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2195 else if (info.chipsetID >= RADEON_RS600)
2196 ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
2197 else
2198 ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
2199 break;
2200 case 2:
2201 if (info.chipsetID >= RADEON_RS600)
2202 ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
2203 else {
2204 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2205 }
2206 break;
2207 case 3: // external dac
2208 if (info.chipsetID >= RADEON_RS600)
2209 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2210 else
2211 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2212 break;
2213 }
2214 break;
2215 case ATOM_DEVICE_LCD1_SUPPORT:
2216 if (info.chipsetID >= RADEON_RS600)
2217 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2218 else
2219 ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
2220 break;
2221 case ATOM_DEVICE_DFP1_SUPPORT:
2222 if ((info.chipsetID == RADEON_RS400)
2223 || (info.chipsetID == RADEON_RS480))
2224 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2225 else if (info.chipsetID >= RADEON_RS600)
2226 ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
2227 else
2228 ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
2229 break;
2230 case ATOM_DEVICE_LCD2_SUPPORT:
2231 case ATOM_DEVICE_DFP2_SUPPORT:
2232 if ((info.chipsetID == RADEON_RS600)
2233 || (info.chipsetID == RADEON_RS690)
2234 || (info.chipsetID == RADEON_RS740))
2235 ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
2236 else if (info.chipsetID >= RADEON_RS600)
2237 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2238 else
2239 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2240 break;
2241 case ATOM_DEVICE_DFP3_SUPPORT:
2242 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2243 break;
2244 }
2245
2246 return ret;
2247 }
2248
2249
2250 uint32
encoder_type_lookup(uint32 encoderID,uint32 connectorFlags)2251 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags)
2252 {
2253 switch (encoderID) {
2254 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2255 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2256 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2257 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2258 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2259 return VIDEO_ENCODER_LVDS;
2260 else
2261 return VIDEO_ENCODER_TMDS;
2262 break;
2263 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2264 return VIDEO_ENCODER_DAC;
2265 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2266 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2267 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2268 return VIDEO_ENCODER_TVDAC;
2269 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2270 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2271 case ENCODER_OBJECT_ID_INTERNAL_DDI:
2272 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2273 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2274 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2275 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2276 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2277 return VIDEO_ENCODER_LVDS;
2278 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2279 return VIDEO_ENCODER_DAC;
2280 else
2281 return VIDEO_ENCODER_TMDS;
2282 break;
2283 case ENCODER_OBJECT_ID_SI170B:
2284 case ENCODER_OBJECT_ID_CH7303:
2285 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2286 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2287 case ENCODER_OBJECT_ID_TITFP513:
2288 case ENCODER_OBJECT_ID_VT1623:
2289 case ENCODER_OBJECT_ID_HDMI_SI1930:
2290 case ENCODER_OBJECT_ID_TRAVIS:
2291 case ENCODER_OBJECT_ID_NUTMEG:
2292 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2293 return VIDEO_ENCODER_LVDS;
2294 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2295 return VIDEO_ENCODER_DAC;
2296 else
2297 return VIDEO_ENCODER_TMDS;
2298 break;
2299 }
2300
2301 return VIDEO_ENCODER_NONE;
2302 }
2303
2304
2305 bool
encoder_is_external(uint32 encoderID)2306 encoder_is_external(uint32 encoderID)
2307 {
2308 switch (encoderID) {
2309 case ENCODER_OBJECT_ID_SI170B:
2310 case ENCODER_OBJECT_ID_CH7303:
2311 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2312 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2313 case ENCODER_OBJECT_ID_TITFP513:
2314 case ENCODER_OBJECT_ID_VT1623:
2315 case ENCODER_OBJECT_ID_HDMI_SI1930:
2316 case ENCODER_OBJECT_ID_TRAVIS:
2317 case ENCODER_OBJECT_ID_NUTMEG:
2318 return true;
2319 }
2320
2321 return false;
2322 }
2323
2324
2325 bool
encoder_is_dp_bridge(uint32 encoderID)2326 encoder_is_dp_bridge(uint32 encoderID)
2327 {
2328 switch (encoderID) {
2329 case ENCODER_OBJECT_ID_TRAVIS:
2330 case ENCODER_OBJECT_ID_NUTMEG:
2331 return true;
2332 }
2333 return false;
2334 }
2335