Skip to content

Commit

Permalink
Merge branch 'radeon-for-airlied' of ../linux-2.6 into drm-linus
Browse files Browse the repository at this point in the history
* '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
  • Loading branch information
Dave Airlie committed Mar 15, 2010
2 parents d5e5ded + d0d6cb8 commit 1fc59ed
Show file tree
Hide file tree
Showing 22 changed files with 445 additions and 185 deletions.
59 changes: 47 additions & 12 deletions drivers/gpu/drm/radeon/atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@

typedef struct {
struct atom_context *ctx;

uint32_t *ps, *ws;
int ps_shift;
uint16_t start;
unsigned last_jump;
unsigned long last_jump_jiffies;
bool abort;
} atom_exec_context;

int atom_debug = 0;
static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);

static uint32_t atom_arg_mask[8] =
{ 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000,
Expand Down Expand Up @@ -604,12 +606,17 @@ static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg)
static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg)
{
int idx = U8((*ptr)++);
int r = 0;

if (idx < ATOM_TABLE_NAMES_CNT)
SDEBUG(" table: %d (%s)\n", idx, atom_table_names[idx]);
else
SDEBUG(" table: %d\n", idx);
if (U16(ctx->ctx->cmd_table + 4 + 2 * idx))
atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
if (r) {
ctx->abort = true;
}
}

static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg)
Expand Down Expand Up @@ -673,6 +680,8 @@ static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg)
static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
{
int execute = 0, target = U16(*ptr);
unsigned long cjiffies;

(*ptr) += 2;
switch (arg) {
case ATOM_COND_ABOVE:
Expand Down Expand Up @@ -700,8 +709,25 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
if (arg != ATOM_COND_ALWAYS)
SDEBUG(" taken: %s\n", execute ? "yes" : "no");
SDEBUG(" target: 0x%04X\n", target);
if (execute)
if (execute) {
if (ctx->last_jump == (ctx->start + target)) {
cjiffies = jiffies;
if (time_after(cjiffies, ctx->last_jump_jiffies)) {
cjiffies -= ctx->last_jump_jiffies;
if ((jiffies_to_msecs(cjiffies) > 1000)) {
DRM_ERROR("atombios stuck in loop for more than 1sec aborting\n");
ctx->abort = true;
}
} else {
/* jiffies wrap around we will just wait a little longer */
ctx->last_jump_jiffies = jiffies;
}
} else {
ctx->last_jump = ctx->start + target;
ctx->last_jump_jiffies = jiffies;
}
*ptr = ctx->start + target;
}
}

static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
Expand Down Expand Up @@ -1104,15 +1130,15 @@ static struct {
atom_op_shr, ATOM_ARG_MC}, {
atom_op_debug, 0},};

static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
{
int base = CU16(ctx->cmd_table + 4 + 2 * index);
int len, ws, ps, ptr;
unsigned char op;
atom_exec_context ectx;

if (!base)
return;
return -EINVAL;

len = CU16(base + ATOM_CT_SIZE_PTR);
ws = CU8(base + ATOM_CT_WS_PTR);
Expand All @@ -1125,6 +1151,8 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
ectx.ps_shift = ps / 4;
ectx.start = base;
ectx.ps = params;
ectx.abort = false;
ectx.last_jump = 0;
if (ws)
ectx.ws = kzalloc(4 * ws, GFP_KERNEL);
else
Expand All @@ -1137,6 +1165,11 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1);
else
SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1);
if (ectx.abort) {
DRM_ERROR("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n",
base, len, ws, ps, ptr - 1);
return -EINVAL;
}

if (op < ATOM_OP_CNT && op > 0)
opcode_table[op].func(&ectx, &ptr,
Expand All @@ -1152,19 +1185,23 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3

if (ws)
kfree(ectx.ws);
return 0;
}

void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
{
int r;

mutex_lock(&ctx->mutex);
/* reset reg block */
ctx->reg_block = 0;
/* reset fb window */
ctx->fb_base = 0;
/* reset io mode */
ctx->io_mode = ATOM_IO_MM;
atom_execute_table_locked(ctx, index, params);
r = atom_execute_table_locked(ctx, index, params);
mutex_unlock(&ctx->mutex);
return r;
}

static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
Expand Down Expand Up @@ -1248,9 +1285,7 @@ int atom_asic_init(struct atom_context *ctx)

if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
return 1;
atom_execute_table(ctx, ATOM_CMD_INIT, ps);

return 0;
return atom_execute_table(ctx, ATOM_CMD_INIT, ps);
}

void atom_destroy(struct atom_context *ctx)
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/radeon/atom.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ struct atom_context {
extern int atom_debug;

struct atom_context *atom_parse(struct card_info *, void *);
void atom_execute_table(struct atom_context *, int, uint32_t *);
int atom_execute_table(struct atom_context *, int, uint32_t *);
int atom_asic_init(struct atom_context *);
void atom_destroy(struct atom_context *);
void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
Expand Down
66 changes: 56 additions & 10 deletions drivers/gpu/drm/radeon/atombios_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,12 +353,55 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}

