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

Commit 9dad76e8 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie
Browse files

drm/radeon/kms: fix prescale calculations



Pre-pcie chips seem to use the reference clock
rather than the sclk.

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent bcc1c2a1
Loading
Loading
Loading
Loading
+85 −10
Original line number Diff line number Diff line
@@ -181,6 +181,87 @@ static void set_data(void *i2c_priv, int data)
	WREG32(rec->en_data_reg, val);
}

static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
{
	struct radeon_pll *spll = &rdev->clock.spll;
	u32 sclk = radeon_get_engine_clock(rdev);
	u32 prescale = 0;
	u32 n, m;
	u8 loop;
	int i2c_clock;

	switch (rdev->family) {
	case CHIP_R100:
	case CHIP_RV100:
	case CHIP_RS100:
	case CHIP_RV200:
	case CHIP_RS200:
	case CHIP_R200:
	case CHIP_RV250:
	case CHIP_RS300:
	case CHIP_RV280:
	case CHIP_R300:
	case CHIP_R350:
	case CHIP_RV350:
		n = (spll->reference_freq) / (4 * 6);
		for (loop = 1; loop < 255; loop++) {
			if ((loop * (loop - 1)) > n)
				break;
		}
		m = loop - 1;
		prescale = m | (loop << 8);
		break;
	case CHIP_RV380:
	case CHIP_RS400:
	case CHIP_RS480:
	case CHIP_R420:
	case CHIP_R423:
	case CHIP_RV410:
		sclk = radeon_get_engine_clock(rdev);
		prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
		break;
	case CHIP_RS600:
	case CHIP_RS690:
	case CHIP_RS740:
		/* todo */
		break;
	case CHIP_RV515:
	case CHIP_R520:
	case CHIP_RV530:
	case CHIP_RV560:
	case CHIP_RV570:
	case CHIP_R580:
		i2c_clock = 50;
		sclk = radeon_get_engine_clock(rdev);
		if (rdev->family == CHIP_R520)
			prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock));
		else
			prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
		break;
	case CHIP_R600:
	case CHIP_RV610:
	case CHIP_RV630:
	case CHIP_RV670:
		/* todo */
		break;
	case CHIP_RV620:
	case CHIP_RV635:
	case CHIP_RS780:
	case CHIP_RS880:
	case CHIP_RV770:
	case CHIP_RV730:
	case CHIP_RV710:
	case CHIP_RV740:
		/* todo */
		break;
	default:
		DRM_ERROR("i2c: unhandled radeon chip\n");
		break;
	}
	return prescale;
}


/* hw i2c engine for r1xx-4xx hardware
 * hw can buffer up to 15 bytes
 */
@@ -192,7 +273,7 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
	struct radeon_i2c_bus_rec *rec = &i2c->rec;
	struct i2c_msg *p;
	int i, j, k, ret = num;
	u32 sclk, prescale;
	u32 prescale;
	u32 i2c_cntl_0, i2c_cntl_1, i2c_data;
	u32 tmp, reg;

@@ -200,8 +281,7 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
	/* take the pm lock since we need a constant sclk */
	mutex_lock(&rdev->pm.mutex);

	sclk = radeon_get_engine_clock(rdev);
	prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
	prescale = radeon_get_i2c_prescale(rdev);

	reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) |
	       RADEON_I2C_START |
@@ -444,9 +524,8 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
	struct radeon_device *rdev = i2c->dev->dev_private;
	struct radeon_i2c_bus_rec *rec = &i2c->rec;
	struct i2c_msg *p;
	int i2c_clock = 50;
	int i, j, remaining, current_count, buffer_offset, ret = num;
	u32 sclk, prescale;
	u32 prescale;
	u32 tmp, reg;
	u32 saved1, saved2;

@@ -454,11 +533,7 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
	/* take the pm lock since we need a constant sclk */
	mutex_lock(&rdev->pm.mutex);

	sclk = radeon_get_engine_clock(rdev);
	if (rdev->family == CHIP_R520)
		prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock));
	else
		prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
	prescale = radeon_get_i2c_prescale(rdev);

	/* clear gpio mask bits */
	tmp = RREG32(rec->mask_clk_reg);