/* * Copyright 2007-8 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Dave Airlie * Alex Deucher
*/
/* on hw with routers, select right port */ if (radeon_connector->router.ddc_valid)
radeon_router_select_ddc_port(radeon_connector);
if (use_aux) {
ret = i2c_transfer(&radeon_connector->ddc_bus->aux.ddc, msgs, 2);
} else {
ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
}
if (ret != 2) /* Couldn't find an accessible DDC on this connector */ returnfalse; /* Probe also for valid EDID header * EDID header starts with: * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00. * Only the first 6 bytes must be valid as
* drm_edid_block_valid() can fix the last 2 bytes */ if (drm_edid_header_is_valid(buf) < 6) { /* Couldn't find an accessible EDID on this
* connector */ returnfalse;
} returntrue;
}
/* RV410 appears to have a bug where the hw i2c in reset * holds the i2c port in a bad state - switch hw i2c away before * doing DDC - do this for all r200s/r300s/r400s for safety sake
*/ if (rec->hw_capable) { if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
u32 reg;
/* set pin direction */
val = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
val |= data ? 0 : rec->en_data_mask;
WREG32(rec->en_data_reg, val);
}
/* hw i2c */
static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
{
u32 sclk = rdev->pm.current_sclk;
u32 prescale = 0;
u32 nm;
u8 n, m, 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:
i2c_clock = 60;
nm = (sclk * 10) / (i2c_clock * 4); for (loop = 1; loop < 255; loop++) { if ((nm / loop) < loop) break;
}
n = loop - 1;
m = loop - 2;
prescale = m | (n << 8); break; case CHIP_RV380: case CHIP_RS400: case CHIP_RS480: case CHIP_R420: case CHIP_R423: case CHIP_RV410:
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; 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; case CHIP_CEDAR: case CHIP_REDWOOD: case CHIP_JUNIPER: case CHIP_CYPRESS: case CHIP_HEMLOCK: /* 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
*/ staticint r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); struct radeon_device *rdev = i2c->dev->dev_private; struct radeon_i2c_bus_rec *rec = &i2c->rec; struct i2c_msg *p; int i, j, k, ret = num;
u32 prescale;
u32 i2c_cntl_0, i2c_cntl_1, i2c_data;
u32 tmp, reg;
mutex_lock(&rdev->dc_hw_i2c_mutex); /* take the pm lock since we need a constant sclk */
mutex_lock(&rdev->pm.mutex);
switch (rdev->family) { case CHIP_R100: case CHIP_RV100: case CHIP_RS100: case CHIP_RV200: case CHIP_RS200: case CHIP_RS300: switch (rec->mask_clk_reg) { case RADEON_GPIO_DVI_DDC: /* no gpio select bit */ break; default:
DRM_ERROR("gpio not supported with hw i2c\n");
ret = -EINVAL; goto done;
} break; case CHIP_R200: /* only bit 4 on r200 */ switch (rec->mask_clk_reg) { case RADEON_GPIO_DVI_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); break; case RADEON_GPIO_MONID:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); break; default:
DRM_ERROR("gpio not supported with hw i2c\n");
ret = -EINVAL; goto done;
} break; case CHIP_RV250: case CHIP_RV280: /* bits 3 and 4 */ switch (rec->mask_clk_reg) { case RADEON_GPIO_DVI_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); break; case RADEON_GPIO_VGA_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2); break; case RADEON_GPIO_CRT2_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); break; default:
DRM_ERROR("gpio not supported with hw i2c\n");
ret = -EINVAL; goto done;
} break; case CHIP_R300: case CHIP_R350: /* only bit 4 on r300/r350 */ switch (rec->mask_clk_reg) { case RADEON_GPIO_VGA_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); break; case RADEON_GPIO_DVI_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); break; default:
DRM_ERROR("gpio not supported with hw i2c\n");
ret = -EINVAL; goto done;
} break; case CHIP_RV350: case CHIP_RV380: case CHIP_R420: case CHIP_R423: case CHIP_RV410: case CHIP_RS400: case CHIP_RS480: /* bits 3 and 4 */ switch (rec->mask_clk_reg) { case RADEON_GPIO_VGA_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1); break; case RADEON_GPIO_DVI_DDC:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2); break; case RADEON_GPIO_MONID:
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3); break; default:
DRM_ERROR("gpio not supported with hw i2c\n");
ret = -EINVAL; goto done;
} break; default:
DRM_ERROR("unsupported asic\n");
ret = -EINVAL; goto done; break;
}
}
WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C); for (i = 0; i < 50; i++) {
udelay(1); if (RREG32(AVIVO_DC_I2C_ARBITRATION) & AVIVO_DC_I2C_SW_CAN_USE_I2C) break;
} if (i == 50) {
DRM_ERROR("failed to get i2c bus\n");
ret = -EBUSY; goto done;
}
reg = AVIVO_DC_I2C_START | AVIVO_DC_I2C_STOP | AVIVO_DC_I2C_EN; switch (rec->mask_clk_reg) { case AVIVO_DC_GPIO_DDC1_MASK:
reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC1); break; case AVIVO_DC_GPIO_DDC2_MASK:
reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC2); break; case AVIVO_DC_GPIO_DDC3_MASK:
reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC3); break; default:
DRM_ERROR("gpio not supported with hw i2c\n");
ret = -EINVAL; goto done;
}
/* check for bus probe */
p = &msgs[0]; if ((num == 1) && (p->len == 0)) {
WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
AVIVO_DC_I2C_NACK |
AVIVO_DC_I2C_HALT));
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
udelay(1);
WREG32(AVIVO_DC_I2C_RESET, 0);
staticint radeon_hw_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); struct radeon_device *rdev = i2c->dev->dev_private; struct radeon_i2c_bus_rec *rec = &i2c->rec; int ret = 0;
mutex_lock(&i2c->mutex);
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: case CHIP_RV380: case CHIP_R420: case CHIP_R423: case CHIP_RV410: case CHIP_RS400: case CHIP_RS480:
ret = r100_hw_i2c_xfer(i2c_adap, msgs, num); break; case CHIP_RS600: case CHIP_RS690: case CHIP_RS740: /* XXX fill in hw i2c implementation */ break; case CHIP_RV515: case CHIP_R520: case CHIP_RV530: case CHIP_RV560: case CHIP_RV570: case CHIP_R580: if (rec->mm_i2c)
ret = r100_hw_i2c_xfer(i2c_adap, msgs, num); else
ret = r500_hw_i2c_xfer(i2c_adap, msgs, num); break; case CHIP_R600: case CHIP_RV610: case CHIP_RV630: case CHIP_RV670: /* XXX fill in hw i2c implementation */ 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: /* XXX fill in hw i2c implementation */ break; case CHIP_CEDAR: case CHIP_REDWOOD: case CHIP_JUNIPER: case CHIP_CYPRESS: case CHIP_HEMLOCK: /* XXX fill in hw i2c implementation */ break; default:
DRM_ERROR("i2c: unhandled radeon chip\n");
ret = -EIO; break;
}
/* Add the default buses */ void radeon_i2c_init(struct radeon_device *rdev)
{ if (radeon_hw_i2c)
DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n");
if (rdev->is_atom_bios)
radeon_atombios_i2c_init(rdev); else
radeon_combios_i2c_init(rdev);
}
/* remove all the buses */ void radeon_i2c_fini(struct radeon_device *rdev)
{ int i;
for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { if (rdev->i2c_bus[i]) {
radeon_i2c_destroy(rdev->i2c_bus[i]);
rdev->i2c_bus[i] = NULL;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.