Skip to content

Commit

Permalink
drm/radeon/kms: use new pre/post_xfer i2c bit algo hooks
Browse files Browse the repository at this point in the history
This allows us to remove the internal bit algo bus used by
the radeon i2c algo.  We now register a radeon algo adapter
if the gpio line is hw capable and the hw inplementation is
available, otherwise we register a bit algo adapter.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Alex Deucher authored and Dave Airlie committed Mar 31, 2010
1 parent 3595be7 commit ac1aade
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 79 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/radeon/radeon_connectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,7 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector)
if (radeon_connector->edid)
kfree(radeon_connector->edid);
if (radeon_dig_connector->dp_i2c_bus)
radeon_i2c_destroy_dp(radeon_dig_connector->dp_i2c_bus);
radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
kfree(radeon_connector->con_priv);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
Expand Down
133 changes: 62 additions & 71 deletions drivers/gpu/drm/radeon/radeon_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
return false;
}

/* bit banging i2c */

static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
{
Expand Down Expand Up @@ -181,6 +182,24 @@ 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)
{
u32 sclk = radeon_get_engine_clock(rdev);
Expand Down Expand Up @@ -757,26 +776,13 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
return ret;
}

static int radeon_sw_i2c_xfer(struct i2c_adapter *i2c_adap,
static int 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);
int ret;

radeon_i2c_do_lock(i2c, 1);
ret = i2c_transfer(&i2c->algo.radeon.bit_adapter, msgs, num);
radeon_i2c_do_lock(i2c, 0);

return ret;
}

static int radeon_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;
int ret = 0;

switch (rdev->family) {
case CHIP_R100:
Expand All @@ -797,37 +803,29 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
case CHIP_RV410:
case CHIP_RS400:
case CHIP_RS480:
if (rec->hw_capable)
ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
else
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
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 */
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
break;
case CHIP_RV515:
case CHIP_R520:
case CHIP_RV530:
case CHIP_RV560:
case CHIP_RV570:
case CHIP_R580:
if (rec->hw_capable) {
if (rec->mm_i2c)
ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
else
ret = r500_hw_i2c_xfer(i2c_adap, msgs, num);
} else
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
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 */
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
break;
case CHIP_RV620:
case CHIP_RV635:
Expand All @@ -838,15 +836,13 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
case CHIP_RV710:
case CHIP_RV740:
/* XXX fill in hw i2c implementation */
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
break;
case CHIP_CEDAR:
case CHIP_REDWOOD:
case CHIP_JUNIPER:
case CHIP_CYPRESS:
case CHIP_HEMLOCK:
/* XXX fill in hw i2c implementation */
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
break;
default:
DRM_ERROR("i2c: unhandled radeon chip\n");
Expand All @@ -857,58 +853,63 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
return ret;
}

static u32 radeon_i2c_func(struct i2c_adapter *adap)
static u32 radeon_hw_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}

static const struct i2c_algorithm radeon_i2c_algo = {
.master_xfer = radeon_i2c_xfer,
.functionality = radeon_i2c_func,
.master_xfer = radeon_hw_i2c_xfer,
.functionality = radeon_hw_i2c_func,
};

struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name)
{
struct radeon_device *rdev = dev->dev_private;
struct radeon_i2c_chan *i2c;
int ret;

i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
if (i2c == NULL)
return NULL;

/* set the internal bit adapter */
i2c->algo.radeon.bit_adapter.owner = THIS_MODULE;
i2c_set_adapdata(&i2c->algo.radeon.bit_adapter, i2c);
sprintf(i2c->algo.radeon.bit_adapter.name, "Radeon internal i2c bit bus %s", name);
i2c->algo.radeon.bit_adapter.algo_data = &i2c->algo.radeon.bit_data;
i2c->algo.radeon.bit_data.setsda = set_data;
i2c->algo.radeon.bit_data.setscl = set_clock;
i2c->algo.radeon.bit_data.getsda = get_data;
i2c->algo.radeon.bit_data.getscl = get_clock;
i2c->algo.radeon.bit_data.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.radeon.bit_data.timeout = 2;
i2c->algo.radeon.bit_data.data = i2c;
ret = i2c_bit_add_bus(&i2c->algo.radeon.bit_adapter);
if (ret) {
DRM_ERROR("Failed to register internal bit i2c %s\n", name);
goto out_free;
}
/* set the radeon i2c adapter */
i2c->dev = dev;
i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE;
i2c->dev = dev;
i2c_set_adapdata(&i2c->adapter, i2c);
sprintf(i2c->adapter.name, "Radeon i2c %s", name);
i2c->adapter.algo_data = &i2c->algo.radeon;
i2c->adapter.algo = &radeon_i2c_algo;
ret = i2c_add_adapter(&i2c->adapter);
if (ret) {
DRM_ERROR("Failed to register i2c %s\n", name);
goto out_free;
if (rec->hw_capable &&
((rdev->family <= CHIP_RS480) ||
((rdev->family >= CHIP_RV515) && (rdev->family <= CHIP_R580)))) {
/* set the radeon hw i2c adapter */
sprintf(i2c->adapter.name, "Radeon i2c hw bus %s", name);
i2c->adapter.algo = &radeon_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 */
sprintf(i2c->adapter.name, "Radeon i2c bit bus %s", name);
i2c->adapter.algo_data = &i2c->algo.bit;
i2c->algo.bit.pre_xfer = pre_xfer;
i2c->algo.bit.post_xfer = post_xfer;
i2c->algo.bit.setsda = set_data;
i2c->algo.bit.setscl = set_clock;
i2c->algo.bit.getsda = get_data;
i2c->algo.bit.getscl = get_clock;
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) {
DRM_ERROR("Failed to register bit i2c %s\n", name);
goto out_free;
}
}

return i2c;
Expand Down Expand Up @@ -953,16 +954,6 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
{
if (!i2c)
return;
i2c_del_adapter(&i2c->algo.radeon.bit_adapter);
i2c_del_adapter(&i2c->adapter);
kfree(i2c);
}

void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c)
{
if (!i2c)
return;

i2c_del_adapter(&i2c->adapter);
kfree(i2c);
}
Expand Down
8 changes: 1 addition & 7 deletions drivers/gpu/drm/radeon/radeon_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,12 @@ struct radeon_pll {
enum radeon_pll_algo algo;
};

struct i2c_algo_radeon_data {
struct i2c_adapter bit_adapter;
struct i2c_algo_bit_data bit_data;
};

struct radeon_i2c_chan {
struct i2c_adapter adapter;
struct drm_device *dev;
union {
struct i2c_algo_bit_data bit;
struct i2c_algo_dp_aux_data dp;
struct i2c_algo_radeon_data radeon;
} algo;
struct radeon_i2c_bus_rec rec;
};
Expand Down Expand Up @@ -435,7 +430,6 @@ extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name);
extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
extern void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c);
extern void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
u8 slave_addr,
u8 addr,
Expand Down

0 comments on commit ac1aade

Please sign in to comment.