diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2014-06-06 04:09:55 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-06-11 02:11:42 -0400 |
commit | 8777c5c11764d8336d8270f96778158c34c92108 (patch) | |
tree | a31c7eb43a6662cb85893a5789539569a20c836d | |
parent | efa366fdf5658ca9ccad38e235818d121b1b8002 (diff) |
drm/nouveau/dp: probe dpcd to determine connectedness
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dp.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_encoder.h | 4 |
3 files changed, 26 insertions, 40 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7dac5e216799..1fa222e8f007 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -111,15 +111,15 @@ nouveau_connector_destroy(struct drm_connector *connector) | |||
111 | kfree(connector); | 111 | kfree(connector); |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct nouveau_i2c_port * | 114 | static struct nouveau_encoder * |
115 | nouveau_connector_ddc_detect(struct drm_connector *connector, | 115 | nouveau_connector_ddc_detect(struct drm_connector *connector) |
116 | struct nouveau_encoder **pnv_encoder) | ||
117 | { | 116 | { |
118 | struct drm_device *dev = connector->dev; | 117 | struct drm_device *dev = connector->dev; |
119 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 118 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
120 | struct nouveau_drm *drm = nouveau_drm(dev); | 119 | struct nouveau_drm *drm = nouveau_drm(dev); |
121 | struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | 120 | struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |
122 | struct nouveau_i2c_port *port = NULL; | 121 | struct nouveau_encoder *nv_encoder; |
122 | struct drm_mode_object *obj; | ||
123 | int i, panel = -ENODEV; | 123 | int i, panel = -ENODEV; |
124 | 124 | ||
125 | /* eDP panels need powering on by us (if the VBIOS doesn't default it | 125 | /* eDP panels need powering on by us (if the VBIOS doesn't default it |
@@ -134,13 +134,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | 137 | for (i = 0; nv_encoder = NULL, i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
138 | struct nouveau_encoder *nv_encoder; | 138 | int id = connector->encoder_ids[i]; |
139 | struct drm_mode_object *obj; | 139 | if (id == 0) |
140 | int id; | ||
141 | |||
142 | id = connector->encoder_ids[i]; | ||
143 | if (!id) | ||
144 | break; | 140 | break; |
145 | 141 | ||
146 | obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); | 142 | obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); |
@@ -148,22 +144,24 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
148 | continue; | 144 | continue; |
149 | nv_encoder = nouveau_encoder(obj_to_encoder(obj)); | 145 | nv_encoder = nouveau_encoder(obj_to_encoder(obj)); |
150 | 146 | ||
151 | port = nv_encoder->i2c; | 147 | if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { |
152 | if (port && nv_probe_i2c(port, 0x50)) { | 148 | int ret = nouveau_dp_detect(nv_encoder); |
153 | *pnv_encoder = nv_encoder; | 149 | if (ret == 0) |
154 | break; | 150 | break; |
151 | } else | ||
152 | if (nv_encoder->i2c) { | ||
153 | if (nv_probe_i2c(nv_encoder->i2c, 0x50)) | ||
154 | break; | ||
155 | } | 155 | } |
156 | |||
157 | port = NULL; | ||
158 | } | 156 | } |
159 | 157 | ||
160 | /* eDP panel not detected, restore panel power GPIO to previous | 158 | /* eDP panel not detected, restore panel power GPIO to previous |
161 | * state to avoid confusing the SOR for other output types. | 159 | * state to avoid confusing the SOR for other output types. |
162 | */ | 160 | */ |
163 | if (!port && panel == 0) | 161 | if (!nv_encoder && panel == 0) |
164 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); | 162 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); |
165 | 163 | ||
166 | return port; | 164 | return nv_encoder; |
167 | } | 165 | } |
168 | 166 | ||
169 | static struct nouveau_encoder * | 167 | static struct nouveau_encoder * |
@@ -262,8 +260,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
262 | if (ret < 0 && ret != -EACCES) | 260 | if (ret < 0 && ret != -EACCES) |
263 | return conn_status; | 261 | return conn_status; |
264 | 262 | ||
265 | i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); | 263 | nv_encoder = nouveau_connector_ddc_detect(connector); |
266 | if (i2c) { | 264 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { |
267 | nv_connector->edid = drm_get_edid(connector, &i2c->adapter); | 265 | nv_connector->edid = drm_get_edid(connector, &i2c->adapter); |
268 | drm_mode_connector_update_edid_property(connector, | 266 | drm_mode_connector_update_edid_property(connector, |
269 | nv_connector->edid); | 267 | nv_connector->edid); |
@@ -273,14 +271,6 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
273 | goto detect_analog; | 271 | goto detect_analog; |
274 | } | 272 | } |
275 | 273 | ||
276 | if (nv_encoder->dcb->type == DCB_OUTPUT_DP && | ||
277 | !nouveau_dp_detect(to_drm_encoder(nv_encoder))) { | ||
278 | NV_ERROR(drm, "Detected %s, but failed init\n", | ||
279 | connector->name); | ||
280 | conn_status = connector_status_disconnected; | ||
281 | goto out; | ||
282 | } | ||
283 | |||
284 | /* Override encoder type for DVI-I based on whether EDID | 274 | /* Override encoder type for DVI-I based on whether EDID |
285 | * says the display is digital or analog, both use the | 275 | * says the display is digital or analog, both use the |
286 | * same i2c channel so the value returned from ddc_detect | 276 | * same i2c channel so the value returned from ddc_detect |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 36fd22500569..5675ffc175ae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -55,11 +55,10 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, | |||
55 | 55 | ||
56 | } | 56 | } |
57 | 57 | ||
58 | bool | 58 | int |
59 | nouveau_dp_detect(struct drm_encoder *encoder) | 59 | nouveau_dp_detect(struct nouveau_encoder *nv_encoder) |
60 | { | 60 | { |
61 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 61 | struct drm_device *dev = nv_encoder->base.base.dev; |
62 | struct drm_device *dev = encoder->dev; | ||
63 | struct nouveau_drm *drm = nouveau_drm(dev); | 62 | struct nouveau_drm *drm = nouveau_drm(dev); |
64 | struct nouveau_i2c_port *auxch; | 63 | struct nouveau_i2c_port *auxch; |
65 | u8 *dpcd = nv_encoder->dp.dpcd; | 64 | u8 *dpcd = nv_encoder->dp.dpcd; |
@@ -67,11 +66,11 @@ nouveau_dp_detect(struct drm_encoder *encoder) | |||
67 | 66 | ||
68 | auxch = nv_encoder->i2c; | 67 | auxch = nv_encoder->i2c; |
69 | if (!auxch) | 68 | if (!auxch) |
70 | return false; | 69 | return -ENODEV; |
71 | 70 | ||
72 | ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8); | 71 | ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8); |
73 | if (ret) | 72 | if (ret) |
74 | return false; | 73 | return ret; |
75 | 74 | ||
76 | nv_encoder->dp.link_bw = 27000 * dpcd[1]; | 75 | nv_encoder->dp.link_bw = 27000 * dpcd[1]; |
77 | nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; | 76 | nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; |
@@ -91,6 +90,5 @@ nouveau_dp_detect(struct drm_encoder *encoder) | |||
91 | nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); | 90 | nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); |
92 | 91 | ||
93 | nouveau_dp_probe_oui(dev, auxch, dpcd); | 92 | nouveau_dp_probe_oui(dev, auxch, dpcd); |
94 | 93 | return 0; | |
95 | return true; | ||
96 | } | 94 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index fcf89c8c67b7..5f0e37fc2849 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
@@ -85,9 +85,7 @@ get_slave_funcs(struct drm_encoder *enc) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /* nouveau_dp.c */ | 87 | /* nouveau_dp.c */ |
88 | bool nouveau_dp_detect(struct drm_encoder *); | 88 | int nouveau_dp_detect(struct nouveau_encoder *); |
89 | void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, | ||
90 | struct nouveau_object *); | ||
91 | 89 | ||
92 | struct nouveau_connector * | 90 | struct nouveau_connector * |
93 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); | 91 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); |