This is a follow on to:
26b5bc986423cf3887e09188cb662ed651c5374d
(drm/radeon/kms: add support for router objects)

That patch added support for systems that use a mux to control
the ddc line routing between the connectors.  This patch adds
support for systems that use a mux to control the encoder
clock and data path routing to the connectors.

Should fix:
https://bugs.freedesktop.org/show_bug.cgi?id=31339

Signed-off-by: Alex Deucher <alexdeuc...@gmail.com>
---
 drivers/gpu/drm/radeon/radeon_atombios.c   |   26 +++++++++++++-----
 drivers/gpu/drm/radeon/radeon_connectors.c |    4 +-
 drivers/gpu/drm/radeon/radeon_display.c    |   18 +++++++-----
 drivers/gpu/drm/radeon/radeon_encoders.c   |    8 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   41 ++++++++++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h       |   17 ++++++++---
 6 files changed, 85 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c 
b/drivers/gpu/drm/radeon/radeon_atombios.c
index ca33baf..07e3afb 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -526,7 +526,8 @@ bool 
radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
        if (crev < 2)
                return false;
 
-       router.valid = false;
+       router.ddc_valid = false;
+       router.cd_valid = false;
 
        obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
        path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
@@ -647,7 +648,8 @@ bool 
radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                                 usDeviceTag));
 
                                } else if (grph_obj_type == 
GRAPH_OBJECT_TYPE_ROUTER) {
-                                       router.valid = false;
+                                       router.ddc_valid = false;
+                                       router.cd_valid = false;
                                        for (k = 0; k < 
router_obj->ucNumberOfObjects; k++) {
                                                u16 router_obj_id = 
le16_to_cpu(router_obj->asObjects[j].usObjectID);
                                                if 
(le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
@@ -657,6 +659,7 @@ bool 
radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                        ATOM_I2C_RECORD 
*i2c_record;
                                                        
ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
                                                        
ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
+                                                       
ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path;
                                                        
ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
                                                                
(ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
                                                                (ctx->bios + 
data_offset +
@@ -690,10 +693,18 @@ bool 
radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                                case 
ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
                                                                        
ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
                                                                                
record;
-                                                                       
router.valid = true;
-                                                                       
router.mux_type = ddc_path->ucMuxType;
-                                                                       
router.mux_control_pin = ddc_path->ucMuxControlPin;
-                                                                       
router.mux_state = ddc_path->ucMuxState[enum_id];
+                                                                       
router.ddc_valid = true;
+                                                                       
router.ddc_mux_type = ddc_path->ucMuxType;
+                                                                       
router.ddc_mux_control_pin = ddc_path->ucMuxControlPin;
+                                                                       
router.ddc_mux_state = ddc_path->ucMuxState[enum_id];
+                                                                       break;
+                                                               case 
ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE:
+                                                                       cd_path 
= (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *)
+                                                                               
record;
+                                                                       
router.cd_valid = true;
+                                                                       
router.cd_mux_type = cd_path->ucMuxType;
+                                                                       
router.cd_mux_control_pin = cd_path->ucMuxControlPin;
+                                                                       
router.cd_mux_state = cd_path->ucMuxState[enum_id];
                                                                        break;
                                                                }
                                                                record = 
(ATOM_COMMON_RECORD_HEADER *)
@@ -860,7 +871,8 @@ bool 
radeon_get_atom_connector_info_from_supported_devices_table(struct
        size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
        struct radeon_router router;
 
-       router.valid = false;
+       router.ddc_valid = false;
+       router.cd_valid = false;
 
        bios_connectors = kzalloc(bc_size, GFP_KERNEL);
        if (!bios_connectors)
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c 
b/drivers/gpu/drm/radeon/radeon_connectors.c
index 4dac4b0..60f283c 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1116,7 +1116,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                                radeon_connector->shared_ddc = true;
                                shared_ddc = true;
                        }
-                       if (radeon_connector->router_bus && router->valid &&
+                       if (radeon_connector->router_bus && router->ddc_valid &&
                            (radeon_connector->router.router_id == 
router->router_id)) {
                                radeon_connector->shared_ddc = false;
                                shared_ddc = false;
@@ -1136,7 +1136,7 @@ radeon_add_atom_connector(struct drm_device *dev,
        radeon_connector->connector_object_id = connector_object_id;
        radeon_connector->hpd = *hpd;
        radeon_connector->router = *router;
-       if (router->valid) {
+       if (router->ddc_valid || router->cd_valid) {
                radeon_connector->router_bus = radeon_i2c_lookup(rdev, 
&router->i2c_info);
                if (!radeon_connector->router_bus)
                        goto failed;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c 
b/drivers/gpu/drm/radeon/radeon_display.c
index 1b2de67..2697801 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -317,10 +317,14 @@ static void radeon_print_display_setup(struct drm_device 
*dev)
                                 radeon_connector->ddc_bus->rec.en_data_reg,
                                 radeon_connector->ddc_bus->rec.y_clk_reg,
                                 radeon_connector->ddc_bus->rec.y_data_reg);
-                       if (radeon_connector->router_bus)
+                       if (radeon_connector->router.ddc_valid)
                                DRM_INFO("  DDC Router 0x%x/0x%x\n",
-                                        
radeon_connector->router.mux_control_pin,
-                                        radeon_connector->router.mux_state);
+                                        
radeon_connector->router.ddc_mux_control_pin,
+                                        
radeon_connector->router.ddc_mux_state);
+                       if (radeon_connector->router.cd_valid)
+                               DRM_INFO("  Clock/Data Router 0x%x/0x%x\n",
+                                        
radeon_connector->router.cd_mux_control_pin,
+                                        radeon_connector->router.cd_mux_state);
                } else {
                        if (connector->connector_type == DRM_MODE_CONNECTOR_VGA 
||
                            connector->connector_type == 
DRM_MODE_CONNECTOR_DVII ||
@@ -400,8 +404,8 @@ int radeon_ddc_get_modes(struct radeon_connector 
*radeon_connector)
        int ret = 0;
 
        /* on hw with routers, select right port */
-       if (radeon_connector->router.valid)
-               radeon_router_select_port(radeon_connector);
+       if (radeon_connector->router.ddc_valid)
+               radeon_router_select_ddc_port(radeon_connector);
 
        if ((radeon_connector->base.connector_type == 
DRM_MODE_CONNECTOR_DisplayPort) ||
            (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
@@ -434,8 +438,8 @@ static int radeon_ddc_dump(struct drm_connector *connector)
        int ret = 0;
 
        /* on hw with routers, select right port */
-       if (radeon_connector->router.valid)
-               radeon_router_select_port(radeon_connector);
+       if (radeon_connector->router.ddc_valid)
+               radeon_router_select_ddc_port(radeon_connector);
 
        if (!radeon_connector->ddc_bus)
                return -1;
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c 
b/drivers/gpu/drm/radeon/radeon_encoders.c
index b8c6847..8feb6dd 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -1702,6 +1702,7 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, 
struct drm_connector *connec
 static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_connector *connector = 
radeon_get_connector_for_encoder(encoder);
 
        if (radeon_encoder->active_device &
            (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
@@ -1713,6 +1714,13 @@ static void radeon_atom_encoder_prepare(struct 
drm_encoder *encoder)
        radeon_atom_output_lock(encoder, true);
        radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
 
+       /* select the clock/data port if it uses a router */
+       if (connector) {
+               struct radeon_connector *radeon_connector = 
to_radeon_connector(connector);
+               if (radeon_connector->router.cd_valid)
+                       radeon_router_select_cd_port(radeon_connector);
+       }
+
        /* this is needed for the pll/ss setup to work correctly in some cases 
*/
        atombios_set_encoder_crtc_source(encoder);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c 
b/drivers/gpu/drm/radeon/radeon_i2c.c
index 6a13ee3..24b8a8b 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -53,8 +53,8 @@ bool radeon_ddc_probe(struct radeon_connector 
*radeon_connector)
        };
 
        /* on hw with routers, select right port */
-       if (radeon_connector->router.valid)
-               radeon_router_select_port(radeon_connector);
+       if (radeon_connector->router.ddc_valid)
+               radeon_router_select_ddc_port(radeon_connector);
 
        ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
        if (ret == 2)
@@ -1084,26 +1084,51 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan 
*i2c_bus,
                          addr, val);
 }
 
-/* router switching */
-void radeon_router_select_port(struct radeon_connector *radeon_connector)
+/* ddc router switching */
+void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector)
 {
        u8 val;
 
-       if (!radeon_connector->router.valid)
+       if (!radeon_connector->router.ddc_valid)
                return;
 
        radeon_i2c_get_byte(radeon_connector->router_bus,
                            radeon_connector->router.i2c_addr,
                            0x3, &val);
-       val &= radeon_connector->router.mux_control_pin;
+       val &= radeon_connector->router.ddc_mux_control_pin;
        radeon_i2c_put_byte(radeon_connector->router_bus,
                            radeon_connector->router.i2c_addr,
                            0x3, val);
        radeon_i2c_get_byte(radeon_connector->router_bus,
                            radeon_connector->router.i2c_addr,
                            0x1, &val);
-       val &= radeon_connector->router.mux_control_pin;
-       val |= radeon_connector->router.mux_state;
+       val &= radeon_connector->router.ddc_mux_control_pin;
+       val |= radeon_connector->router.ddc_mux_state;
+       radeon_i2c_put_byte(radeon_connector->router_bus,
+                           radeon_connector->router.i2c_addr,
+                           0x1, val);
+}
+
+/* clock/data router switching */
+void radeon_router_select_cd_port(struct radeon_connector *radeon_connector)
+{
+       u8 val;
+
+       if (!radeon_connector->router.cd_valid)
+               return;
+
+       radeon_i2c_get_byte(radeon_connector->router_bus,
+                           radeon_connector->router.i2c_addr,
+                           0x3, &val);
+       val &= radeon_connector->router.cd_mux_control_pin;
+       radeon_i2c_put_byte(radeon_connector->router_bus,
+                           radeon_connector->router.i2c_addr,
+                           0x3, val);
+       radeon_i2c_get_byte(radeon_connector->router_bus,
+                           radeon_connector->router.i2c_addr,
+                           0x1, &val);
+       val &= radeon_connector->router.cd_mux_control_pin;
+       val |= radeon_connector->router.cd_mux_state;
        radeon_i2c_put_byte(radeon_connector->router_bus,
                            radeon_connector->router.i2c_addr,
                            0x1, val);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h 
b/drivers/gpu/drm/radeon/radeon_mode.h
index feaa5e7..51e2126 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -403,13 +403,19 @@ struct radeon_hpd {
 };
 
 struct radeon_router {
-       bool valid;
        u32 router_id;
        struct radeon_i2c_bus_rec i2c_info;
        u8 i2c_addr;
-       u8 mux_type;
-       u8 mux_control_pin;
-       u8 mux_state;
+       /* i2c mux */
+       bool ddc_valid;
+       u8 ddc_mux_type;
+       u8 ddc_mux_control_pin;
+       u8 ddc_mux_state;
+       /* clock/data mux */
+       bool cd_valid;
+       u8 cd_mux_type;
+       u8 cd_mux_control_pin;
+       u8 cd_mux_state;
 };
 
 struct radeon_connector {
@@ -490,7 +496,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
                                u8 slave_addr,
                                u8 addr,
                                u8 val);
-extern void radeon_router_select_port(struct radeon_connector 
*radeon_connector);
+extern void radeon_router_select_ddc_port(struct radeon_connector 
*radeon_connector);
+extern void radeon_router_select_cd_port(struct radeon_connector 
*radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
-- 
1.7.1.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to