blob: 57a29f36115eb3859774bcdfaea4cd3343859ed8 [file] [log] [blame]
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001/*
2 * Copyright 2007-8 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Dave Airlie
24 * Alex Deucher
25 */
26#include "drmP.h"
27#include "drm_crtc_helper.h"
28#include "radeon_drm.h"
29#include "radeon.h"
30#include "atom.h"
31
32extern int atom_debug;
33
Alex Deucher5a9bcac2009-10-08 15:09:31 -040034/* evil but including atombios.h is much worse */
35bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
36 struct drm_display_mode *mode);
37
Jerome Glisse771fe6b2009-06-05 14:42:42 +020038uint32_t
39radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
40{
41 struct radeon_device *rdev = dev->dev_private;
42 uint32_t ret = 0;
43
44 switch (supported_device) {
45 case ATOM_DEVICE_CRT1_SUPPORT:
46 case ATOM_DEVICE_TV1_SUPPORT:
47 case ATOM_DEVICE_TV2_SUPPORT:
48 case ATOM_DEVICE_CRT2_SUPPORT:
49 case ATOM_DEVICE_CV_SUPPORT:
50 switch (dac) {
51 case 1: /* dac a */
52 if ((rdev->family == CHIP_RS300) ||
53 (rdev->family == CHIP_RS400) ||
54 (rdev->family == CHIP_RS480))
55 ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
56 else if (ASIC_IS_AVIVO(rdev))
57 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
58 else
59 ret = ENCODER_OBJECT_ID_INTERNAL_DAC1;
60 break;
61 case 2: /* dac b */
62 if (ASIC_IS_AVIVO(rdev))
63 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
64 else {
65 /*if (rdev->family == CHIP_R200)
66 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
67 else*/
68 ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
69 }
70 break;
71 case 3: /* external dac */
72 if (ASIC_IS_AVIVO(rdev))
73 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
74 else
75 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
76 break;
77 }
78 break;
79 case ATOM_DEVICE_LCD1_SUPPORT:
80 if (ASIC_IS_AVIVO(rdev))
81 ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
82 else
83 ret = ENCODER_OBJECT_ID_INTERNAL_LVDS;
84 break;
85 case ATOM_DEVICE_DFP1_SUPPORT:
86 if ((rdev->family == CHIP_RS300) ||
87 (rdev->family == CHIP_RS400) ||
88 (rdev->family == CHIP_RS480))
89 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
90 else if (ASIC_IS_AVIVO(rdev))
91 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
92 else
93 ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1;
94 break;
95 case ATOM_DEVICE_LCD2_SUPPORT:
96 case ATOM_DEVICE_DFP2_SUPPORT:
97 if ((rdev->family == CHIP_RS600) ||
98 (rdev->family == CHIP_RS690) ||
99 (rdev->family == CHIP_RS740))
100 ret = ENCODER_OBJECT_ID_INTERNAL_DDI;
101 else if (ASIC_IS_AVIVO(rdev))
102 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
103 else
104 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
105 break;
106 case ATOM_DEVICE_DFP3_SUPPORT:
107 ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
108 break;
109 }
110
111 return ret;
112}
113
114void
115radeon_link_encoder_connector(struct drm_device *dev)
116{
117 struct drm_connector *connector;
118 struct radeon_connector *radeon_connector;
119 struct drm_encoder *encoder;
120 struct radeon_encoder *radeon_encoder;
121
122 /* walk the list and link encoders to connectors */
123 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
124 radeon_connector = to_radeon_connector(connector);
125 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
126 radeon_encoder = to_radeon_encoder(encoder);
127 if (radeon_encoder->devices & radeon_connector->devices)
128 drm_mode_connector_attach_encoder(connector, encoder);
129 }
130 }
131}
132
Dave Airlie4ce001a2009-08-13 16:32:14 +1000133void radeon_encoder_set_active_device(struct drm_encoder *encoder)
134{
135 struct drm_device *dev = encoder->dev;
136 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
137 struct drm_connector *connector;
138
139 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
140 if (connector->encoder == encoder) {
141 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
142 radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
Dave Airlief641e512009-09-08 11:17:38 +1000143 DRM_DEBUG("setting active device to %08x from %08x %08x for encoder %d\n",
144 radeon_encoder->active_device, radeon_encoder->devices,
145 radeon_connector->devices, encoder->encoder_type);
Dave Airlie4ce001a2009-08-13 16:32:14 +1000146 }
147 }
148}
149
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200150static struct drm_connector *
151radeon_get_connector_for_encoder(struct drm_encoder *encoder)
152{
153 struct drm_device *dev = encoder->dev;
154 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
155 struct drm_connector *connector;
156 struct radeon_connector *radeon_connector;
157
158 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
159 radeon_connector = to_radeon_connector(connector);
160 if (radeon_encoder->devices & radeon_connector->devices)
161 return connector;
162 }
163 return NULL;
164}
165
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200166static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
167 struct drm_display_mode *mode,
168 struct drm_display_mode *adjusted_mode)
169{
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200170 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
Alex Deucher5a9bcac2009-10-08 15:09:31 -0400171 struct drm_device *dev = encoder->dev;
172 struct radeon_device *rdev = dev->dev_private;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200173
Alex Deucher8c2a6d72009-10-14 02:00:42 -0400174 /* set the active encoder to connector routing */
175 radeon_encoder_set_active_device(encoder);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200176 drm_mode_set_crtcinfo(adjusted_mode, 0);
177
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200178 /* hw bug */
179 if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
180 && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
181 adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
182
Alex Deucher80297e82009-11-12 14:55:14 -0500183 /* get the native mode for LVDS */
184 if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
185 struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
186 int mode_id = adjusted_mode->base.id;
187 *adjusted_mode = *native_mode;
188 if (!ASIC_IS_AVIVO(rdev)) {
189 adjusted_mode->hdisplay = mode->hdisplay;
190 adjusted_mode->vdisplay = mode->vdisplay;
191 }
192 adjusted_mode->base.id = mode_id;
193 }
194
195 /* get the native mode for TV */
Alex Deucherceefedd2009-10-13 23:57:47 -0400196 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
Alex Deucher5a9bcac2009-10-08 15:09:31 -0400197 struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
198 if (tv_dac) {
199 if (tv_dac->tv_std == TV_STD_NTSC ||
200 tv_dac->tv_std == TV_STD_NTSC_J ||
201 tv_dac->tv_std == TV_STD_PAL_M)
202 radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
203 else
204 radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
205 }
206 }
207
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200208 return true;
209}
210
211static void
212atombios_dac_setup(struct drm_encoder *encoder, int action)
213{
214 struct drm_device *dev = encoder->dev;
215 struct radeon_device *rdev = dev->dev_private;
216 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
217 DAC_ENCODER_CONTROL_PS_ALLOCATION args;
218 int index = 0, num = 0;
Dave Airlie445282d2009-09-09 17:40:54 +1000219 struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200220 enum radeon_tv_std tv_std = TV_STD_NTSC;
221
Dave Airlie445282d2009-09-09 17:40:54 +1000222 if (dac_info->tv_std)
223 tv_std = dac_info->tv_std;
224
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200225 memset(&args, 0, sizeof(args));
226
227 switch (radeon_encoder->encoder_id) {
228 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
229 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
230 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
231 num = 1;
232 break;
233 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
234 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
235 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
236 num = 2;
237 break;
238 }
239
240 args.ucAction = action;
241
Dave Airlie4ce001a2009-08-13 16:32:14 +1000242 if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200243 args.ucDacStandard = ATOM_DAC1_PS2;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000244 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200245 args.ucDacStandard = ATOM_DAC1_CV;
246 else {
247 switch (tv_std) {
248 case TV_STD_PAL:
249 case TV_STD_PAL_M:
250 case TV_STD_SCART_PAL:
251 case TV_STD_SECAM:
252 case TV_STD_PAL_CN:
253 args.ucDacStandard = ATOM_DAC1_PAL;
254 break;
255 case TV_STD_NTSC:
256 case TV_STD_NTSC_J:
257 case TV_STD_PAL_60:
258 default:
259 args.ucDacStandard = ATOM_DAC1_NTSC;
260 break;
261 }
262 }
263 args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
264
265 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
266
267}
268
269static void
270atombios_tv_setup(struct drm_encoder *encoder, int action)
271{
272 struct drm_device *dev = encoder->dev;
273 struct radeon_device *rdev = dev->dev_private;
274 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
275 TV_ENCODER_CONTROL_PS_ALLOCATION args;
276 int index = 0;
Dave Airlie445282d2009-09-09 17:40:54 +1000277 struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200278 enum radeon_tv_std tv_std = TV_STD_NTSC;
279
Dave Airlie445282d2009-09-09 17:40:54 +1000280 if (dac_info->tv_std)
281 tv_std = dac_info->tv_std;
282
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200283 memset(&args, 0, sizeof(args));
284
285 index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
286
287 args.sTVEncoder.ucAction = action;
288
Dave Airlie4ce001a2009-08-13 16:32:14 +1000289 if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200290 args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
291 else {
292 switch (tv_std) {
293 case TV_STD_NTSC:
294 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
295 break;
296 case TV_STD_PAL:
297 args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
298 break;
299 case TV_STD_PAL_M:
300 args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
301 break;
302 case TV_STD_PAL_60:
303 args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
304 break;
305 case TV_STD_NTSC_J:
306 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
307 break;
308 case TV_STD_SCART_PAL:
309 args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
310 break;
311 case TV_STD_SECAM:
312 args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
313 break;
314 case TV_STD_PAL_CN:
315 args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
316 break;
317 default:
318 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
319 break;
320 }
321 }
322
323 args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
324
325 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
326
327}
328
329void
330atombios_external_tmds_setup(struct drm_encoder *encoder, int action)
331{
332 struct drm_device *dev = encoder->dev;
333 struct radeon_device *rdev = dev->dev_private;
334 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
335 ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args;
336 int index = 0;
337
338 memset(&args, 0, sizeof(args));
339
340 index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
341
342 args.sXTmdsEncoder.ucEnable = action;
343
344 if (radeon_encoder->pixel_clock > 165000)
345 args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
346
347 /*if (pScrn->rgbBits == 8)*/
348 args.sXTmdsEncoder.ucMisc |= (1 << 1);
349
350 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
351
352}
353
354static void
355atombios_ddia_setup(struct drm_encoder *encoder, int action)
356{
357 struct drm_device *dev = encoder->dev;
358 struct radeon_device *rdev = dev->dev_private;
359 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
360 DVO_ENCODER_CONTROL_PS_ALLOCATION args;
361 int index = 0;
362
363 memset(&args, 0, sizeof(args));
364
365 index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
366
367 args.sDVOEncoder.ucAction = action;
368 args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
369
370 if (radeon_encoder->pixel_clock > 165000)
371 args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
372
373 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
374
375}
376
377union lvds_encoder_control {
378 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1;
379 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
380};
381
382static void
383atombios_digital_setup(struct drm_encoder *encoder, int action)
384{
385 struct drm_device *dev = encoder->dev;
386 struct radeon_device *rdev = dev->dev_private;
387 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
388 union lvds_encoder_control args;
389 int index = 0;
390 uint8_t frev, crev;
391 struct radeon_encoder_atom_dig *dig;
392 struct drm_connector *connector;
393 struct radeon_connector *radeon_connector;
394 struct radeon_connector_atom_dig *dig_connector;
395
396 connector = radeon_get_connector_for_encoder(encoder);
397 if (!connector)
398 return;
399
400 radeon_connector = to_radeon_connector(connector);
401
402 if (!radeon_encoder->enc_priv)
403 return;
404
405 dig = radeon_encoder->enc_priv;
406
407 if (!radeon_connector->con_priv)
408 return;
409
410 dig_connector = radeon_connector->con_priv;
411
412 memset(&args, 0, sizeof(args));
413
414 switch (radeon_encoder->encoder_id) {
415 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
416 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
417 break;
418 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
419 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
420 index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
421 break;
422 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
423 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
424 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
425 else
426 index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
427 break;
428 }
429
430 atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
431
432 switch (frev) {
433 case 1:
434 case 2:
435 switch (crev) {
436 case 1:
437 args.v1.ucMisc = 0;
438 args.v1.ucAction = action;
Alex Deucher0294cf4f2009-10-15 16:16:35 -0400439 if (drm_detect_hdmi_monitor(radeon_connector->edid))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200440 args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
441 args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
442 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
443 if (dig->lvds_misc & (1 << 0))
444 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
445 if (dig->lvds_misc & (1 << 1))
446 args.v1.ucMisc |= (1 << 1);
447 } else {
448 if (dig_connector->linkb)
449 args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
450 if (radeon_encoder->pixel_clock > 165000)
451 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
452 /*if (pScrn->rgbBits == 8) */
453 args.v1.ucMisc |= (1 << 1);
454 }
455 break;
456 case 2:
457 case 3:
458 args.v2.ucMisc = 0;
459 args.v2.ucAction = action;
460 if (crev == 3) {
461 if (dig->coherent_mode)
462 args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
463 }
Alex Deucher0294cf4f2009-10-15 16:16:35 -0400464 if (drm_detect_hdmi_monitor(radeon_connector->edid))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200465 args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
466 args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
467 args.v2.ucTruncate = 0;
468 args.v2.ucSpatial = 0;
469 args.v2.ucTemporal = 0;
470 args.v2.ucFRC = 0;
471 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
472 if (dig->lvds_misc & (1 << 0))
473 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
474 if (dig->lvds_misc & (1 << 5)) {
475 args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
476 if (dig->lvds_misc & (1 << 1))
477 args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
478 }
479 if (dig->lvds_misc & (1 << 6)) {
480 args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
481 if (dig->lvds_misc & (1 << 1))
482 args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
483 if (((dig->lvds_misc >> 2) & 0x3) == 2)
484 args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
485 }
486 } else {
487 if (dig_connector->linkb)
488 args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
489 if (radeon_encoder->pixel_clock > 165000)
490 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
491 }
492 break;
493 default:
494 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
495 break;
496 }
497 break;
498 default:
499 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
500 break;
501 }
502
503 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
504
505}
506
507int
508atombios_get_encoder_mode(struct drm_encoder *encoder)
509{
510 struct drm_connector *connector;
511 struct radeon_connector *radeon_connector;
512
513 connector = radeon_get_connector_for_encoder(encoder);
514 if (!connector)
515 return 0;
516
517 radeon_connector = to_radeon_connector(connector);
518
519 switch (connector->connector_type) {
520 case DRM_MODE_CONNECTOR_DVII:
Alex Deucher705af9c2009-09-10 16:31:13 -0400521 case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
Alex Deucher0294cf4f2009-10-15 16:16:35 -0400522 if (drm_detect_hdmi_monitor(radeon_connector->edid))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200523 return ATOM_ENCODER_MODE_HDMI;
524 else if (radeon_connector->use_digital)
525 return ATOM_ENCODER_MODE_DVI;
526 else
527 return ATOM_ENCODER_MODE_CRT;
528 break;
529 case DRM_MODE_CONNECTOR_DVID:
530 case DRM_MODE_CONNECTOR_HDMIA:
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200531 default:
Alex Deucher0294cf4f2009-10-15 16:16:35 -0400532 if (drm_detect_hdmi_monitor(radeon_connector->edid))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200533 return ATOM_ENCODER_MODE_HDMI;
534 else
535 return ATOM_ENCODER_MODE_DVI;
536 break;
537 case DRM_MODE_CONNECTOR_LVDS:
538 return ATOM_ENCODER_MODE_LVDS;
539 break;
540 case DRM_MODE_CONNECTOR_DisplayPort:
541 /*if (radeon_output->MonType == MT_DP)
542 return ATOM_ENCODER_MODE_DP;
543 else*/
Alex Deucher0294cf4f2009-10-15 16:16:35 -0400544 if (drm_detect_hdmi_monitor(radeon_connector->edid))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200545 return ATOM_ENCODER_MODE_HDMI;
546 else
547 return ATOM_ENCODER_MODE_DVI;
548 break;
549 case CONNECTOR_DVI_A:
550 case CONNECTOR_VGA:
551 return ATOM_ENCODER_MODE_CRT;
552 break;
553 case CONNECTOR_STV:
554 case CONNECTOR_CTV:
555 case CONNECTOR_DIN:
556 /* fix me */
557 return ATOM_ENCODER_MODE_TV;
558 /*return ATOM_ENCODER_MODE_CV;*/
559 break;
560 }
561}
562
563static void
564atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
565{
566 struct drm_device *dev = encoder->dev;
567 struct radeon_device *rdev = dev->dev_private;
568 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
569 DIG_ENCODER_CONTROL_PS_ALLOCATION args;
570 int index = 0, num = 0;
571 uint8_t frev, crev;
572 struct radeon_encoder_atom_dig *dig;
573 struct drm_connector *connector;
574 struct radeon_connector *radeon_connector;
575 struct radeon_connector_atom_dig *dig_connector;
576
577 connector = radeon_get_connector_for_encoder(encoder);
578 if (!connector)
579 return;
580
581 radeon_connector = to_radeon_connector(connector);
582
583 if (!radeon_connector->con_priv)
584 return;
585
586 dig_connector = radeon_connector->con_priv;
587
588 if (!radeon_encoder->enc_priv)
589 return;
590
591 dig = radeon_encoder->enc_priv;
592
593 memset(&args, 0, sizeof(args));
594
595 if (ASIC_IS_DCE32(rdev)) {
596 if (dig->dig_block)
597 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
598 else
599 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
600 num = dig->dig_block + 1;
601 } else {
602 switch (radeon_encoder->encoder_id) {
603 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
604 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
605 num = 1;
606 break;
607 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
608 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
609 num = 2;
610 break;
611 }
612 }
613
614 atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
615
616 args.ucAction = action;
617 args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
618
619 if (ASIC_IS_DCE32(rdev)) {
620 switch (radeon_encoder->encoder_id) {
621 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
622 args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
623 break;
624 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
625 args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
626 break;
627 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
628 args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
629 break;
630 }
631 } else {
632 switch (radeon_encoder->encoder_id) {
633 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
634 args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
635 break;
636 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
637 args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2;
638 break;
639 }
640 }
641
642 if (radeon_encoder->pixel_clock > 165000) {
643 args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
644 args.ucLaneNum = 8;
645 } else {
646 if (dig_connector->linkb)
647 args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
648 else
649 args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
650 args.ucLaneNum = 4;
651 }
652
653 args.ucEncoderMode = atombios_get_encoder_mode(encoder);
654
655 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
656
657}
658
659union dig_transmitter_control {
660 DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
661 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
662};
663
664static void
665atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
666{
667 struct drm_device *dev = encoder->dev;
668 struct radeon_device *rdev = dev->dev_private;
669 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
670 union dig_transmitter_control args;
671 int index = 0, num = 0;
672 uint8_t frev, crev;
673 struct radeon_encoder_atom_dig *dig;
674 struct drm_connector *connector;
675 struct radeon_connector *radeon_connector;
676 struct radeon_connector_atom_dig *dig_connector;
677
678 connector = radeon_get_connector_for_encoder(encoder);
679 if (!connector)
680 return;
681
682 radeon_connector = to_radeon_connector(connector);
683
684 if (!radeon_encoder->enc_priv)
685 return;
686
687 dig = radeon_encoder->enc_priv;
688
689 if (!radeon_connector->con_priv)
690 return;
691
692 dig_connector = radeon_connector->con_priv;
693
694 memset(&args, 0, sizeof(args));
695
696 if (ASIC_IS_DCE32(rdev))
697 index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
698 else {
699 switch (radeon_encoder->encoder_id) {
700 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
701 index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
702 break;
703 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
704 index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
705 break;
706 }
707 }
708
709 atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
710
711 args.v1.ucAction = action;
Alex Deucherf95a9f02009-11-05 02:21:06 -0500712 if (action == ATOM_TRANSMITTER_ACTION_INIT) {
713 args.v1.usInitInfo = radeon_connector->connector_object_id;
714 } else {
715 if (radeon_encoder->pixel_clock > 165000)
716 args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
717 else
718 args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
719 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200720 if (ASIC_IS_DCE32(rdev)) {
Alex Deucherf95a9f02009-11-05 02:21:06 -0500721 if (radeon_encoder->pixel_clock > 165000)
Alex Deucher4170a6c2009-11-05 01:16:23 -0500722 args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200723 if (dig->dig_block)
724 args.v2.acConfig.ucEncoderSel = 1;
725
726 switch (radeon_encoder->encoder_id) {
727 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
728 args.v2.acConfig.ucTransmitterSel = 0;
729 num = 0;
730 break;
731 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
732 args.v2.acConfig.ucTransmitterSel = 1;
733 num = 1;
734 break;
735 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
736 args.v2.acConfig.ucTransmitterSel = 2;
737 num = 2;
738 break;
739 }
740
741 if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
742 if (dig->coherent_mode)
743 args.v2.acConfig.fCoherentMode = 1;
744 }
745 } else {
746 args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200747
748 switch (radeon_encoder->encoder_id) {
749 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
750 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
751 if (rdev->flags & RADEON_IS_IGP) {
752 if (radeon_encoder->pixel_clock > 165000) {
753 args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
754 ATOM_TRANSMITTER_CONFIG_LINKA_B);
755 if (dig_connector->igp_lane_info & 0x3)
756 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
757 else if (dig_connector->igp_lane_info & 0xc)
758 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
759 } else {
760 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
761 if (dig_connector->igp_lane_info & 0x1)
762 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
763 else if (dig_connector->igp_lane_info & 0x2)
764 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
765 else if (dig_connector->igp_lane_info & 0x4)
766 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
767 else if (dig_connector->igp_lane_info & 0x8)
768 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
769 }
770 } else {
771 if (radeon_encoder->pixel_clock > 165000)
772 args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
773 ATOM_TRANSMITTER_CONFIG_LINKA_B |
774 ATOM_TRANSMITTER_CONFIG_LANE_0_7);
775 else {
776 if (dig_connector->linkb)
777 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
778 else
779 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
780 }
781 }
782 break;
783 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
784 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
785 if (radeon_encoder->pixel_clock > 165000)
786 args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
787 ATOM_TRANSMITTER_CONFIG_LINKA_B |
788 ATOM_TRANSMITTER_CONFIG_LANE_0_7);
789 else {
790 if (dig_connector->linkb)
791 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
792 else
793 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
794 }
795 break;
796 }
797
798 if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
799 if (dig->coherent_mode)
800 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
801 }
802 }
803
804 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
805
806}
807
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200808static void
809atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
810{
811 struct drm_device *dev = encoder->dev;
812 struct radeon_device *rdev = dev->dev_private;
813 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
814 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
815 ENABLE_YUV_PS_ALLOCATION args;
816 int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
817 uint32_t temp, reg;
818
819 memset(&args, 0, sizeof(args));
820
821 if (rdev->family >= CHIP_R600)
822 reg = R600_BIOS_3_SCRATCH;
823 else
824 reg = RADEON_BIOS_3_SCRATCH;
825
826 /* XXX: fix up scratch reg handling */
827 temp = RREG32(reg);
Dave Airlie4ce001a2009-08-13 16:32:14 +1000828 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200829 WREG32(reg, (ATOM_S3_TV1_ACTIVE |
830 (radeon_crtc->crtc_id << 18)));
Dave Airlie4ce001a2009-08-13 16:32:14 +1000831 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200832 WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
833 else
834 WREG32(reg, 0);
835
836 if (enable)
837 args.ucEnable = ATOM_ENABLE;
838 args.ucCRTC = radeon_crtc->crtc_id;
839
840 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
841
842 WREG32(reg, temp);
843}
844
845static void
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200846radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
847{
848 struct drm_device *dev = encoder->dev;
849 struct radeon_device *rdev = dev->dev_private;
850 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
851 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
852 int index = 0;
853 bool is_dig = false;
854
855 memset(&args, 0, sizeof(args));
856
Dave Airlief641e512009-09-08 11:17:38 +1000857 DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
858 radeon_encoder->encoder_id, mode, radeon_encoder->devices,
859 radeon_encoder->active_device);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200860 switch (radeon_encoder->encoder_id) {
861 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
862 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
863 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
864 break;
865 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
866 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
867 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
868 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
869 is_dig = true;
870 break;
871 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
872 case ENCODER_OBJECT_ID_INTERNAL_DDI:
873 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
874 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
875 break;
876 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
877 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
878 break;
879 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
880 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
881 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
882 else
883 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
884 break;
885 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
886 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
Alex Deucher8c2a6d72009-10-14 02:00:42 -0400887 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200888 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
Alex Deucher8c2a6d72009-10-14 02:00:42 -0400889 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200890 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
891 else
892 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
893 break;
894 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
895 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
Alex Deucher8c2a6d72009-10-14 02:00:42 -0400896 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200897 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
Alex Deucher8c2a6d72009-10-14 02:00:42 -0400898 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200899 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
900 else
901 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
902 break;
903 }
904
905 if (is_dig) {
906 switch (mode) {
907 case DRM_MODE_DPMS_ON:
908 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
909 break;
910 case DRM_MODE_DPMS_STANDBY:
911 case DRM_MODE_DPMS_SUSPEND:
912 case DRM_MODE_DPMS_OFF:
913 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
914 break;
915 }
916 } else {
917 switch (mode) {
918 case DRM_MODE_DPMS_ON:
919 args.ucAction = ATOM_ENABLE;
920 break;
921 case DRM_MODE_DPMS_STANDBY:
922 case DRM_MODE_DPMS_SUSPEND:
923 case DRM_MODE_DPMS_OFF:
924 args.ucAction = ATOM_DISABLE;
925 break;
926 }
927 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
928 }
929 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
930}
931
932union crtc_sourc_param {
933 SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
934 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
935};
936
937static void
938atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
939{
940 struct drm_device *dev = encoder->dev;
941 struct radeon_device *rdev = dev->dev_private;
942 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
943 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
944 union crtc_sourc_param args;
945 int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
946 uint8_t frev, crev;
947
948 memset(&args, 0, sizeof(args));
949
950 atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
951
952 switch (frev) {
953 case 1:
954 switch (crev) {
955 case 1:
956 default:
957 if (ASIC_IS_AVIVO(rdev))
958 args.v1.ucCRTC = radeon_crtc->crtc_id;
959 else {
960 if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
961 args.v1.ucCRTC = radeon_crtc->crtc_id;
962 } else {
963 args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
964 }
965 }
966 switch (radeon_encoder->encoder_id) {
967 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
968 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
969 args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
970 break;
971 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
972 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
973 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
974 args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
975 else
976 args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
977 break;
978 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
979 case ENCODER_OBJECT_ID_INTERNAL_DDI:
980 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
981 args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
982 break;
983 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
984 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
Dave Airlie4ce001a2009-08-13 16:32:14 +1000985 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200986 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000987 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200988 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
989 else
990 args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
991 break;
992 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
993 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
Dave Airlie4ce001a2009-08-13 16:32:14 +1000994 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200995 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000996 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200997 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
998 else
999 args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1000 break;
1001 }
1002 break;
1003 case 2:
1004 args.v2.ucCRTC = radeon_crtc->crtc_id;
1005 args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
1006 switch (radeon_encoder->encoder_id) {
1007 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1008 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1009 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1010 if (ASIC_IS_DCE32(rdev)) {
1011 if (radeon_crtc->crtc_id)
1012 args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1013 else
1014 args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1015 } else
1016 args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
1017 break;
1018 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1019 args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
1020 break;
1021 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1022 args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
1023 break;
1024 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
Dave Airlie4ce001a2009-08-13 16:32:14 +10001025 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001026 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001027 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001028 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1029 else
1030 args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
1031 break;
1032 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
Dave Airlie4ce001a2009-08-13 16:32:14 +10001033 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001034 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001035 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001036 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
1037 else
1038 args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1039 break;
1040 }
1041 break;
1042 }
1043 break;
1044 default:
1045 DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
1046 break;
1047 }
1048
1049 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1050
1051}
1052
1053static void
1054atombios_apply_encoder_quirks(struct drm_encoder *encoder,
1055 struct drm_display_mode *mode)
1056{
1057 struct drm_device *dev = encoder->dev;
1058 struct radeon_device *rdev = dev->dev_private;
1059 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1060 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1061
1062 /* Funky macbooks */
1063 if ((dev->pdev->device == 0x71C5) &&
1064 (dev->pdev->subsystem_vendor == 0x106b) &&
1065 (dev->pdev->subsystem_device == 0x0080)) {
1066 if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
1067 uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
1068
1069 lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
1070 lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
1071
1072 WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
1073 }
1074 }
1075
1076 /* set scaler clears this on some chips */
Alex Deucherceefedd2009-10-13 23:57:47 -04001077 if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) {
1078 if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
1079 WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
1080 AVIVO_D1MODE_INTERLEAVE_EN);
1081 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001082}
1083
1084static void
1085radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
1086 struct drm_display_mode *mode,
1087 struct drm_display_mode *adjusted_mode)
1088{
1089 struct drm_device *dev = encoder->dev;
1090 struct radeon_device *rdev = dev->dev_private;
1091 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1092 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1093
1094 if (radeon_encoder->enc_priv) {
1095 struct radeon_encoder_atom_dig *dig;
1096
1097 dig = radeon_encoder->enc_priv;
1098 dig->dig_block = radeon_crtc->crtc_id;
1099 }
1100 radeon_encoder->pixel_clock = adjusted_mode->clock;
1101
1102 radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001103 atombios_set_encoder_crtc_source(encoder);
1104
1105 if (ASIC_IS_AVIVO(rdev)) {
Dave Airlie4ce001a2009-08-13 16:32:14 +10001106 if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001107 atombios_yuv_setup(encoder, true);
1108 else
1109 atombios_yuv_setup(encoder, false);
1110 }
1111
1112 switch (radeon_encoder->encoder_id) {
1113 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1114 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1115 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1116 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1117 atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
1118 break;
1119 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1120 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1121 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1122 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1123 /* disable the encoder and transmitter */
1124 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
1125 atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
1126
1127 /* setup and enable the encoder and transmitter */
1128 atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
Alex Deucherf95a9f02009-11-05 02:21:06 -05001129 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001130 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP);
1131 atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
1132 break;
1133 case ENCODER_OBJECT_ID_INTERNAL_DDI:
1134 atombios_ddia_setup(encoder, ATOM_ENABLE);
1135 break;
1136 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1137 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1138 atombios_external_tmds_setup(encoder, ATOM_ENABLE);
1139 break;
1140 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1141 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1142 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1143 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1144 atombios_dac_setup(encoder, ATOM_ENABLE);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001145 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001146 atombios_tv_setup(encoder, ATOM_ENABLE);
1147 break;
1148 }
1149 atombios_apply_encoder_quirks(encoder, adjusted_mode);
1150}
1151
1152static bool
Dave Airlie4ce001a2009-08-13 16:32:14 +10001153atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001154{
1155 struct drm_device *dev = encoder->dev;
1156 struct radeon_device *rdev = dev->dev_private;
1157 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001158 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001159
1160 if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
1161 ATOM_DEVICE_CV_SUPPORT |
1162 ATOM_DEVICE_CRT_SUPPORT)) {
1163 DAC_LOAD_DETECTION_PS_ALLOCATION args;
1164 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1165 uint8_t frev, crev;
1166
1167 memset(&args, 0, sizeof(args));
1168
1169 atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
1170
1171 args.sDacload.ucMisc = 0;
1172
1173 if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
1174 (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
1175 args.sDacload.ucDacType = ATOM_DAC_A;
1176 else
1177 args.sDacload.ucDacType = ATOM_DAC_B;
1178
Dave Airlie4ce001a2009-08-13 16:32:14 +10001179 if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001180 args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001181 else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001182 args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001183 else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001184 args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
1185 if (crev >= 3)
1186 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001187 } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001188 args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
1189 if (crev >= 3)
1190 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1191 }
1192
1193 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1194
1195 return true;
1196 } else
1197 return false;
1198}
1199
1200static enum drm_connector_status
1201radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
1202{
1203 struct drm_device *dev = encoder->dev;
1204 struct radeon_device *rdev = dev->dev_private;
1205 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001206 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001207 uint32_t bios_0_scratch;
1208
Dave Airlie4ce001a2009-08-13 16:32:14 +10001209 if (!atombios_dac_load_detect(encoder, connector)) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001210 DRM_DEBUG("detect returned false \n");
1211 return connector_status_unknown;
1212 }
1213
1214 if (rdev->family >= CHIP_R600)
1215 bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
1216 else
1217 bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
1218
Dave Airlie4ce001a2009-08-13 16:32:14 +10001219 DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
1220 if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001221 if (bios_0_scratch & ATOM_S0_CRT1_MASK)
1222 return connector_status_connected;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001223 }
1224 if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001225 if (bios_0_scratch & ATOM_S0_CRT2_MASK)
1226 return connector_status_connected;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001227 }
1228 if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001229 if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
1230 return connector_status_connected;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001231 }
1232 if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001233 if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
1234 return connector_status_connected; /* CTV */
1235 else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
1236 return connector_status_connected; /* STV */
1237 }
1238 return connector_status_disconnected;
1239}
1240
1241static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
1242{
1243 radeon_atom_output_lock(encoder, true);
1244 radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
1245}
1246
1247static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
1248{
1249 radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
1250 radeon_atom_output_lock(encoder, false);
1251}
1252
Dave Airlie4ce001a2009-08-13 16:32:14 +10001253static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
1254{
1255 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1256 radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001257 radeon_encoder->active_device = 0;
1258}
1259
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001260static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
1261 .dpms = radeon_atom_encoder_dpms,
1262 .mode_fixup = radeon_atom_mode_fixup,
1263 .prepare = radeon_atom_encoder_prepare,
1264 .mode_set = radeon_atom_encoder_mode_set,
1265 .commit = radeon_atom_encoder_commit,
Dave Airlie4ce001a2009-08-13 16:32:14 +10001266 .disable = radeon_atom_encoder_disable,
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001267 /* no detect for TMDS/LVDS yet */
1268};
1269
1270static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
1271 .dpms = radeon_atom_encoder_dpms,
1272 .mode_fixup = radeon_atom_mode_fixup,
1273 .prepare = radeon_atom_encoder_prepare,
1274 .mode_set = radeon_atom_encoder_mode_set,
1275 .commit = radeon_atom_encoder_commit,
1276 .detect = radeon_atom_dac_detect,
1277};
1278
1279void radeon_enc_destroy(struct drm_encoder *encoder)
1280{
1281 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1282 kfree(radeon_encoder->enc_priv);
1283 drm_encoder_cleanup(encoder);
1284 kfree(radeon_encoder);
1285}
1286
1287static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
1288 .destroy = radeon_enc_destroy,
1289};
1290
Dave Airlie4ce001a2009-08-13 16:32:14 +10001291struct radeon_encoder_atom_dac *
1292radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
1293{
1294 struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
1295
1296 if (!dac)
1297 return NULL;
1298
1299 dac->tv_std = TV_STD_NTSC;
1300 return dac;
1301}
1302
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001303struct radeon_encoder_atom_dig *
1304radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
1305{
1306 struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
1307
1308 if (!dig)
1309 return NULL;
1310
1311 /* coherent mode by default */
1312 dig->coherent_mode = true;
1313
1314 return dig;
1315}
1316
1317void
1318radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
1319{
Dave Airliedfee5612009-10-02 09:19:09 +10001320 struct radeon_device *rdev = dev->dev_private;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001321 struct drm_encoder *encoder;
1322 struct radeon_encoder *radeon_encoder;
1323
1324 /* see if we already added it */
1325 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1326 radeon_encoder = to_radeon_encoder(encoder);
1327 if (radeon_encoder->encoder_id == encoder_id) {
1328 radeon_encoder->devices |= supported_device;
1329 return;
1330 }
1331
1332 }
1333
1334 /* add a new one */
1335 radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
1336 if (!radeon_encoder)
1337 return;
1338
1339 encoder = &radeon_encoder->base;
Dave Airliedfee5612009-10-02 09:19:09 +10001340 if (rdev->flags & RADEON_SINGLE_CRTC)
1341 encoder->possible_crtcs = 0x1;
1342 else
1343 encoder->possible_crtcs = 0x3;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001344 encoder->possible_clones = 0;
1345
1346 radeon_encoder->enc_priv = NULL;
1347
1348 radeon_encoder->encoder_id = encoder_id;
1349 radeon_encoder->devices = supported_device;
Jerome Glissec93bb852009-07-13 21:04:08 +02001350 radeon_encoder->rmx_type = RMX_OFF;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001351
1352 switch (radeon_encoder->encoder_id) {
1353 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1354 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1355 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1356 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1357 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1358 radeon_encoder->rmx_type = RMX_FULL;
1359 drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
1360 radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
1361 } else {
1362 drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
1363 radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
1364 }
1365 drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
1366 break;
1367 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1368 drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
1369 drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
1370 break;
1371 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1372 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1373 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1374 drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001375 radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001376 drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
1377 break;
1378 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1379 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1380 case ENCODER_OBJECT_ID_INTERNAL_DDI:
1381 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1382 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1383 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1384 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
Alex Deucher60d15f52009-09-08 14:22:45 -04001385 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1386 radeon_encoder->rmx_type = RMX_FULL;
1387 drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
1388 radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
1389 } else {
1390 drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
1391 radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
1392 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001393 drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
1394 break;
1395 }
1396}