static void atombios_disable_ss(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
u32 ss_cntl;

if (ASIC_IS_DCE4(rdev)) {
switch (radeon_crtc->pll_id) {
case ATOM_PPLL1:
ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL);
ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
WREG32(EVERGREEN_P1PLL_SS_CNTL, ss_cntl);
break;
case ATOM_PPLL2:
ss_cntl = RREG32(EVERGREEN_P2PLL_SS_CNTL);
ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
WREG32(EVERGREEN_P2PLL_SS_CNTL, ss_cntl);
break;
case ATOM_DCPLL:
case ATOM_PPLL_INVALID:
return;
}
} else if (ASIC_IS_AVIVO(rdev)) {
switch (radeon_crtc->pll_id) {
case ATOM_PPLL1:
ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
ss_cntl &= ~1;
WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl);
break;
case ATOM_PPLL2:
ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);
ss_cntl &= ~1;
WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl);
break;
case ATOM_DCPLL:
case ATOM_PPLL_INVALID:
return;
}
}
}


union atom_enable_ss {
ENABLE_LVDS_SS_PARAMETERS legacy;
ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1;
};

static void atombios_set_ss(struct drm_crtc *crtc, int enable)
static void atombios_enable_ss(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
Expand Down Expand Up @@ -387,9 +430,9 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
step = dig->ss->step;
delay = dig->ss->delay;
range = dig->ss->range;
} else if (enable)
} else
return;
} else if (enable)
} else
return;
break;
}
Expand All @@ -406,13 +449,13 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
args.v1.ucSpreadSpectrumDelay = delay;
args.v1.ucSpreadSpectrumRange = range;
args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
args.v1.ucEnable = enable;
args.v1.ucEnable = ATOM_ENABLE;
} else {
args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
args.legacy.ucSpreadSpectrumType = type;
args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
args.legacy.ucEnable = enable;
args.legacy.ucEnable = ATOM_ENABLE;
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
Expand Down Expand Up @@ -482,6 +525,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
pll->algo = dig->pll_algo;
pll->flags |= RADEON_PLL_IS_LCD;
}
} else {
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
Expand Down Expand Up @@ -1083,15 +1127,12 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,

/* TODO color tiling */

/* pick pll */
radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);

atombios_set_ss(crtc, 0);
atombios_disable_ss(crtc);
/* always set DCPLL */
if (ASIC_IS_DCE4(rdev))
atombios_crtc_set_dcpll(crtc);
atombios_crtc_set_pll(crtc, adjusted_mode);
atombios_set_ss(crtc, 1);
atombios_enable_ss(crtc);

if (ASIC_IS_DCE4(rdev))
atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
Expand Down Expand Up @@ -1120,6 +1161,11 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,

static void atombios_crtc_prepare(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);

/* pick pll */
radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);

atombios_lock_crtc(crtc, ATOM_ENABLE);
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/r100.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,12 @@ int r100_irq_process(struct radeon_device *rdev)
/* Vertical blank interrupts */
if (status & RADEON_CRTC_VBLANK_STAT) {
drm_handle_vblank(rdev->ddev, 0);
rdev->pm.vblank_sync = true;
wake_up(&rdev->irq.vblank_queue);
}
if (status & RADEON_CRTC2_VBLANK_STAT) {
drm_handle_vblank(rdev->ddev, 1);
rdev->pm.vblank_sync = true;
wake_up(&rdev->irq.vblank_queue);
}
if (status & RADEON_FP_DETECT_STAT) {
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/r600.c
Original file line number Diff line number Diff line change
Expand Up @@ -2765,6 +2765,7 @@ int r600_irq_process(struct radeon_device *rdev)
case 0: /* D1 vblank */
if (disp_int & LB_D1_VBLANK_INTERRUPT) {
drm_handle_vblank(rdev->ddev, 0);
rdev->pm.vblank_sync = true;
wake_up(&rdev->irq.vblank_queue);
disp_int &= ~LB_D1_VBLANK_INTERRUPT;
DRM_DEBUG("IH: D1 vblank\n");
Expand All @@ -2786,6 +2787,7 @@ int r600_irq_process(struct radeon_device *rdev)
case 0: /* D2 vblank */
if (disp_int & LB_D2_VBLANK_INTERRUPT) {
drm_handle_vblank(rdev->ddev, 1);
rdev->pm.vblank_sync = true;
wake_up(&rdev->irq.vblank_queue);
disp_int &= ~LB_D2_VBLANK_INTERRUPT;
DRM_DEBUG("IH: D2 vblank\n");
Expand Down
Loading

0 comments on commit 1fc59ed

Please sign in to comment.