diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-02-06 17:06:42 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-02-08 18:32:32 -0500 |
commit | 57fcab620d05c3eb32b4787ce7501565c4c3162d (patch) | |
tree | caa3b6f9ce5b5f4ccaf059423d29c91b9bd9b6e4 /drivers/gpu/drm | |
parent | 6d7f2d8da106ecf794a5a3e98c4239f348119e3c (diff) |
drm/radeon/kms: take the pm mutex when using hw i2c
we need a constant sclk for i2c prescale. Also,
get the current sclk when calculating prescale rather
than using the default sclk.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_i2c.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index b47a5615fe6a..272c45db5cec 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
@@ -192,12 +192,16 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
192 | struct radeon_i2c_bus_rec *rec = &i2c->rec; | 192 | struct radeon_i2c_bus_rec *rec = &i2c->rec; |
193 | struct i2c_msg *p; | 193 | struct i2c_msg *p; |
194 | int i, j, k, ret = num; | 194 | int i, j, k, ret = num; |
195 | /* XXX: use get_engine_clock() to get the current sclk */ | 195 | u32 sclk, prescale; |
196 | u32 prescale = (((rdev->clock.default_sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; | ||
197 | u32 i2c_cntl_0, i2c_cntl_1, i2c_data; | 196 | u32 i2c_cntl_0, i2c_cntl_1, i2c_data; |
198 | u32 tmp, reg; | 197 | u32 tmp, reg; |
199 | 198 | ||
200 | mutex_lock(&rdev->dc_hw_i2c_mutex); | 199 | mutex_lock(&rdev->dc_hw_i2c_mutex); |
200 | /* take the pm lock since we need a constant sclk */ | ||
201 | mutex_lock(&rdev->pm.mutex); | ||
202 | |||
203 | sclk = radeon_get_engine_clock(rdev); | ||
204 | prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; | ||
201 | 205 | ||
202 | reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) | | 206 | reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) | |
203 | RADEON_I2C_START | | 207 | RADEON_I2C_START | |
@@ -424,6 +428,7 @@ done: | |||
424 | WREG32(RADEON_BIOS_6_SCRATCH, tmp); | 428 | WREG32(RADEON_BIOS_6_SCRATCH, tmp); |
425 | } | 429 | } |
426 | 430 | ||
431 | mutex_unlock(&rdev->pm.mutex); | ||
427 | mutex_unlock(&rdev->dc_hw_i2c_mutex); | 432 | mutex_unlock(&rdev->dc_hw_i2c_mutex); |
428 | 433 | ||
429 | return ret; | 434 | return ret; |
@@ -441,12 +446,19 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
441 | struct i2c_msg *p; | 446 | struct i2c_msg *p; |
442 | int i2c_clock = 50; | 447 | int i2c_clock = 50; |
443 | int i, j, remaining, current_count, buffer_offset, ret = num; | 448 | int i, j, remaining, current_count, buffer_offset, ret = num; |
444 | /* XXX: use get_engine_clock() to get the current sclk */ | 449 | u32 sclk, prescale; |
445 | u32 prescale; | ||
446 | u32 tmp, reg; | 450 | u32 tmp, reg; |
447 | u32 saved1, saved2; | 451 | u32 saved1, saved2; |
448 | 452 | ||
449 | mutex_lock(&rdev->dc_hw_i2c_mutex); | 453 | mutex_lock(&rdev->dc_hw_i2c_mutex); |
454 | /* take the pm lock since we need a constant sclk */ | ||
455 | mutex_lock(&rdev->pm.mutex); | ||
456 | |||
457 | sclk = radeon_get_engine_clock(rdev); | ||
458 | if (rdev->family == CHIP_R520) | ||
459 | prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock)); | ||
460 | else | ||
461 | prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; | ||
450 | 462 | ||
451 | /* clear gpio mask bits */ | 463 | /* clear gpio mask bits */ |
452 | tmp = RREG32(rec->mask_clk_reg); | 464 | tmp = RREG32(rec->mask_clk_reg); |
@@ -500,11 +512,6 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
500 | goto done; | 512 | goto done; |
501 | } | 513 | } |
502 | 514 | ||
503 | if (rdev->family == CHIP_R520) | ||
504 | prescale = (127 << 8) + ((rdev->clock.default_sclk * 10) / (4 * 127 * i2c_clock)); | ||
505 | else | ||
506 | prescale = (((rdev->clock.default_sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128; | ||
507 | |||
508 | reg = AVIVO_DC_I2C_START | AVIVO_DC_I2C_STOP | AVIVO_DC_I2C_EN; | 515 | reg = AVIVO_DC_I2C_START | AVIVO_DC_I2C_STOP | AVIVO_DC_I2C_EN; |
509 | switch (rec->mask_clk_reg) { | 516 | switch (rec->mask_clk_reg) { |
510 | case AVIVO_DC_GPIO_DDC1_MASK: | 517 | case AVIVO_DC_GPIO_DDC1_MASK: |
@@ -662,6 +669,7 @@ done: | |||
662 | tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE; | 669 | tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE; |
663 | WREG32(RADEON_BIOS_6_SCRATCH, tmp); | 670 | WREG32(RADEON_BIOS_6_SCRATCH, tmp); |
664 | 671 | ||
672 | mutex_unlock(&rdev->pm.mutex); | ||
665 | mutex_unlock(&rdev->dc_hw_i2c_mutex); | 673 | mutex_unlock(&rdev->dc_hw_i2c_mutex); |
666 | 674 | ||
667 | return ret; | 675 | return ret; |