From 5ef6d7b414e297f31903ff437e69f587a5b75586 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Tigeot?= Date: Wed, 26 Jun 2019 23:12:18 +0200 Subject: [PATCH] drm/radeon: Switch to Linux i2c APIs * Enable radeon.hw_i2c by default * Sync some code with Linux 3.19.8 in passing --- sys/dev/drm/radeon/atombios_dp.c | 137 ++----- sys/dev/drm/radeon/atombios_i2c.c | 100 +---- sys/dev/drm/radeon/radeon_connectors.c | 170 ++++----- sys/dev/drm/radeon/radeon_drv.c | 4 + sys/dev/drm/radeon/radeon_i2c.c | 489 +++++++------------------ sys/dev/drm/radeon/radeon_mode.h | 10 +- 6 files changed, 254 insertions(+), 656 deletions(-) diff --git a/sys/dev/drm/radeon/atombios_dp.c b/sys/dev/drm/radeon/atombios_dp.c index 5bdf5e787f..5bf825dfaa 100644 --- a/sys/dev/drm/radeon/atombios_dp.c +++ b/sys/dev/drm/radeon/atombios_dp.c @@ -99,8 +99,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, memset(&args, 0, sizeof(args)); - lockmgr(&chan->mutex, LK_EXCLUSIVE); - lockmgr(&rdev->mode_info.atom_context->scratch_mutex, LK_EXCLUSIVE); + mutex_lock(&chan->mutex); + mutex_lock(&rdev->mode_info.atom_context->scratch_mutex); base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); @@ -148,8 +148,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, r = recv_bytes; done: - lockmgr(&rdev->mode_info.atom_context->scratch_mutex, LK_RELEASE); - lockmgr(&chan->mutex, LK_RELEASE); + mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex); + mutex_unlock(&chan->mutex); return r; } @@ -219,98 +219,17 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) void radeon_dp_aux_init(struct radeon_connector *radeon_connector) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - - dig_connector->dp_i2c_bus->rec.hpd = radeon_connector->hpd.hpd; /* XXX check*/ - dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev; - dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer; -} - -int radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte) -{ - struct i2c_algo_dp_aux_data *algo_data = device_get_softc(dev); - struct radeon_i2c_chan *auxch = algo_data->priv; - u16 address = algo_data->address; - u8 msg[5]; - u8 reply[2]; - unsigned retry; - int msg_bytes; - int reply_bytes = 1; int ret; - u8 ack; - /* Set up the address */ - msg[0] = address; - msg[1] = address >> 8; + radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd; + radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; + radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer; - /* Set up the command byte */ - if (mode & MODE_I2C_READ) { - msg[2] = DP_AUX_I2C_READ << 4; - msg_bytes = 4; - msg[3] = msg_bytes << 4; - } else { - msg[2] = DP_AUX_I2C_WRITE << 4; - msg_bytes = 5; - msg[3] = msg_bytes << 4; - msg[4] = write_byte; - } + ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux); + if (!ret) + radeon_connector->ddc_bus->has_aux = true; - /* special handling for start/stop */ - if (mode & (MODE_I2C_START | MODE_I2C_STOP)) - msg[3] = 3 << 4; - - /* Set MOT bit for all but stop */ - if ((mode & MODE_I2C_STOP) == 0) - msg[2] |= DP_AUX_I2C_MOT << 4; - - for (retry = 0; retry < 7; retry++) { - ret = radeon_process_aux_ch(auxch, - msg, msg_bytes, reply, reply_bytes, 0, &ack); - if (ret == -EBUSY) - continue; - else if (ret < 0) { - DRM_DEBUG_KMS("aux_ch failed %d\n", ret); - return ret; - } - - switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) { - case DP_AUX_NATIVE_REPLY_ACK: - /* I2C-over-AUX Reply field is only valid - * when paired with AUX ACK. - */ - break; - case DP_AUX_NATIVE_REPLY_NACK: - DRM_DEBUG_KMS("aux_ch native nack\n"); - return -EREMOTEIO; - case DP_AUX_NATIVE_REPLY_DEFER: - DRM_DEBUG_KMS("aux_ch native defer\n"); - usleep_range(500, 600); - continue; - default: - DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); - return -EREMOTEIO; - } - - switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) { - case DP_AUX_I2C_REPLY_ACK: - if (mode == MODE_I2C_READ) - *read_byte = reply[0]; - return (0); /* XXX: why 0 and not msg size? */ - case DP_AUX_I2C_REPLY_NACK: - DRM_DEBUG_KMS("aux_i2c nack\n"); - return -EREMOTEIO; - case DP_AUX_I2C_REPLY_DEFER: - DRM_DEBUG_KMS("aux_i2c defer\n"); - usleep_range(400, 500); - break; - default: - DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); - return -EREMOTEIO; - } - } - - DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); - return -EREMOTEIO; + WARN(ret, "drm_dp_aux_register() failed with error %d\n", ret); } /***** general DP utility functions *****/ @@ -458,12 +377,11 @@ static u8 radeon_dp_encoder_service(struct radeon_device *rdev, u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; struct drm_device *dev = radeon_connector->base.dev; struct radeon_device *rdev = dev->dev_private; return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, - dig_connector->dp_i2c_bus->rec.i2c_id, 0); + radeon_connector->ddc_bus->rec.i2c_id, 0); } static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) @@ -474,12 +392,12 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_SINK_OUI, buf, 3) == 3) - DRM_DEBUG_KMS("Sink OUI: %02hhx%02hhx%02hhx\n", + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3) == 3) + DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_BRANCH_OUI, buf, 3) == 3) - DRM_DEBUG_KMS("Branch OUI: %02hhx%02hhx%02hhx\n", + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3) == 3) + DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); } @@ -489,15 +407,13 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) u8 msg[DP_DPCD_SIZE]; int ret; - char dpcd_hex_dump[DP_DPCD_SIZE * 3]; - - ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg, + ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, DP_DPCD_SIZE); if (ret > 0) { memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); - DRM_DEBUG_KMS("DPCD: %s\n", hexncpy(dig_connector->dpcd, - sizeof(dig_connector->dpcd), - dpcd_hex_dump, sizeof(dpcd_hex_dump), " ")); + + DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd), + dig_connector->dpcd); radeon_dp_probe_oui(radeon_connector); @@ -528,7 +444,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, if (dp_bridge != ENCODER_OBJECT_ID_NONE) { /* DP bridge chips */ - if (drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; @@ -540,7 +456,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, } } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { /* eDP */ - if (drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; @@ -599,7 +515,8 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) u8 link_status[DP_LINK_STATUS_SIZE]; struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0) + if (drm_dp_dpcd_read_link_status(&radeon_connector->ddc_bus->aux, link_status) + <= 0) return false; if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) return false; @@ -619,7 +536,7 @@ void radeon_dp_set_rx_power_state(struct drm_connector *connector, /* power up/down the sink */ if (dig_connector->dpcd[0] >= 0x11) { - drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux, + drm_dp_dpcd_writeb(&radeon_connector->ddc_bus->aux, DP_SET_POWER, power_state); usleep_range(1000, 2000); } @@ -921,7 +838,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, else dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; - if (drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, DP_MAX_LANE_COUNT, &tmp) + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp) == 1) { if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) dp_info.tp3_supported = true; @@ -937,7 +854,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, dp_info.connector = connector; dp_info.dp_lane_count = dig_connector->dp_lane_count; dp_info.dp_clock = dig_connector->dp_clock; - dp_info.aux = &dig_connector->dp_i2c_bus->aux; + dp_info.aux = &radeon_connector->ddc_bus->aux; if (radeon_dp_link_train_init(&dp_info)) goto done; diff --git a/sys/dev/drm/radeon/atombios_i2c.c b/sys/dev/drm/radeon/atombios_i2c.c index 4ed0a79f85..4378e54060 100644 --- a/sys/dev/drm/radeon/atombios_i2c.c +++ b/sys/dev/drm/radeon/atombios_i2c.c @@ -21,18 +21,11 @@ * * Authors: Alex Deucher * - * $FreeBSD: head/sys/dev/drm2/radeon/atombios_i2c.c 254885 2013-08-25 19:37:15Z dumbbell $ */ - #include #include -#include -#include -#include #include "radeon.h" #include "atom.h" -#include "iicbus_if.h" -#include "iicbb_if.h" #define TARGET_HW_I2C_CLOCK 50 @@ -54,8 +47,8 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, memset(&args, 0, sizeof(args)); - lockmgr(&chan->mutex, LK_EXCLUSIVE); - lockmgr(&rdev->mode_info.atom_context->scratch_mutex, LK_EXCLUSIVE); + mutex_lock(&chan->mutex); + mutex_lock(&rdev->mode_info.atom_context->scratch_mutex); base = (unsigned char *)rdev->mode_info.atom_context->scratch; @@ -103,17 +96,19 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, radeon_atom_copy_swap(buf, base, num, false); done: - lockmgr(&rdev->mode_info.atom_context->scratch_mutex, LK_RELEASE); - lockmgr(&chan->mutex, LK_RELEASE); + mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex); + mutex_unlock(&chan->mutex); return r; } -static int -radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num) +int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num); +int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); - struct iic_msg *p; + struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); + struct i2c_msg *p; int i, remaining, current_count, buffer_offset, max_bytes, ret; u8 flags; @@ -121,12 +116,12 @@ radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num) p = &msgs[0]; if ((num == 1) && (p->len == 0)) { ret = radeon_process_i2c_ch(i2c, - p->slave, HW_I2C_WRITE, + p->addr, HW_I2C_WRITE, NULL, 0); if (ret) return ret; else - return (0); + return num; } for (i = 0; i < num; i++) { @@ -134,7 +129,7 @@ radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num) remaining = p->len; buffer_offset = 0; /* max_bytes are a limitation of ProcessI2cChannelTransaction not the hw */ - if (p->flags & IIC_M_RD) { + if (p->flags & I2C_M_RD) { max_bytes = ATOM_MAX_HW_I2C_READ; flags = HW_I2C_READ; } else { @@ -147,7 +142,7 @@ radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num) else current_count = remaining; ret = radeon_process_i2c_ch(i2c, - p->slave, flags, + p->addr, flags, &p->buf[buffer_offset], current_count); if (ret) return ret; @@ -156,71 +151,12 @@ radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num) } } - return (0); -} - -static int -radeon_atom_hw_i2c_probe(device_t dev) -{ - - return (BUS_PROBE_SPECIFIC); + return num; } -static int -radeon_atom_hw_i2c_attach(device_t dev) +u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap);; +u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap) { - struct radeon_i2c_chan *i2c; - device_t iic_dev; - - i2c = device_get_softc(dev); - device_set_desc(dev, i2c->name); - - /* add generic bit-banging code */ - iic_dev = device_add_child(dev, "iicbus", -1); - if (iic_dev == NULL) - return (ENXIO); - device_quiet(iic_dev); - - /* attach and probe added child */ - bus_generic_attach(dev); - - return (0); -} - -static int -radeon_atom_hw_i2c_detach(device_t dev) -{ - /* detach bit-banding code. */ - bus_generic_detach(dev); - - /* delete bit-banding code. */ - device_delete_children(dev); - return (0); -} - -static int -radeon_atom_hw_i2c_reset(device_t dev, u_char speed, - u_char addr, u_char *oldaddr) -{ - - return (0); + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } -static device_method_t radeon_atom_hw_i2c_methods[] = { - DEVMETHOD(device_probe, radeon_atom_hw_i2c_probe), - DEVMETHOD(device_attach, radeon_atom_hw_i2c_attach), - DEVMETHOD(device_detach, radeon_atom_hw_i2c_detach), - DEVMETHOD(iicbus_reset, radeon_atom_hw_i2c_reset), - DEVMETHOD(iicbus_transfer, radeon_atom_hw_i2c_xfer), - DEVMETHOD_END -}; - -static driver_t radeon_atom_hw_i2c_driver = { - "radeon_atom_hw_i2c", - radeon_atom_hw_i2c_methods, - 0 -}; - -static devclass_t radeon_atom_hw_i2c_devclass; -DRIVER_MODULE_ORDERED(radeon_atom_hw_i2c, drm, radeon_atom_hw_i2c_driver, - radeon_atom_hw_i2c_devclass, NULL, NULL, SI_ORDER_ANY); diff --git a/sys/dev/drm/radeon/radeon_connectors.c b/sys/dev/drm/radeon/radeon_connectors.c index 4087a68655..3bc2862d51 100644 --- a/sys/dev/drm/radeon/radeon_connectors.c +++ b/sys/dev/drm/radeon/radeon_connectors.c @@ -31,11 +31,7 @@ #include "radeon.h" #include "atom.h" -#include - -#ifdef PM_TODO #include -#endif void radeon_connector_hotplug(struct drm_connector *connector) { @@ -290,10 +286,11 @@ struct edid *radeon_connector_edid(struct drm_connector *connector) return radeon_connector->edid; } -static void radeon_connector_get_edid(struct radeon_connector *radeon_connector) +static void radeon_connector_get_edid(struct drm_connector *connector) { - struct drm_device *dev = radeon_connector->base.dev; + struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); if (radeon_connector->edid) return; @@ -302,27 +299,26 @@ static void radeon_connector_get_edid(struct radeon_connector *radeon_connector) if (radeon_connector->router.ddc_valid) radeon_router_select_ddc_port(radeon_connector); - if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != - ENCODER_OBJECT_ID_NONE) { - struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - - if (dig->dp_i2c_bus) - radeon_connector->edid = drm_get_edid_iic(&radeon_connector->base, - dig->dp_i2c_bus->adapter); - } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || - (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { + if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) != + ENCODER_OBJECT_ID_NONE) && + radeon_connector->ddc_bus->has_aux) { + radeon_connector->edid = drm_get_edid(connector, + &radeon_connector->ddc_bus->aux.ddc); + } else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) || + (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || - dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus) - radeon_connector->edid = drm_get_edid_iic(&radeon_connector->base, - dig->dp_i2c_bus->adapter); - else if (radeon_connector->ddc_bus && !radeon_connector->edid) - radeon_connector->edid = drm_get_edid_iic(&radeon_connector->base, - radeon_connector->ddc_bus->adapter); + dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && + radeon_connector->ddc_bus->has_aux) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &radeon_connector->ddc_bus->aux.ddc); + else if (radeon_connector->ddc_bus) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &radeon_connector->ddc_bus->adapter); } else if (radeon_connector->ddc_bus) { - radeon_connector->edid = drm_get_edid_iic(&radeon_connector->base, - radeon_connector->ddc_bus->adapter); + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &radeon_connector->ddc_bus->adapter); } if (!radeon_connector->edid) { @@ -334,8 +330,8 @@ static void radeon_connector_get_edid(struct radeon_connector *radeon_connector) if (rdev->is_atom_bios) { /* some laptops provide a hardcoded edid in rom for LCDs */ - if (((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_LVDS) || - (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP))) + if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) || + (connector->connector_type == DRM_MODE_CONNECTOR_eDP))) radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev); } else { /* some servers provide a hardcoded edid in rom for KVMs */ @@ -344,25 +340,28 @@ static void radeon_connector_get_edid(struct radeon_connector *radeon_connector) } } -static void radeon_connector_free_edid(struct radeon_connector *radeon_connector) +static void radeon_connector_free_edid(struct drm_connector *connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + if (radeon_connector->edid) { kfree(radeon_connector->edid); radeon_connector->edid = NULL; } } -static int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) +static int radeon_ddc_get_modes(struct drm_connector *connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); int ret; if (radeon_connector->edid) { - drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); - ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); - drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid); + drm_mode_connector_update_edid_property(connector, radeon_connector->edid); + ret = drm_add_edid_modes(connector, radeon_connector->edid); + drm_edid_to_eld(connector, radeon_connector->edid); return ret; } - drm_mode_connector_update_edid_property(&radeon_connector->base, NULL); + drm_mode_connector_update_edid_property(connector, NULL); return 0; } @@ -765,23 +764,20 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, static int radeon_lvds_get_modes(struct drm_connector *connector) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder; int ret = 0; struct drm_display_mode *mode; - if (radeon_connector->ddc_bus) { - radeon_connector_get_edid(radeon_connector); - ret = radeon_ddc_get_modes(radeon_connector); - if (ret > 0) { - encoder = radeon_best_single_encoder(connector); - if (encoder) { - radeon_fixup_lvds_native_mode(encoder, connector); - /* add scaled modes */ - radeon_add_common_modes(encoder, connector); - } - return ret; + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); + if (ret > 0) { + encoder = radeon_best_single_encoder(connector); + if (encoder) { + radeon_fixup_lvds_native_mode(encoder, connector); + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); } + return ret; } encoder = radeon_best_single_encoder(connector); @@ -864,17 +860,9 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) } /* check for edid as well */ - radeon_connector_get_edid(radeon_connector); + radeon_connector_get_edid(connector); if (radeon_connector->edid) ret = connector_status_connected; - else { - if (radeon_connector->ddc_bus) { - radeon_connector->edid = drm_get_edid_iic(&radeon_connector->base, - radeon_connector->ddc_bus->adapter); - if (radeon_connector->edid) - ret = connector_status_connected; - } - } /* check acpi lid status ??? */ radeon_connector_update_scratch_regs(connector, ret); @@ -889,7 +877,7 @@ static void radeon_connector_destroy(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); - radeon_connector_free_edid(radeon_connector); + radeon_connector_free_edid(connector); kfree(radeon_connector->con_priv); drm_connector_unregister(connector); drm_connector_cleanup(connector); @@ -948,11 +936,10 @@ static const struct drm_connector_funcs radeon_lvds_connector_funcs = { static int radeon_vga_get_modes(struct drm_connector *connector) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); int ret; - radeon_connector_get_edid(radeon_connector); - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); radeon_get_native_mode(connector); @@ -999,8 +986,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force) dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; - radeon_connector_free_edid(radeon_connector); - radeon_connector_get_edid(radeon_connector); + radeon_connector_free_edid(connector); + radeon_connector_get_edid(connector); if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", @@ -1014,7 +1001,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force) * with a shared ddc line (often vga + hdmi) */ if (radeon_connector->use_digital && radeon_connector->shared_ddc) { - radeon_connector_free_edid(radeon_connector); + radeon_connector_free_edid(connector); ret = connector_status_disconnected; } else { ret = connector_status_connected; @@ -1220,8 +1207,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; - radeon_connector_free_edid(radeon_connector); - radeon_connector_get_edid(radeon_connector); + radeon_connector_free_edid(connector); + radeon_connector_get_edid(connector); if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", @@ -1246,7 +1233,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) * with a shared ddc line (often vga + hdmi) */ if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) { - radeon_connector_free_edid(radeon_connector); + radeon_connector_free_edid(connector); ret = connector_status_disconnected; } else { ret = connector_status_connected; @@ -1270,7 +1257,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) { /* hpd is our only option in this case */ if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { - radeon_connector_free_edid(radeon_connector); + radeon_connector_free_edid(connector); ret = connector_status_disconnected; } } @@ -1466,20 +1453,6 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = { .force = radeon_dvi_force, }; -static void radeon_dp_connector_destroy(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; - - radeon_connector_free_edid(radeon_connector); - if (radeon_dig_connector->dp_i2c_bus) - radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus); - kfree(radeon_connector->con_priv); - drm_connector_unregister(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - static int radeon_dp_get_modes(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -1495,8 +1468,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) if (!radeon_dig_connector->edp_on) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_ON); - radeon_connector_get_edid(radeon_connector); - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); if (!radeon_dig_connector->edp_on) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_OFF); @@ -1507,8 +1480,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) if (encoder) radeon_atom_ext_encoder_setup_ddc(encoder); } - radeon_connector_get_edid(radeon_connector); - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); } if (ret > 0) { @@ -1541,8 +1514,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) if (encoder) radeon_atom_ext_encoder_setup_ddc(encoder); } - radeon_connector_get_edid(radeon_connector); - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); radeon_get_native_mode(connector); } @@ -1637,7 +1610,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) goto out; } - radeon_connector_free_edid(radeon_connector); + radeon_connector_free_edid(connector); if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { @@ -1775,7 +1748,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_connector_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1784,7 +1757,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_lvds_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1793,7 +1766,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_lvds_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1890,17 +1863,10 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; if (i2c_bus->valid) { - /* add DP i2c bus */ - if (connector_type == DRM_MODE_CONNECTOR_eDP) - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); - else - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); - if (radeon_dig_connector->dp_i2c_bus) + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (radeon_connector->ddc_bus) has_aux = true; else - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); } switch (connector_type) { @@ -2132,10 +2098,6 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { - /* add DP i2c bus */ - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); - if (!radeon_dig_connector->dp_i2c_bus) - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (radeon_connector->ddc_bus) has_aux = true; @@ -2181,14 +2143,10 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { - /* add DP i2c bus */ - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); - if (radeon_dig_connector->dp_i2c_bus) + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (radeon_connector->ddc_bus) has_aux = true; else - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); } drm_object_attach_property(&radeon_connector->base.base, diff --git a/sys/dev/drm/radeon/radeon_drv.c b/sys/dev/drm/radeon/radeon_drv.c index 1f29e402ec..54ec26d7e4 100644 --- a/sys/dev/drm/radeon/radeon_drv.c +++ b/sys/dev/drm/radeon/radeon_drv.c @@ -158,7 +158,11 @@ int radeon_connector_table = 0; int radeon_tv = 1; int radeon_audio = -1; int radeon_disp_priority = 0; +#ifdef __DragonFly__ +int radeon_hw_i2c = 1; +#else int radeon_hw_i2c = 0; +#endif int radeon_pcie_gen2 = -1; int radeon_msi = -1; int radeon_lockup_timeout = 10000; diff --git a/sys/dev/drm/radeon/radeon_i2c.c b/sys/dev/drm/radeon/radeon_i2c.c index b262ae247b..6db203f941 100644 --- a/sys/dev/drm/radeon/radeon_i2c.c +++ b/sys/dev/drm/radeon/radeon_i2c.c @@ -22,21 +22,18 @@ * * Authors: Dave Airlie * Alex Deucher - * - * $FreeBSD: head/sys/dev/drm2/radeon/radeon_i2c.c 254885 2013-08-25 19:37:15Z dumbbell $ */ +#include #include #include #include -#include -#include -#include -#include #include "radeon.h" #include "atom.h" -#include "iicbus_if.h" -#include "iicbb_if.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 @@ -47,16 +44,16 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) u8 out = 0x0; u8 buf[8]; int ret; - struct iic_msg msgs[] = { + struct i2c_msg msgs[] = { { - .slave = DDC_ADDR << 1, + .addr = DDC_ADDR, .flags = 0, .len = 1, .buf = &out, }, { - .slave = DDC_ADDR << 1, - .flags = IIC_M_RD, + .addr = DDC_ADDR, + .flags = I2C_M_RD, .len = 8, .buf = buf, } @@ -67,13 +64,12 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) radeon_router_select_ddc_port(radeon_connector); if (use_aux) { - struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - ret = iicbus_transfer(dig->dp_i2c_bus->adapter, msgs, 2); + ret = i2c_transfer(&radeon_connector->ddc_bus->aux.ddc, msgs, 2); } else { - ret = iicbus_transfer(radeon_connector->ddc_bus->adapter, msgs, 2); + ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); } - if (ret != 0) + if (ret != 2) /* Couldn't find an accessible DDC on this connector */ return false; /* Probe also for valid EDID header @@ -91,14 +87,14 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) /* bit banging i2c */ -static int radeon_iicbb_pre_xfer(device_t dev) +static int pre_xfer(struct i2c_adapter *i2c_adap) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); + 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; - lockmgr(&i2c->mutex, LK_EXCLUSIVE); + mutex_lock(&i2c->mutex); /* 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 @@ -116,7 +112,7 @@ static int radeon_iicbb_pre_xfer(device_t dev) else reg = RADEON_GPIO_CRT2_DDC; - lockmgr(&rdev->dc_hw_i2c_mutex, LK_EXCLUSIVE); + mutex_lock(&rdev->dc_hw_i2c_mutex); if (rec->a_clk_reg == reg) { WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1))); @@ -124,7 +120,7 @@ static int radeon_iicbb_pre_xfer(device_t dev) WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3))); } - lockmgr(&rdev->dc_hw_i2c_mutex, LK_RELEASE); + mutex_unlock(&rdev->dc_hw_i2c_mutex); } } @@ -161,9 +157,9 @@ static int radeon_iicbb_pre_xfer(device_t dev) return 0; } -static void radeon_iicbb_post_xfer(device_t dev) +static void post_xfer(struct i2c_adapter *i2c_adap) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); + 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; @@ -177,12 +173,12 @@ static void radeon_iicbb_post_xfer(device_t dev) WREG32(rec->mask_data_reg, temp); temp = RREG32(rec->mask_data_reg); - lockmgr(&i2c->mutex, LK_RELEASE); + mutex_unlock(&i2c->mutex); } -static int radeon_iicbb_get_clock(device_t dev) +static int get_clock(void *i2c_priv) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_i2c_chan *i2c = i2c_priv; struct radeon_device *rdev = i2c->dev->dev_private; struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -195,9 +191,9 @@ static int radeon_iicbb_get_clock(device_t dev) } -static int radeon_iicbb_get_data(device_t dev) +static int get_data(void *i2c_priv) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_i2c_chan *i2c = i2c_priv; struct radeon_device *rdev = i2c->dev->dev_private; struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -209,9 +205,9 @@ static int radeon_iicbb_get_data(device_t dev) return (val != 0); } -static void radeon_iicbb_set_clock(device_t dev, int clock) +static void set_clock(void *i2c_priv, int clock) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_i2c_chan *i2c = i2c_priv; struct radeon_device *rdev = i2c->dev->dev_private; struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -222,9 +218,9 @@ static void radeon_iicbb_set_clock(device_t dev, int clock) WREG32(rec->en_clk_reg, val); } -static void radeon_iicbb_set_data(device_t dev, int data) +static void set_data(void *i2c_priv, int data) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); + struct radeon_i2c_chan *i2c = i2c_priv; struct radeon_device *rdev = i2c->dev->dev_private; struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -235,82 +231,6 @@ static void radeon_iicbb_set_data(device_t dev, int data) WREG32(rec->en_data_reg, val); } -static int -radeon_iicbb_probe(device_t dev) -{ - - return (BUS_PROBE_DEFAULT); -} - -static int -radeon_iicbb_attach(device_t dev) -{ - struct radeon_i2c_chan *i2c; - device_t iic_dev; - - i2c = device_get_softc(dev); - device_set_desc(dev, i2c->name); - - /* add generic bit-banging code */ - iic_dev = device_add_child(dev, "iicbb", -1); - if (iic_dev == NULL) - return (ENXIO); - device_quiet(iic_dev); - - /* attach and probe added child */ - bus_generic_attach(dev); - - return (0); -} - -static int -radeon_iicbb_detach(device_t dev) -{ - - /* detach bit-banding code. */ - bus_generic_detach(dev); - - /* delete bit-banding code. */ - device_delete_children(dev); - return (0); -} - -static int -radeon_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) -{ - - /* Not sure what to do here. */ - return 0; -} - -static device_method_t radeon_iicbb_methods[] = { - DEVMETHOD(device_probe, radeon_iicbb_probe), - DEVMETHOD(device_attach, radeon_iicbb_attach), - DEVMETHOD(device_detach, radeon_iicbb_detach), - - DEVMETHOD(bus_add_child, bus_generic_add_child), - DEVMETHOD(bus_print_child, bus_generic_print_child), - - DEVMETHOD(iicbb_reset, radeon_iicbb_reset), - DEVMETHOD(iicbb_pre_xfer, radeon_iicbb_pre_xfer), - DEVMETHOD(iicbb_post_xfer, radeon_iicbb_post_xfer), - DEVMETHOD(iicbb_setsda, radeon_iicbb_set_data), - DEVMETHOD(iicbb_setscl, radeon_iicbb_set_clock), - DEVMETHOD(iicbb_getsda, radeon_iicbb_get_data), - DEVMETHOD(iicbb_getscl, radeon_iicbb_get_clock), - DEVMETHOD_END -}; - -static driver_t radeon_iicbb_driver = { - "radeon_iicbb", - radeon_iicbb_methods, - 0 /* softc will be allocated by parent */ -}; -static devclass_t radeon_iicbb_devclass; -DRIVER_MODULE_ORDERED(radeon_iicbb, drm, radeon_iicbb_driver, - radeon_iicbb_devclass, NULL, NULL, SI_ORDER_FIRST); -DRIVER_MODULE(iicbb, radeon_iicbb, iicbb_driver, iicbb_devclass, NULL, NULL); - /* hw i2c */ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) @@ -403,20 +323,21 @@ static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) /* hw i2c engine for r1xx-4xx hardware * hw can buffer up to 15 bytes */ -static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, - struct iic_msg *msgs, int num) +static int 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 iic_msg *p; - int i, j, k, ret = 0; + struct i2c_msg *p; + int i, j, k, ret = num; u32 prescale; u32 i2c_cntl_0, i2c_cntl_1, i2c_data; u32 tmp, reg; - lockmgr(&rdev->dc_hw_i2c_mutex, LK_EXCLUSIVE); + mutex_lock(&rdev->dc_hw_i2c_mutex); /* take the pm lock since we need a constant sclk */ - lockmgr(&rdev->pm.mutex, LK_EXCLUSIVE); + mutex_lock(&rdev->pm.mutex); prescale = radeon_get_i2c_prescale(rdev); @@ -453,7 +374,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = EINVAL; + ret = -EINVAL; goto done; } break; @@ -468,7 +389,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = EINVAL; + ret = -EINVAL; goto done; } break; @@ -487,7 +408,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = EINVAL; + ret = -EINVAL; goto done; } break; @@ -503,7 +424,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = EINVAL; + ret = -EINVAL; goto done; } break; @@ -527,13 +448,13 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = EINVAL; + ret = -EINVAL; goto done; } break; default: DRM_ERROR("unsupported asic\n"); - ret = EINVAL; + ret = -EINVAL; goto done; break; } @@ -546,7 +467,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST)); - WREG32(i2c_data, (p->slave << 1) & 0xff); + WREG32(i2c_data, (p->addr << 1) & 0xff); WREG32(i2c_data, 0); WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) | (1 << RADEON_I2C_ADDR_COUNT_SHIFT) | @@ -564,7 +485,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, else { DRM_DEBUG("i2c write error 0x%08x\n", tmp); WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); - ret = EIO; + ret = -EIO; goto done; } } @@ -574,12 +495,12 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, for (i = 0; i < num; i++) { p = &msgs[i]; for (j = 0; j < p->len; j++) { - if (p->flags & IIC_M_RD) { + if (p->flags & I2C_M_RD) { WREG32(i2c_cntl_0, (RADEON_I2C_DONE | RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST)); - WREG32(i2c_data, ((p->slave << 1) & 0xff) | 0x1); + WREG32(i2c_data, ((p->addr << 1) & 0xff) | 0x1); WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) | (1 << RADEON_I2C_ADDR_COUNT_SHIFT) | RADEON_I2C_EN | @@ -596,7 +517,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, else { DRM_DEBUG("i2c read error 0x%08x\n", tmp); WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); - ret = EIO; + ret = -EIO; goto done; } } @@ -606,7 +527,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST)); - WREG32(i2c_data, (p->slave << 1) & 0xff); + WREG32(i2c_data, (p->addr << 1) & 0xff); WREG32(i2c_data, p->buf[j]); WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) | (1 << RADEON_I2C_ADDR_COUNT_SHIFT) | @@ -624,7 +545,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c, else { DRM_DEBUG("i2c write error 0x%08x\n", tmp); WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); - ret = EIO; + ret = -EIO; goto done; } } @@ -646,8 +567,8 @@ done: WREG32(RADEON_BIOS_6_SCRATCH, tmp); } - lockmgr(&rdev->pm.mutex, LK_RELEASE); - lockmgr(&rdev->dc_hw_i2c_mutex, LK_RELEASE); + mutex_unlock(&rdev->pm.mutex); + mutex_unlock(&rdev->dc_hw_i2c_mutex); return ret; } @@ -655,20 +576,21 @@ done: /* hw i2c engine for r5xx hardware * hw can buffer up to 15 bytes */ -static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, - struct iic_msg *msgs, int num) +static int r500_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 iic_msg *p; - int i, j, remaining, current_count, buffer_offset, ret = 0; + struct i2c_msg *p; + int i, j, remaining, current_count, buffer_offset, ret = num; u32 prescale; u32 tmp, reg; u32 saved1, saved2; - lockmgr(&rdev->dc_hw_i2c_mutex, LK_EXCLUSIVE); + mutex_lock(&rdev->dc_hw_i2c_mutex); /* take the pm lock since we need a constant sclk */ - lockmgr(&rdev->pm.mutex, LK_EXCLUSIVE); + mutex_lock(&rdev->pm.mutex); prescale = radeon_get_i2c_prescale(rdev); @@ -720,7 +642,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, } if (i == 50) { DRM_ERROR("failed to get i2c bus\n"); - ret = EBUSY; + ret = -EBUSY; goto done; } @@ -737,7 +659,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = EINVAL; + ret = -EINVAL; goto done; } @@ -751,7 +673,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, udelay(1); WREG32(AVIVO_DC_I2C_RESET, 0); - WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff); + WREG32(AVIVO_DC_I2C_DATA, (p->addr << 1) & 0xff); WREG32(AVIVO_DC_I2C_DATA, 0); WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48)); @@ -771,7 +693,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, else { DRM_DEBUG("i2c write error 0x%08x\n", tmp); WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); - ret = EIO; + ret = -EIO; goto done; } } @@ -782,7 +704,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, p = &msgs[i]; remaining = p->len; buffer_offset = 0; - if (p->flags & IIC_M_RD) { + if (p->flags & I2C_M_RD) { while (remaining) { if (remaining > 15) current_count = 15; @@ -795,7 +717,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, udelay(1); WREG32(AVIVO_DC_I2C_RESET, 0); - WREG32(AVIVO_DC_I2C_DATA, ((p->slave << 1) & 0xff) | 0x1); + WREG32(AVIVO_DC_I2C_DATA, ((p->addr << 1) & 0xff) | 0x1); WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48)); WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) | AVIVO_DC_I2C_DATA_COUNT(current_count) | @@ -813,7 +735,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, else { DRM_DEBUG("i2c read error 0x%08x\n", tmp); WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); - ret = EIO; + ret = -EIO; goto done; } } @@ -835,7 +757,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, udelay(1); WREG32(AVIVO_DC_I2C_RESET, 0); - WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff); + WREG32(AVIVO_DC_I2C_DATA, (p->addr << 1) & 0xff); for (j = 0; j < current_count; j++) WREG32(AVIVO_DC_I2C_DATA, p->buf[buffer_offset + j]); @@ -856,7 +778,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c, else { DRM_DEBUG("i2c write error 0x%08x\n", tmp); WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); - ret = EIO; + ret = -EIO; goto done; } } @@ -881,21 +803,21 @@ done: tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE; WREG32(RADEON_BIOS_6_SCRATCH, tmp); - lockmgr(&rdev->pm.mutex, LK_RELEASE); - lockmgr(&rdev->dc_hw_i2c_mutex, LK_RELEASE); + mutex_unlock(&rdev->pm.mutex); + mutex_unlock(&rdev->dc_hw_i2c_mutex); return ret; } -static int radeon_hw_i2c_xfer(device_t dev, - struct iic_msg *msgs, uint32_t num) +static int radeon_hw_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) { - struct radeon_i2c_chan *i2c = device_get_softc(dev); + 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; - lockmgr(&i2c->mutex, LK_EXCLUSIVE); + mutex_lock(&i2c->mutex); switch (rdev->family) { case CHIP_R100: @@ -916,7 +838,7 @@ static int radeon_hw_i2c_xfer(device_t dev, case CHIP_RV410: case CHIP_RS400: case CHIP_RS480: - ret = r100_hw_i2c_xfer(i2c, msgs, num); + ret = r100_hw_i2c_xfer(i2c_adap, msgs, num); break; case CHIP_RS600: case CHIP_RS690: @@ -930,9 +852,9 @@ static int radeon_hw_i2c_xfer(device_t dev, case CHIP_RV570: case CHIP_R580: if (rec->mm_i2c) - ret = r100_hw_i2c_xfer(i2c, msgs, num); + ret = r100_hw_i2c_xfer(i2c_adap, msgs, num); else - ret = r500_hw_i2c_xfer(i2c, msgs, num); + ret = r500_hw_i2c_xfer(i2c_adap, msgs, num); break; case CHIP_R600: case CHIP_RV610: @@ -959,91 +881,36 @@ static int radeon_hw_i2c_xfer(device_t dev, break; default: DRM_ERROR("i2c: unhandled radeon chip\n"); - ret = EIO; + ret = -EIO; break; } - lockmgr(&i2c->mutex, LK_RELEASE); + mutex_unlock(&i2c->mutex); return ret; } -static int -radeon_hw_i2c_probe(device_t dev) -{ - - return (BUS_PROBE_SPECIFIC); -} - -static int -radeon_hw_i2c_attach(device_t dev) -{ - struct radeon_i2c_chan *i2c; - device_t iic_dev; - - i2c = device_get_softc(dev); - device_set_desc(dev, i2c->name); - - /* add generic bit-banging code */ - iic_dev = device_add_child(dev, "iicbus", -1); - if (iic_dev == NULL) - return (ENXIO); - device_quiet(iic_dev); - - /* attach and probe added child */ - bus_generic_attach(dev); - - return (0); -} - -static int -radeon_hw_i2c_detach(device_t dev) -{ - - /* detach bit-banding code. */ - bus_generic_detach(dev); - - /* delete bit-banding code. */ - device_delete_children(dev); - return (0); -} - -static int -radeon_hw_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) +static u32 radeon_hw_i2c_func(struct i2c_adapter *adap) { - - /* Not sure what to do here. */ - return 0; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } - -static device_method_t radeon_hw_i2c_methods[] = { - DEVMETHOD(device_probe, radeon_hw_i2c_probe), - DEVMETHOD(device_attach, radeon_hw_i2c_attach), - DEVMETHOD(device_detach, radeon_hw_i2c_detach), - DEVMETHOD(iicbus_reset, radeon_hw_i2c_reset), - DEVMETHOD(iicbus_transfer, radeon_hw_i2c_xfer), - DEVMETHOD_END +static const struct i2c_algorithm radeon_i2c_algo = { + .master_xfer = radeon_hw_i2c_xfer, + .functionality = radeon_hw_i2c_func, }; -static driver_t radeon_hw_i2c_driver = { - "radeon_hw_i2c", - radeon_hw_i2c_methods, - 0 /* softc will be allocated by parent */ +static const struct i2c_algorithm radeon_atom_i2c_algo = { + .master_xfer = radeon_atom_hw_i2c_xfer, + .functionality = radeon_atom_hw_i2c_func, }; -static devclass_t radeon_hw_i2c_devclass; -DRIVER_MODULE_ORDERED(radeon_hw_i2c, drm, radeon_hw_i2c_driver, - radeon_hw_i2c_devclass, NULL, NULL, SI_ORDER_FIRST); -DRIVER_MODULE(iicbus, radeon_hw_i2c, iicbus_driver, iicbus_devclass, NULL, NULL); - 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; - device_t iicbus_dev; int ret; /* don't add the mm_i2c bus unless hw_i2c is enabled */ @@ -1054,14 +921,14 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, if (i2c == NULL) return NULL; - /* - * Grab Giant before messing with newbus devices, just in case - * we do not hold it already. - */ - get_mplock(); - i2c->rec = *rec; +#if 0 + i2c->adapter.owner = THIS_MODULE; + i2c->adapter.class = I2C_CLASS_DDC; +#endif + i2c->adapter.dev.parent = &dev->pdev->dev; i2c->dev = dev; + i2c_set_adapdata(&i2c->adapter, i2c); lockinit(&i2c->mutex, "ri2cmtx", 0, LK_CANRECURSE); if (rec->mm_i2c || (rec->hw_capable && @@ -1069,133 +936,47 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, ((rdev->family <= CHIP_RS480) || ((rdev->family >= CHIP_RV515) && (rdev->family <= CHIP_R580))))) { /* set the radeon hw i2c adapter */ - ksnprintf(i2c->name, sizeof(i2c->name), - "Radeon i2c hw bus %s", name); - iicbus_dev = device_add_child(dev->dev->bsddev, "radeon_hw_i2c", -1); - if (iicbus_dev == NULL) { - DRM_ERROR("Failed to create bridge for hw i2c %s\n", - name); - goto out_free; - } - device_quiet(iicbus_dev); - device_set_softc(iicbus_dev, i2c); - - ret = device_probe_and_attach(iicbus_dev); - if (ret != 0) { - DRM_ERROR("Attach failed for bridge for hw i2c %s\n", - name); - device_delete_child(dev->dev->bsddev, iicbus_dev); - goto out_free; - } - - i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1); - if (i2c->adapter == NULL) { - DRM_ERROR("hw i2c bridge doesn't have iicbus child\n"); - device_delete_child(dev->dev->bsddev, iicbus_dev); + snprintf(i2c->adapter.name, sizeof(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 if (rec->hw_capable && radeon_hw_i2c && ASIC_IS_DCE3(rdev)) { /* hw i2c using atom */ - ksnprintf(i2c->name, sizeof(i2c->name), - "Radeon i2c hw bus %s", name); - iicbus_dev = device_add_child(dev->dev->bsddev, "radeon_atom_hw_i2c", -1); - if (iicbus_dev == NULL) { - DRM_ERROR("Failed to create bridge for hw i2c %s\n", - name); - goto out_free; - } - device_quiet(iicbus_dev); - device_set_softc(iicbus_dev, i2c); - - ret = device_probe_and_attach(iicbus_dev); - if (ret != 0) { - DRM_ERROR("Attach failed for bridge for hw i2c %s\n", - name); - device_delete_child(dev->dev->bsddev, iicbus_dev); - goto out_free; - } - - i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1); - if (i2c->adapter == NULL) { - DRM_ERROR("hw i2c bridge doesn't have iicbus child\n"); - device_delete_child(dev->dev->bsddev, iicbus_dev); + 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 { - device_t iicbb_dev; - /* set the radeon bit adapter */ - ksnprintf(i2c->name, sizeof(i2c->name), - "Radeon i2c bit bus %s", name); - iicbus_dev = device_add_child(dev->dev->bsddev, "radeon_iicbb", -1); - if (iicbus_dev == NULL) { - DRM_ERROR("Failed to create bridge for bb i2c %s\n", - name); - goto out_free; - } - device_quiet(iicbus_dev); - device_set_softc(iicbus_dev, i2c); - - ret = device_probe_and_attach(iicbus_dev); - if (ret != 0) { - DRM_ERROR("Attach failed for bridge for bb i2c %s\n", - name); - device_delete_child(dev->dev->bsddev, iicbus_dev); - goto out_free; - } - - iicbb_dev = device_find_child(iicbus_dev, "iicbb", -1); - if (iicbb_dev == NULL) { - DRM_ERROR("bb i2c bridge doesn't have iicbb child\n"); - device_delete_child(dev->dev->bsddev, iicbus_dev); - goto out_free; - } - - i2c->adapter = device_find_child(iicbb_dev, "iicbus", -1); - if (i2c->adapter == NULL) { - DRM_ERROR( - "bbbus bridge doesn't have iicbus grandchild\n"); - device_delete_child(dev->dev->bsddev, iicbus_dev); + snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), + "Radeon i2c bit bus %s", name); + i2c->adapter.algo_data = &i2c->bit; + i2c->bit.pre_xfer = pre_xfer; + i2c->bit.post_xfer = post_xfer; + i2c->bit.setsda = set_data; + i2c->bit.setscl = set_clock; + i2c->bit.getsda = get_data; + i2c->bit.getscl = get_clock; + i2c->bit.udelay = 10; + i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ + i2c->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; } } - i2c->iic_bus = iicbus_dev; - - rel_mplock(); - - return i2c; -out_free: - rel_mplock(); - kfree(i2c); - return NULL; - -} - -struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, - struct radeon_i2c_bus_rec *rec, - const char *name) -{ - struct radeon_i2c_chan *i2c; - int ret; - - i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL); - if (i2c == NULL) - return NULL; - - i2c->rec = *rec; - i2c->dev = dev; - ksnprintf(i2c->name, sizeof(i2c->name), "Radeon aux bus %s", name); - ret = iic_dp_aux_add_bus(dev->dev->bsddev, i2c->name, - radeon_dp_i2c_aux_ch, i2c, &i2c->iic_bus, - &i2c->adapter); - if (ret) { - DRM_INFO("Failed to register i2c %s\n", name); - goto out_free; - } - return i2c; out_free: kfree(i2c); @@ -1207,15 +988,9 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) { if (!i2c) return; - if (i2c->iic_bus != NULL) { - int ret; - - get_mplock(); - ret = device_delete_child(i2c->dev->dev->bsddev, i2c->iic_bus); - rel_mplock(); - KASSERT(ret == 0, ("unable to detach iic bus %s: %d", - i2c->name, ret)); - } + i2c_del_adapter(&i2c->adapter); + if (i2c->has_aux) + drm_dp_aux_unregister(&i2c->aux); kfree(i2c); } @@ -1275,6 +1050,11 @@ struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, return NULL; } +struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) +{ + return NULL; +} + void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus, u8 slave_addr, u8 addr, @@ -1282,16 +1062,16 @@ void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus, { u8 out_buf[2]; u8 in_buf[2]; - struct iic_msg msgs[] = { + struct i2c_msg msgs[] = { { - .slave = slave_addr << 1, + .addr = slave_addr, .flags = 0, .len = 1, .buf = out_buf, }, { - .slave = slave_addr << 1, - .flags = IIC_M_RD, + .addr = slave_addr, + .flags = I2C_M_RD, .len = 1, .buf = in_buf, } @@ -1300,11 +1080,10 @@ void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus, out_buf[0] = addr; out_buf[1] = 0; - if (iicbus_transfer(i2c_bus->adapter, msgs, 2) == 0) { + if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) { *val = in_buf[0]; DRM_DEBUG("val = 0x%02x\n", *val); } else { - *val = 0; /* avoid gcc warning */ DRM_DEBUG("i2c 0x%02x 0x%02x read failed\n", addr, *val); } @@ -1316,8 +1095,8 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, u8 val) { uint8_t out_buf[2]; - struct iic_msg msg = { - .slave = slave_addr << 1, + struct i2c_msg msg = { + .addr = slave_addr, .flags = 0, .len = 2, .buf = out_buf, @@ -1326,7 +1105,7 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, out_buf[0] = addr; out_buf[1] = val; - if (iicbus_transfer(i2c_bus->adapter, &msg, 1) != 0) + if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1) DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n", addr, val); } diff --git a/sys/dev/drm/radeon/radeon_mode.h b/sys/dev/drm/radeon/radeon_mode.h index ad532fb57e..e91884f5ce 100644 --- a/sys/dev/drm/radeon/radeon_mode.h +++ b/sys/dev/drm/radeon/radeon_mode.h @@ -35,6 +35,8 @@ #include #include #include +#include +#include struct radeon_bo; struct radeon_device; @@ -187,13 +189,13 @@ struct radeon_pll { }; struct radeon_i2c_chan { - device_t adapter; - device_t iic_bus; + struct i2c_adapter adapter; struct drm_device *dev; + struct i2c_algo_bit_data bit; struct radeon_i2c_bus_rec rec; struct drm_dp_aux aux; + bool has_aux; struct lock mutex; - char name[48]; }; /* mostly for macs, but really any system without connector tables */ @@ -752,6 +754,8 @@ extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connec extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); +extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); + extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, struct radeon_atom_ss *ss, int id); -- 2.41.0