atombios_output.c revision b7e1c893
1/*
2 * Copyright © 2007 Red Hat, Inc.
3 * Copyright 2007  Advanced Micro Devices, 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 (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 *    Dave Airlie <airlied@redhat.com>
26 *    Alex Deucher <alexdeucher@gmail.com>
27 *
28 */
29
30/*
31 * avivo output handling functions.
32 */
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36/* DPMS */
37#define DPMS_SERVER
38#include <X11/extensions/dpms.h>
39#include <unistd.h>
40
41#include "radeon.h"
42#include "radeon_reg.h"
43#include "radeon_macros.h"
44#include "radeon_atombios.h"
45
46#include "ati_pciids_gen.h"
47
48const char *device_name[12] = {
49    "CRT1",
50    "LCD1",
51    "TV1",
52    "DFP1",
53    "CRT2",
54    "LCD2",
55    "TV2",
56    "DFP2",
57    "CV",
58    "DFP3",
59    "DFP4",
60    "DFP5",
61};
62
63static int
64atombios_output_dac_setup(xf86OutputPtr output, int action)
65{
66    RADEONOutputPrivatePtr radeon_output = output->driver_private;
67    RADEONInfoPtr info       = RADEONPTR(output->scrn);
68    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
69    radeon_tvout_ptr tvout = &radeon_output->tvout;
70    DAC_ENCODER_CONTROL_PS_ALLOCATION disp_data;
71    AtomBiosArgRec data;
72    unsigned char *space;
73    int index = 0, num = 0;
74    int clock = radeon_output->pixel_clock;
75
76    if (radeon_encoder == NULL)
77	return ATOM_NOT_IMPLEMENTED;
78
79    memset(&disp_data,0, sizeof(disp_data));
80
81    switch (radeon_encoder->encoder_id) {
82    case ENCODER_OBJECT_ID_INTERNAL_DAC1:
83    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
84	index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
85	num = 1;
86	break;
87    case ENCODER_OBJECT_ID_INTERNAL_DAC2:
88    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
89	index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
90	num = 2;
91	break;
92    }
93
94    disp_data.ucAction =action;
95
96    if (radeon_output->active_device & (ATOM_DEVICE_CRT_SUPPORT))
97	disp_data.ucDacStandard = ATOM_DAC1_PS2;
98    else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
99	disp_data.ucDacStandard = ATOM_DAC1_CV;
100    else {
101	switch (tvout->tvStd) {
102	case TV_STD_PAL:
103	case TV_STD_PAL_M:
104	case TV_STD_SCART_PAL:
105	case TV_STD_SECAM:
106	case TV_STD_PAL_CN:
107	    disp_data.ucDacStandard = ATOM_DAC1_PAL;
108	    break;
109	case TV_STD_NTSC:
110	case TV_STD_NTSC_J:
111	case TV_STD_PAL_60:
112	default:
113	    disp_data.ucDacStandard = ATOM_DAC1_NTSC;
114	    break;
115	}
116    }
117    disp_data.usPixelClock = cpu_to_le16(clock / 10);
118
119    data.exec.index = index;
120    data.exec.dataSpace = (void *)&space;
121    data.exec.pspace = &disp_data;
122
123    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
124	ErrorF("Output DAC%d setup success\n", num);
125	return ATOM_SUCCESS;
126    }
127
128    ErrorF("Output DAC%d setup failed\n", num);
129    return ATOM_NOT_IMPLEMENTED;
130
131}
132
133static int
134atombios_output_tv_setup(xf86OutputPtr output, int action)
135{
136    RADEONOutputPrivatePtr radeon_output = output->driver_private;
137    radeon_tvout_ptr tvout = &radeon_output->tvout;
138    RADEONInfoPtr info       = RADEONPTR(output->scrn);
139    TV_ENCODER_CONTROL_PS_ALLOCATION disp_data;
140    AtomBiosArgRec data;
141    unsigned char *space;
142    int clock = radeon_output->pixel_clock;
143
144    memset(&disp_data,0, sizeof(disp_data));
145
146    disp_data.sTVEncoder.ucAction = action;
147
148    if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
149	disp_data.sTVEncoder.ucTvStandard = ATOM_TV_CV;
150    else {
151	switch (tvout->tvStd) {
152	case TV_STD_NTSC:
153	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
154	    break;
155	case TV_STD_PAL:
156	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
157	    break;
158	case TV_STD_PAL_M:
159	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
160	    break;
161	case TV_STD_PAL_60:
162	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
163	    break;
164	case TV_STD_NTSC_J:
165	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
166	    break;
167	case TV_STD_SCART_PAL:
168	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
169	    break;
170	case TV_STD_SECAM:
171	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
172	    break;
173	case TV_STD_PAL_CN:
174	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
175	    break;
176	default:
177	    disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
178	    break;
179	}
180    }
181
182    disp_data.sTVEncoder.usPixelClock = cpu_to_le16(clock / 10);
183    data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
184    data.exec.dataSpace = (void *)&space;
185    data.exec.pspace = &disp_data;
186
187    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
188	ErrorF("Output TV setup success\n");
189	return ATOM_SUCCESS;
190    }
191
192    ErrorF("Output TV setup failed\n");
193    return ATOM_NOT_IMPLEMENTED;
194
195}
196
197int
198atombios_external_tmds_setup(xf86OutputPtr output, int action)
199{
200    RADEONOutputPrivatePtr radeon_output = output->driver_private;
201    ScrnInfoPtr pScrn = output->scrn;
202    RADEONInfoPtr info       = RADEONPTR(pScrn);
203    ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION disp_data;
204    AtomBiosArgRec data;
205    unsigned char *space;
206    int clock = radeon_output->pixel_clock;
207
208    memset(&disp_data,0, sizeof(disp_data));
209
210    disp_data.sXTmdsEncoder.ucEnable = action;
211
212    if (clock > 165000)
213	disp_data.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
214
215    if (pScrn->rgbBits == 8)
216	disp_data.sXTmdsEncoder.ucMisc |= (1 << 1);
217
218    data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
219    data.exec.dataSpace = (void *)&space;
220    data.exec.pspace = &disp_data;
221
222    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
223	ErrorF("External TMDS setup success\n");
224	return ATOM_SUCCESS;
225    }
226
227    ErrorF("External TMDS setup failed\n");
228    return ATOM_NOT_IMPLEMENTED;
229}
230
231static int
232atombios_output_ddia_setup(xf86OutputPtr output, int action)
233{
234    RADEONOutputPrivatePtr radeon_output = output->driver_private;
235    RADEONInfoPtr info       = RADEONPTR(output->scrn);
236    DVO_ENCODER_CONTROL_PS_ALLOCATION disp_data;
237    AtomBiosArgRec data;
238    unsigned char *space;
239    int clock = radeon_output->pixel_clock;
240
241    memset(&disp_data,0, sizeof(disp_data));
242
243    disp_data.sDVOEncoder.ucAction = action;
244    disp_data.sDVOEncoder.usPixelClock = cpu_to_le16(clock / 10);
245
246    if (clock > 165000)
247	disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
248
249    data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
250    data.exec.dataSpace = (void *)&space;
251    data.exec.pspace = &disp_data;
252
253    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
254	ErrorF("DDIA setup success\n");
255	return ATOM_SUCCESS;
256    }
257
258    ErrorF("DDIA setup failed\n");
259    return ATOM_NOT_IMPLEMENTED;
260}
261
262static int
263atombios_output_digital_setup(xf86OutputPtr output, int action)
264{
265    RADEONOutputPrivatePtr radeon_output = output->driver_private;
266    ScrnInfoPtr pScrn = output->scrn;
267    RADEONInfoPtr info       = RADEONPTR(pScrn);
268    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
269    LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data;
270    LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 disp_data2;
271    AtomBiosArgRec data;
272    unsigned char *space;
273    int index = 0;
274    int major, minor;
275    int lvds_misc = 0;
276    int clock = radeon_output->pixel_clock;
277
278    if (radeon_encoder == NULL)
279	return ATOM_NOT_IMPLEMENTED;
280
281    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
282	radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv;
283	if (lvds == NULL)
284	    return ATOM_NOT_IMPLEMENTED;
285	lvds_misc = lvds->lvds_misc;
286    }
287
288    memset(&disp_data,0, sizeof(disp_data));
289    memset(&disp_data2,0, sizeof(disp_data2));
290
291    switch (radeon_encoder->encoder_id) {
292    case ENCODER_OBJECT_ID_INTERNAL_LVDS:
293	index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
294	break;
295    case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
296    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
297	index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
298	break;
299    case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
300    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
301	if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT))
302	    index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
303	else
304	    index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
305	break;
306    }
307
308    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
309
310    /*ErrorF("table is %d %d\n", major, minor);*/
311    switch (major) {
312    case 0:
313    case 1:
314    case 2:
315	switch (minor) {
316	case 1:
317	    disp_data.ucMisc = 0;
318	    disp_data.ucAction = action;
319	    if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) ||
320		(radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B))
321		disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
322	    disp_data.usPixelClock = cpu_to_le16(clock / 10);
323	    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
324		if (lvds_misc & (1 << 0))
325		    disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL;
326		if (lvds_misc & (1 << 1))
327		    disp_data.ucMisc |= (1 << 1);
328	    } else {
329		if (radeon_output->linkb)
330		    disp_data.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
331		if (clock > 165000)
332		    disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL;
333		if (pScrn->rgbBits == 8)
334		    disp_data.ucMisc |= (1 << 1);
335	    }
336	    data.exec.pspace = &disp_data;
337	    break;
338	case 2:
339	case 3:
340	    disp_data2.ucMisc = 0;
341	    disp_data2.ucAction = action;
342	    if (minor == 3) {
343		if (radeon_output->coherent_mode) {
344		    disp_data2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
345		    xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Coherent Mode enabled\n");
346		}
347	    }
348	    if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) ||
349		(radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B))
350		disp_data2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
351	    disp_data2.usPixelClock = cpu_to_le16(clock / 10);
352	    disp_data2.ucTruncate = 0;
353	    disp_data2.ucSpatial = 0;
354	    disp_data2.ucTemporal = 0;
355	    disp_data2.ucFRC = 0;
356	    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
357		if (lvds_misc & (1 << 0))
358		    disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
359		if (lvds_misc & (1 << 5)) {
360		    disp_data2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
361		    if (lvds_misc & (1 << 1))
362			disp_data2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
363		}
364		if (lvds_misc & (1 << 6)) {
365		    disp_data2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
366		    if (lvds_misc & (1 << 1))
367			disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
368		    if (((lvds_misc >> 2) & 0x3) == 2)
369			disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
370		}
371	    } else {
372		if (radeon_output->linkb)
373		    disp_data2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
374		if (clock > 165000)
375		    disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
376	    }
377	    data.exec.pspace = &disp_data2;
378	    break;
379	default:
380	    ErrorF("Unknown table version\n");
381	    exit(-1);
382	}
383	break;
384    default:
385	ErrorF("Unknown table version\n");
386	exit(-1);
387    }
388
389    data.exec.index = index;
390    data.exec.dataSpace = (void *)&space;
391
392    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
393	ErrorF("Output digital setup success\n");
394	return ATOM_SUCCESS;
395    }
396
397    ErrorF("Output digital setup failed\n");
398    return ATOM_NOT_IMPLEMENTED;
399}
400
401static int
402atombios_maybe_hdmi_mode(xf86OutputPtr output)
403{
404#ifndef EDID_COMPLETE_RAWDATA
405    /* there's no getting this right unless we have complete EDID */
406    return ATOM_ENCODER_MODE_HDMI;
407#else
408    if (output && xf86MonitorIsHDMI(output->MonInfo))
409	return ATOM_ENCODER_MODE_HDMI;
410
411    return ATOM_ENCODER_MODE_DVI;
412#endif
413}
414
415int
416atombios_get_encoder_mode(xf86OutputPtr output)
417{
418    RADEONOutputPrivatePtr radeon_output = output->driver_private;
419
420    /* DVI should really be atombios_maybe_hdmi_mode() as well */
421    switch (radeon_output->ConnectorType) {
422    case CONNECTOR_DVI_I:
423	if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT))
424	    return ATOM_ENCODER_MODE_DVI;
425	else
426	    return ATOM_ENCODER_MODE_CRT;
427	break;
428    case CONNECTOR_DVI_D:
429    default:
430	return ATOM_ENCODER_MODE_DVI;
431	break;
432    case CONNECTOR_HDMI_TYPE_A:
433    case CONNECTOR_HDMI_TYPE_B:
434	return atombios_maybe_hdmi_mode(output);
435	break;
436    case CONNECTOR_LVDS:
437	return ATOM_ENCODER_MODE_LVDS;
438	break;
439    case CONNECTOR_DISPLAY_PORT:
440	if (radeon_output->MonType == MT_DP)
441	    return ATOM_ENCODER_MODE_DP;
442	else
443	    return atombios_maybe_hdmi_mode(output);
444	break;
445    case CONNECTOR_DVI_A:
446    case CONNECTOR_VGA:
447    case CONNECTOR_STV:
448    case CONNECTOR_CTV:
449    case CONNECTOR_DIN:
450	if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
451	    return ATOM_ENCODER_MODE_TV;
452	else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
453	    return ATOM_ENCODER_MODE_CV;
454	else
455	    return ATOM_ENCODER_MODE_CRT;
456	break;
457    }
458
459}
460
461static const int dp_clocks[] = {
462    16200,
463    27000,
464    32400,
465    54000,
466    0,
467    0,
468    64800,
469    108000,
470};
471static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
472
473static int
474dp_lanes_for_mode_clock(int mode_clock)
475{
476    int i;
477
478    for (i = 0; i < num_dp_clocks; i++)
479	if (dp_clocks[i] > (mode_clock / 10))
480	    return (i / 2) + 1;
481
482    return 0;
483}
484
485static int
486dp_link_clock_for_mode_clock(int mode_clock)
487{
488    int i;
489
490    for (i = 0; i < num_dp_clocks; i++)
491	if (dp_clocks[i] > (mode_clock / 10))
492	    return (dp_clocks[i % 2]);
493
494    return 0;
495}
496
497static int
498atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
499{
500    RADEONOutputPrivatePtr radeon_output = output->driver_private;
501    RADEONInfoPtr info       = RADEONPTR(output->scrn);
502    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
503    DIG_ENCODER_CONTROL_PS_ALLOCATION disp_data;
504    AtomBiosArgRec data;
505    unsigned char *space;
506    int index = 0, major, minor, num = 0;
507    int clock = radeon_output->pixel_clock;
508    int dig_block = radeon_output->dig_block;
509
510    if (radeon_encoder == NULL)
511	return ATOM_NOT_IMPLEMENTED;
512
513    memset(&disp_data,0, sizeof(disp_data));
514
515    if (IS_DCE32_VARIANT) {
516	if (dig_block)
517	    index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
518	else
519	    index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
520	num = dig_block + 1;
521    } else {
522	switch (radeon_encoder->encoder_id) {
523	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
524	    index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
525	    num = 1;
526	    break;
527	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
528	    index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
529	    num = 2;
530	    break;
531	}
532    }
533
534    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
535
536    disp_data.ucAction = action;
537    disp_data.usPixelClock = cpu_to_le16(clock / 10);
538
539    if (IS_DCE32_VARIANT) {
540	switch (radeon_encoder->encoder_id) {
541	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
542	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
543	    break;
544	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
545	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
546	    break;
547	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
548	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
549	    break;
550	}
551    } else {
552	switch (radeon_encoder->encoder_id) {
553	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
554	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_UNIPHY;
555	    break;
556	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
557	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_LVTMA;
558	    break;
559	}
560    }
561
562    disp_data.ucEncoderMode = atombios_get_encoder_mode(output);
563
564    if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
565	if (radeon_output->linkb)
566	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
567	else
568	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
569
570	if (dp_link_clock_for_mode_clock(clock) == 27000)
571	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
572
573	disp_data.ucLaneNum = dp_lanes_for_mode_clock(clock);
574    } else if (clock > 165000) {
575	disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
576	disp_data.ucLaneNum = 8;
577    } else {
578	if (radeon_output->linkb)
579	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
580	else
581	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
582
583	disp_data.ucLaneNum = 4;
584    }
585
586    data.exec.index = index;
587    data.exec.dataSpace = (void *)&space;
588    data.exec.pspace = &disp_data;
589
590    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
591	ErrorF("Output DIG%d encoder setup success\n", num);
592	return ATOM_SUCCESS;
593    }
594
595    ErrorF("Output DIG%d setup failed\n", num);
596    return ATOM_NOT_IMPLEMENTED;
597
598}
599
600union dig_transmitter_control {
601    DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
602    DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
603};
604
605static int
606atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
607{
608    RADEONOutputPrivatePtr radeon_output = output->driver_private;
609    RADEONInfoPtr info       = RADEONPTR(output->scrn);
610    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
611    union dig_transmitter_control disp_data;
612    AtomBiosArgRec data;
613    unsigned char *space;
614    int index = 0, num = 0;
615    int major, minor;
616    int clock = radeon_output->pixel_clock;
617    int dig_block = radeon_output->dig_block;
618
619    if (radeon_encoder == NULL)
620        return ATOM_NOT_IMPLEMENTED;
621
622    memset(&disp_data,0, sizeof(disp_data));
623
624    if (IS_DCE32_VARIANT)
625	index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
626    else {
627	switch (radeon_encoder->encoder_id) {
628	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
629	    index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
630	    break;
631	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
632	    index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
633	    break;
634	}
635    }
636
637    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
638
639    disp_data.v1.ucAction = action;
640
641    if (IS_DCE32_VARIANT) {
642	if (radeon_output->MonType == MT_DP) {
643	    disp_data.v2.usPixelClock =
644		cpu_to_le16(dp_link_clock_for_mode_clock(clock));
645	    disp_data.v2.acConfig.fDPConnector = 1;
646	} else if (clock > 165000) {
647	    disp_data.v2.usPixelClock = cpu_to_le16((clock * 10 * 2) / 100);
648	    disp_data.v2.acConfig.fDualLinkConnector = 1;
649	} else {
650	    disp_data.v2.usPixelClock = cpu_to_le16((clock * 10 * 4) / 100);
651	}
652	if (dig_block)
653	    disp_data.v2.acConfig.ucEncoderSel = 1;
654
655	switch (radeon_encoder->encoder_id) {
656	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
657	    disp_data.v2.acConfig.ucTransmitterSel = 0;
658	    num = 0;
659	    break;
660	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
661	    disp_data.v2.acConfig.ucTransmitterSel = 1;
662	    num = 1;
663	    break;
664	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
665	    disp_data.v2.acConfig.ucTransmitterSel = 2;
666	    num = 2;
667	    break;
668	}
669
670	if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
671	    if (radeon_output->coherent_mode) {
672		disp_data.v2.acConfig.fCoherentMode = 1;
673		xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode enabled\n",disp_data.v2.acConfig.ucTransmitterSel);
674	    } else
675		xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode disabled\n",disp_data.v2.acConfig.ucTransmitterSel);
676	}
677    } else {
678	disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
679
680	if (radeon_output->MonType == MT_DP)
681	    disp_data.v1.usPixelClock =
682		cpu_to_le16(dp_link_clock_for_mode_clock(clock));
683	else
684	    disp_data.v1.usPixelClock = cpu_to_le16((clock) / 10);
685
686	switch (radeon_encoder->encoder_id) {
687	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
688	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
689	    if (info->IsIGP) {
690		if (clock > 165000) {
691		    disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
692					      ATOM_TRANSMITTER_CONFIG_LINKA_B);
693
694		    if (radeon_output->igp_lane_info & 0x3)
695			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
696		    else if (radeon_output->igp_lane_info & 0xc)
697			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
698		} else {
699		    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
700		    if (radeon_output->igp_lane_info & 0x1)
701			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
702		    else if (radeon_output->igp_lane_info & 0x2)
703			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
704		    else if (radeon_output->igp_lane_info & 0x4)
705			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
706		    else if (radeon_output->igp_lane_info & 0x8)
707			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
708		}
709	    } else {
710		if (clock > 165000)
711		    disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
712					      ATOM_TRANSMITTER_CONFIG_LINKA_B |
713					      ATOM_TRANSMITTER_CONFIG_LANE_0_7);
714		else {
715		    /* XXX */
716		    if (radeon_output->linkb)
717			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
718		    else
719			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
720		}
721	    }
722	    break;
723	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
724	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
725	    if (clock > 165000)
726		disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
727					  ATOM_TRANSMITTER_CONFIG_LINKA_B |
728					  ATOM_TRANSMITTER_CONFIG_LANE_0_7);
729	    else {
730		/* XXX */
731		if (radeon_output->linkb)
732		    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
733		else
734		    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
735	    }
736	    break;
737	}
738
739	if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
740	    if (radeon_output->coherent_mode &&
741		radeon_output->MonType != MT_DP) {
742		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
743		xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
744			"DIG%d transmitter: Coherent Mode enabled\n", num);
745	    } else {
746		xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
747			"DIG%d transmitter: Coherent Mode disabled\n", num);
748	    }
749	}
750    }
751
752    data.exec.index = index;
753    data.exec.dataSpace = (void *)&space;
754    data.exec.pspace = &disp_data;
755
756    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
757	if (IS_DCE32_VARIANT)
758	    ErrorF("Output UNIPHY%d transmitter setup success\n", num);
759	else
760	   ErrorF("Output DIG%d transmitter setup success\n", num);
761	return ATOM_SUCCESS;
762    }
763
764    ErrorF("Output DIG%d transmitter setup failed\n", num);
765    return ATOM_NOT_IMPLEMENTED;
766
767}
768
769static void atom_rv515_force_tv_scaler(ScrnInfoPtr pScrn)
770{
771    RADEONInfoPtr info       = RADEONPTR(pScrn);
772    unsigned char *RADEONMMIO = info->MMIO;
773
774    OUTREG(0x659C,0x0);
775    OUTREG(0x6594,0x705);
776    OUTREG(0x65A4,0x10001);
777    OUTREG(0x65D8,0x0);
778    OUTREG(0x65B0,0x0);
779    OUTREG(0x65C0,0x0);
780    OUTREG(0x65D4,0x0);
781    OUTREG(0x6578,0x0);
782    OUTREG(0x657C,0x841880A8);
783    OUTREG(0x6578,0x1);
784    OUTREG(0x657C,0x84208680);
785    OUTREG(0x6578,0x2);
786    OUTREG(0x657C,0xBFF880B0);
787    OUTREG(0x6578,0x100);
788    OUTREG(0x657C,0x83D88088);
789    OUTREG(0x6578,0x101);
790    OUTREG(0x657C,0x84608680);
791    OUTREG(0x6578,0x102);
792    OUTREG(0x657C,0xBFF080D0);
793    OUTREG(0x6578,0x200);
794    OUTREG(0x657C,0x83988068);
795    OUTREG(0x6578,0x201);
796    OUTREG(0x657C,0x84A08680);
797    OUTREG(0x6578,0x202);
798    OUTREG(0x657C,0xBFF080F8);
799    OUTREG(0x6578,0x300);
800    OUTREG(0x657C,0x83588058);
801    OUTREG(0x6578,0x301);
802    OUTREG(0x657C,0x84E08660);
803    OUTREG(0x6578,0x302);
804    OUTREG(0x657C,0xBFF88120);
805    OUTREG(0x6578,0x400);
806    OUTREG(0x657C,0x83188040);
807    OUTREG(0x6578,0x401);
808    OUTREG(0x657C,0x85008660);
809    OUTREG(0x6578,0x402);
810    OUTREG(0x657C,0xBFF88150);
811    OUTREG(0x6578,0x500);
812    OUTREG(0x657C,0x82D88030);
813    OUTREG(0x6578,0x501);
814    OUTREG(0x657C,0x85408640);
815    OUTREG(0x6578,0x502);
816    OUTREG(0x657C,0xBFF88180);
817    OUTREG(0x6578,0x600);
818    OUTREG(0x657C,0x82A08018);
819    OUTREG(0x6578,0x601);
820    OUTREG(0x657C,0x85808620);
821    OUTREG(0x6578,0x602);
822    OUTREG(0x657C,0xBFF081B8);
823    OUTREG(0x6578,0x700);
824    OUTREG(0x657C,0x82608010);
825    OUTREG(0x6578,0x701);
826    OUTREG(0x657C,0x85A08600);
827    OUTREG(0x6578,0x702);
828    OUTREG(0x657C,0x800081F0);
829    OUTREG(0x6578,0x800);
830    OUTREG(0x657C,0x8228BFF8);
831    OUTREG(0x6578,0x801);
832    OUTREG(0x657C,0x85E085E0);
833    OUTREG(0x6578,0x802);
834    OUTREG(0x657C,0xBFF88228);
835    OUTREG(0x6578,0x10000);
836    OUTREG(0x657C,0x82A8BF00);
837    OUTREG(0x6578,0x10001);
838    OUTREG(0x657C,0x82A08CC0);
839    OUTREG(0x6578,0x10002);
840    OUTREG(0x657C,0x8008BEF8);
841    OUTREG(0x6578,0x10100);
842    OUTREG(0x657C,0x81F0BF28);
843    OUTREG(0x6578,0x10101);
844    OUTREG(0x657C,0x83608CA0);
845    OUTREG(0x6578,0x10102);
846    OUTREG(0x657C,0x8018BED0);
847    OUTREG(0x6578,0x10200);
848    OUTREG(0x657C,0x8148BF38);
849    OUTREG(0x6578,0x10201);
850    OUTREG(0x657C,0x84408C80);
851    OUTREG(0x6578,0x10202);
852    OUTREG(0x657C,0x8008BEB8);
853    OUTREG(0x6578,0x10300);
854    OUTREG(0x657C,0x80B0BF78);
855    OUTREG(0x6578,0x10301);
856    OUTREG(0x657C,0x85008C20);
857    OUTREG(0x6578,0x10302);
858    OUTREG(0x657C,0x8020BEA0);
859    OUTREG(0x6578,0x10400);
860    OUTREG(0x657C,0x8028BF90);
861    OUTREG(0x6578,0x10401);
862    OUTREG(0x657C,0x85E08BC0);
863    OUTREG(0x6578,0x10402);
864    OUTREG(0x657C,0x8018BE90);
865    OUTREG(0x6578,0x10500);
866    OUTREG(0x657C,0xBFB8BFB0);
867    OUTREG(0x6578,0x10501);
868    OUTREG(0x657C,0x86C08B40);
869    OUTREG(0x6578,0x10502);
870    OUTREG(0x657C,0x8010BE90);
871    OUTREG(0x6578,0x10600);
872    OUTREG(0x657C,0xBF58BFC8);
873    OUTREG(0x6578,0x10601);
874    OUTREG(0x657C,0x87A08AA0);
875    OUTREG(0x6578,0x10602);
876    OUTREG(0x657C,0x8010BE98);
877    OUTREG(0x6578,0x10700);
878    OUTREG(0x657C,0xBF10BFF0);
879    OUTREG(0x6578,0x10701);
880    OUTREG(0x657C,0x886089E0);
881    OUTREG(0x6578,0x10702);
882    OUTREG(0x657C,0x8018BEB0);
883    OUTREG(0x6578,0x10800);
884    OUTREG(0x657C,0xBED8BFE8);
885    OUTREG(0x6578,0x10801);
886    OUTREG(0x657C,0x89408940);
887    OUTREG(0x6578,0x10802);
888    OUTREG(0x657C,0xBFE8BED8);
889    OUTREG(0x6578,0x20000);
890    OUTREG(0x657C,0x80008000);
891    OUTREG(0x6578,0x20001);
892    OUTREG(0x657C,0x90008000);
893    OUTREG(0x6578,0x20002);
894    OUTREG(0x657C,0x80008000);
895    OUTREG(0x6578,0x20003);
896    OUTREG(0x657C,0x80008000);
897    OUTREG(0x6578,0x20100);
898    OUTREG(0x657C,0x80108000);
899    OUTREG(0x6578,0x20101);
900    OUTREG(0x657C,0x8FE0BF70);
901    OUTREG(0x6578,0x20102);
902    OUTREG(0x657C,0xBFE880C0);
903    OUTREG(0x6578,0x20103);
904    OUTREG(0x657C,0x80008000);
905    OUTREG(0x6578,0x20200);
906    OUTREG(0x657C,0x8018BFF8);
907    OUTREG(0x6578,0x20201);
908    OUTREG(0x657C,0x8F80BF08);
909    OUTREG(0x6578,0x20202);
910    OUTREG(0x657C,0xBFD081A0);
911    OUTREG(0x6578,0x20203);
912    OUTREG(0x657C,0xBFF88000);
913    OUTREG(0x6578,0x20300);
914    OUTREG(0x657C,0x80188000);
915    OUTREG(0x6578,0x20301);
916    OUTREG(0x657C,0x8EE0BEC0);
917    OUTREG(0x6578,0x20302);
918    OUTREG(0x657C,0xBFB082A0);
919    OUTREG(0x6578,0x20303);
920    OUTREG(0x657C,0x80008000);
921    OUTREG(0x6578,0x20400);
922    OUTREG(0x657C,0x80188000);
923    OUTREG(0x6578,0x20401);
924    OUTREG(0x657C,0x8E00BEA0);
925    OUTREG(0x6578,0x20402);
926    OUTREG(0x657C,0xBF8883C0);
927    OUTREG(0x6578,0x20403);
928    OUTREG(0x657C,0x80008000);
929    OUTREG(0x6578,0x20500);
930    OUTREG(0x657C,0x80188000);
931    OUTREG(0x6578,0x20501);
932    OUTREG(0x657C,0x8D00BE90);
933    OUTREG(0x6578,0x20502);
934    OUTREG(0x657C,0xBF588500);
935    OUTREG(0x6578,0x20503);
936    OUTREG(0x657C,0x80008008);
937    OUTREG(0x6578,0x20600);
938    OUTREG(0x657C,0x80188000);
939    OUTREG(0x6578,0x20601);
940    OUTREG(0x657C,0x8BC0BE98);
941    OUTREG(0x6578,0x20602);
942    OUTREG(0x657C,0xBF308660);
943    OUTREG(0x6578,0x20603);
944    OUTREG(0x657C,0x80008008);
945    OUTREG(0x6578,0x20700);
946    OUTREG(0x657C,0x80108000);
947    OUTREG(0x6578,0x20701);
948    OUTREG(0x657C,0x8A80BEB0);
949    OUTREG(0x6578,0x20702);
950    OUTREG(0x657C,0xBF0087C0);
951    OUTREG(0x6578,0x20703);
952    OUTREG(0x657C,0x80008008);
953    OUTREG(0x6578,0x20800);
954    OUTREG(0x657C,0x80108000);
955    OUTREG(0x6578,0x20801);
956    OUTREG(0x657C,0x8920BED0);
957    OUTREG(0x6578,0x20802);
958    OUTREG(0x657C,0xBED08920);
959    OUTREG(0x6578,0x20803);
960    OUTREG(0x657C,0x80008010);
961    OUTREG(0x6578,0x30000);
962    OUTREG(0x657C,0x90008000);
963    OUTREG(0x6578,0x30001);
964    OUTREG(0x657C,0x80008000);
965    OUTREG(0x6578,0x30100);
966    OUTREG(0x657C,0x8FE0BF90);
967    OUTREG(0x6578,0x30101);
968    OUTREG(0x657C,0xBFF880A0);
969    OUTREG(0x6578,0x30200);
970    OUTREG(0x657C,0x8F60BF40);
971    OUTREG(0x6578,0x30201);
972    OUTREG(0x657C,0xBFE88180);
973    OUTREG(0x6578,0x30300);
974    OUTREG(0x657C,0x8EC0BF00);
975    OUTREG(0x6578,0x30301);
976    OUTREG(0x657C,0xBFC88280);
977    OUTREG(0x6578,0x30400);
978    OUTREG(0x657C,0x8DE0BEE0);
979    OUTREG(0x6578,0x30401);
980    OUTREG(0x657C,0xBFA083A0);
981    OUTREG(0x6578,0x30500);
982    OUTREG(0x657C,0x8CE0BED0);
983    OUTREG(0x6578,0x30501);
984    OUTREG(0x657C,0xBF7884E0);
985    OUTREG(0x6578,0x30600);
986    OUTREG(0x657C,0x8BA0BED8);
987    OUTREG(0x6578,0x30601);
988    OUTREG(0x657C,0xBF508640);
989    OUTREG(0x6578,0x30700);
990    OUTREG(0x657C,0x8A60BEE8);
991    OUTREG(0x6578,0x30701);
992    OUTREG(0x657C,0xBF2087A0);
993    OUTREG(0x6578,0x30800);
994    OUTREG(0x657C,0x8900BF00);
995    OUTREG(0x6578,0x30801);
996    OUTREG(0x657C,0xBF008900);
997}
998
999static int
1000atombios_output_yuv_setup(xf86OutputPtr output, Bool enable)
1001{
1002    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1003    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1004    RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
1005    ENABLE_YUV_PS_ALLOCATION disp_data;
1006    AtomBiosArgRec data;
1007    unsigned char *space;
1008    unsigned char *RADEONMMIO = info->MMIO;
1009    uint32_t temp, reg;
1010
1011    if (info->ChipFamily >= CHIP_FAMILY_R600)
1012	reg = R600_BIOS_3_SCRATCH;
1013    else
1014	reg = RADEON_BIOS_3_SCRATCH;
1015
1016    //fix up scratch reg handling
1017    temp = INREG(reg);
1018    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
1019	OUTREG(reg, (ATOM_S3_TV1_ACTIVE |
1020		     (radeon_crtc->crtc_id << 18)));
1021    else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
1022	OUTREG(reg, (ATOM_S3_CV_ACTIVE |
1023		     (radeon_crtc->crtc_id << 24)));
1024    else
1025	OUTREG(reg, 0);
1026
1027    memset(&disp_data, 0, sizeof(disp_data));
1028
1029    if (enable)
1030	disp_data.ucEnable = ATOM_ENABLE;
1031    disp_data.ucCRTC = radeon_crtc->crtc_id;
1032
1033    data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
1034    data.exec.dataSpace = (void *)&space;
1035    data.exec.pspace = &disp_data;
1036
1037    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1038
1039	OUTREG(reg, temp);
1040
1041	ErrorF("crtc %d YUV %s setup success\n", radeon_crtc->crtc_id, enable ? "enable" : "disable");
1042	return ATOM_SUCCESS;
1043    }
1044
1045    OUTREG(reg, temp);
1046
1047    ErrorF("crtc %d YUV %s setup failed\n", radeon_crtc->crtc_id, enable ? "enable" : "disable");
1048    return ATOM_NOT_IMPLEMENTED;
1049
1050}
1051
1052static int
1053atombios_output_overscan_setup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
1054{
1055    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1056    RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
1057    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1058    SET_CRTC_OVERSCAN_PS_ALLOCATION overscan_param;
1059    AtomBiosArgRec data;
1060    unsigned char *space;
1061    memset(&overscan_param, 0, sizeof(overscan_param));
1062
1063    overscan_param.usOverscanRight = 0;
1064    overscan_param.usOverscanLeft = 0;
1065    overscan_param.usOverscanBottom = 0;
1066    overscan_param.usOverscanTop = 0;
1067    overscan_param.ucCRTC = radeon_crtc->crtc_id;
1068
1069    if (radeon_output->Flags & RADEON_USE_RMX) {
1070	if (radeon_output->rmx_type == RMX_FULL) {
1071	    overscan_param.usOverscanRight = 0;
1072	    overscan_param.usOverscanLeft = 0;
1073	    overscan_param.usOverscanBottom = 0;
1074	    overscan_param.usOverscanTop = 0;
1075	} else if (radeon_output->rmx_type == RMX_CENTER) {
1076	    overscan_param.usOverscanTop = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2;
1077	    overscan_param.usOverscanBottom = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2;
1078	    overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2;
1079	    overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2;
1080	} else if (radeon_output->rmx_type == RMX_ASPECT) {
1081	    int a1 = mode->CrtcVDisplay * adjusted_mode->CrtcHDisplay;
1082	    int a2 = adjusted_mode->CrtcVDisplay * mode->CrtcHDisplay;
1083
1084	    if (a1 > a2) {
1085		overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2;
1086		overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2;
1087	    } else if (a2 > a1) {
1088		overscan_param.usOverscanLeft = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2;
1089		overscan_param.usOverscanRight = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2;
1090	    }
1091	}
1092    }
1093
1094    data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
1095    data.exec.dataSpace = (void *)&space;
1096    data.exec.pspace = &overscan_param;
1097
1098    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1099	ErrorF("Set CRTC %d Overscan success\n", radeon_crtc->crtc_id);
1100	return ATOM_SUCCESS ;
1101    }
1102
1103    ErrorF("Set CRTC %d Overscan failed\n", radeon_crtc->crtc_id);
1104    return ATOM_NOT_IMPLEMENTED;
1105}
1106
1107static int
1108atombios_output_scaler_setup(xf86OutputPtr output)
1109{
1110    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1111    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1112    radeon_tvout_ptr tvout = &radeon_output->tvout;
1113    RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
1114    ENABLE_SCALER_PS_ALLOCATION disp_data;
1115    AtomBiosArgRec data;
1116    unsigned char *space;
1117
1118    if (!IS_AVIVO_VARIANT && radeon_crtc->crtc_id)
1119	return ATOM_SUCCESS;
1120
1121    memset(&disp_data, 0, sizeof(disp_data));
1122
1123    disp_data.ucScaler = radeon_crtc->crtc_id;
1124
1125    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
1126	switch (tvout->tvStd) {
1127	case TV_STD_NTSC:
1128	    disp_data.ucTVStandard = ATOM_TV_NTSC;
1129	    break;
1130	case TV_STD_PAL:
1131	    disp_data.ucTVStandard = ATOM_TV_PAL;
1132	    break;
1133	case TV_STD_PAL_M:
1134	    disp_data.ucTVStandard = ATOM_TV_PALM;
1135	    break;
1136	case TV_STD_PAL_60:
1137	    disp_data.ucTVStandard = ATOM_TV_PAL60;
1138	    break;
1139	case TV_STD_NTSC_J:
1140	    disp_data.ucTVStandard = ATOM_TV_NTSCJ;
1141	    break;
1142	case TV_STD_SCART_PAL:
1143	    disp_data.ucTVStandard = ATOM_TV_PAL; /* ??? */
1144	    break;
1145	case TV_STD_SECAM:
1146	    disp_data.ucTVStandard = ATOM_TV_SECAM;
1147	    break;
1148	case TV_STD_PAL_CN:
1149	    disp_data.ucTVStandard = ATOM_TV_PALCN;
1150	    break;
1151	default:
1152	    disp_data.ucTVStandard = ATOM_TV_NTSC;
1153	    break;
1154	}
1155	disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
1156        ErrorF("Using TV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable);
1157    } else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) {
1158	disp_data.ucTVStandard = ATOM_TV_CV;
1159	disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
1160        ErrorF("Using CV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable);
1161    } else if (radeon_output->Flags & RADEON_USE_RMX) {
1162	ErrorF("Using RMX\n");
1163	if (radeon_output->rmx_type == RMX_FULL)
1164	    disp_data.ucEnable = ATOM_SCALER_EXPANSION;
1165	else if (radeon_output->rmx_type == RMX_CENTER)
1166	    disp_data.ucEnable = ATOM_SCALER_CENTER;
1167	else if (radeon_output->rmx_type == RMX_ASPECT)
1168	    disp_data.ucEnable = ATOM_SCALER_EXPANSION;
1169    } else {
1170	ErrorF("Not using RMX\n");
1171	if (IS_AVIVO_VARIANT)
1172	    disp_data.ucEnable = ATOM_SCALER_DISABLE;
1173	else
1174	    disp_data.ucEnable = ATOM_SCALER_CENTER;
1175    }
1176
1177    data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
1178    data.exec.dataSpace = (void *)&space;
1179    data.exec.pspace = &disp_data;
1180
1181    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1182	if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
1183	    && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) {
1184	    ErrorF("forcing TV scaler\n");
1185	    atom_rv515_force_tv_scaler(output->scrn);
1186	}
1187	ErrorF("scaler %d setup success\n", radeon_crtc->crtc_id);
1188	return ATOM_SUCCESS;
1189    }
1190
1191    ErrorF("scaler %d setup failed\n", radeon_crtc->crtc_id);
1192    return ATOM_NOT_IMPLEMENTED;
1193
1194}
1195
1196void
1197atombios_output_dpms(xf86OutputPtr output, int mode)
1198{
1199    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1200    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
1201    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1202    DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION disp_data;
1203    AtomBiosArgRec data;
1204    unsigned char *space;
1205    int index = 0;
1206    Bool is_dig = FALSE;
1207
1208    if (radeon_encoder == NULL)
1209        return;
1210
1211    switch (radeon_encoder->encoder_id) {
1212    case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1213    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1214	index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1215	break;
1216    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1217    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1218    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1219    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1220	is_dig = TRUE;
1221	break;
1222    case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1223    case ENCODER_OBJECT_ID_INTERNAL_DDI:
1224    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1225	index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1226	break;
1227    case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1228	index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1229	break;
1230    case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1231	if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT))
1232	    index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1233	else
1234	    index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1235	break;
1236    case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1237    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1238	if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
1239	    index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1240	else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
1241	    index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1242	else
1243	    index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1244	break;
1245    case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1246    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1247	if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
1248	    index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1249	else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
1250	    index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1251	else
1252	    index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1253	break;
1254    }
1255
1256    switch (mode) {
1257    case DPMSModeOn:
1258	radeon_encoder->devices |= radeon_output->active_device;
1259	if (is_dig)
1260	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
1261	else {
1262	    disp_data.ucAction = ATOM_ENABLE;
1263	    data.exec.index = index;
1264	    data.exec.dataSpace = (void *)&space;
1265	    data.exec.pspace = &disp_data;
1266
1267	    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS)
1268		ErrorF("Output %s enable success\n",
1269		       device_name[radeon_get_device_index(radeon_output->active_device)]);
1270	    else
1271		ErrorF("Output %s enable failed\n",
1272		       device_name[radeon_get_device_index(radeon_output->active_device)]);
1273	}
1274	break;
1275    case DPMSModeStandby:
1276    case DPMSModeSuspend:
1277    case DPMSModeOff:
1278	radeon_encoder->devices &= ~(radeon_output->active_device);
1279	if (!radeon_encoder->devices) {
1280	    if (is_dig)
1281		atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
1282	    else {
1283		disp_data.ucAction = ATOM_DISABLE;
1284		data.exec.index = index;
1285		data.exec.dataSpace = (void *)&space;
1286		data.exec.pspace = &disp_data;
1287
1288		if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data)
1289		    == ATOM_SUCCESS)
1290		    ErrorF("Output %s disable success\n",
1291			   device_name[radeon_get_device_index(radeon_output->active_device)]);
1292		else
1293		    ErrorF("Output %s disable failed\n",
1294			   device_name[radeon_get_device_index(radeon_output->active_device)]);
1295	    }
1296	}
1297	break;
1298    }
1299}
1300
1301static void
1302atombios_set_output_crtc_source(xf86OutputPtr output)
1303{
1304    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1305    RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
1306    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1307    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
1308    AtomBiosArgRec data;
1309    unsigned char *space;
1310    SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_src_param;
1311    SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc_src_param2;
1312    int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
1313    int major, minor;
1314
1315    if (radeon_encoder == NULL)
1316	return;
1317
1318    memset(&crtc_src_param, 0, sizeof(crtc_src_param));
1319    memset(&crtc_src_param2, 0, sizeof(crtc_src_param2));
1320    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
1321
1322    /*ErrorF("select crtc source table is %d %d\n", major, minor);*/
1323
1324    switch(major) {
1325    case 1:
1326	switch(minor) {
1327	case 0:
1328	case 1:
1329	default:
1330	    if (IS_AVIVO_VARIANT)
1331		crtc_src_param.ucCRTC = radeon_crtc->crtc_id;
1332	    else {
1333		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)
1334		    crtc_src_param.ucCRTC = radeon_crtc->crtc_id;
1335		else
1336		    crtc_src_param.ucCRTC = radeon_crtc->crtc_id << 2;
1337	    }
1338	    switch (radeon_encoder->encoder_id) {
1339	    case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1340	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1341		crtc_src_param.ucDevice = ATOM_DEVICE_DFP1_INDEX;
1342		break;
1343	    case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1344	    case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1345		if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT)
1346		    crtc_src_param.ucDevice = ATOM_DEVICE_LCD1_INDEX;
1347		else
1348		    crtc_src_param.ucDevice = ATOM_DEVICE_DFP3_INDEX;
1349		break;
1350	    case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1351	    case ENCODER_OBJECT_ID_INTERNAL_DDI:
1352	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1353		crtc_src_param.ucDevice = ATOM_DEVICE_DFP2_INDEX;
1354		break;
1355	    case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1356	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1357		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
1358		    crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX;
1359		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
1360		    crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX;
1361		else
1362		    crtc_src_param.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1363		break;
1364	    case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1365	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1366		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
1367		    crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX;
1368		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
1369		    crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX;
1370		else
1371		    crtc_src_param.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1372		break;
1373	    }
1374	    data.exec.pspace = &crtc_src_param;
1375	    /*ErrorF("device sourced: 0x%x\n", crtc_src_param.ucDevice);*/
1376	    break;
1377	case 2:
1378	    crtc_src_param2.ucCRTC = radeon_crtc->crtc_id;
1379	    crtc_src_param2.ucEncodeMode = atombios_get_encoder_mode(output);
1380	    switch (radeon_encoder->encoder_id) {
1381	    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1382	    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1383	    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1384		if (IS_DCE32_VARIANT) {
1385		    if (radeon_crtc->crtc_id)
1386			crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1387		    else
1388			crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1389		} else
1390		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1391		break;
1392	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1393		crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1394		break;
1395	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1396		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
1397		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1398		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
1399		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1400		else
1401		    crtc_src_param2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1402		break;
1403	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1404		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
1405		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1406		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
1407		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1408		else
1409		    crtc_src_param2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1410		break;
1411	    }
1412	    data.exec.pspace = &crtc_src_param2;
1413	    /*ErrorF("device sourced: 0x%x\n", crtc_src_param2.ucEncoderID);*/
1414	    break;
1415	}
1416	break;
1417    default:
1418	ErrorF("Unknown table version\n");
1419	exit(-1);
1420    }
1421
1422    data.exec.index = index;
1423    data.exec.dataSpace = (void *)&space;
1424
1425    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1426	ErrorF("Set CRTC %d Source success\n", radeon_crtc->crtc_id);
1427	return;
1428    }
1429
1430    ErrorF("Set CRTC Source failed\n");
1431    return;
1432}
1433
1434static void
1435atombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode)
1436{
1437    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1438    RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
1439    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1440    unsigned char *RADEONMMIO = info->MMIO;
1441
1442    /* Funky macbooks */
1443    if ((info->Chipset == PCI_CHIP_RV530_71C5) &&
1444	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) &&
1445	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) {
1446	if (radeon_output->MonType == MT_LCD) {
1447	    if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1448		uint32_t lvtma_bit_depth_control = INREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1449
1450		lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1451		lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1452
1453		OUTREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1454	    }
1455	}
1456    }
1457
1458    /* set scaler clears this on some chips */
1459    if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE))
1460	OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN);
1461}
1462
1463void
1464atombios_output_mode_set(xf86OutputPtr output,
1465			 DisplayModePtr mode,
1466			 DisplayModePtr adjusted_mode)
1467{
1468    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1469    RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
1470    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
1471    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1472    if (radeon_encoder == NULL)
1473        return;
1474
1475    radeon_output->pixel_clock = adjusted_mode->Clock;
1476    radeon_output->dig_block = radeon_crtc->crtc_id;
1477    atombios_output_overscan_setup(output, mode, adjusted_mode);
1478    atombios_output_scaler_setup(output);
1479    atombios_set_output_crtc_source(output);
1480
1481    if (IS_AVIVO_VARIANT) {
1482	if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
1483	    atombios_output_yuv_setup(output, TRUE);
1484	else
1485	    atombios_output_yuv_setup(output, FALSE);
1486    }
1487
1488    switch (radeon_encoder->encoder_id) {
1489    case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1490    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1491    case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1492    case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1493	atombios_output_digital_setup(output, PANEL_ENCODER_ACTION_ENABLE);
1494	break;
1495    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1496    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1497    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1498    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1499	/* disable encoder and transmitter */
1500	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE);
1501	atombios_output_dig_encoder_setup(output, ATOM_DISABLE);
1502
1503	/* setup and enable the encoder and transmitter */
1504	atombios_output_dig_encoder_setup(output, ATOM_ENABLE);
1505	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP);
1506	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE);
1507	break;
1508    case ENCODER_OBJECT_ID_INTERNAL_DDI:
1509	atombios_output_ddia_setup(output, ATOM_ENABLE);
1510	break;
1511    case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1512    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1513	atombios_external_tmds_setup(output, ATOM_ENABLE);
1514	break;
1515    case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1516    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1517    case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1518    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1519	atombios_output_dac_setup(output, ATOM_ENABLE);
1520	if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
1521	    atombios_output_tv_setup(output, ATOM_ENABLE);
1522	break;
1523    }
1524    atombios_apply_output_quirks(output, adjusted_mode);
1525}
1526
1527static AtomBiosResult
1528atom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output)
1529{
1530    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1531    RADEONInfoPtr info       = RADEONPTR(output->scrn);
1532    DAC_LOAD_DETECTION_PS_ALLOCATION dac_data;
1533    AtomBiosArgRec data;
1534    unsigned char *space;
1535    int major, minor;
1536    int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1537
1538    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
1539
1540    dac_data.sDacload.ucMisc = 0;
1541
1542    if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) {
1543	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
1544	if (info->encoders[ATOM_DEVICE_CRT1_INDEX] &&
1545	    ((info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1546	     (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
1547	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
1548	else
1549	    dac_data.sDacload.ucDacType = ATOM_DAC_B;
1550    } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) {
1551	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
1552	if (info->encoders[ATOM_DEVICE_CRT2_INDEX] &&
1553	    ((info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1554	     (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
1555	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
1556	else
1557	    dac_data.sDacload.ucDacType = ATOM_DAC_B;
1558    } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) {
1559	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
1560	if (info->encoders[ATOM_DEVICE_CV_INDEX] &&
1561	    ((info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1562	     (info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
1563	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
1564	else
1565	    dac_data.sDacload.ucDacType = ATOM_DAC_B;
1566	if (minor >= 3)
1567	    dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1568    } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
1569	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
1570	if (info->encoders[ATOM_DEVICE_TV1_INDEX] &&
1571	    ((info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1572	     (info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
1573	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
1574	else
1575	    dac_data.sDacload.ucDacType = ATOM_DAC_B;
1576	if (minor >= 3)
1577	    dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1578    } else
1579	return ATOM_NOT_IMPLEMENTED;
1580
1581    data.exec.index = index;
1582    data.exec.dataSpace = (void *)&space;
1583    data.exec.pspace = &dac_data;
1584
1585    if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1586	ErrorF("Dac detection success\n");
1587	return ATOM_SUCCESS ;
1588    }
1589
1590    ErrorF("DAC detection failed\n");
1591    return ATOM_NOT_IMPLEMENTED;
1592}
1593
1594RADEONMonitorType
1595atombios_dac_detect(xf86OutputPtr output)
1596{
1597    ScrnInfoPtr pScrn = output->scrn;
1598    RADEONInfoPtr info       = RADEONPTR(pScrn);
1599    unsigned char *RADEONMMIO = info->MMIO;
1600    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1601    RADEONMonitorType MonType = MT_NONE;
1602    AtomBiosResult ret;
1603    uint32_t bios_0_scratch;
1604
1605    if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
1606	if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
1607	    if (radeon_output->ConnectorType == CONNECTOR_STV)
1608		return MT_STV;
1609	    else
1610		return MT_CTV;
1611	}
1612    }
1613
1614    ret = atom_bios_dac_load_detect(info->atomBIOS, output);
1615    if (ret == ATOM_SUCCESS) {
1616	if (info->ChipFamily >= CHIP_FAMILY_R600)
1617	    bios_0_scratch = INREG(R600_BIOS_0_SCRATCH);
1618	else
1619	    bios_0_scratch = INREG(RADEON_BIOS_0_SCRATCH);
1620	/*ErrorF("DAC connect %08X\n", (unsigned int)bios_0_scratch);*/
1621
1622	if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) {
1623	    if (bios_0_scratch & ATOM_S0_CRT1_MASK)
1624		MonType = MT_CRT;
1625	} else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) {
1626	    if (bios_0_scratch & ATOM_S0_CRT2_MASK)
1627		MonType = MT_CRT;
1628	} else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) {
1629	    if (bios_0_scratch & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A))
1630		MonType = MT_CV;
1631	} else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
1632	    if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
1633		MonType = MT_CTV;
1634	    else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
1635		MonType = MT_STV;
1636	}
1637    }
1638
1639    return MonType;
1640}
1641
1642