diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-14 21:08:56 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-03-14 21:08:59 -0400 |
commit | 1fc59eda33e55f8787901e3501d695bf5ecec48b (patch) | |
tree | 9a86d6e5728f67670de441dd892cd9a09f67423b /drivers/gpu | |
parent | d5e5deddf67389eabc3d9b13004c108120d397e1 (diff) | |
parent | d0d6cb81e7eb34d83461070ca3e919fba1db437c (diff) |
Merge branch 'radeon-for-airlied' of ../linux-2.6 into drm-linus
* 'radeon-for-airlied' of ../linux-2.6:
drm/radeon/kms: prepare for more reclocking operations
drm/radeon/kms: switch to condition waiting for reclocking
drm/radeon/r600: add missing license and comments to r600_blit_shaders.c
drm/radeon/kms: improve coding style a little
drm/radeon/kms: remove dead audio/HDMI code
drm/radeon/kms: enable audio engine on DCE32
drm/radeon/kms: add HDMI code for pre-DCE3 R6xx GPUs
drm/radeon/kms: clean assigning HDMI blocks to encoders
drm/radeon/kms: clean HDMI definitions
drm/radeon/kms/rs4xx: make sure crtcs are enabled when setting timing
drm/radeon/kms/r1xx: enable hw i2c
drm/radeon/kms: fix i2c prescale calc on older radeons
drm/radeon/kms: fix for hw i2c
drm/radeon/kms: fix pal tv-out support on legacy IGP chips
drm/radeon/kms: further spread spectrum fixes
drm/radeon/kms: use lcd pll limits when available
drm/radeon/kms/atom: spread spectrum fix
drm/radeon/kms: catch atombios infinite loop and break out of it
drm/radeon: add new RS880 pci id
Diffstat (limited to 'drivers/gpu')
21 files changed, 444 insertions, 185 deletions
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index d75788feac6c..b7fe660985c4 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c | |||
@@ -52,15 +52,17 @@ | |||
52 | 52 | ||
53 | typedef struct { | 53 | typedef struct { |
54 | struct atom_context *ctx; | 54 | struct atom_context *ctx; |
55 | |||
56 | uint32_t *ps, *ws; | 55 | uint32_t *ps, *ws; |
57 | int ps_shift; | 56 | int ps_shift; |
58 | uint16_t start; | 57 | uint16_t start; |
58 | unsigned last_jump; | ||
59 | unsigned long last_jump_jiffies; | ||
60 | bool abort; | ||
59 | } atom_exec_context; | 61 | } atom_exec_context; |
60 | 62 | ||
61 | int atom_debug = 0; | 63 | int atom_debug = 0; |
62 | static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params); | 64 | static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params); |
63 | void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params); | 65 | int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params); |
64 | 66 | ||
65 | static uint32_t atom_arg_mask[8] = | 67 | static uint32_t atom_arg_mask[8] = |
66 | { 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000, | 68 | { 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000, |
@@ -604,12 +606,17 @@ static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg) | |||
604 | static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg) | 606 | static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg) |
605 | { | 607 | { |
606 | int idx = U8((*ptr)++); | 608 | int idx = U8((*ptr)++); |
609 | int r = 0; | ||
610 | |||
607 | if (idx < ATOM_TABLE_NAMES_CNT) | 611 | if (idx < ATOM_TABLE_NAMES_CNT) |
608 | SDEBUG(" table: %d (%s)\n", idx, atom_table_names[idx]); | 612 | SDEBUG(" table: %d (%s)\n", idx, atom_table_names[idx]); |
609 | else | 613 | else |
610 | SDEBUG(" table: %d\n", idx); | 614 | SDEBUG(" table: %d\n", idx); |
611 | if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) | 615 | if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) |
612 | atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift); | 616 | r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift); |
617 | if (r) { | ||
618 | ctx->abort = true; | ||
619 | } | ||
613 | } | 620 | } |
614 | 621 | ||
615 | static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg) | 622 | static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg) |
@@ -673,6 +680,8 @@ static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg) | |||
673 | static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) | 680 | static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) |
674 | { | 681 | { |
675 | int execute = 0, target = U16(*ptr); | 682 | int execute = 0, target = U16(*ptr); |
683 | unsigned long cjiffies; | ||
684 | |||
676 | (*ptr) += 2; | 685 | (*ptr) += 2; |
677 | switch (arg) { | 686 | switch (arg) { |
678 | case ATOM_COND_ABOVE: | 687 | case ATOM_COND_ABOVE: |
@@ -700,8 +709,25 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) | |||
700 | if (arg != ATOM_COND_ALWAYS) | 709 | if (arg != ATOM_COND_ALWAYS) |
701 | SDEBUG(" taken: %s\n", execute ? "yes" : "no"); | 710 | SDEBUG(" taken: %s\n", execute ? "yes" : "no"); |
702 | SDEBUG(" target: 0x%04X\n", target); | 711 | SDEBUG(" target: 0x%04X\n", target); |
703 | if (execute) | 712 | if (execute) { |
713 | if (ctx->last_jump == (ctx->start + target)) { | ||
714 | cjiffies = jiffies; | ||
715 | if (time_after(cjiffies, ctx->last_jump_jiffies)) { | ||
716 | cjiffies -= ctx->last_jump_jiffies; | ||
717 | if ((jiffies_to_msecs(cjiffies) > 1000)) { | ||
718 | DRM_ERROR("atombios stuck in loop for more than 1sec aborting\n"); | ||
719 | ctx->abort = true; | ||
720 | } | ||
721 | } else { | ||
722 | /* jiffies wrap around we will just wait a little longer */ | ||
723 | ctx->last_jump_jiffies = jiffies; | ||
724 | } | ||
725 | } else { | ||
726 | ctx->last_jump = ctx->start + target; | ||
727 | ctx->last_jump_jiffies = jiffies; | ||
728 | } | ||
704 | *ptr = ctx->start + target; | 729 | *ptr = ctx->start + target; |
730 | } | ||
705 | } | 731 | } |
706 | 732 | ||
707 | static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg) | 733 | static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg) |
@@ -1104,7 +1130,7 @@ static struct { | |||
1104 | atom_op_shr, ATOM_ARG_MC}, { | 1130 | atom_op_shr, ATOM_ARG_MC}, { |
1105 | atom_op_debug, 0},}; | 1131 | atom_op_debug, 0},}; |
1106 | 1132 | ||
1107 | static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params) | 1133 | static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params) |
1108 | { | 1134 | { |
1109 | int base = CU16(ctx->cmd_table + 4 + 2 * index); | 1135 | int base = CU16(ctx->cmd_table + 4 + 2 * index); |
1110 | int len, ws, ps, ptr; | 1136 | int len, ws, ps, ptr; |
@@ -1112,7 +1138,7 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 | |||
1112 | atom_exec_context ectx; | 1138 | atom_exec_context ectx; |
1113 | 1139 | ||
1114 | if (!base) | 1140 | if (!base) |
1115 | return; | 1141 | return -EINVAL; |
1116 | 1142 | ||
1117 | len = CU16(base + ATOM_CT_SIZE_PTR); | 1143 | len = CU16(base + ATOM_CT_SIZE_PTR); |
1118 | ws = CU8(base + ATOM_CT_WS_PTR); | 1144 | ws = CU8(base + ATOM_CT_WS_PTR); |
@@ -1125,6 +1151,8 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 | |||
1125 | ectx.ps_shift = ps / 4; | 1151 | ectx.ps_shift = ps / 4; |
1126 | ectx.start = base; | 1152 | ectx.start = base; |
1127 | ectx.ps = params; | 1153 | ectx.ps = params; |
1154 | ectx.abort = false; | ||
1155 | ectx.last_jump = 0; | ||
1128 | if (ws) | 1156 | if (ws) |
1129 | ectx.ws = kzalloc(4 * ws, GFP_KERNEL); | 1157 | ectx.ws = kzalloc(4 * ws, GFP_KERNEL); |
1130 | else | 1158 | else |
@@ -1137,6 +1165,11 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 | |||
1137 | SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1); | 1165 | SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1); |
1138 | else | 1166 | else |
1139 | SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1); | 1167 | SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1); |
1168 | if (ectx.abort) { | ||
1169 | DRM_ERROR("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n", | ||
1170 | base, len, ws, ps, ptr - 1); | ||
1171 | return -EINVAL; | ||
1172 | } | ||
1140 | 1173 | ||
1141 | if (op < ATOM_OP_CNT && op > 0) | 1174 | if (op < ATOM_OP_CNT && op > 0) |
1142 | opcode_table[op].func(&ectx, &ptr, | 1175 | opcode_table[op].func(&ectx, &ptr, |
@@ -1152,10 +1185,13 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 | |||
1152 | 1185 | ||
1153 | if (ws) | 1186 | if (ws) |
1154 | kfree(ectx.ws); | 1187 | kfree(ectx.ws); |
1188 | return 0; | ||
1155 | } | 1189 | } |
1156 | 1190 | ||
1157 | void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) | 1191 | int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) |
1158 | { | 1192 | { |
1193 | int r; | ||
1194 | |||
1159 | mutex_lock(&ctx->mutex); | 1195 | mutex_lock(&ctx->mutex); |
1160 | /* reset reg block */ | 1196 | /* reset reg block */ |
1161 | ctx->reg_block = 0; | 1197 | ctx->reg_block = 0; |
@@ -1163,8 +1199,9 @@ void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) | |||
1163 | ctx->fb_base = 0; | 1199 | ctx->fb_base = 0; |
1164 | /* reset io mode */ | 1200 | /* reset io mode */ |
1165 | ctx->io_mode = ATOM_IO_MM; | 1201 | ctx->io_mode = ATOM_IO_MM; |
1166 | atom_execute_table_locked(ctx, index, params); | 1202 | r = atom_execute_table_locked(ctx, index, params); |
1167 | mutex_unlock(&ctx->mutex); | 1203 | mutex_unlock(&ctx->mutex); |
1204 | return r; | ||
1168 | } | 1205 | } |
1169 | 1206 | ||
1170 | static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 }; | 1207 | static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 }; |
@@ -1248,9 +1285,7 @@ int atom_asic_init(struct atom_context *ctx) | |||
1248 | 1285 | ||
1249 | if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT)) | 1286 | if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT)) |
1250 | return 1; | 1287 | return 1; |
1251 | atom_execute_table(ctx, ATOM_CMD_INIT, ps); | 1288 | return atom_execute_table(ctx, ATOM_CMD_INIT, ps); |
1252 | |||
1253 | return 0; | ||
1254 | } | 1289 | } |
1255 | 1290 | ||
1256 | void atom_destroy(struct atom_context *ctx) | 1291 | void atom_destroy(struct atom_context *ctx) |
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index bc73781423a1..1b2626314804 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h | |||
@@ -140,7 +140,7 @@ struct atom_context { | |||
140 | extern int atom_debug; | 140 | extern int atom_debug; |
141 | 141 | ||
142 | struct atom_context *atom_parse(struct card_info *, void *); | 142 | struct atom_context *atom_parse(struct card_info *, void *); |
143 | void atom_execute_table(struct atom_context *, int, uint32_t *); | 143 | int atom_execute_table(struct atom_context *, int, uint32_t *); |
144 | int atom_asic_init(struct atom_context *); | 144 | int atom_asic_init(struct atom_context *); |
145 | void atom_destroy(struct atom_context *); | 145 | void atom_destroy(struct atom_context *); |
146 | void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start); | 146 | void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start); |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index dd9fdf560611..7c30e2e74c85 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -353,12 +353,55 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, | |||
353 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 353 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
354 | } | 354 | } |
355 | 355 | ||
356 | static void atombios_disable_ss(struct drm_crtc *crtc) | ||
357 | { | ||
358 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
359 | struct drm_device *dev = crtc->dev; | ||
360 | struct radeon_device *rdev = dev->dev_private; | ||
361 | u32 ss_cntl; | ||
362 | |||
363 | if (ASIC_IS_DCE4(rdev)) { | ||
364 | switch (radeon_crtc->pll_id) { | ||
365 | case ATOM_PPLL1: | ||
366 | ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL); | ||
367 | ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; | ||
368 | WREG32(EVERGREEN_P1PLL_SS_CNTL, ss_cntl); | ||
369 | break; | ||
370 | case ATOM_PPLL2: | ||
371 | ss_cntl = RREG32(EVERGREEN_P2PLL_SS_CNTL); | ||
372 | ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; | ||
373 | WREG32(EVERGREEN_P2PLL_SS_CNTL, ss_cntl); | ||
374 | break; | ||
375 | case ATOM_DCPLL: | ||
376 | case ATOM_PPLL_INVALID: | ||
377 | return; | ||
378 | } | ||
379 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
380 | switch (radeon_crtc->pll_id) { | ||
381 | case ATOM_PPLL1: | ||
382 | ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); | ||
383 | ss_cntl &= ~1; | ||
384 | WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl); | ||
385 | break; | ||
386 | case ATOM_PPLL2: | ||
387 | ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL); | ||
388 | ss_cntl &= ~1; | ||
389 | WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl); | ||
390 | break; | ||
391 | case ATOM_DCPLL: | ||
392 | case ATOM_PPLL_INVALID: | ||
393 | return; | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | |||
398 | |||
356 | union atom_enable_ss { | 399 | union atom_enable_ss { |
357 | ENABLE_LVDS_SS_PARAMETERS legacy; | 400 | ENABLE_LVDS_SS_PARAMETERS legacy; |
358 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; | 401 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; |
359 | }; | 402 | }; |
360 | 403 | ||
361 | static void atombios_set_ss(struct drm_crtc *crtc, int enable) | 404 | static void atombios_enable_ss(struct drm_crtc *crtc) |
362 | { | 405 | { |
363 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 406 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
364 | struct drm_device *dev = crtc->dev; | 407 | struct drm_device *dev = crtc->dev; |
@@ -387,9 +430,9 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
387 | step = dig->ss->step; | 430 | step = dig->ss->step; |
388 | delay = dig->ss->delay; | 431 | delay = dig->ss->delay; |
389 | range = dig->ss->range; | 432 | range = dig->ss->range; |
390 | } else if (enable) | 433 | } else |
391 | return; | 434 | return; |
392 | } else if (enable) | 435 | } else |
393 | return; | 436 | return; |
394 | break; | 437 | break; |
395 | } | 438 | } |
@@ -406,13 +449,13 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
406 | args.v1.ucSpreadSpectrumDelay = delay; | 449 | args.v1.ucSpreadSpectrumDelay = delay; |
407 | args.v1.ucSpreadSpectrumRange = range; | 450 | args.v1.ucSpreadSpectrumRange = range; |
408 | args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 451 | args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
409 | args.v1.ucEnable = enable; | 452 | args.v1.ucEnable = ATOM_ENABLE; |
410 | } else { | 453 | } else { |
411 | args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage); | 454 | args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage); |
412 | args.legacy.ucSpreadSpectrumType = type; | 455 | args.legacy.ucSpreadSpectrumType = type; |
413 | args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2; | 456 | args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2; |
414 | args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4; | 457 | args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4; |
415 | args.legacy.ucEnable = enable; | 458 | args.legacy.ucEnable = ATOM_ENABLE; |
416 | } | 459 | } |
417 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 460 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
418 | } | 461 | } |
@@ -482,6 +525,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
482 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { | 525 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { |
483 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 526 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
484 | pll->algo = dig->pll_algo; | 527 | pll->algo = dig->pll_algo; |
528 | pll->flags |= RADEON_PLL_IS_LCD; | ||
485 | } | 529 | } |
486 | } else { | 530 | } else { |
487 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 531 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
@@ -1083,15 +1127,12 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
1083 | 1127 | ||
1084 | /* TODO color tiling */ | 1128 | /* TODO color tiling */ |
1085 | 1129 | ||
1086 | /* pick pll */ | 1130 | atombios_disable_ss(crtc); |
1087 | radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); | ||
1088 | |||
1089 | atombios_set_ss(crtc, 0); | ||
1090 | /* always set DCPLL */ | 1131 | /* always set DCPLL */ |
1091 | if (ASIC_IS_DCE4(rdev)) | 1132 | if (ASIC_IS_DCE4(rdev)) |
1092 | atombios_crtc_set_dcpll(crtc); | 1133 | atombios_crtc_set_dcpll(crtc); |
1093 | atombios_crtc_set_pll(crtc, adjusted_mode); | 1134 | atombios_crtc_set_pll(crtc, adjusted_mode); |
1094 | atombios_set_ss(crtc, 1); | 1135 | atombios_enable_ss(crtc); |
1095 | 1136 | ||
1096 | if (ASIC_IS_DCE4(rdev)) | 1137 | if (ASIC_IS_DCE4(rdev)) |
1097 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 1138 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
@@ -1120,6 +1161,11 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, | |||
1120 | 1161 | ||
1121 | static void atombios_crtc_prepare(struct drm_crtc *crtc) | 1162 | static void atombios_crtc_prepare(struct drm_crtc *crtc) |
1122 | { | 1163 | { |
1164 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
1165 | |||
1166 | /* pick pll */ | ||
1167 | radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); | ||
1168 | |||
1123 | atombios_lock_crtc(crtc, ATOM_ENABLE); | 1169 | atombios_lock_crtc(crtc, ATOM_ENABLE); |
1124 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | 1170 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
1125 | } | 1171 | } |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 91eb762eb3f9..73f9a79ed64d 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -312,10 +312,12 @@ int r100_irq_process(struct radeon_device *rdev) | |||
312 | /* Vertical blank interrupts */ | 312 | /* Vertical blank interrupts */ |
313 | if (status & RADEON_CRTC_VBLANK_STAT) { | 313 | if (status & RADEON_CRTC_VBLANK_STAT) { |
314 | drm_handle_vblank(rdev->ddev, 0); | 314 | drm_handle_vblank(rdev->ddev, 0); |
315 | rdev->pm.vblank_sync = true; | ||
315 | wake_up(&rdev->irq.vblank_queue); | 316 | wake_up(&rdev->irq.vblank_queue); |
316 | } | 317 | } |
317 | if (status & RADEON_CRTC2_VBLANK_STAT) { | 318 | if (status & RADEON_CRTC2_VBLANK_STAT) { |
318 | drm_handle_vblank(rdev->ddev, 1); | 319 | drm_handle_vblank(rdev->ddev, 1); |
320 | rdev->pm.vblank_sync = true; | ||
319 | wake_up(&rdev->irq.vblank_queue); | 321 | wake_up(&rdev->irq.vblank_queue); |
320 | } | 322 | } |
321 | if (status & RADEON_FP_DETECT_STAT) { | 323 | if (status & RADEON_FP_DETECT_STAT) { |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index c52290197292..5b56a1b3902c 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -2765,6 +2765,7 @@ restart_ih: | |||
2765 | case 0: /* D1 vblank */ | 2765 | case 0: /* D1 vblank */ |
2766 | if (disp_int & LB_D1_VBLANK_INTERRUPT) { | 2766 | if (disp_int & LB_D1_VBLANK_INTERRUPT) { |
2767 | drm_handle_vblank(rdev->ddev, 0); | 2767 | drm_handle_vblank(rdev->ddev, 0); |
2768 | rdev->pm.vblank_sync = true; | ||
2768 | wake_up(&rdev->irq.vblank_queue); | 2769 | wake_up(&rdev->irq.vblank_queue); |
2769 | disp_int &= ~LB_D1_VBLANK_INTERRUPT; | 2770 | disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
2770 | DRM_DEBUG("IH: D1 vblank\n"); | 2771 | DRM_DEBUG("IH: D1 vblank\n"); |
@@ -2786,6 +2787,7 @@ restart_ih: | |||
2786 | case 0: /* D2 vblank */ | 2787 | case 0: /* D2 vblank */ |
2787 | if (disp_int & LB_D2_VBLANK_INTERRUPT) { | 2788 | if (disp_int & LB_D2_VBLANK_INTERRUPT) { |
2788 | drm_handle_vblank(rdev->ddev, 1); | 2789 | drm_handle_vblank(rdev->ddev, 1); |
2790 | rdev->pm.vblank_sync = true; | ||
2789 | wake_up(&rdev->irq.vblank_queue); | 2791 | wake_up(&rdev->irq.vblank_queue); |
2790 | disp_int &= ~LB_D2_VBLANK_INTERRUPT; | 2792 | disp_int &= ~LB_D2_VBLANK_INTERRUPT; |
2791 | DRM_DEBUG("IH: D2 vblank\n"); | 2793 | DRM_DEBUG("IH: D2 vblank\n"); |
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index db928016d034..dac7042b797e 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c | |||
@@ -182,41 +182,6 @@ int r600_audio_init(struct radeon_device *rdev) | |||
182 | } | 182 | } |
183 | 183 | ||
184 | /* | 184 | /* |
185 | * determin how the encoders and audio interface is wired together | ||
186 | */ | ||
187 | int r600_audio_tmds_index(struct drm_encoder *encoder) | ||
188 | { | ||
189 | struct drm_device *dev = encoder->dev; | ||
190 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
191 | struct drm_encoder *other; | ||
192 | |||
193 | switch (radeon_encoder->encoder_id) { | ||
194 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
195 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
196 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
197 | return 0; | ||
198 | |||
199 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
200 | /* special case check if an TMDS1 is present */ | ||
201 | list_for_each_entry(other, &dev->mode_config.encoder_list, head) { | ||
202 | if (to_radeon_encoder(other)->encoder_id == | ||
203 | ENCODER_OBJECT_ID_INTERNAL_TMDS1) | ||
204 | return 1; | ||
205 | } | ||
206 | return 0; | ||
207 | |||
208 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
209 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
210 | return 1; | ||
211 | |||
212 | default: | ||
213 | DRM_ERROR("Unsupported encoder type 0x%02X\n", | ||
214 | radeon_encoder->encoder_id); | ||
215 | return -1; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * atach the audio codec to the clock source of the encoder | 185 | * atach the audio codec to the clock source of the encoder |
221 | */ | 186 | */ |
222 | void r600_audio_set_clock(struct drm_encoder *encoder, int clock) | 187 | void r600_audio_set_clock(struct drm_encoder *encoder, int clock) |
@@ -224,6 +189,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) | |||
224 | struct drm_device *dev = encoder->dev; | 189 | struct drm_device *dev = encoder->dev; |
225 | struct radeon_device *rdev = dev->dev_private; | 190 | struct radeon_device *rdev = dev->dev_private; |
226 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 191 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
192 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
227 | int base_rate = 48000; | 193 | int base_rate = 48000; |
228 | 194 | ||
229 | switch (radeon_encoder->encoder_id) { | 195 | switch (radeon_encoder->encoder_id) { |
@@ -231,32 +197,34 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) | |||
231 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | 197 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: |
232 | WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); | 198 | WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); |
233 | break; | 199 | break; |
234 | |||
235 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 200 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
236 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 201 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
237 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 202 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
238 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | 203 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
239 | WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); | 204 | WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); |
240 | break; | 205 | break; |
241 | |||
242 | default: | 206 | default: |
243 | DRM_ERROR("Unsupported encoder type 0x%02X\n", | 207 | DRM_ERROR("Unsupported encoder type 0x%02X\n", |
244 | radeon_encoder->encoder_id); | 208 | radeon_encoder->encoder_id); |
245 | return; | 209 | return; |
246 | } | 210 | } |
247 | 211 | ||
248 | switch (r600_audio_tmds_index(encoder)) { | 212 | switch (dig->dig_encoder) { |
249 | case 0: | 213 | case 0: |
250 | WREG32(R600_AUDIO_PLL1_MUL, base_rate*50); | 214 | WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); |
251 | WREG32(R600_AUDIO_PLL1_DIV, clock*100); | 215 | WREG32(R600_AUDIO_PLL1_DIV, clock * 100); |
252 | WREG32(R600_AUDIO_CLK_SRCSEL, 0); | 216 | WREG32(R600_AUDIO_CLK_SRCSEL, 0); |
253 | break; | 217 | break; |
254 | 218 | ||
255 | case 1: | 219 | case 1: |
256 | WREG32(R600_AUDIO_PLL2_MUL, base_rate*50); | 220 | WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); |
257 | WREG32(R600_AUDIO_PLL2_DIV, clock*100); | 221 | WREG32(R600_AUDIO_PLL2_DIV, clock * 100); |
258 | WREG32(R600_AUDIO_CLK_SRCSEL, 1); | 222 | WREG32(R600_AUDIO_CLK_SRCSEL, 1); |
259 | break; | 223 | break; |
224 | default: | ||
225 | dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n", | ||
226 | radeon_encoder->encoder_id); | ||
227 | return; | ||
260 | } | 228 | } |
261 | } | 229 | } |
262 | 230 | ||
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.c b/drivers/gpu/drm/radeon/r600_blit_shaders.c index a112c59f9d82..0271b53fa2dd 100644 --- a/drivers/gpu/drm/radeon/r600_blit_shaders.c +++ b/drivers/gpu/drm/radeon/r600_blit_shaders.c | |||
@@ -1,7 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * 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) AND/OR ITS SUPPLIERS 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 OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Alex Deucher <alexander.deucher@amd.com> | ||
25 | */ | ||
1 | 26 | ||
2 | #include <linux/types.h> | 27 | #include <linux/types.h> |
3 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
4 | 29 | ||
30 | /* | ||
31 | * R6xx+ cards need to use the 3D engine to blit data which requires | ||
32 | * quite a bit of hw state setup. Rather than pull the whole 3D driver | ||
33 | * (which normally generates the 3D state) into the DRM, we opt to use | ||
34 | * statically generated state tables. The regsiter state and shaders | ||
35 | * were hand generated to support blitting functionality. See the 3D | ||
36 | * driver or documentation for descriptions of the registers and | ||
37 | * shader instructions. | ||
38 | */ | ||
39 | |||
5 | const u32 r6xx_default_state[] = | 40 | const u32 r6xx_default_state[] = |
6 | { | 41 | { |
7 | 0xc0002400, | 42 | 0xc0002400, |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index fcc949df0e5d..029fa1406d1d 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -42,13 +42,13 @@ enum r600_hdmi_color_format { | |||
42 | */ | 42 | */ |
43 | enum r600_hdmi_iec_status_bits { | 43 | enum r600_hdmi_iec_status_bits { |
44 | AUDIO_STATUS_DIG_ENABLE = 0x01, | 44 | AUDIO_STATUS_DIG_ENABLE = 0x01, |
45 | AUDIO_STATUS_V = 0x02, | 45 | AUDIO_STATUS_V = 0x02, |
46 | AUDIO_STATUS_VCFG = 0x04, | 46 | AUDIO_STATUS_VCFG = 0x04, |
47 | AUDIO_STATUS_EMPHASIS = 0x08, | 47 | AUDIO_STATUS_EMPHASIS = 0x08, |
48 | AUDIO_STATUS_COPYRIGHT = 0x10, | 48 | AUDIO_STATUS_COPYRIGHT = 0x10, |
49 | AUDIO_STATUS_NONAUDIO = 0x20, | 49 | AUDIO_STATUS_NONAUDIO = 0x20, |
50 | AUDIO_STATUS_PROFESSIONAL = 0x40, | 50 | AUDIO_STATUS_PROFESSIONAL = 0x40, |
51 | AUDIO_STATUS_LEVEL = 0x80 | 51 | AUDIO_STATUS_LEVEL = 0x80 |
52 | }; | 52 | }; |
53 | 53 | ||
54 | struct { | 54 | struct { |
@@ -85,7 +85,7 @@ struct { | |||
85 | static void r600_hdmi_calc_CTS(uint32_t clock, int *CTS, int N, int freq) | 85 | static void r600_hdmi_calc_CTS(uint32_t clock, int *CTS, int N, int freq) |
86 | { | 86 | { |
87 | if (*CTS == 0) | 87 | if (*CTS == 0) |
88 | *CTS = clock*N/(128*freq)*1000; | 88 | *CTS = clock * N / (128 * freq) * 1000; |
89 | DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", | 89 | DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", |
90 | N, *CTS, freq); | 90 | N, *CTS, freq); |
91 | } | 91 | } |
@@ -131,11 +131,11 @@ static void r600_hdmi_infoframe_checksum(uint8_t packetType, | |||
131 | uint8_t length, | 131 | uint8_t length, |
132 | uint8_t *frame) | 132 | uint8_t *frame) |
133 | { | 133 | { |
134 | int i; | 134 | int i; |
135 | frame[0] = packetType + versionNumber + length; | 135 | frame[0] = packetType + versionNumber + length; |
136 | for (i = 1; i <= length; i++) | 136 | for (i = 1; i <= length; i++) |
137 | frame[0] += frame[i]; | 137 | frame[0] += frame[i]; |
138 | frame[0] = 0x100 - frame[0]; | 138 | frame[0] = 0x100 - frame[0]; |
139 | } | 139 | } |
140 | 140 | ||
141 | /* | 141 | /* |
@@ -417,90 +417,141 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, | |||
417 | WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); | 417 | WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); |
418 | } | 418 | } |
419 | 419 | ||
420 | /* | 420 | static int r600_hdmi_find_free_block(struct drm_device *dev) |
421 | * enable/disable the HDMI engine | 421 | { |
422 | */ | 422 | struct radeon_device *rdev = dev->dev_private; |
423 | void r600_hdmi_enable(struct drm_encoder *encoder, int enable) | 423 | struct drm_encoder *encoder; |
424 | struct radeon_encoder *radeon_encoder; | ||
425 | bool free_blocks[3] = { true, true, true }; | ||
426 | |||
427 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
428 | radeon_encoder = to_radeon_encoder(encoder); | ||
429 | switch (radeon_encoder->hdmi_offset) { | ||
430 | case R600_HDMI_BLOCK1: | ||
431 | free_blocks[0] = false; | ||
432 | break; | ||
433 | case R600_HDMI_BLOCK2: | ||
434 | free_blocks[1] = false; | ||
435 | break; | ||
436 | case R600_HDMI_BLOCK3: | ||
437 | free_blocks[2] = false; | ||
438 | break; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690) { | ||
443 | return free_blocks[0] ? R600_HDMI_BLOCK1 : 0; | ||
444 | } else if (rdev->family >= CHIP_R600) { | ||
445 | if (free_blocks[0]) | ||
446 | return R600_HDMI_BLOCK1; | ||
447 | else if (free_blocks[1]) | ||
448 | return R600_HDMI_BLOCK2; | ||
449 | } | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static void r600_hdmi_assign_block(struct drm_encoder *encoder) | ||
424 | { | 454 | { |
425 | struct drm_device *dev = encoder->dev; | 455 | struct drm_device *dev = encoder->dev; |
426 | struct radeon_device *rdev = dev->dev_private; | 456 | struct radeon_device *rdev = dev->dev_private; |
427 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 457 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
428 | uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; | 458 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
429 | 459 | ||
430 | if (!offset) | 460 | if (!dig) { |
461 | dev_err(rdev->dev, "Enabling HDMI on non-dig encoder\n"); | ||
431 | return; | 462 | return; |
463 | } | ||
432 | 464 | ||
433 | DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset); | 465 | if (ASIC_IS_DCE4(rdev)) { |
434 | 466 | /* TODO */ | |
435 | /* some version of atombios ignore the enable HDMI flag | 467 | } else if (ASIC_IS_DCE3(rdev)) { |
436 | * so enabling/disabling HDMI was moved here for TMDS1+2 */ | 468 | radeon_encoder->hdmi_offset = dig->dig_encoder ? |
437 | switch (radeon_encoder->encoder_id) { | 469 | R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1; |
438 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | 470 | if (ASIC_IS_DCE32(rdev)) |
439 | WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4); | 471 | radeon_encoder->hdmi_config_offset = dig->dig_encoder ? |
440 | WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0); | 472 | R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1; |
441 | break; | 473 | } else if (rdev->family >= CHIP_R600) { |
442 | 474 | radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev); | |
443 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
444 | WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4); | ||
445 | WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0); | ||
446 | break; | ||
447 | |||
448 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
449 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
450 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
451 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
452 | /* This part is doubtfull in my opinion */ | ||
453 | WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0); | ||
454 | break; | ||
455 | |||
456 | default: | ||
457 | DRM_ERROR("unknown HDMI output type\n"); | ||
458 | break; | ||
459 | } | 475 | } |
460 | } | 476 | } |
461 | 477 | ||
462 | /* | 478 | /* |
463 | * determin at which register offset the HDMI encoder is | 479 | * enable the HDMI engine |
464 | */ | 480 | */ |
465 | void r600_hdmi_init(struct drm_encoder *encoder) | 481 | void r600_hdmi_enable(struct drm_encoder *encoder) |
466 | { | 482 | { |
483 | struct drm_device *dev = encoder->dev; | ||
484 | struct radeon_device *rdev = dev->dev_private; | ||
467 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 485 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
468 | 486 | ||
469 | switch (radeon_encoder->encoder_id) { | 487 | if (!radeon_encoder->hdmi_offset) { |
470 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | 488 | r600_hdmi_assign_block(encoder); |
471 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | 489 | if (!radeon_encoder->hdmi_offset) { |
472 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | 490 | dev_warn(rdev->dev, "Could not find HDMI block for " |
473 | radeon_encoder->hdmi_offset = R600_HDMI_TMDS1; | 491 | "0x%x encoder\n", radeon_encoder->encoder_id); |
474 | break; | 492 | return; |
475 | 493 | } | |
476 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | 494 | } |
477 | switch (r600_audio_tmds_index(encoder)) { | 495 | |
478 | case 0: | 496 | if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { |
479 | radeon_encoder->hdmi_offset = R600_HDMI_TMDS1; | 497 | WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1); |
498 | } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { | ||
499 | int offset = radeon_encoder->hdmi_offset; | ||
500 | switch (radeon_encoder->encoder_id) { | ||
501 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
502 | WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4); | ||
503 | WREG32(offset + R600_HDMI_ENABLE, 0x101); | ||
480 | break; | 504 | break; |
481 | case 1: | 505 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: |
482 | radeon_encoder->hdmi_offset = R600_HDMI_TMDS2; | 506 | WREG32_P(AVIVO_LVTMA_CNTL, 0x4, ~0x4); |
507 | WREG32(offset + R600_HDMI_ENABLE, 0x105); | ||
483 | break; | 508 | break; |
484 | default: | 509 | default: |
485 | radeon_encoder->hdmi_offset = 0; | 510 | dev_err(rdev->dev, "Unknown HDMI output type\n"); |
486 | break; | 511 | break; |
487 | } | 512 | } |
488 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | 513 | } |
489 | radeon_encoder->hdmi_offset = R600_HDMI_TMDS2; | ||
490 | break; | ||
491 | 514 | ||
492 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | 515 | DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
493 | radeon_encoder->hdmi_offset = R600_HDMI_DIG; | 516 | radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); |
494 | break; | 517 | } |
495 | 518 | ||
496 | default: | 519 | /* |
497 | radeon_encoder->hdmi_offset = 0; | 520 | * disable the HDMI engine |
498 | break; | 521 | */ |
522 | void r600_hdmi_disable(struct drm_encoder *encoder) | ||
523 | { | ||
524 | struct drm_device *dev = encoder->dev; | ||
525 | struct radeon_device *rdev = dev->dev_private; | ||
526 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
527 | |||
528 | if (!radeon_encoder->hdmi_offset) { | ||
529 | dev_err(rdev->dev, "Disabling not enabled HDMI\n"); | ||
530 | return; | ||
499 | } | 531 | } |
500 | 532 | ||
501 | DRM_DEBUG("using HDMI engine at offset 0x%04X for encoder 0x%x\n", | 533 | DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
502 | radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); | 534 | radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); |
535 | |||
536 | if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { | ||
537 | WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); | ||
538 | } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { | ||
539 | int offset = radeon_encoder->hdmi_offset; | ||
540 | switch (radeon_encoder->encoder_id) { | ||
541 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
542 | WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4); | ||
543 | WREG32(offset + R600_HDMI_ENABLE, 0); | ||
544 | break; | ||
545 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
546 | WREG32_P(AVIVO_LVTMA_CNTL, 0, ~0x4); | ||
547 | WREG32(offset + R600_HDMI_ENABLE, 0); | ||
548 | break; | ||
549 | default: | ||
550 | dev_err(rdev->dev, "Unknown HDMI output type\n"); | ||
551 | break; | ||
552 | } | ||
553 | } | ||
503 | 554 | ||
504 | /* TODO: make this configureable */ | 555 | radeon_encoder->hdmi_offset = 0; |
505 | radeon_encoder->hdmi_audio_workaround = 0; | 556 | radeon_encoder->hdmi_config_offset = 0; |
506 | } | 557 | } |
diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index d0e28ffdeda9..7b1d22370f6e 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h | |||
@@ -152,9 +152,9 @@ | |||
152 | #define R600_AUDIO_STATUS_BITS 0x73d8 | 152 | #define R600_AUDIO_STATUS_BITS 0x73d8 |
153 | 153 | ||
154 | /* HDMI base register addresses */ | 154 | /* HDMI base register addresses */ |
155 | #define R600_HDMI_TMDS1 0x7400 | 155 | #define R600_HDMI_BLOCK1 0x7400 |
156 | #define R600_HDMI_TMDS2 0x7700 | 156 | #define R600_HDMI_BLOCK2 0x7700 |
157 | #define R600_HDMI_DIG 0x7800 | 157 | #define R600_HDMI_BLOCK3 0x7800 |
158 | 158 | ||
159 | /* HDMI registers */ | 159 | /* HDMI registers */ |
160 | #define R600_HDMI_ENABLE 0x00 | 160 | #define R600_HDMI_ENABLE 0x00 |
@@ -185,4 +185,8 @@ | |||
185 | #define R600_HDMI_AUDIO_DEBUG_2 0xe8 | 185 | #define R600_HDMI_AUDIO_DEBUG_2 0xe8 |
186 | #define R600_HDMI_AUDIO_DEBUG_3 0xec | 186 | #define R600_HDMI_AUDIO_DEBUG_3 0xec |
187 | 187 | ||
188 | /* HDMI additional config base register addresses */ | ||
189 | #define R600_HDMI_CONFIG1 0x7600 | ||
190 | #define R600_HDMI_CONFIG2 0x7a00 | ||
191 | |||
188 | #endif | 192 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 829e26e8a4bb..b54d4f36c4da 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -687,6 +687,7 @@ struct radeon_pm { | |||
687 | bool downclocked; | 687 | bool downclocked; |
688 | int active_crtcs; | 688 | int active_crtcs; |
689 | int req_vblank; | 689 | int req_vblank; |
690 | bool vblank_sync; | ||
690 | fixed20_12 max_bandwidth; | 691 | fixed20_12 max_bandwidth; |
691 | fixed20_12 igp_sideport_mclk; | 692 | fixed20_12 igp_sideport_mclk; |
692 | fixed20_12 igp_system_mclk; | 693 | fixed20_12 igp_system_mclk; |
@@ -1322,7 +1323,8 @@ extern int r600_audio_tmds_index(struct drm_encoder *encoder); | |||
1322 | extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); | 1323 | extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); |
1323 | extern void r600_audio_fini(struct radeon_device *rdev); | 1324 | extern void r600_audio_fini(struct radeon_device *rdev); |
1324 | extern void r600_hdmi_init(struct drm_encoder *encoder); | 1325 | extern void r600_hdmi_init(struct drm_encoder *encoder); |
1325 | extern void r600_hdmi_enable(struct drm_encoder *encoder, int enable); | 1326 | extern void r600_hdmi_enable(struct drm_encoder *encoder); |
1327 | extern void r600_hdmi_disable(struct drm_encoder *encoder); | ||
1326 | extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); | 1328 | extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); |
1327 | extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); | 1329 | extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); |
1328 | extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, | 1330 | extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 93783b15c81d..e4540b2b859c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -887,6 +887,20 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) | |||
887 | p1pll->pll_out_max = | 887 | p1pll->pll_out_max = |
888 | le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); | 888 | le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); |
889 | 889 | ||
890 | if (crev >= 4) { | ||
891 | p1pll->lcd_pll_out_min = | ||
892 | le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100; | ||
893 | if (p1pll->lcd_pll_out_min == 0) | ||
894 | p1pll->lcd_pll_out_min = p1pll->pll_out_min; | ||
895 | p1pll->lcd_pll_out_max = | ||
896 | le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100; | ||
897 | if (p1pll->lcd_pll_out_max == 0) | ||
898 | p1pll->lcd_pll_out_max = p1pll->pll_out_max; | ||
899 | } else { | ||
900 | p1pll->lcd_pll_out_min = p1pll->pll_out_min; | ||
901 | p1pll->lcd_pll_out_max = p1pll->pll_out_max; | ||
902 | } | ||
903 | |||
890 | if (p1pll->pll_out_min == 0) { | 904 | if (p1pll->pll_out_min == 0) { |
891 | if (ASIC_IS_AVIVO(rdev)) | 905 | if (ASIC_IS_AVIVO(rdev)) |
892 | p1pll->pll_out_min = 64800; | 906 | p1pll->pll_out_min = 64800; |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 69af81d9f5ae..6d87e70a505b 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -531,10 +531,7 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
531 | case CHIP_RS300: | 531 | case CHIP_RS300: |
532 | switch (ddc_line) { | 532 | switch (ddc_line) { |
533 | case RADEON_GPIO_DVI_DDC: | 533 | case RADEON_GPIO_DVI_DDC: |
534 | /* in theory this should be hw capable, | 534 | i2c.hw_capable = true; |
535 | * but it doesn't seem to work | ||
536 | */ | ||
537 | i2c.hw_capable = false; | ||
538 | break; | 535 | break; |
539 | default: | 536 | default: |
540 | i2c.hw_capable = false; | 537 | i2c.hw_capable = false; |
@@ -633,6 +630,8 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) | |||
633 | p1pll->reference_div = RBIOS16(pll_info + 0x10); | 630 | p1pll->reference_div = RBIOS16(pll_info + 0x10); |
634 | p1pll->pll_out_min = RBIOS32(pll_info + 0x12); | 631 | p1pll->pll_out_min = RBIOS32(pll_info + 0x12); |
635 | p1pll->pll_out_max = RBIOS32(pll_info + 0x16); | 632 | p1pll->pll_out_max = RBIOS32(pll_info + 0x16); |
633 | p1pll->lcd_pll_out_min = p1pll->pll_out_min; | ||
634 | p1pll->lcd_pll_out_max = p1pll->pll_out_max; | ||
636 | 635 | ||
637 | if (rev > 9) { | 636 | if (rev > 9) { |
638 | p1pll->pll_in_min = RBIOS32(pll_info + 0x36); | 637 | p1pll->pll_in_min = RBIOS32(pll_info + 0x36); |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index ba8d806dcf39..ff5f09953c0a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -469,10 +469,19 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
469 | uint32_t best_error = 0xffffffff; | 469 | uint32_t best_error = 0xffffffff; |
470 | uint32_t best_vco_diff = 1; | 470 | uint32_t best_vco_diff = 1; |
471 | uint32_t post_div; | 471 | uint32_t post_div; |
472 | u32 pll_out_min, pll_out_max; | ||
472 | 473 | ||
473 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); | 474 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); |
474 | freq = freq * 1000; | 475 | freq = freq * 1000; |
475 | 476 | ||
477 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
478 | pll_out_min = pll->lcd_pll_out_min; | ||
479 | pll_out_max = pll->lcd_pll_out_max; | ||
480 | } else { | ||
481 | pll_out_min = pll->pll_out_min; | ||
482 | pll_out_max = pll->pll_out_max; | ||
483 | } | ||
484 | |||
476 | if (pll->flags & RADEON_PLL_USE_REF_DIV) | 485 | if (pll->flags & RADEON_PLL_USE_REF_DIV) |
477 | min_ref_div = max_ref_div = pll->reference_div; | 486 | min_ref_div = max_ref_div = pll->reference_div; |
478 | else { | 487 | else { |
@@ -536,10 +545,10 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
536 | tmp = (uint64_t)pll->reference_freq * feedback_div; | 545 | tmp = (uint64_t)pll->reference_freq * feedback_div; |
537 | vco = radeon_div(tmp, ref_div); | 546 | vco = radeon_div(tmp, ref_div); |
538 | 547 | ||
539 | if (vco < pll->pll_out_min) { | 548 | if (vco < pll_out_min) { |
540 | min_feed_div = feedback_div + 1; | 549 | min_feed_div = feedback_div + 1; |
541 | continue; | 550 | continue; |
542 | } else if (vco > pll->pll_out_max) { | 551 | } else if (vco > pll_out_max) { |
543 | max_feed_div = feedback_div; | 552 | max_feed_div = feedback_div; |
544 | continue; | 553 | continue; |
545 | } | 554 | } |
@@ -675,6 +684,15 @@ calc_fb_ref_div(struct radeon_pll *pll, | |||
675 | { | 684 | { |
676 | fixed20_12 ffreq, max_error, error, pll_out, a; | 685 | fixed20_12 ffreq, max_error, error, pll_out, a; |
677 | u32 vco; | 686 | u32 vco; |
687 | u32 pll_out_min, pll_out_max; | ||
688 | |||
689 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
690 | pll_out_min = pll->lcd_pll_out_min; | ||
691 | pll_out_max = pll->lcd_pll_out_max; | ||
692 | } else { | ||
693 | pll_out_min = pll->pll_out_min; | ||
694 | pll_out_max = pll->pll_out_max; | ||
695 | } | ||
678 | 696 | ||
679 | ffreq.full = rfixed_const(freq); | 697 | ffreq.full = rfixed_const(freq); |
680 | /* max_error = ffreq * 0.0025; */ | 698 | /* max_error = ffreq * 0.0025; */ |
@@ -686,7 +704,7 @@ calc_fb_ref_div(struct radeon_pll *pll, | |||
686 | vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac)); | 704 | vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac)); |
687 | vco = vco / ((*ref_div) * 10); | 705 | vco = vco / ((*ref_div) * 10); |
688 | 706 | ||
689 | if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max)) | 707 | if ((vco < pll_out_min) || (vco > pll_out_max)) |
690 | continue; | 708 | continue; |
691 | 709 | ||
692 | /* pll_out = vco / post_div; */ | 710 | /* pll_out = vco / post_div; */ |
@@ -714,6 +732,15 @@ static void radeon_compute_pll_new(struct radeon_pll *pll, | |||
714 | { | 732 | { |
715 | u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0; | 733 | u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0; |
716 | u32 best_freq = 0, vco_frequency; | 734 | u32 best_freq = 0, vco_frequency; |
735 | u32 pll_out_min, pll_out_max; | ||
736 | |||
737 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
738 | pll_out_min = pll->lcd_pll_out_min; | ||
739 | pll_out_max = pll->lcd_pll_out_max; | ||
740 | } else { | ||
741 | pll_out_min = pll->pll_out_min; | ||
742 | pll_out_max = pll->pll_out_max; | ||
743 | } | ||
717 | 744 | ||
718 | /* freq = freq / 10; */ | 745 | /* freq = freq / 10; */ |
719 | do_div(freq, 10); | 746 | do_div(freq, 10); |
@@ -724,7 +751,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll, | |||
724 | goto done; | 751 | goto done; |
725 | 752 | ||
726 | vco_frequency = freq * post_div; | 753 | vco_frequency = freq * post_div; |
727 | if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max)) | 754 | if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max)) |
728 | goto done; | 755 | goto done; |
729 | 756 | ||
730 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { | 757 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { |
@@ -749,7 +776,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll, | |||
749 | continue; | 776 | continue; |
750 | 777 | ||
751 | vco_frequency = freq * post_div; | 778 | vco_frequency = freq * post_div; |
752 | if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max)) | 779 | if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max)) |
753 | continue; | 780 | continue; |
754 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { | 781 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { |
755 | ref_div = pll->reference_div; | 782 | ref_div = pll->reference_div; |
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index bc926ea0a530..a236c75496c4 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
@@ -593,7 +593,6 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
593 | } | 593 | } |
594 | 594 | ||
595 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 595 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
596 | r600_hdmi_enable(encoder, hdmi_detected); | ||
597 | } | 596 | } |
598 | 597 | ||
599 | int | 598 | int |
@@ -1216,6 +1215,9 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
1216 | } | 1215 | } |
1217 | 1216 | ||
1218 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 1217 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
1218 | |||
1219 | /* update scratch regs with new routing */ | ||
1220 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
1219 | } | 1221 | } |
1220 | 1222 | ||
1221 | static void | 1223 | static void |
@@ -1326,19 +1328,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1326 | struct drm_device *dev = encoder->dev; | 1328 | struct drm_device *dev = encoder->dev; |
1327 | struct radeon_device *rdev = dev->dev_private; | 1329 | struct radeon_device *rdev = dev->dev_private; |
1328 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1330 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
1329 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
1330 | 1331 | ||
1331 | if (radeon_encoder->active_device & | ||
1332 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | ||
1333 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
1334 | if (dig) | ||
1335 | dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); | ||
1336 | } | ||
1337 | radeon_encoder->pixel_clock = adjusted_mode->clock; | 1332 | radeon_encoder->pixel_clock = adjusted_mode->clock; |
1338 | 1333 | ||
1339 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
1340 | atombios_set_encoder_crtc_source(encoder); | ||
1341 | |||
1342 | if (ASIC_IS_AVIVO(rdev)) { | 1334 | if (ASIC_IS_AVIVO(rdev)) { |
1343 | if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) | 1335 | if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) |
1344 | atombios_yuv_setup(encoder, true); | 1336 | atombios_yuv_setup(encoder, true); |
@@ -1396,9 +1388,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
1396 | } | 1388 | } |
1397 | atombios_apply_encoder_quirks(encoder, adjusted_mode); | 1389 | atombios_apply_encoder_quirks(encoder, adjusted_mode); |
1398 | 1390 | ||
1399 | /* XXX */ | 1391 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { |
1400 | if (!ASIC_IS_DCE4(rdev)) | 1392 | r600_hdmi_enable(encoder); |
1401 | r600_hdmi_setmode(encoder, adjusted_mode); | 1393 | r600_hdmi_setmode(encoder, adjusted_mode); |
1394 | } | ||
1402 | } | 1395 | } |
1403 | 1396 | ||
1404 | static bool | 1397 | static bool |
@@ -1492,8 +1485,20 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec | |||
1492 | 1485 | ||
1493 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | 1486 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) |
1494 | { | 1487 | { |
1488 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
1489 | |||
1490 | if (radeon_encoder->active_device & | ||
1491 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | ||
1492 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
1493 | if (dig) | ||
1494 | dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); | ||
1495 | } | ||
1496 | |||
1495 | radeon_atom_output_lock(encoder, true); | 1497 | radeon_atom_output_lock(encoder, true); |
1496 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1498 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
1499 | |||
1500 | /* this is needed for the pll/ss setup to work correctly in some cases */ | ||
1501 | atombios_set_encoder_crtc_source(encoder); | ||
1497 | } | 1502 | } |
1498 | 1503 | ||
1499 | static void radeon_atom_encoder_commit(struct drm_encoder *encoder) | 1504 | static void radeon_atom_encoder_commit(struct drm_encoder *encoder) |
@@ -1509,6 +1514,8 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
1509 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1514 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
1510 | 1515 | ||
1511 | if (radeon_encoder_is_digital(encoder)) { | 1516 | if (radeon_encoder_is_digital(encoder)) { |
1517 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) | ||
1518 | r600_hdmi_disable(encoder); | ||
1512 | dig = radeon_encoder->enc_priv; | 1519 | dig = radeon_encoder->enc_priv; |
1513 | dig->dig_encoder = -1; | 1520 | dig->dig_encoder = -1; |
1514 | } | 1521 | } |
@@ -1659,6 +1666,4 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su | |||
1659 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); | 1666 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); |
1660 | break; | 1667 | break; |
1661 | } | 1668 | } |
1662 | |||
1663 | r600_hdmi_init(encoder); | ||
1664 | } | 1669 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 4ae50c19589f..f007fcb1191b 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
@@ -183,11 +183,10 @@ static void set_data(void *i2c_priv, int data) | |||
183 | 183 | ||
184 | static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) | 184 | static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) |
185 | { | 185 | { |
186 | struct radeon_pll *spll = &rdev->clock.spll; | ||
187 | u32 sclk = radeon_get_engine_clock(rdev); | 186 | u32 sclk = radeon_get_engine_clock(rdev); |
188 | u32 prescale = 0; | 187 | u32 prescale = 0; |
189 | u32 n, m; | 188 | u32 nm; |
190 | u8 loop; | 189 | u8 n, m, loop; |
191 | int i2c_clock; | 190 | int i2c_clock; |
192 | 191 | ||
193 | switch (rdev->family) { | 192 | switch (rdev->family) { |
@@ -203,13 +202,15 @@ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) | |||
203 | case CHIP_R300: | 202 | case CHIP_R300: |
204 | case CHIP_R350: | 203 | case CHIP_R350: |
205 | case CHIP_RV350: | 204 | case CHIP_RV350: |
206 | n = (spll->reference_freq) / (4 * 6); | 205 | i2c_clock = 60; |
206 | nm = (sclk * 10) / (i2c_clock * 4); | ||
207 | for (loop = 1; loop < 255; loop++) { | 207 | for (loop = 1; loop < 255; loop++) { |
208 | if ((loop * (loop - 1)) > n) | 208 | if ((nm / loop) < loop) |
209 | break; | 209 | break; |
210 | } | 210 | } |
211 | m = loop - 1; | 211 | n = loop - 1; |
212 | prescale = m | (loop << 8); | 212 | m = loop - 2; |
213 | prescale = m | (n << 8); | ||
213 | break; | 214 | break; |
214 | case CHIP_RV380: | 215 | case CHIP_RV380: |
215 | case CHIP_RS400: | 216 | case CHIP_RS400: |
@@ -217,7 +218,6 @@ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) | |||
217 | case CHIP_R420: | 218 | case CHIP_R420: |
218 | case CHIP_R423: | 219 | case CHIP_R423: |
219 | case CHIP_RV410: | 220 | case CHIP_RV410: |
220 | sclk = radeon_get_engine_clock(rdev); | ||
221 | prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; | 221 | prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; |
222 | break; | 222 | break; |
223 | case CHIP_RS600: | 223 | case CHIP_RS600: |
@@ -232,7 +232,6 @@ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) | |||
232 | case CHIP_RV570: | 232 | case CHIP_RV570: |
233 | case CHIP_R580: | 233 | case CHIP_R580: |
234 | i2c_clock = 50; | 234 | i2c_clock = 50; |
235 | sclk = radeon_get_engine_clock(rdev); | ||
236 | if (rdev->family == CHIP_R520) | 235 | if (rdev->family == CHIP_R520) |
237 | prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock)); | 236 | prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock)); |
238 | else | 237 | else |
@@ -291,6 +290,7 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
291 | prescale = radeon_get_i2c_prescale(rdev); | 290 | prescale = radeon_get_i2c_prescale(rdev); |
292 | 291 | ||
293 | reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) | | 292 | reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) | |
293 | RADEON_I2C_DRIVE_EN | | ||
294 | RADEON_I2C_START | | 294 | RADEON_I2C_START | |
295 | RADEON_I2C_STOP | | 295 | RADEON_I2C_STOP | |
296 | RADEON_I2C_GO); | 296 | RADEON_I2C_GO); |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index df23d6a01d02..88865e38fe30 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
@@ -603,6 +603,10 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod | |||
603 | ? RADEON_CRTC2_INTERLACE_EN | 603 | ? RADEON_CRTC2_INTERLACE_EN |
604 | : 0)); | 604 | : 0)); |
605 | 605 | ||
606 | /* rs4xx chips seem to like to have the crtc enabled when the timing is set */ | ||
607 | if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) | ||
608 | crtc2_gen_cntl |= RADEON_CRTC2_EN; | ||
609 | |||
606 | disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); | 610 | disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); |
607 | disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; | 611 | disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; |
608 | 612 | ||
@@ -630,6 +634,10 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod | |||
630 | ? RADEON_CRTC_INTERLACE_EN | 634 | ? RADEON_CRTC_INTERLACE_EN |
631 | : 0)); | 635 | : 0)); |
632 | 636 | ||
637 | /* rs4xx chips seem to like to have the crtc enabled when the timing is set */ | ||
638 | if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) | ||
639 | crtc_gen_cntl |= RADEON_CRTC_EN; | ||
640 | |||
633 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | 641 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); |
634 | crtc_ext_cntl |= (RADEON_XCRT_CNT_EN | | 642 | crtc_ext_cntl |= (RADEON_XCRT_CNT_EN | |
635 | RADEON_CRTC_VSYNC_DIS | | 643 | RADEON_CRTC_VSYNC_DIS | |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_tv.c b/drivers/gpu/drm/radeon/radeon_legacy_tv.c index 417684daef4c..f2ed27c8055b 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_tv.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_tv.c | |||
@@ -57,6 +57,10 @@ | |||
57 | #define NTSC_TV_PLL_N_14 693 | 57 | #define NTSC_TV_PLL_N_14 693 |
58 | #define NTSC_TV_PLL_P_14 7 | 58 | #define NTSC_TV_PLL_P_14 7 |
59 | 59 | ||
60 | #define PAL_TV_PLL_M_14 19 | ||
61 | #define PAL_TV_PLL_N_14 353 | ||
62 | #define PAL_TV_PLL_P_14 5 | ||
63 | |||
60 | #define VERT_LEAD_IN_LINES 2 | 64 | #define VERT_LEAD_IN_LINES 2 |
61 | #define FRAC_BITS 0xe | 65 | #define FRAC_BITS 0xe |
62 | #define FRAC_MASK 0x3fff | 66 | #define FRAC_MASK 0x3fff |
@@ -205,9 +209,24 @@ static const struct radeon_tv_mode_constants available_tv_modes[] = { | |||
205 | 630627, /* defRestart */ | 209 | 630627, /* defRestart */ |
206 | 347, /* crtcPLL_N */ | 210 | 347, /* crtcPLL_N */ |
207 | 14, /* crtcPLL_M */ | 211 | 14, /* crtcPLL_M */ |
208 | 8, /* crtcPLL_postDiv */ | 212 | 8, /* crtcPLL_postDiv */ |
209 | 1022, /* pixToTV */ | 213 | 1022, /* pixToTV */ |
210 | }, | 214 | }, |
215 | { /* PAL timing for 14 Mhz ref clk */ | ||
216 | 800, /* horResolution */ | ||
217 | 600, /* verResolution */ | ||
218 | TV_STD_PAL, /* standard */ | ||
219 | 1131, /* horTotal */ | ||
220 | 742, /* verTotal */ | ||
221 | 813, /* horStart */ | ||
222 | 840, /* horSyncStart */ | ||
223 | 633, /* verSyncStart */ | ||
224 | 708369, /* defRestart */ | ||
225 | 211, /* crtcPLL_N */ | ||
226 | 9, /* crtcPLL_M */ | ||
227 | 8, /* crtcPLL_postDiv */ | ||
228 | 759, /* pixToTV */ | ||
229 | }, | ||
211 | }; | 230 | }; |
212 | 231 | ||
213 | #define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes) | 232 | #define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes) |
@@ -242,7 +261,7 @@ static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(stru | |||
242 | if (pll->reference_freq == 2700) | 261 | if (pll->reference_freq == 2700) |
243 | const_ptr = &available_tv_modes[1]; | 262 | const_ptr = &available_tv_modes[1]; |
244 | else | 263 | else |
245 | const_ptr = &available_tv_modes[1]; /* FIX ME */ | 264 | const_ptr = &available_tv_modes[3]; |
246 | } | 265 | } |
247 | return const_ptr; | 266 | return const_ptr; |
248 | } | 267 | } |
@@ -685,9 +704,9 @@ void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, | |||
685 | n = PAL_TV_PLL_N_27; | 704 | n = PAL_TV_PLL_N_27; |
686 | p = PAL_TV_PLL_P_27; | 705 | p = PAL_TV_PLL_P_27; |
687 | } else { | 706 | } else { |
688 | m = PAL_TV_PLL_M_27; | 707 | m = PAL_TV_PLL_M_14; |
689 | n = PAL_TV_PLL_N_27; | 708 | n = PAL_TV_PLL_N_14; |
690 | p = PAL_TV_PLL_P_27; | 709 | p = PAL_TV_PLL_P_14; |
691 | } | 710 | } |
692 | } | 711 | } |
693 | 712 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 1702b820aa4d..55a41757eed1 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -129,6 +129,7 @@ struct radeon_tmds_pll { | |||
129 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) | 129 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) |
130 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) | 130 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) |
131 | #define RADEON_PLL_USE_POST_DIV (1 << 12) | 131 | #define RADEON_PLL_USE_POST_DIV (1 << 12) |
132 | #define RADEON_PLL_IS_LCD (1 << 13) | ||
132 | 133 | ||
133 | /* pll algo */ | 134 | /* pll algo */ |
134 | enum radeon_pll_algo { | 135 | enum radeon_pll_algo { |
@@ -149,6 +150,8 @@ struct radeon_pll { | |||
149 | uint32_t pll_in_max; | 150 | uint32_t pll_in_max; |
150 | uint32_t pll_out_min; | 151 | uint32_t pll_out_min; |
151 | uint32_t pll_out_max; | 152 | uint32_t pll_out_max; |
153 | uint32_t lcd_pll_out_min; | ||
154 | uint32_t lcd_pll_out_max; | ||
152 | uint32_t best_vco; | 155 | uint32_t best_vco; |
153 | 156 | ||
154 | /* divider limits */ | 157 | /* divider limits */ |
@@ -342,6 +345,7 @@ struct radeon_encoder { | |||
342 | struct drm_display_mode native_mode; | 345 | struct drm_display_mode native_mode; |
343 | void *enc_priv; | 346 | void *enc_priv; |
344 | int hdmi_offset; | 347 | int hdmi_offset; |
348 | int hdmi_config_offset; | ||
345 | int hdmi_audio_workaround; | 349 | int hdmi_audio_workaround; |
346 | int hdmi_buffer_status; | 350 | int hdmi_buffer_status; |
347 | }; | 351 | }; |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index d4d1c39a0e99..4f37b524de7e 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #define RADEON_RECLOCK_DELAY_MS 200 | 28 | #define RADEON_RECLOCK_DELAY_MS 200 |
29 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 | 29 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 |
30 | 30 | ||
31 | static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish); | ||
31 | static void radeon_pm_set_clocks_locked(struct radeon_device *rdev); | 32 | static void radeon_pm_set_clocks_locked(struct radeon_device *rdev); |
32 | static void radeon_pm_set_clocks(struct radeon_device *rdev); | 33 | static void radeon_pm_set_clocks(struct radeon_device *rdev); |
33 | static void radeon_pm_idle_work_handler(struct work_struct *work); | 34 | static void radeon_pm_idle_work_handler(struct work_struct *work); |
@@ -179,6 +180,16 @@ static void radeon_get_power_state(struct radeon_device *rdev, | |||
179 | rdev->pm.requested_power_state->non_clock_info.pcie_lanes); | 180 | rdev->pm.requested_power_state->non_clock_info.pcie_lanes); |
180 | } | 181 | } |
181 | 182 | ||
183 | static inline void radeon_sync_with_vblank(struct radeon_device *rdev) | ||
184 | { | ||
185 | if (rdev->pm.active_crtcs) { | ||
186 | rdev->pm.vblank_sync = false; | ||
187 | wait_event_timeout( | ||
188 | rdev->irq.vblank_queue, rdev->pm.vblank_sync, | ||
189 | msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); | ||
190 | } | ||
191 | } | ||
192 | |||
182 | static void radeon_set_power_state(struct radeon_device *rdev) | 193 | static void radeon_set_power_state(struct radeon_device *rdev) |
183 | { | 194 | { |
184 | /* if *_clock_mode are the same, *_power_state are as well */ | 195 | /* if *_clock_mode are the same, *_power_state are as well */ |
@@ -189,11 +200,28 @@ static void radeon_set_power_state(struct radeon_device *rdev) | |||
189 | rdev->pm.requested_clock_mode->sclk, | 200 | rdev->pm.requested_clock_mode->sclk, |
190 | rdev->pm.requested_clock_mode->mclk, | 201 | rdev->pm.requested_clock_mode->mclk, |
191 | rdev->pm.requested_power_state->non_clock_info.pcie_lanes); | 202 | rdev->pm.requested_power_state->non_clock_info.pcie_lanes); |
203 | |||
192 | /* set pcie lanes */ | 204 | /* set pcie lanes */ |
205 | /* TODO */ | ||
206 | |||
193 | /* set voltage */ | 207 | /* set voltage */ |
208 | /* TODO */ | ||
209 | |||
194 | /* set engine clock */ | 210 | /* set engine clock */ |
211 | radeon_sync_with_vblank(rdev); | ||
212 | radeon_pm_debug_check_in_vbl(rdev, false); | ||
195 | radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); | 213 | radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); |
214 | radeon_pm_debug_check_in_vbl(rdev, true); | ||
215 | |||
216 | #if 0 | ||
196 | /* set memory clock */ | 217 | /* set memory clock */ |
218 | if (rdev->asic->set_memory_clock) { | ||
219 | radeon_sync_with_vblank(rdev); | ||
220 | radeon_pm_debug_check_in_vbl(rdev, false); | ||
221 | radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk); | ||
222 | radeon_pm_debug_check_in_vbl(rdev, true); | ||
223 | } | ||
224 | #endif | ||
197 | 225 | ||
198 | rdev->pm.current_power_state = rdev->pm.requested_power_state; | 226 | rdev->pm.current_power_state = rdev->pm.requested_power_state; |
199 | rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; | 227 | rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; |
@@ -333,10 +361,7 @@ static void radeon_pm_set_clocks_locked(struct radeon_device *rdev) | |||
333 | break; | 361 | break; |
334 | } | 362 | } |
335 | 363 | ||
336 | /* check if we are in vblank */ | ||
337 | radeon_pm_debug_check_in_vbl(rdev, false); | ||
338 | radeon_set_power_state(rdev); | 364 | radeon_set_power_state(rdev); |
339 | radeon_pm_debug_check_in_vbl(rdev, true); | ||
340 | rdev->pm.planned_action = PM_ACTION_NONE; | 365 | rdev->pm.planned_action = PM_ACTION_NONE; |
341 | } | 366 | } |
342 | 367 | ||
@@ -353,10 +378,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
353 | rdev->pm.req_vblank |= (1 << 1); | 378 | rdev->pm.req_vblank |= (1 << 1); |
354 | drm_vblank_get(rdev->ddev, 1); | 379 | drm_vblank_get(rdev->ddev, 1); |
355 | } | 380 | } |
356 | if (rdev->pm.active_crtcs) | 381 | radeon_pm_set_clocks_locked(rdev); |
357 | wait_event_interruptible_timeout( | ||
358 | rdev->irq.vblank_queue, 0, | ||
359 | msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); | ||
360 | if (rdev->pm.req_vblank & (1 << 0)) { | 382 | if (rdev->pm.req_vblank & (1 << 0)) { |
361 | rdev->pm.req_vblank &= ~(1 << 0); | 383 | rdev->pm.req_vblank &= ~(1 << 0); |
362 | drm_vblank_put(rdev->ddev, 0); | 384 | drm_vblank_put(rdev->ddev, 0); |
@@ -366,7 +388,6 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
366 | drm_vblank_put(rdev->ddev, 1); | 388 | drm_vblank_put(rdev->ddev, 1); |
367 | } | 389 | } |
368 | 390 | ||
369 | radeon_pm_set_clocks_locked(rdev); | ||
370 | mutex_unlock(&rdev->cp.mutex); | 391 | mutex_unlock(&rdev->cp.mutex); |
371 | } | 392 | } |
372 | 393 | ||
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 47f046b78c6b..ac7c27adfb70 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -392,10 +392,12 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
392 | /* Vertical blank interrupts */ | 392 | /* Vertical blank interrupts */ |
393 | if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) { | 393 | if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) { |
394 | drm_handle_vblank(rdev->ddev, 0); | 394 | drm_handle_vblank(rdev->ddev, 0); |
395 | rdev->pm.vblank_sync = true; | ||
395 | wake_up(&rdev->irq.vblank_queue); | 396 | wake_up(&rdev->irq.vblank_queue); |
396 | } | 397 | } |
397 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) { | 398 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) { |
398 | drm_handle_vblank(rdev->ddev, 1); | 399 | drm_handle_vblank(rdev->ddev, 1); |
400 | rdev->pm.vblank_sync = true; | ||
399 | wake_up(&rdev->irq.vblank_queue); | 401 | wake_up(&rdev->irq.vblank_queue); |
400 | } | 402 | } |
401 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) { | 403 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) { |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 37887dee12af..8f0c9253c5bb 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -1013,6 +1013,13 @@ int rv770_resume(struct radeon_device *rdev) | |||
1013 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | 1013 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); |
1014 | return r; | 1014 | return r; |
1015 | } | 1015 | } |
1016 | |||
1017 | r = r600_audio_init(rdev); | ||
1018 | if (r) { | ||
1019 | dev_err(rdev->dev, "radeon: audio init failed\n"); | ||
1020 | return r; | ||
1021 | } | ||
1022 | |||
1016 | return r; | 1023 | return r; |
1017 | 1024 | ||
1018 | } | 1025 | } |
@@ -1021,6 +1028,7 @@ int rv770_suspend(struct radeon_device *rdev) | |||
1021 | { | 1028 | { |
1022 | int r; | 1029 | int r; |
1023 | 1030 | ||
1031 | r600_audio_fini(rdev); | ||
1024 | /* FIXME: we should wait for ring to be empty */ | 1032 | /* FIXME: we should wait for ring to be empty */ |
1025 | r700_cp_stop(rdev); | 1033 | r700_cp_stop(rdev); |
1026 | rdev->cp.ready = false; | 1034 | rdev->cp.ready = false; |
@@ -1144,6 +1152,13 @@ int rv770_init(struct radeon_device *rdev) | |||
1144 | } | 1152 | } |
1145 | } | 1153 | } |
1146 | } | 1154 | } |
1155 | |||
1156 | r = r600_audio_init(rdev); | ||
1157 | if (r) { | ||
1158 | dev_err(rdev->dev, "radeon: audio init failed\n"); | ||
1159 | return r; | ||
1160 | } | ||
1161 | |||
1147 | return 0; | 1162 | return 0; |
1148 | } | 1163 | } |
1149 | 1164 | ||