blob: b8149cbc0c70ca3511f748d13e05cb85c16073e9 [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
Dave Airlie4ce001a2009-08-13 16:32:14 +100032static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
33{
34 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
35 struct drm_encoder_helper_funcs *encoder_funcs;
36
37 encoder_funcs = encoder->helper_private;
38 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
39 radeon_encoder->active_device = 0;
40}
Jerome Glisse771fe6b2009-06-05 14:42:42 +020041
Jerome Glisse771fe6b2009-06-05 14:42:42 +020042static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
43{
44 struct drm_device *dev = encoder->dev;
45 struct radeon_device *rdev = dev->dev_private;
46 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
47 uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
48 int panel_pwr_delay = 2000;
Alex Deucher3890ddf2010-01-12 11:16:57 -050049 bool is_mac = false;
Dave Airlied9fdaaf2010-08-02 10:42:55 +100050 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +020051
52 if (radeon_encoder->enc_priv) {
53 if (rdev->is_atom_bios) {
54 struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
55 panel_pwr_delay = lvds->panel_pwr_delay;
56 } else {
57 struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
58 panel_pwr_delay = lvds->panel_pwr_delay;
59 }
60 }
61
Alex Deucher3890ddf2010-01-12 11:16:57 -050062 /* macs (and possibly some x86 oem systems?) wire up LVDS strangely
63 * Taken from radeonfb.
64 */
65 if ((rdev->mode_info.connector_table == CT_IBOOK) ||
66 (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) ||
67 (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) ||
68 (rdev->mode_info.connector_table == CT_POWERBOOK_VGA))
69 is_mac = true;
70
Jerome Glisse771fe6b2009-06-05 14:42:42 +020071 switch (mode) {
72 case DRM_MODE_DPMS_ON:
73 disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
74 disp_pwr_man |= RADEON_AUTO_PWRUP_EN;
75 WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man);
76 lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
77 lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
78 WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
79 udelay(1000);
80
81 lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
82 lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
83 WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
84
85 lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
86 lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
Alex Deucher3890ddf2010-01-12 11:16:57 -050087 if (is_mac)
88 lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
Jerome Glisse771fe6b2009-06-05 14:42:42 +020089 lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
90 udelay(panel_pwr_delay * 1000);
91 WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
92 break;
93 case DRM_MODE_DPMS_STANDBY:
94 case DRM_MODE_DPMS_SUSPEND:
95 case DRM_MODE_DPMS_OFF:
96 pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
97 WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
98 lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
99 lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
Alex Deucher3890ddf2010-01-12 11:16:57 -0500100 if (is_mac) {
101 lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
102 WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
103 lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN);
104 } else {
105 WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
106 lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
107 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200108 udelay(panel_pwr_delay * 1000);
109 WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
110 WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
Alex Deucher15cb02c2010-07-21 19:37:21 -0400111 udelay(panel_pwr_delay * 1000);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200112 break;
113 }
114
115 if (rdev->is_atom_bios)
116 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
117 else
118 radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
Rafał Miłeckic913e232009-12-22 23:02:16 +0100119
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200120}
121
122static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
123{
124 struct radeon_device *rdev = encoder->dev->dev_private;
125
126 if (rdev->is_atom_bios)
127 radeon_atom_output_lock(encoder, true);
128 else
129 radeon_combios_output_lock(encoder, true);
130 radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
131}
132
133static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
134{
135 struct radeon_device *rdev = encoder->dev->dev_private;
136
137 radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON);
138 if (rdev->is_atom_bios)
139 radeon_atom_output_lock(encoder, false);
140 else
141 radeon_combios_output_lock(encoder, false);
142}
143
144static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
145 struct drm_display_mode *mode,
146 struct drm_display_mode *adjusted_mode)
147{
148 struct drm_device *dev = encoder->dev;
149 struct radeon_device *rdev = dev->dev_private;
150 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
151 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
152 uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl;
153
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000154 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200155
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200156 lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
157 lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
158
159 lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
Alex Deucher32f48ff2009-11-30 01:54:16 -0500160 if (rdev->is_atom_bios) {
161 /* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
162 * need to call that on resume to set up the reg properly.
163 */
164 radeon_encoder->pixel_clock = adjusted_mode->clock;
165 atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
166 lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
167 } else {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200168 struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
169 if (lvds) {
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000170 DRM_DEBUG_KMS("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200171 lvds_gen_cntl = lvds->lvds_gen_cntl;
172 lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
173 (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
174 lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
175 (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
176 } else
177 lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
Alex Deucher32f48ff2009-11-30 01:54:16 -0500178 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200179 lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
180 lvds_gen_cntl &= ~(RADEON_LVDS_ON |
181 RADEON_LVDS_BLON |
182 RADEON_LVDS_EN |
183 RADEON_LVDS_RST_FM);
184
185 if (ASIC_IS_R300(rdev))
186 lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
187
188 if (radeon_crtc->crtc_id == 0) {
189 if (ASIC_IS_R300(rdev)) {
Jerome Glissec93bb852009-07-13 21:04:08 +0200190 if (radeon_encoder->rmx_type != RMX_OFF)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200191 lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
192 } else
193 lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
194 } else {
195 if (ASIC_IS_R300(rdev))
196 lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
197 else
198 lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
199 }
200
201 WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
202 WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
203 WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl);
204
205 if (rdev->family == CHIP_RV410)
206 WREG32(RADEON_CLOCK_CNTL_INDEX, 0);
207
208 if (rdev->is_atom_bios)
209 radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
210 else
211 radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
212}
213
Alex Deucher80297e82009-11-12 14:55:14 -0500214static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
215 struct drm_display_mode *mode,
216 struct drm_display_mode *adjusted_mode)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200217{
218 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
219
Alex Deucher8c2a6d72009-10-14 02:00:42 -0400220 /* set the active encoder to connector routing */
221 radeon_encoder_set_active_device(encoder);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200222 drm_mode_set_crtcinfo(adjusted_mode, 0);
223
Alex Deucher80297e82009-11-12 14:55:14 -0500224 /* get the native mode for LVDS */
Alex Deucher35153872010-04-30 12:00:44 -0400225 if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
226 radeon_panel_mode_fixup(encoder, adjusted_mode);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200227
228 return true;
229}
230
231static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
232 .dpms = radeon_legacy_lvds_dpms,
Alex Deucher80297e82009-11-12 14:55:14 -0500233 .mode_fixup = radeon_legacy_mode_fixup,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200234 .prepare = radeon_legacy_lvds_prepare,
235 .mode_set = radeon_legacy_lvds_mode_set,
236 .commit = radeon_legacy_lvds_commit,
Dave Airlie4ce001a2009-08-13 16:32:14 +1000237 .disable = radeon_legacy_encoder_disable,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200238};
239
240
241static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
242 .destroy = radeon_enc_destroy,
243};
244
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200245static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
246{
247 struct drm_device *dev = encoder->dev;
248 struct radeon_device *rdev = dev->dev_private;
249 uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
250 uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL);
251 uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
252
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000253 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200254
255 switch (mode) {
256 case DRM_MODE_DPMS_ON:
257 crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
258 dac_cntl &= ~RADEON_DAC_PDWN;
259 dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
260 RADEON_DAC_PDWN_G |
261 RADEON_DAC_PDWN_B);
262 break;
263 case DRM_MODE_DPMS_STANDBY:
264 case DRM_MODE_DPMS_SUSPEND:
265 case DRM_MODE_DPMS_OFF:
266 crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
267 dac_cntl |= RADEON_DAC_PDWN;
268 dac_macro_cntl |= (RADEON_DAC_PDWN_R |
269 RADEON_DAC_PDWN_G |
270 RADEON_DAC_PDWN_B);
271 break;
272 }
273
274 WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
275 WREG32(RADEON_DAC_CNTL, dac_cntl);
276 WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
277
278 if (rdev->is_atom_bios)
279 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
280 else
281 radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
Rafał Miłeckic913e232009-12-22 23:02:16 +0100282
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200283}
284
285static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
286{
287 struct radeon_device *rdev = encoder->dev->dev_private;
288
289 if (rdev->is_atom_bios)
290 radeon_atom_output_lock(encoder, true);
291 else
292 radeon_combios_output_lock(encoder, true);
293 radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
294}
295
296static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
297{
298 struct radeon_device *rdev = encoder->dev->dev_private;
299
300 radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON);
301
302 if (rdev->is_atom_bios)
303 radeon_atom_output_lock(encoder, false);
304 else
305 radeon_combios_output_lock(encoder, false);
306}
307
308static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
309 struct drm_display_mode *mode,
310 struct drm_display_mode *adjusted_mode)
311{
312 struct drm_device *dev = encoder->dev;
313 struct radeon_device *rdev = dev->dev_private;
314 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
315 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
316 uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl;
317
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000318 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200319
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200320 if (radeon_crtc->crtc_id == 0) {
321 if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
322 disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
323 ~(RADEON_DISP_DAC_SOURCE_MASK);
324 WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
325 } else {
326 dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~(RADEON_DAC2_DAC_CLK_SEL);
327 WREG32(RADEON_DAC_CNTL2, dac2_cntl);
328 }
329 } else {
330 if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
331 disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
332 ~(RADEON_DISP_DAC_SOURCE_MASK);
333 disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
334 WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
335 } else {
336 dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL;
337 WREG32(RADEON_DAC_CNTL2, dac2_cntl);
338 }
339 }
340
341 dac_cntl = (RADEON_DAC_MASK_ALL |
342 RADEON_DAC_VGA_ADR_EN |
343 /* TODO 6-bits */
344 RADEON_DAC_8BIT_EN);
345
346 WREG32_P(RADEON_DAC_CNTL,
347 dac_cntl,
348 RADEON_DAC_RANGE_CNTL |
349 RADEON_DAC_BLANKING);
350
351 if (radeon_encoder->enc_priv) {
352 struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv;
353 dac_macro_cntl = p_dac->ps2_pdac_adj;
354 } else
355 dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
356 dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B;
357 WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
358
359 if (rdev->is_atom_bios)
360 radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
361 else
362 radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
363}
364
365static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder,
366 struct drm_connector *connector)
367{
368 struct drm_device *dev = encoder->dev;
369 struct radeon_device *rdev = dev->dev_private;
370 uint32_t vclk_ecp_cntl, crtc_ext_cntl;
371 uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
372 enum drm_connector_status found = connector_status_disconnected;
373 bool color = true;
374
375 /* save the regs we need */
376 vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
377 crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
378 dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
379 dac_cntl = RREG32(RADEON_DAC_CNTL);
380 dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
381
382 tmp = vclk_ecp_cntl &
383 ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
384 WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
385
386 tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
387 WREG32(RADEON_CRTC_EXT_CNTL, tmp);
388
389 tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
390 RADEON_DAC_FORCE_DATA_EN;
391
392 if (color)
393 tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
394 else
395 tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
396
397 if (ASIC_IS_R300(rdev))
398 tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
399 else
400 tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
401
402 WREG32(RADEON_DAC_EXT_CNTL, tmp);
403
404 tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
405 tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
406 WREG32(RADEON_DAC_CNTL, tmp);
407
408 tmp &= ~(RADEON_DAC_PDWN_R |
409 RADEON_DAC_PDWN_G |
410 RADEON_DAC_PDWN_B);
411
412 WREG32(RADEON_DAC_MACRO_CNTL, tmp);
413
414 udelay(2000);
415
416 if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
417 found = connector_status_connected;
418
419 /* restore the regs we used */
420 WREG32(RADEON_DAC_CNTL, dac_cntl);
421 WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
422 WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
423 WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
424 WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
425
426 return found;
427}
428
429static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
430 .dpms = radeon_legacy_primary_dac_dpms,
Alex Deucher80297e82009-11-12 14:55:14 -0500431 .mode_fixup = radeon_legacy_mode_fixup,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200432 .prepare = radeon_legacy_primary_dac_prepare,
433 .mode_set = radeon_legacy_primary_dac_mode_set,
434 .commit = radeon_legacy_primary_dac_commit,
435 .detect = radeon_legacy_primary_dac_detect,
Dave Airlie4ce001a2009-08-13 16:32:14 +1000436 .disable = radeon_legacy_encoder_disable,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200437};
438
439
440static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = {
441 .destroy = radeon_enc_destroy,
442};
443
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200444static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
445{
446 struct drm_device *dev = encoder->dev;
447 struct radeon_device *rdev = dev->dev_private;
448 uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL);
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000449 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200450
451 switch (mode) {
452 case DRM_MODE_DPMS_ON:
453 fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
454 break;
455 case DRM_MODE_DPMS_STANDBY:
456 case DRM_MODE_DPMS_SUSPEND:
457 case DRM_MODE_DPMS_OFF:
458 fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
459 break;
460 }
461
462 WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
463
464 if (rdev->is_atom_bios)
465 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
466 else
467 radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
Rafał Miłeckic913e232009-12-22 23:02:16 +0100468
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200469}
470
471static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
472{
473 struct radeon_device *rdev = encoder->dev->dev_private;
474
475 if (rdev->is_atom_bios)
476 radeon_atom_output_lock(encoder, true);
477 else
478 radeon_combios_output_lock(encoder, true);
479 radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
480}
481
482static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
483{
484 struct radeon_device *rdev = encoder->dev->dev_private;
485
486 radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON);
487
488 if (rdev->is_atom_bios)
489 radeon_atom_output_lock(encoder, true);
490 else
491 radeon_combios_output_lock(encoder, true);
492}
493
494static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
495 struct drm_display_mode *mode,
496 struct drm_display_mode *adjusted_mode)
497{
498 struct drm_device *dev = encoder->dev;
499 struct radeon_device *rdev = dev->dev_private;
500 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
501 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
502 uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl;
503 int i;
504
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000505 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200506
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200507 tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
508 tmp &= 0xfffff;
509 if (rdev->family == CHIP_RV280) {
510 /* bit 22 of TMDS_PLL_CNTL is read-back inverted */
511 tmp ^= (1 << 22);
512 tmds_pll_cntl ^= (1 << 22);
513 }
514
515 if (radeon_encoder->enc_priv) {
516 struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv;
517
518 for (i = 0; i < 4; i++) {
519 if (tmds->tmds_pll[i].freq == 0)
520 break;
521 if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) {
522 tmp = tmds->tmds_pll[i].value ;
523 break;
524 }
525 }
526 }
527
528 if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) {
529 if (tmp & 0xfff00000)
530 tmds_pll_cntl = tmp;
531 else {
532 tmds_pll_cntl &= 0xfff00000;
533 tmds_pll_cntl |= tmp;
534 }
535 } else
536 tmds_pll_cntl = tmp;
537
538 tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) &
539 ~(RADEON_TMDS_TRANSMITTER_PLLRST);
540
541 if (rdev->family == CHIP_R200 ||
542 rdev->family == CHIP_R100 ||
543 ASIC_IS_R300(rdev))
544 tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
545 else /* RV chips got this bit reversed */
546 tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN;
547
548 fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) |
549 (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
550 RADEON_FP_CRTC_DONT_SHADOW_HEND));
551
552 fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
553
Alex Deucher1b4d7d72009-10-15 01:33:35 -0400554 fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
555 RADEON_FP_DFP_SYNC_SEL |
556 RADEON_FP_CRT_SYNC_SEL |
557 RADEON_FP_CRTC_LOCK_8DOT |
558 RADEON_FP_USE_SHADOW_EN |
559 RADEON_FP_CRTC_USE_SHADOW_VEND |
560 RADEON_FP_CRT_SYNC_ALT);
561
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200562 if (1) /* FIXME rgbBits == 8 */
563 fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */
564 else
565 fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
566
567 if (radeon_crtc->crtc_id == 0) {
568 if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
569 fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
Jerome Glissec93bb852009-07-13 21:04:08 +0200570 if (radeon_encoder->rmx_type != RMX_OFF)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200571 fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
572 else
573 fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
574 } else
Alex Deucher1b4d7d72009-10-15 01:33:35 -0400575 fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200576 } else {
577 if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
578 fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
579 fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
580 } else
581 fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
582 }
583
584 WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl);
585 WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl);
586 WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
587
588 if (rdev->is_atom_bios)
589 radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
590 else
591 radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
592}
593
594static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
595 .dpms = radeon_legacy_tmds_int_dpms,
Alex Deucher80297e82009-11-12 14:55:14 -0500596 .mode_fixup = radeon_legacy_mode_fixup,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200597 .prepare = radeon_legacy_tmds_int_prepare,
598 .mode_set = radeon_legacy_tmds_int_mode_set,
599 .commit = radeon_legacy_tmds_int_commit,
Dave Airlie4ce001a2009-08-13 16:32:14 +1000600 .disable = radeon_legacy_encoder_disable,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200601};
602
603
604static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = {
605 .destroy = radeon_enc_destroy,
606};
607
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200608static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
609{
610 struct drm_device *dev = encoder->dev;
611 struct radeon_device *rdev = dev->dev_private;
612 uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000613 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200614
615 switch (mode) {
616 case DRM_MODE_DPMS_ON:
617 fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
618 fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
619 break;
620 case DRM_MODE_DPMS_STANDBY:
621 case DRM_MODE_DPMS_SUSPEND:
622 case DRM_MODE_DPMS_OFF:
623 fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
624 fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
625 break;
626 }
627
628 WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
629
630 if (rdev->is_atom_bios)
631 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
632 else
633 radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
Rafał Miłeckic913e232009-12-22 23:02:16 +0100634
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200635}
636
637static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
638{
639 struct radeon_device *rdev = encoder->dev->dev_private;
640
641 if (rdev->is_atom_bios)
642 radeon_atom_output_lock(encoder, true);
643 else
644 radeon_combios_output_lock(encoder, true);
645 radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
646}
647
648static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
649{
650 struct radeon_device *rdev = encoder->dev->dev_private;
651 radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON);
652
653 if (rdev->is_atom_bios)
654 radeon_atom_output_lock(encoder, false);
655 else
656 radeon_combios_output_lock(encoder, false);
657}
658
659static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
660 struct drm_display_mode *mode,
661 struct drm_display_mode *adjusted_mode)
662{
663 struct drm_device *dev = encoder->dev;
664 struct radeon_device *rdev = dev->dev_private;
665 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
666 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
667 uint32_t fp2_gen_cntl;
668
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000669 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200670
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200671 if (rdev->is_atom_bios) {
672 radeon_encoder->pixel_clock = adjusted_mode->clock;
673 atombios_external_tmds_setup(encoder, ATOM_ENABLE);
674 fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
675 } else {
676 fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
677
678 if (1) /* FIXME rgbBits == 8 */
679 fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
680 else
681 fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
682
683 fp2_gen_cntl &= ~(RADEON_FP2_ON |
684 RADEON_FP2_DVO_EN |
685 RADEON_FP2_DVO_RATE_SEL_SDR);
686
687 /* XXX: these are oem specific */
688 if (ASIC_IS_R300(rdev)) {
689 if ((dev->pdev->device == 0x4850) &&
690 (dev->pdev->subsystem_vendor == 0x1028) &&
691 (dev->pdev->subsystem_device == 0x2001)) /* Dell Inspiron 8600 */
692 fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE;
693 else
694 fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
695
696 /*if (mode->clock > 165000)
697 fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
698 }
Alex Deucherfcec5702009-11-10 21:25:07 -0500699 if (!radeon_combios_external_tmds_setup(encoder))
700 radeon_external_tmds_setup(encoder);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200701 }
702
703 if (radeon_crtc->crtc_id == 0) {
704 if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
705 fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
Jerome Glissec93bb852009-07-13 21:04:08 +0200706 if (radeon_encoder->rmx_type != RMX_OFF)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200707 fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
708 else
709 fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
710 } else
711 fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
712 } else {
713 if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
714 fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
715 fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
716 } else
717 fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
718 }
719
720 WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
721
722 if (rdev->is_atom_bios)
723 radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
724 else
725 radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
726}
727
Alex Deucherfcec5702009-11-10 21:25:07 -0500728static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
729{
730 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
731 struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
732 if (tmds) {
733 if (tmds->i2c_bus)
734 radeon_i2c_destroy(tmds->i2c_bus);
735 }
736 kfree(radeon_encoder->enc_priv);
737 drm_encoder_cleanup(encoder);
738 kfree(radeon_encoder);
739}
740
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200741static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
742 .dpms = radeon_legacy_tmds_ext_dpms,
Alex Deucher80297e82009-11-12 14:55:14 -0500743 .mode_fixup = radeon_legacy_mode_fixup,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200744 .prepare = radeon_legacy_tmds_ext_prepare,
745 .mode_set = radeon_legacy_tmds_ext_mode_set,
746 .commit = radeon_legacy_tmds_ext_commit,
Dave Airlie4ce001a2009-08-13 16:32:14 +1000747 .disable = radeon_legacy_encoder_disable,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200748};
749
750
751static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
Alex Deucherfcec5702009-11-10 21:25:07 -0500752 .destroy = radeon_ext_tmds_enc_destroy,
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200753};
754
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200755static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
756{
757 struct drm_device *dev = encoder->dev;
758 struct radeon_device *rdev = dev->dev_private;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000759 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200760 uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000761 uint32_t tv_master_cntl = 0;
762 bool is_tv;
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000763 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200764
Dave Airlie4ce001a2009-08-13 16:32:14 +1000765 is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
766
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200767 if (rdev->family == CHIP_R200)
768 fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
769 else {
Dave Airlie4ce001a2009-08-13 16:32:14 +1000770 if (is_tv)
771 tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
772 else
773 crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200774 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
775 }
776
777 switch (mode) {
778 case DRM_MODE_DPMS_ON:
779 if (rdev->family == CHIP_R200) {
780 fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
781 } else {
Dave Airlie4ce001a2009-08-13 16:32:14 +1000782 if (is_tv)
783 tv_master_cntl |= RADEON_TV_ON;
784 else
785 crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
786
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200787 if (rdev->family == CHIP_R420 ||
Dave Airlie4ce001a2009-08-13 16:32:14 +1000788 rdev->family == CHIP_R423 ||
789 rdev->family == CHIP_RV410)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200790 tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
Dave Airlie4ce001a2009-08-13 16:32:14 +1000791 R420_TV_DAC_GDACPD |
792 R420_TV_DAC_BDACPD |
793 RADEON_TV_DAC_BGSLEEP);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200794 else
795 tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
Dave Airlie4ce001a2009-08-13 16:32:14 +1000796 RADEON_TV_DAC_GDACPD |
797 RADEON_TV_DAC_BDACPD |
798 RADEON_TV_DAC_BGSLEEP);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200799 }
800 break;
801 case DRM_MODE_DPMS_STANDBY:
802 case DRM_MODE_DPMS_SUSPEND:
803 case DRM_MODE_DPMS_OFF:
804 if (rdev->family == CHIP_R200)
805 fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
806 else {
Dave Airlie4ce001a2009-08-13 16:32:14 +1000807 if (is_tv)
808 tv_master_cntl &= ~RADEON_TV_ON;
809 else
810 crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
811
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200812 if (rdev->family == CHIP_R420 ||
Alex Deucher77416182010-04-06 00:05:46 -0400813 rdev->family == CHIP_R423 ||
814 rdev->family == CHIP_RV410)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200815 tv_dac_cntl |= (R420_TV_DAC_RDACPD |
816 R420_TV_DAC_GDACPD |
817 R420_TV_DAC_BDACPD |
818 RADEON_TV_DAC_BGSLEEP);
819 else
820 tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
821 RADEON_TV_DAC_GDACPD |
822 RADEON_TV_DAC_BDACPD |
823 RADEON_TV_DAC_BGSLEEP);
824 }
825 break;
826 }
827
828 if (rdev->family == CHIP_R200) {
829 WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
830 } else {
Dave Airlie4ce001a2009-08-13 16:32:14 +1000831 if (is_tv)
832 WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
833 else
834 WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200835 WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
836 }
837
838 if (rdev->is_atom_bios)
839 radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
840 else
841 radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
Rafał Miłeckic913e232009-12-22 23:02:16 +0100842
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200843}
844
845static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
846{
847 struct radeon_device *rdev = encoder->dev->dev_private;
848
849 if (rdev->is_atom_bios)
850 radeon_atom_output_lock(encoder, true);
851 else
852 radeon_combios_output_lock(encoder, true);
853 radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
854}
855
856static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
857{
858 struct radeon_device *rdev = encoder->dev->dev_private;
859
860 radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON);
861
862 if (rdev->is_atom_bios)
863 radeon_atom_output_lock(encoder, true);
864 else
865 radeon_combios_output_lock(encoder, true);
866}
867
868static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
869 struct drm_display_mode *mode,
870 struct drm_display_mode *adjusted_mode)
871{
872 struct drm_device *dev = encoder->dev;
873 struct radeon_device *rdev = dev->dev_private;
874 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
875 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
Dave Airlie4ce001a2009-08-13 16:32:14 +1000876 struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200877 uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000878 uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0;
879 bool is_tv = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200880
Dave Airlied9fdaaf2010-08-02 10:42:55 +1000881 DRM_DEBUG_KMS("\n");
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200882
Dave Airlie4ce001a2009-08-13 16:32:14 +1000883 is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
884
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200885 if (rdev->family != CHIP_R200) {
886 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
887 if (rdev->family == CHIP_R420 ||
Alex Deucher77416182010-04-06 00:05:46 -0400888 rdev->family == CHIP_R423 ||
889 rdev->family == CHIP_RV410) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200890 tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
Alex Deucher77416182010-04-06 00:05:46 -0400891 RADEON_TV_DAC_BGADJ_MASK |
892 R420_TV_DAC_DACADJ_MASK |
893 R420_TV_DAC_RDACPD |
894 R420_TV_DAC_GDACPD |
895 R420_TV_DAC_BDACPD |
896 R420_TV_DAC_TVENABLE);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200897 } else {
898 tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
Alex Deucher77416182010-04-06 00:05:46 -0400899 RADEON_TV_DAC_BGADJ_MASK |
900 RADEON_TV_DAC_DACADJ_MASK |
901 RADEON_TV_DAC_RDACPD |
902 RADEON_TV_DAC_GDACPD |
903 RADEON_TV_DAC_BDACPD);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200904 }
905
Alex Deucher77416182010-04-06 00:05:46 -0400906 tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
907
908 if (is_tv) {
909 if (tv_dac->tv_std == TV_STD_NTSC ||
910 tv_dac->tv_std == TV_STD_NTSC_J ||
911 tv_dac->tv_std == TV_STD_PAL_M ||
912 tv_dac->tv_std == TV_STD_PAL_60)
913 tv_dac_cntl |= tv_dac->ntsc_tvdac_adj;
914 else
915 tv_dac_cntl |= tv_dac->pal_tvdac_adj;
916
917 if (tv_dac->tv_std == TV_STD_NTSC ||
918 tv_dac->tv_std == TV_STD_NTSC_J)
919 tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
920 else
921 tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200922 } else
Alex Deucher77416182010-04-06 00:05:46 -0400923 tv_dac_cntl |= (RADEON_TV_DAC_STD_PS2 |
924 tv_dac->ps2_tvdac_adj);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200925
926 WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
927 }
928
929 if (ASIC_IS_R300(rdev)) {
930 gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
931 disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
Dave Airlie1ab064d2010-06-09 14:03:48 +1000932 } else if (rdev->family != CHIP_R200)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200933 disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
Dave Airlie1ab064d2010-06-09 14:03:48 +1000934 else if (rdev->family == CHIP_R200)
Dave Airlie4ce001a2009-08-13 16:32:14 +1000935 fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200936
Dave Airlie1ab064d2010-06-09 14:03:48 +1000937 if (rdev->family >= CHIP_R200)
938 disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
939
Dave Airlie4ce001a2009-08-13 16:32:14 +1000940 if (is_tv) {
941 uint32_t dac_cntl;
942
943 dac_cntl = RREG32(RADEON_DAC_CNTL);
944 dac_cntl &= ~RADEON_DAC_TVO_EN;
945 WREG32(RADEON_DAC_CNTL, dac_cntl);
946
947 if (ASIC_IS_R300(rdev))
948 gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1;
949
950 dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL;
951 if (radeon_crtc->crtc_id == 0) {
952 if (ASIC_IS_R300(rdev)) {
953 disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
954 disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC |
955 RADEON_DISP_TV_SOURCE_CRTC);
956 }
957 if (rdev->family >= CHIP_R200) {
958 disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
959 } else {
960 disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
961 }
962 } else {
963 if (ASIC_IS_R300(rdev)) {
964 disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
965 disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
966 }
967 if (rdev->family >= CHIP_R200) {
968 disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
969 } else {
970 disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
971 }
972 }
973 WREG32(RADEON_DAC_CNTL2, dac2_cntl);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200974 } else {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200975
Dave Airlie4ce001a2009-08-13 16:32:14 +1000976 dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
977
978 if (radeon_crtc->crtc_id == 0) {
979 if (ASIC_IS_R300(rdev)) {
980 disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
981 disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
982 } else if (rdev->family == CHIP_R200) {
983 fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
984 RADEON_FP2_DVO_RATE_SEL_SDR);
985 } else
986 disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
987 } else {
988 if (ASIC_IS_R300(rdev)) {
989 disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
990 disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
991 } else if (rdev->family == CHIP_R200) {
992 fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
993 RADEON_FP2_DVO_RATE_SEL_SDR);
994 fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
995 } else
996 disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
997 }
998 WREG32(RADEON_DAC_CNTL2, dac2_cntl);
999 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001000
1001 if (ASIC_IS_R300(rdev)) {
1002 WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001003 WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
Dave Airlie1ab064d2010-06-09 14:03:48 +10001004 } else if (rdev->family != CHIP_R200)
1005 WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
1006 else if (rdev->family == CHIP_R200)
1007 WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001008
1009 if (rdev->family >= CHIP_R200)
1010 WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
Dave Airlie4ce001a2009-08-13 16:32:14 +10001011
1012 if (is_tv)
1013 radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
1014
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001015 if (rdev->is_atom_bios)
1016 radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1017 else
1018 radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
1019
1020}
1021
Dave Airlie4ce001a2009-08-13 16:32:14 +10001022static bool r300_legacy_tv_detect(struct drm_encoder *encoder,
1023 struct drm_connector *connector)
1024{
1025 struct drm_device *dev = encoder->dev;
1026 struct radeon_device *rdev = dev->dev_private;
1027 uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
1028 uint32_t disp_output_cntl, gpiopad_a, tmp;
1029 bool found = false;
1030
1031 /* save regs needed */
1032 gpiopad_a = RREG32(RADEON_GPIOPAD_A);
1033 dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1034 crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1035 dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
1036 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1037 disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
1038
1039 WREG32_P(RADEON_GPIOPAD_A, 0, ~1);
1040
1041 WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL);
1042
1043 WREG32(RADEON_CRTC2_GEN_CNTL,
1044 RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
1045
1046 tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1047 tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1048 WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
1049
1050 WREG32(RADEON_DAC_EXT_CNTL,
1051 RADEON_DAC2_FORCE_BLANK_OFF_EN |
1052 RADEON_DAC2_FORCE_DATA_EN |
1053 RADEON_DAC_FORCE_DATA_SEL_RGB |
1054 (0xec << RADEON_DAC_FORCE_DATA_SHIFT));
1055
1056 WREG32(RADEON_TV_DAC_CNTL,
1057 RADEON_TV_DAC_STD_NTSC |
1058 (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1059 (6 << RADEON_TV_DAC_DACADJ_SHIFT));
1060
1061 RREG32(RADEON_TV_DAC_CNTL);
1062 mdelay(4);
1063
1064 WREG32(RADEON_TV_DAC_CNTL,
1065 RADEON_TV_DAC_NBLANK |
1066 RADEON_TV_DAC_NHOLD |
1067 RADEON_TV_MONITOR_DETECT_EN |
1068 RADEON_TV_DAC_STD_NTSC |
1069 (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1070 (6 << RADEON_TV_DAC_DACADJ_SHIFT));
1071
1072 RREG32(RADEON_TV_DAC_CNTL);
1073 mdelay(6);
1074
1075 tmp = RREG32(RADEON_TV_DAC_CNTL);
1076 if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
1077 found = true;
Dave Airlied9fdaaf2010-08-02 10:42:55 +10001078 DRM_DEBUG_KMS("S-video TV connection detected\n");
Dave Airlie4ce001a2009-08-13 16:32:14 +10001079 } else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
1080 found = true;
Dave Airlied9fdaaf2010-08-02 10:42:55 +10001081 DRM_DEBUG_KMS("Composite TV connection detected\n");
Dave Airlie4ce001a2009-08-13 16:32:14 +10001082 }
1083
1084 WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1085 WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1086 WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1087 WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1088 WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1089 WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1090 return found;
1091}
1092
1093static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
1094 struct drm_connector *connector)
1095{
1096 struct drm_device *dev = encoder->dev;
1097 struct radeon_device *rdev = dev->dev_private;
1098 uint32_t tv_dac_cntl, dac_cntl2;
1099 uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp;
1100 bool found = false;
1101
1102 if (ASIC_IS_R300(rdev))
1103 return r300_legacy_tv_detect(encoder, connector);
1104
1105 dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1106 tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
1107 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1108 config_cntl = RREG32(RADEON_CONFIG_CNTL);
1109 tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL);
1110
1111 tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
1112 WREG32(RADEON_DAC_CNTL2, tmp);
1113
1114 tmp = tv_master_cntl | RADEON_TV_ON;
1115 tmp &= ~(RADEON_TV_ASYNC_RST |
1116 RADEON_RESTART_PHASE_FIX |
1117 RADEON_CRT_FIFO_CE_EN |
1118 RADEON_TV_FIFO_CE_EN |
1119 RADEON_RE_SYNC_NOW_SEL_MASK);
1120 tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
1121 WREG32(RADEON_TV_MASTER_CNTL, tmp);
1122
1123 tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
1124 RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
1125 (8 << RADEON_TV_DAC_BGADJ_SHIFT);
1126
1127 if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
1128 tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
1129 else
1130 tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
1131 WREG32(RADEON_TV_DAC_CNTL, tmp);
1132
1133 tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
1134 RADEON_RED_MX_FORCE_DAC_DATA |
1135 RADEON_GRN_MX_FORCE_DAC_DATA |
1136 RADEON_BLU_MX_FORCE_DAC_DATA |
1137 (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
1138 WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
1139
1140 mdelay(3);
1141 tmp = RREG32(RADEON_TV_DAC_CNTL);
1142 if (tmp & RADEON_TV_DAC_GDACDET) {
1143 found = true;
Dave Airlied9fdaaf2010-08-02 10:42:55 +10001144 DRM_DEBUG_KMS("S-video TV connection detected\n");
Dave Airlie4ce001a2009-08-13 16:32:14 +10001145 } else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
1146 found = true;
Dave Airlied9fdaaf2010-08-02 10:42:55 +10001147 DRM_DEBUG_KMS("Composite TV connection detected\n");
Dave Airlie4ce001a2009-08-13 16:32:14 +10001148 }
1149
1150 WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
1151 WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1152 WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
1153 WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1154 return found;
1155}
1156
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001157static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
1158 struct drm_connector *connector)
1159{
1160 struct drm_device *dev = encoder->dev;
1161 struct radeon_device *rdev = dev->dev_private;
1162 uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
1163 uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
1164 enum drm_connector_status found = connector_status_disconnected;
Dave Airlie4ce001a2009-08-13 16:32:14 +10001165 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1166 struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001167 bool color = true;
Dave Airlieb62e9482010-06-08 10:42:28 +10001168 struct drm_crtc *crtc;
1169
1170 /* find out if crtc2 is in use or if this encoder is using it */
1171 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1172 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1173 if ((radeon_crtc->crtc_id == 1) && crtc->enabled) {
1174 if (encoder->crtc != crtc) {
1175 return connector_status_disconnected;
1176 }
1177 }
1178 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001179
Dave Airlie4ce001a2009-08-13 16:32:14 +10001180 if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
1181 connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
1182 connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) {
1183 bool tv_detect;
1184
1185 if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT))
1186 return connector_status_disconnected;
1187
1188 tv_detect = radeon_legacy_tv_detect(encoder, connector);
1189 if (tv_detect && tv_dac)
1190 found = connector_status_connected;
1191 return found;
1192 }
1193
1194 /* don't probe if the encoder is being used for something else not CRT related */
1195 if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) {
1196 DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device);
1197 return connector_status_disconnected;
1198 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001199
1200 /* save the regs we need */
1201 pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
1202 gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
1203 disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
1204 disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
1205 crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
1206 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1207 dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
1208 dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
1209
1210 tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
1211 | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
1212 WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
1213
1214 if (ASIC_IS_R300(rdev))
1215 WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
1216
1217 tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
1218 tmp |= RADEON_CRTC2_CRT2_ON |
1219 (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
1220
1221 WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
1222
1223 if (ASIC_IS_R300(rdev)) {
1224 tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1225 tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1226 WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
1227 } else {
1228 tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
1229 WREG32(RADEON_DISP_HW_DEBUG, tmp);
1230 }
1231
1232 tmp = RADEON_TV_DAC_NBLANK |
1233 RADEON_TV_DAC_NHOLD |
1234 RADEON_TV_MONITOR_DETECT_EN |
1235 RADEON_TV_DAC_STD_PS2;
1236
1237 WREG32(RADEON_TV_DAC_CNTL, tmp);
1238
1239 tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
1240 RADEON_DAC2_FORCE_DATA_EN;
1241
1242 if (color)
1243 tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
1244 else
1245 tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
1246
1247 if (ASIC_IS_R300(rdev))
1248 tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
1249 else
1250 tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
1251
1252 WREG32(RADEON_DAC_EXT_CNTL, tmp);
1253
1254 tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
1255 WREG32(RADEON_DAC_CNTL2, tmp);
1256
1257 udelay(10000);
1258
1259 if (ASIC_IS_R300(rdev)) {
1260 if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
1261 found = connector_status_connected;
1262 } else {
1263 if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT)
1264 found = connector_status_connected;
1265 }
1266
1267 /* restore regs we used */
1268 WREG32(RADEON_DAC_CNTL2, dac_cntl2);
1269 WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1270 WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1271 WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1272
1273 if (ASIC_IS_R300(rdev)) {
1274 WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1275 WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1276 } else {
1277 WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
1278 }
1279 WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
1280
Dave Airlie4ce001a2009-08-13 16:32:14 +10001281 return found;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001282
1283}
1284
1285static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
1286 .dpms = radeon_legacy_tv_dac_dpms,
Alex Deucher80297e82009-11-12 14:55:14 -05001287 .mode_fixup = radeon_legacy_mode_fixup,
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001288 .prepare = radeon_legacy_tv_dac_prepare,
1289 .mode_set = radeon_legacy_tv_dac_mode_set,
1290 .commit = radeon_legacy_tv_dac_commit,
1291 .detect = radeon_legacy_tv_dac_detect,
Dave Airlie4ce001a2009-08-13 16:32:14 +10001292 .disable = radeon_legacy_encoder_disable,
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001293};
1294
1295
1296static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = {
1297 .destroy = radeon_enc_destroy,
1298};
1299
Dave Airlie445282d2009-09-09 17:40:54 +10001300
1301static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder)
1302{
1303 struct drm_device *dev = encoder->base.dev;
1304 struct radeon_device *rdev = dev->dev_private;
1305 struct radeon_encoder_int_tmds *tmds = NULL;
1306 bool ret;
1307
1308 tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
1309
1310 if (!tmds)
1311 return NULL;
1312
1313 if (rdev->is_atom_bios)
1314 ret = radeon_atombios_get_tmds_info(encoder, tmds);
1315 else
1316 ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
1317
1318 if (ret == false)
1319 radeon_legacy_get_tmds_info_from_table(encoder, tmds);
1320
1321 return tmds;
1322}
1323
Alex Deucherfcec5702009-11-10 21:25:07 -05001324static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
1325{
1326 struct drm_device *dev = encoder->base.dev;
1327 struct radeon_device *rdev = dev->dev_private;
1328 struct radeon_encoder_ext_tmds *tmds = NULL;
1329 bool ret;
1330
1331 if (rdev->is_atom_bios)
1332 return NULL;
1333
1334 tmds = kzalloc(sizeof(struct radeon_encoder_ext_tmds), GFP_KERNEL);
1335
1336 if (!tmds)
1337 return NULL;
1338
1339 ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
1340
1341 if (ret == false)
1342 radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
1343
1344 return tmds;
1345}
1346
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001347void
1348radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
1349{
1350 struct radeon_device *rdev = dev->dev_private;
1351 struct drm_encoder *encoder;
1352 struct radeon_encoder *radeon_encoder;
1353
1354 /* see if we already added it */
1355 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1356 radeon_encoder = to_radeon_encoder(encoder);
1357 if (radeon_encoder->encoder_id == encoder_id) {
1358 radeon_encoder->devices |= supported_device;
1359 return;
1360 }
1361
1362 }
1363
1364 /* add a new one */
1365 radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
1366 if (!radeon_encoder)
1367 return;
1368
1369 encoder = &radeon_encoder->base;
Dave Airliedfee5612009-10-02 09:19:09 +10001370 if (rdev->flags & RADEON_SINGLE_CRTC)
1371 encoder->possible_crtcs = 0x1;
1372 else
1373 encoder->possible_crtcs = 0x3;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001374
1375 radeon_encoder->enc_priv = NULL;
1376
1377 radeon_encoder->encoder_id = encoder_id;
1378 radeon_encoder->devices = supported_device;
Jerome Glissec93bb852009-07-13 21:04:08 +02001379 radeon_encoder->rmx_type = RMX_OFF;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001380
1381 switch (radeon_encoder->encoder_id) {
1382 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
Dave Airlie80e69142009-08-17 10:22:37 +10001383 encoder->possible_crtcs = 0x1;
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001384 drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS);
1385 drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
1386 if (rdev->is_atom_bios)
1387 radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
1388 else
1389 radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder);
1390 radeon_encoder->rmx_type = RMX_FULL;
1391 break;
1392 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1393 drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS);
1394 drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
Dave Airlie445282d2009-09-09 17:40:54 +10001395 radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001396 break;
1397 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1398 drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
1399 drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001400 if (rdev->is_atom_bios)
1401 radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder);
1402 else
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001403 radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder);
1404 break;
1405 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1406 drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC);
1407 drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs);
Alex Deucher6fe7ac32009-06-12 17:26:08 +00001408 if (rdev->is_atom_bios)
1409 radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder);
1410 else
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001411 radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder);
1412 break;
1413 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1414 drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
1415 drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
1416 if (!rdev->is_atom_bios)
Alex Deucherfcec5702009-11-10 21:25:07 -05001417 radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001418 break;
1419 }
1420}