aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_i2c.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c111
1 files changed, 49 insertions, 62 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 91ef8f6..c90425c 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -23,41 +23,39 @@
* Authors: Dave Airlie
* Alex Deucher
*/
-
#include "drmP.h"
-#include "drm_edid.h"
#include "radeon_drm.h"
#include "radeon.h"
#include "atom.h"
-extern int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num);
-extern u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap);
-
/**
* radeon_ddc_probe
*
*/
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
{
u8 out = 0x0;
u8 buf[8];
int ret;
struct i2c_msg msgs[] = {
{
- .addr = DDC_ADDR,
+ .addr = 0x50,
.flags = 0,
.len = 1,
.buf = &out,
},
{
- .addr = DDC_ADDR,
+ .addr = 0x50,
.flags = I2C_M_RD,
- .len = 8,
+ .len = 1,
.buf = buf,
}
};
+ /* Read 8 bytes from i2c for extended probe of EDID header */
+ if (requires_extended_probe)
+ msgs[1].len = 8;
+
/* on hw with routers, select right port */
if (radeon_connector->router.ddc_valid)
radeon_router_select_ddc_port(radeon_connector);
@@ -66,24 +64,25 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
if (ret != 2)
/* Couldn't find an accessible DDC on this connector */
return false;
- /* 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 */
- return false;
+ if (requires_extended_probe) {
+ /* 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 */
+ return false;
+ }
}
return true;
}
/* bit banging i2c */
-static int pre_xfer(struct i2c_adapter *i2c_adap)
+static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
{
- 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;
uint32_t temp;
@@ -138,30 +137,19 @@ static int pre_xfer(struct i2c_adapter *i2c_adap)
WREG32(rec->en_data_reg, temp);
/* mask the gpio pins for software use */
- temp = RREG32(rec->mask_clk_reg) | rec->mask_clk_mask;
- WREG32(rec->mask_clk_reg, temp);
temp = RREG32(rec->mask_clk_reg);
-
- temp = RREG32(rec->mask_data_reg) | rec->mask_data_mask;
- WREG32(rec->mask_data_reg, temp);
- temp = RREG32(rec->mask_data_reg);
-
- return 0;
-}
-
-static void post_xfer(struct i2c_adapter *i2c_adap)
-{
- 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;
- uint32_t temp;
-
- /* unmask the gpio pins for software use */
- temp = RREG32(rec->mask_clk_reg) & ~rec->mask_clk_mask;
+ if (lock_state)
+ temp |= rec->mask_clk_mask;
+ else
+ temp &= ~rec->mask_clk_mask;
WREG32(rec->mask_clk_reg, temp);
temp = RREG32(rec->mask_clk_reg);
- temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask;
+ temp = RREG32(rec->mask_data_reg);
+ if (lock_state)
+ temp |= rec->mask_data_mask;
+ else
+ temp &= ~rec->mask_data_mask;
WREG32(rec->mask_data_reg, temp);
temp = RREG32(rec->mask_data_reg);
}
@@ -221,6 +209,22 @@ static void set_data(void *i2c_priv, int data)
WREG32(rec->en_data_reg, val);
}
+static int pre_xfer(struct i2c_adapter *i2c_adap)
+{
+ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+
+ radeon_i2c_do_lock(i2c, 1);
+
+ return 0;
+}
+
+static void post_xfer(struct i2c_adapter *i2c_adap)
+{
+ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+
+ radeon_i2c_do_lock(i2c, 0);
+}
+
/* hw i2c */
static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
@@ -886,11 +890,6 @@ static const struct i2c_algorithm radeon_i2c_algo = {
.functionality = radeon_hw_i2c_func,
};
-static const struct i2c_algorithm radeon_atom_i2c_algo = {
- .master_xfer = radeon_atom_hw_i2c_xfer,
- .functionality = radeon_atom_hw_i2c_func,
-};
-
struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name)
@@ -910,7 +909,6 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.class = I2C_CLASS_DDC;
- i2c->adapter.dev.parent = &dev->pdev->dev;
i2c->dev = dev;
i2c_set_adapdata(&i2c->adapter, i2c);
if (rec->mm_i2c ||
@@ -927,18 +925,6 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
DRM_ERROR("Failed to register hw i2c %s\n", name);
goto out_free;
}
- } else if (rec->hw_capable &&
- radeon_hw_i2c &&
- ASIC_IS_DCE3(rdev)) {
- /* hw i2c using atom */
- snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
- "Radeon i2c hw bus %s", name);
- i2c->adapter.algo = &radeon_atom_i2c_algo;
- ret = i2c_add_adapter(&i2c->adapter);
- if (ret) {
- DRM_ERROR("Failed to register hw i2c %s\n", name);
- goto out_free;
- }
} else {
/* set the radeon bit adapter */
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
@@ -950,8 +936,10 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
i2c->algo.bit.setscl = set_clock;
i2c->algo.bit.getsda = get_data;
i2c->algo.bit.getscl = get_clock;
- i2c->algo.bit.udelay = 10;
- i2c->algo.bit.timeout = usecs_to_jiffies(2200); /* from VESA */
+ i2c->algo.bit.udelay = 20;
+ /* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
+ * make this, 2 jiffies is a lot more reliable */
+ i2c->algo.bit.timeout = 2;
i2c->algo.bit.data = i2c;
ret = i2c_bit_add_bus(&i2c->adapter);
if (ret) {
@@ -981,7 +969,6 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.class = I2C_CLASS_DDC;
- i2c->adapter.dev.parent = &dev->pdev->dev;
i2c->dev = dev;
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
"Radeon aux bus %s", name);