Announcement

Collapse
No announcement yet.

890GX/HD4290 dual display question

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #91
    Originally posted by droidhacker View Post
    There's no question that something is wired wrong

    Wow. You definitely have an answer for everything.
    I'll try that out tonight.

    pad mode... I guess then that the overall state of the connector can be put into a weird mode where it is a hybrid of DVI and DP?
    The pads are either in i2c or aux mode. There's no weird in-between state, it's either one or the other. This only relates to the pins used for aux and i2c (used to get the edid and to train the link for DP), the encoder state is irrelevant for monitor detection.

    Originally posted by droidhacker View Post
    Now... the bios technically should post to the DP monitor, which means that there is some setup happening in vbios stage that, in the case where it is wired wrong, sets those pads in AUX mode. When they're set that way, presumably, they are STUCK that way until it is explicitly changed. So is it a possibility that when NOT explicitly setting the pads into DDC mode, the reason it typically still works is because the vbios already did it and/or it simply defaults that way when stuff isn't wired wrong?
    You need to switch the pad mode when you want to use aux vs i2c. The state of the register is left in whatever state was last used. If the vbios tried to probe a DP monitor they will be in AUX mode, if the last thing it tried was non-DP it will be in i2c mode. The vbios doesn't try i2c since the sink type always returns DP on your board. I think that is the fundamental problem with your board: the pins are wired such that there always appears to be a DP monitor attached.

    Originally posted by droidhacker View Post
    I just found something that does it... program called ddccontrol. On my computer here at work, which is a radeon with DVI and HDMI ports driving a pair of DVI monitors, it finds EDIDs for both monitors. Checked mine remotely, still only finds the one. So I'm crossing my fingers for it being in hybrid-confused mode.

    Guess I'll see if your patch does the job.. otherwise I might just modify the for loop in radeon_add_common_modes and take out the first two if's. That should at least get me native resolution kms, which will at least make it functional for me.
    In your case, you'll still have to hack radeon_dp_detect() since the sink type always returns DP on your board which is wrong. it should only return DP when there is actually a DP monitor attached. In addtion to patch I linked to, you'll need something like:

    --- a/drivers/gpu/drm/radeon/radeon_connectors.c
    +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
    @@ -998,6 +998,10 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
    }
    }

    + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
    + if (radeon_ddc_probe(radeon_connector))
    + ret = connector_status_connected;
    +
    return ret;
    }


    Originally posted by droidhacker View Post
    ** In the event that your patch doesn't work on account of this thing just being too badly wired, it would be neat to be able to get some manual control over some of these settings without having to resort to one-off kernel hacks. I.e. radeon.forceDPDVI=1 and radeon.maxCommonMode=x,y would make some useful kernel arguments.
    Options like this get tricky when you have multiple connectors. If you have more than 1 DP port, which one does forceDPDVI apply to? As for the maxCommonMode that gets tricky as well since the mode timings can vary wildly between monitors. The linux framebuffer layer really need to learn the concept of multiple heads.

    Something like the following should allow you to force the connector on in non-DP mode using xrandr:

    --- a/drivers/gpu/drm/radeon/radeon_connectors.c
    +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
    @@ -990,12 +990,14 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
    if (radeon_dp_getdpcd(radeon_connector)) {
    radeon_dig_connector->dp_sink_type = sink_type;
    ret = connector_status_connected;
    - }
    + } else
    + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
    } else {
    if (radeon_ddc_probe(radeon_connector)) {
    radeon_dig_connector->dp_sink_type = sink_type;
    ret = connector_status_connected;
    - }
    + } else
    + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
    }

    return ret;

    Comment


    • #92
      Originally posted by agd5f View Post
      The pads are either in i2c or aux mode. There's no weird in-between state, it's either one or the other. This only relates to the pins used for aux and i2c (used to get the edid and to train the link for DP), the encoder state is irrelevant for monitor detection.
      That is what I meant -- having the encoder in DVI at the same time as the AUX pins in AUX mode is the weird state since that configuration is incompatible with everything.

      You need to switch the pad mode when you want to use aux vs i2c. The state of the register is left in whatever state was last used. If the vbios tried to probe a DP monitor they will be in AUX mode, if the last thing it tried was non-DP it will be in i2c mode. The vbios doesn't try i2c since the sink type always returns DP on your board. I think that is the fundamental problem with your board: the pins are wired such that there always appears to be a DP monitor attached.
      That is what I was guessing at. Thank you for confirming. The monitor was probed in DP mode when the power was turned on so that the bios would be able to post to it. That set the pads into AUX mode and it stayed there.

      When you say that it usually works anyway, that's got to be because the monitor was probed in DVI mode during power on, so they stay there.... generally keeps working because that's what it was set to.

      In your case, you'll still have to hack radeon_dp_detect() since the sink type always returns DP on your board which is wrong. it should only return DP when there is actually a DP monitor attached. In addtion to patch I linked to, you'll need something like:

      --- a/drivers/gpu/drm/radeon/radeon_connectors.c
      +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
      @@ -998,6 +998,10 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
      }
      }

      + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
      + if (radeon_ddc_probe(radeon_connector))
      + ret = connector_status_connected;
      +
      return ret;
      }
      Got that already...

      Options like this get tricky when you have multiple connectors. If you have more than 1 DP port, which one does forceDPDVI apply to?
      ... any that aren't working, i.e. radeon_dp_getdpcd()==false. It obviously makes no sense at all to force a DP monitor that DOES work into a mode where it CAN'T work, and if radeon_dp_getdpcd() fails, there's no way that DP is going to work anyway.

      As for the maxCommonMode that gets tricky as well since the mode timings can vary wildly between monitors.
      As it is, the common modes are all just being thrown in with generic 60 Hz (from what I can see)... which is better than nothing since they *might* work, and might supersedes *won't* (as in "won't be available"). If it is available as an option, you get to try, if it doesn't work, nothing is lost.

      The linux framebuffer layer really need to learn the concept of multiple heads.
      That would definitely be nice.

      Something like the following should allow you to force the connector on in non-DP mode using xrandr:

      --- a/drivers/gpu/drm/radeon/radeon_connectors.c
      +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
      @@ -990,12 +990,14 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
      if (radeon_dp_getdpcd(radeon_connector)) {
      radeon_dig_connector->dp_sink_type = sink_type;
      ret = connector_status_connected;
      - }
      + } else
      + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
      } else {
      if (radeon_ddc_probe(radeon_connector)) {
      radeon_dig_connector->dp_sink_type = sink_type;
      ret = connector_status_connected;
      - }
      + } else
      + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
      }

      return ret;
      It might be better like this:

      --- a/drivers/gpu/drm/radeon/radeon_connectors.c
      +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
      @@ -990,12 +990,14 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
      if (radeon_dp_getdpcd(radeon_connector)) {
      radeon_dig_connector->dp_sink_type = sink_type;
      ret = connector_status_connected;
      - }
      + } else
      + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
      } else {
      if (radeon_ddc_probe(radeon_connector)) {
      - radeon_dig_connector->dp_sink_type = sink_type;
      ret = connector_status_connected;
      }

      + radeon_dig_connector->dp_sink_type = sink_type;
      }

      return ret;

      ** since in the second case, we already know that sink_type is NOT set to DP, so just let it set to whatever it is, but no activating it.

      Comment


      • #93
        You also don't need the radeon_i2c_do_lock() anymore. that's taken care of the i2c core now (assuming you have a newish kernel, 2.6.33 or 34 I think).
        I can't find where radeon_i2c_do_lock() is being called from when doing a ddc_probe....

        Comment


        • #94
          Originally posted by droidhacker View Post
          I can't find where radeon_i2c_do_lock() is being called from when doing a ddc_probe....
          It's part of the i2c core now. The driver registers the callbacks when it sets up the bus. See the pre_xfer()/post_xfer() functions in radeon_i2c.c

          Comment


          • #95
            Originally posted by droidhacker View Post
            ... any that aren't working, i.e. radeon_dp_getdpcd()==false. It obviously makes no sense at all to force a DP monitor that DOES work into a mode where it CAN'T work, and if radeon_dp_getdpcd() fails, there's no way that DP is going to work anyway.
            Right. No need for an option. That should be the default behavior.

            Originally posted by droidhacker View Post
            As it is, the common modes are all just being thrown in with generic 60 Hz (from what I can see)... which is better than nothing since they *might* work, and might supersedes *won't* (as in "won't be available"). If it is available as an option, you get to try, if it doesn't work, nothing is lost.
            You can already do that with the kernel fb video= stuff.

            Originally posted by droidhacker View Post
            It might be better like this:

            --- a/drivers/gpu/drm/radeon/radeon_connectors.c
            +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
            @@ -990,12 +990,14 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
            if (radeon_dp_getdpcd(radeon_connector)) {
            radeon_dig_connector->dp_sink_type = sink_type;
            ret = connector_status_connected;
            - }
            + } else
            + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
            } else {
            if (radeon_ddc_probe(radeon_connector)) {
            - radeon_dig_connector->dp_sink_type = sink_type;
            ret = connector_status_connected;
            }

            + radeon_dig_connector->dp_sink_type = sink_type;
            }

            return ret;

            ** since in the second case, we already know that sink_type is NOT set to DP, so just let it set to whatever it is, but no activating it.
            Sure. Doesn't really matter though. The sink type is only DVI or DP. eDP (embedded DP) should be special cased however since you won't ever be attaching a non-DP monitor to an eDP port.

            Comment


            • #96
              Originally posted by agd5f View Post
              Right. No need for an option. That should be the default behavior.
              You mean as opposed to what it is doing now, which is:

              if (sink_type==DP && getdpcd()){
              connected;
              else if (sink_type!=DP && ddc_probe()) {
              connected;
              else {
              screw_you();
              }

              Should be:

              if (sink_type==DP && getdpcd()){
              connected;
              else if (sink_type!=DP && ddc_probe()) {
              connected;
              else {
              sink_type=DVI;
              leave_not_connected_and_hope_it'll_turn_on_later() ;
              }

              Whereas forceing it would be to do:

              if (sink_type==DP && getdpcd()){
              connected;
              else if (sink_type!=DP && ddc_probe()) {
              connected;
              else {
              sink_type=DVI;
              if (force){
              connected;
              }
              }

              You can already do that with the kernel fb video= stuff.
              Ok, I guess I'm not clear about how that works, something like
              video=radeonfb:1600x1200-32@60
              ??

              Sure. Doesn't really matter though. The sink type is only DVI or DP. eDP (embedded DP) should be special cased however since you won't ever be attaching a non-DP monitor to an eDP port.
              Right... because VGA is impossible since there is no analog output from any pins on the chip related to the DP, and HDMI==DVI.


              I didn't get anywhere last night with your patch. The patch runs, but still nothing. I think at this point I'm just going to concentrate on getting the initial mode set to native resolution. I think I need more equipment to properly diagnose this thing, like an oscilloscope, and though this is still a fascinating experiment, I can't really justify an expense like that for the use I'll be putting it to.

              Comment


              • #97
                radeonfb sounds like the legacy framebuffer (ie in comparison to radeondrmfb or whatever it was)

                Comment


                • #98
                  Originally posted by nanonyme View Post
                  radeonfb sounds like the legacy framebuffer (ie in comparison to radeondrmfb or whatever it was)
                  That sounds right.

                  Comment


                  • #99
                    Originally posted by droidhacker View Post
                    You mean as opposed to what it is doing now, which is:
                    To be fair, this is really only an issue on broken boards like yours.

                    Originally posted by droidhacker View Post
                    Ok, I guess I'm not clear about how that works, something like
                    video=radeonfb:1600x1200-32@60
                    ??
                    See the bottom of this page:
                    http://nouveau.freedesktop.org/wiki/KernelModeSetting
                    Something like:
                    video=DisplayPort-1:1600x1200@60
                    See /sys/class/drm for the connector names for your board.

                    Originally posted by droidhacker View Post
                    Right... because VGA is impossible since there is no analog output from any pins on the chip related to the DP, and HDMI==DVI.
                    Yes.

                    Originally posted by droidhacker View Post
                    I didn't get anywhere last night with your patch. The patch runs, but still nothing. I think at this point I'm just going to concentrate on getting the initial mode set to native resolution. I think I need more equipment to properly diagnose this thing, like an oscilloscope, and though this is still a fascinating experiment, I can't really justify an expense like that for the use I'll be putting it to.
                    Right, I suspected you wouldn't. I don't think those pins are wired up properly for either i2c or aux. Neither the drivers, nor the vbios has been able to get an EDID via aux or i2c as far as I can tell. If you want to force the initial mode to whatever the panel's native mode is, you have to manually add the native modeline in radeon_dp_get_modes().

                    Comment


                    • Originally posted by agd5f View Post
                      To be fair, this is really only an issue on broken boards like yours.
                      I feel special

                      See the bottom of this page:
                      http://nouveau.freedesktop.org/wiki/KernelModeSetting
                      Something like:
                      video=DisplayPort-1:1600x1200@60
                      See /sys/class/drm for the connector names for your board.
                      That would be the goodness
                      You think that the "e" option (output forced to ON) would take care of the "connected" state?

                      If it would, could be fixed to, or an additional option added to, then that, along with setting a sensible default sink_type would bring this broken board into a manual-but-usable state... i.e.
                      video=DisplayPort-0:1920x1200@60e

                      Right, I suspected you wouldn't. I don't think those pins are wired up properly for either i2c or aux. Neither the drivers, nor the vbios has been able to get an EDID via aux or i2c as far as I can tell. If you want to force the initial mode to whatever the panel's native mode is, you have to manually add the native modeline in radeon_dp_get_modes().
                      Is it *possible* that DP does NOT require the AUX channel to operate? One line in the 780 document you linked to somewhat implies that it may not be required... in section 1.2.12 on page 1-8, it says "Supports the Auxilary Channel (AUX CH)", which is presented as a FEATURE. If it was a hard requirement, why would it be presented as a feature?

                      Comment


                      • Or maybe 'D'? I'd at least think DisplayPort was a digital output.

                        Comment


                        • Originally posted by droidhacker View Post
                          I feel special


                          That would be the goodness
                          You think that the "e" option (output forced to ON) would take care of the "connected" state?

                          If it would, could be fixed to, or an additional option added to, then that, along with setting a sensible default sink_type would bring this broken board into a manual-but-usable state... i.e.
                          video=DisplayPort-0:1920x1200@60e
                          Yeah, I think that should do it.

                          Originally posted by droidhacker View Post
                          Is it *possible* that DP does NOT require the AUX channel to operate? One line in the 780 document you linked to somewhat implies that it may not be required... in section 1.2.12 on page 1-8, it says "Supports the Auxilary Channel (AUX CH)", which is presented as a FEATURE. If it was a hard requirement, why would it be presented as a feature?
                          AUX is required for DP since you need AUX to communicate with the monitor (get the EDID, DPCD, train the link, etc.).

                          Comment


                          • Originally posted by agd5f View Post
                            Yeah, I think that should do it.
                            About this patch:
                            http://lists.freedesktop.org/archive...st/003139.html

                            Wouldn't it be better to do this:

                            Code:
                            diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
                            index 20c353c..31a09cd 100644
                            --- a/drivers/gpu/drm/radeon/radeon_connectors.c
                            +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
                            @@ -977,24 +977,25 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
                             	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                             	enum drm_connector_status ret = connector_status_disconnected;
                             	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
                            -	u8 sink_type;
                             
                             	if (radeon_connector->edid) {
                             		kfree(radeon_connector->edid);
                             		radeon_connector->edid = NULL;
                             	}
                             
                            -	sink_type = radeon_dp_getsinktype(radeon_connector);
                            -	if ((sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
                            -	    (sink_type == CONNECTOR_OBJECT_ID_eDP)) {
                            -		if (radeon_dp_getdpcd(radeon_connector)) {
                            -			radeon_dig_connector->dp_sink_type = sink_type;
                            +	if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                            +		/* eDP is always DP */
                            +		radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
                            +		if (radeon_dp_getdpcd(radeon_connector))
                             			ret = connector_status_connected;
                            -		}
                             	} else {
                            -		if (radeon_ddc_probe(radeon_connector)) {
                            -			radeon_dig_connector->dp_sink_type = sink_type;
                            -			ret = connector_status_connected;
                            +		radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
                            +		if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
                            +			if (radeon_dp_getdpcd(radeon_connector))
                            +				ret = connector_status_connected;
                            +			else {
                            +				radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
                            +				if (radeon_ddc_probe(radeon_connector))
                            +					ret = connector_status_connected;
                            +			}
                            +		} else {
                            +			if (radeon_ddc_probe(radeon_connector))
                            +				ret = connector_status_connected;
                             		}
                             	}
                            It wouldn't break anything since we already know that the DP CAN'T work, but would leave it in a state where it would work with certain boards that are wired wrong by at least setting a sensible default state.

                            I know it is a workaround for one special case defect, but I wonder how many people are suffering with this (or similar) defects and are resigned to it being broken?

                            I also note that there are quite a number of workarounds elsewhere that deal with specific board defects, i.e. in radeon_atombios.c function radeon_atom_apply_quirks(), so it wouldn't even be unprecedented to add a workaround for a specific defect.

                            In this case though, the workaround would compensate for a class of defects that *could* be present on ANY DP board where the OEM didn't properly plan for supporting DP++.

                            Comment


                            • I'm fairly certain that I found some nastys in drivers/gpu/drm/drm_modes.c

                              In the function drm_cvt_mode(), when parameter "reduced" is set to TRUE, the hsync_start and hsync_end values calculated are... wrong, and the vsync_start and vsync_end values aren't calculated at all.

                              This is when compared to the values calculated by the "cvt" command, i.e.
                              cvt -r 1920 1200
                              # 1920x1200 59.95 Hz (CVT 2.30MA-R) hsync: 74.04 kHz; pclk: 154.00 MHz
                              Modeline "1920x1200R" 154.00 1920 1968 2000 2080 1200 1203 1209 1235 +hsync -vsync

                              The values generated by drm_cvt_mode(dev,1920,1200,60,true,false,false) are:
                              154.00 1920 32 32 2080 1200 0 0 1235 +hsync -vsync

                              Comment


                              • For anyone interested, for now (might look at the cvt algo later), I've jigged in my mode like this;

                                Code:
                                static int radeon_dp_get_modes(struct drm_connector *connector)
                                {
                                	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                                	int ret;
                                	struct drm_display_mode *mode = NULL;
                                	struct drm_device *dev = radeon_connector->base.dev;
                                
                                	ret = radeon_ddc_get_modes(radeon_connector);
                                	//mode = drm_cvt_mode(dev, 1920, 1200, 60, true, false, false);
                                	if (mode = drm_mode_create(dev)){
                                		mode->hdisplay=1920;
                                		mode->vdisplay=1200;
                                		mode->vtotal=1235;
                                		mode->htotal=2080;
                                		mode->hsync_end=2000;
                                		mode->hsync_start=1968;
                                		mode->vsync_start=1203;
                                		mode->vsync_end=1209;
                                		mode->clock=154000;
                                		drm_mode_set_name(mode);
                                		mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC);
                                	}
                                
                                	drm_mode_probed_add(connector, mode);
                                	return ret;
                                }

                                Comment

                                Working...
                                X