Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1fc59eda authored by Dave Airlie's avatar Dave Airlie
Browse files

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
parents d5e5dedd d0d6cb81
Loading
Loading
Loading
Loading
+47 −12
Original line number Diff line number Diff line
@@ -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,
@@ -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)
@@ -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:
@@ -700,9 +709,26 @@ 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)
{
@@ -1104,7 +1130,7 @@ 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;
@@ -1112,7 +1138,7 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
	atom_exec_context ectx;

	if (!base)
		return;
		return -EINVAL;

	len = CU16(base + ATOM_CT_SIZE_PTR);
	ws = CU8(base + ATOM_CT_WS_PTR);
@@ -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
@@ -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,
@@ -1152,10 +1185,13 @@ 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;
@@ -1163,8 +1199,9 @@ void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
	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 };
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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);
+56 −10
Original line number Diff line number Diff line
@@ -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;
@@ -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;
		}
@@ -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);
}
@@ -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)
@@ -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);
@@ -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);
}
+2 −0
Original line number Diff line number Diff line
@@ -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) {
+2 −0
Original line number Diff line number Diff line
@@ -2765,6 +2765,7 @@ restart_ih:
			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");
@@ -2786,6 +2787,7 @@ restart_ih:
			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");
Loading