Rev 1233 | Rev 1268 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1233 | Rev 1246 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright 2007-8 Advanced Micro Devices, Inc. |
2 | * Copyright 2007-8 Advanced Micro Devices, Inc. |
3 | * Copyright 2008 Red Hat Inc. |
3 | * Copyright 2008 Red Hat Inc. |
4 | * |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the "Software"), |
6 | * copy of this software and associated documentation files (the "Software"), |
7 | * to deal in the Software without restriction, including without limitation |
7 | * to deal in the Software without restriction, including without limitation |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * and/or sell copies of the Software, and to permit persons to whom the |
10 | * Software is furnished to do so, subject to the following conditions: |
10 | * Software is furnished to do so, subject to the following conditions: |
11 | * |
11 | * |
12 | * The above copyright notice and this permission notice shall be included in |
12 | * The above copyright notice and this permission notice shall be included in |
13 | * all copies or substantial portions of the Software. |
13 | * all copies or substantial portions of the Software. |
14 | * |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
21 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * |
22 | * |
23 | * Authors: Dave Airlie |
23 | * Authors: Dave Airlie |
24 | * Alex Deucher |
24 | * Alex Deucher |
25 | */ |
25 | */ |
26 | #include "drmP.h" |
26 | #include "drmP.h" |
27 | #include "drm_edid.h" |
27 | #include "drm_edid.h" |
28 | #include "drm_crtc_helper.h" |
28 | #include "drm_crtc_helper.h" |
29 | #include "drm_fb_helper.h" |
29 | #include "drm_fb_helper.h" |
30 | #include "radeon_drm.h" |
30 | #include "radeon_drm.h" |
31 | #include "radeon.h" |
31 | #include "radeon.h" |
32 | #include "atom.h" |
32 | #include "atom.h" |
33 | 33 | ||
34 | extern void |
34 | extern void |
35 | radeon_combios_connected_scratch_regs(struct drm_connector *connector, |
35 | radeon_combios_connected_scratch_regs(struct drm_connector *connector, |
36 | struct drm_encoder *encoder, |
36 | struct drm_encoder *encoder, |
37 | bool connected); |
37 | bool connected); |
38 | extern void |
38 | extern void |
39 | radeon_atombios_connected_scratch_regs(struct drm_connector *connector, |
39 | radeon_atombios_connected_scratch_regs(struct drm_connector *connector, |
40 | struct drm_encoder *encoder, |
40 | struct drm_encoder *encoder, |
41 | bool connected); |
41 | bool connected); |
42 | 42 | ||
43 | static void radeon_property_change_mode(struct drm_encoder *encoder) |
43 | static void radeon_property_change_mode(struct drm_encoder *encoder) |
44 | { |
44 | { |
45 | struct drm_crtc *crtc = encoder->crtc; |
45 | struct drm_crtc *crtc = encoder->crtc; |
46 | 46 | ||
47 | if (crtc && crtc->enabled) { |
47 | if (crtc && crtc->enabled) { |
48 | drm_crtc_helper_set_mode(crtc, &crtc->mode, |
48 | drm_crtc_helper_set_mode(crtc, &crtc->mode, |
49 | crtc->x, crtc->y, crtc->fb); |
49 | crtc->x, crtc->y, crtc->fb); |
50 | } |
50 | } |
51 | } |
51 | } |
52 | static void |
52 | static void |
53 | radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status) |
53 | radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status) |
54 | { |
54 | { |
55 | struct drm_device *dev = connector->dev; |
55 | struct drm_device *dev = connector->dev; |
56 | struct radeon_device *rdev = dev->dev_private; |
56 | struct radeon_device *rdev = dev->dev_private; |
57 | struct drm_encoder *best_encoder = NULL; |
57 | struct drm_encoder *best_encoder = NULL; |
58 | struct drm_encoder *encoder = NULL; |
58 | struct drm_encoder *encoder = NULL; |
59 | struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; |
59 | struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; |
60 | struct drm_mode_object *obj; |
60 | struct drm_mode_object *obj; |
61 | bool connected; |
61 | bool connected; |
62 | int i; |
62 | int i; |
63 | 63 | ||
64 | best_encoder = connector_funcs->best_encoder(connector); |
64 | best_encoder = connector_funcs->best_encoder(connector); |
65 | 65 | ||
66 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
66 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
67 | if (connector->encoder_ids[i] == 0) |
67 | if (connector->encoder_ids[i] == 0) |
68 | break; |
68 | break; |
69 | 69 | ||
70 | obj = drm_mode_object_find(connector->dev, |
70 | obj = drm_mode_object_find(connector->dev, |
71 | connector->encoder_ids[i], |
71 | connector->encoder_ids[i], |
72 | DRM_MODE_OBJECT_ENCODER); |
72 | DRM_MODE_OBJECT_ENCODER); |
73 | if (!obj) |
73 | if (!obj) |
74 | continue; |
74 | continue; |
75 | 75 | ||
76 | encoder = obj_to_encoder(obj); |
76 | encoder = obj_to_encoder(obj); |
77 | 77 | ||
78 | if ((encoder == best_encoder) && (status == connector_status_connected)) |
78 | if ((encoder == best_encoder) && (status == connector_status_connected)) |
79 | connected = true; |
79 | connected = true; |
80 | else |
80 | else |
81 | connected = false; |
81 | connected = false; |
82 | 82 | ||
83 | if (rdev->is_atom_bios) |
83 | if (rdev->is_atom_bios) |
84 | radeon_atombios_connected_scratch_regs(connector, encoder, connected); |
84 | radeon_atombios_connected_scratch_regs(connector, encoder, connected); |
85 | else |
85 | else |
86 | radeon_combios_connected_scratch_regs(connector, encoder, connected); |
86 | radeon_combios_connected_scratch_regs(connector, encoder, connected); |
87 | 87 | ||
88 | } |
88 | } |
89 | } |
89 | } |
90 | 90 | ||
91 | struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type) |
91 | struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type) |
92 | { |
92 | { |
93 | struct drm_mode_object *obj; |
93 | struct drm_mode_object *obj; |
94 | struct drm_encoder *encoder; |
94 | struct drm_encoder *encoder; |
95 | int i; |
95 | int i; |
96 | 96 | ||
97 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
97 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
98 | if (connector->encoder_ids[i] == 0) |
98 | if (connector->encoder_ids[i] == 0) |
99 | break; |
99 | break; |
100 | 100 | ||
101 | obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
101 | obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
102 | if (!obj) |
102 | if (!obj) |
103 | continue; |
103 | continue; |
104 | 104 | ||
105 | encoder = obj_to_encoder(obj); |
105 | encoder = obj_to_encoder(obj); |
106 | if (encoder->encoder_type == encoder_type) |
106 | if (encoder->encoder_type == encoder_type) |
107 | return encoder; |
107 | return encoder; |
108 | } |
108 | } |
109 | return NULL; |
109 | return NULL; |
110 | } |
110 | } |
111 | 111 | ||
112 | struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector) |
112 | struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector) |
113 | { |
113 | { |
114 | int enc_id = connector->encoder_ids[0]; |
114 | int enc_id = connector->encoder_ids[0]; |
115 | struct drm_mode_object *obj; |
115 | struct drm_mode_object *obj; |
116 | struct drm_encoder *encoder; |
116 | struct drm_encoder *encoder; |
117 | 117 | ||
118 | /* pick the encoder ids */ |
118 | /* pick the encoder ids */ |
119 | if (enc_id) { |
119 | if (enc_id) { |
120 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); |
120 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); |
121 | if (!obj) |
121 | if (!obj) |
122 | return NULL; |
122 | return NULL; |
123 | encoder = obj_to_encoder(obj); |
123 | encoder = obj_to_encoder(obj); |
124 | return encoder; |
124 | return encoder; |
125 | } |
125 | } |
126 | return NULL; |
126 | return NULL; |
127 | } |
127 | } |
128 | 128 | ||
129 | /* |
129 | /* |
130 | * radeon_connector_analog_encoder_conflict_solve |
130 | * radeon_connector_analog_encoder_conflict_solve |
131 | * - search for other connectors sharing this encoder |
131 | * - search for other connectors sharing this encoder |
132 | * if priority is true, then set them disconnected if this is connected |
132 | * if priority is true, then set them disconnected if this is connected |
133 | * if priority is false, set us disconnected if they are connected |
133 | * if priority is false, set us disconnected if they are connected |
134 | */ |
134 | */ |
135 | static enum drm_connector_status |
135 | static enum drm_connector_status |
136 | radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector, |
136 | radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector, |
137 | struct drm_encoder *encoder, |
137 | struct drm_encoder *encoder, |
138 | enum drm_connector_status current_status, |
138 | enum drm_connector_status current_status, |
139 | bool priority) |
139 | bool priority) |
140 | { |
140 | { |
141 | struct drm_device *dev = connector->dev; |
141 | struct drm_device *dev = connector->dev; |
142 | struct drm_connector *conflict; |
142 | struct drm_connector *conflict; |
143 | int i; |
143 | int i; |
144 | 144 | ||
145 | list_for_each_entry(conflict, &dev->mode_config.connector_list, head) { |
145 | list_for_each_entry(conflict, &dev->mode_config.connector_list, head) { |
146 | if (conflict == connector) |
146 | if (conflict == connector) |
147 | continue; |
147 | continue; |
148 | 148 | ||
149 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
149 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
150 | if (conflict->encoder_ids[i] == 0) |
150 | if (conflict->encoder_ids[i] == 0) |
151 | break; |
151 | break; |
152 | 152 | ||
153 | /* if the IDs match */ |
153 | /* if the IDs match */ |
154 | if (conflict->encoder_ids[i] == encoder->base.id) { |
154 | if (conflict->encoder_ids[i] == encoder->base.id) { |
155 | if (conflict->status != connector_status_connected) |
155 | if (conflict->status != connector_status_connected) |
156 | continue; |
156 | continue; |
157 | 157 | ||
158 | if (priority == true) { |
158 | if (priority == true) { |
159 | DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); |
159 | DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); |
160 | DRM_INFO("in favor of %s\n", drm_get_connector_name(connector)); |
160 | DRM_INFO("in favor of %s\n", drm_get_connector_name(connector)); |
161 | conflict->status = connector_status_disconnected; |
161 | conflict->status = connector_status_disconnected; |
162 | radeon_connector_update_scratch_regs(conflict, connector_status_disconnected); |
162 | radeon_connector_update_scratch_regs(conflict, connector_status_disconnected); |
163 | } else { |
163 | } else { |
164 | DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); |
164 | DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); |
165 | DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict)); |
165 | DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict)); |
166 | current_status = connector_status_disconnected; |
166 | current_status = connector_status_disconnected; |
167 | } |
167 | } |
168 | break; |
168 | break; |
169 | } |
169 | } |
170 | } |
170 | } |
171 | } |
171 | } |
172 | return current_status; |
172 | return current_status; |
173 | 173 | ||
174 | } |
174 | } |
175 | 175 | ||
176 | static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder) |
176 | static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder) |
177 | { |
177 | { |
178 | struct drm_device *dev = encoder->dev; |
178 | struct drm_device *dev = encoder->dev; |
179 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
179 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
180 | struct drm_display_mode *mode = NULL; |
180 | struct drm_display_mode *mode = NULL; |
181 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
181 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
182 | 182 | ||
183 | if (native_mode->panel_xres != 0 && |
183 | if (native_mode->panel_xres != 0 && |
184 | native_mode->panel_yres != 0 && |
184 | native_mode->panel_yres != 0 && |
185 | native_mode->dotclock != 0) { |
185 | native_mode->dotclock != 0) { |
186 | mode = drm_mode_create(dev); |
186 | mode = drm_mode_create(dev); |
187 | 187 | ||
188 | mode->hdisplay = native_mode->panel_xres; |
188 | mode->hdisplay = native_mode->panel_xres; |
189 | mode->vdisplay = native_mode->panel_yres; |
189 | mode->vdisplay = native_mode->panel_yres; |
190 | 190 | ||
191 | mode->htotal = mode->hdisplay + native_mode->hblank; |
191 | mode->htotal = mode->hdisplay + native_mode->hblank; |
192 | mode->hsync_start = mode->hdisplay + native_mode->hoverplus; |
192 | mode->hsync_start = mode->hdisplay + native_mode->hoverplus; |
193 | mode->hsync_end = mode->hsync_start + native_mode->hsync_width; |
193 | mode->hsync_end = mode->hsync_start + native_mode->hsync_width; |
194 | mode->vtotal = mode->vdisplay + native_mode->vblank; |
194 | mode->vtotal = mode->vdisplay + native_mode->vblank; |
195 | mode->vsync_start = mode->vdisplay + native_mode->voverplus; |
195 | mode->vsync_start = mode->vdisplay + native_mode->voverplus; |
196 | mode->vsync_end = mode->vsync_start + native_mode->vsync_width; |
196 | mode->vsync_end = mode->vsync_start + native_mode->vsync_width; |
197 | mode->clock = native_mode->dotclock; |
197 | mode->clock = native_mode->dotclock; |
198 | mode->flags = 0; |
198 | mode->flags = 0; |
199 | 199 | ||
200 | mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; |
200 | mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; |
201 | drm_mode_set_name(mode); |
201 | drm_mode_set_name(mode); |
202 | 202 | ||
203 | DRM_DEBUG("Adding native panel mode %s\n", mode->name); |
203 | DRM_DEBUG("Adding native panel mode %s\n", mode->name); |
204 | } |
204 | } |
205 | return mode; |
205 | return mode; |
206 | } |
206 | } |
207 | 207 | ||
208 | static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector) |
208 | static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector) |
209 | { |
209 | { |
210 | struct drm_device *dev = encoder->dev; |
210 | struct drm_device *dev = encoder->dev; |
211 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
211 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
212 | struct drm_display_mode *mode = NULL; |
212 | struct drm_display_mode *mode = NULL; |
213 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
213 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
214 | int i; |
214 | int i; |
215 | struct mode_size { |
215 | struct mode_size { |
216 | int w; |
216 | int w; |
217 | int h; |
217 | int h; |
218 | } common_modes[17] = { |
218 | } common_modes[17] = { |
219 | { 640, 480}, |
219 | { 640, 480}, |
220 | { 720, 480}, |
220 | { 720, 480}, |
221 | { 800, 600}, |
221 | { 800, 600}, |
222 | { 848, 480}, |
222 | { 848, 480}, |
223 | {1024, 768}, |
223 | {1024, 768}, |
224 | {1152, 768}, |
224 | {1152, 768}, |
225 | {1280, 720}, |
225 | {1280, 720}, |
226 | {1280, 800}, |
226 | {1280, 800}, |
227 | {1280, 854}, |
227 | {1280, 854}, |
228 | {1280, 960}, |
228 | {1280, 960}, |
229 | {1280, 1024}, |
229 | {1280, 1024}, |
230 | {1440, 900}, |
230 | {1440, 900}, |
231 | {1400, 1050}, |
231 | {1400, 1050}, |
232 | {1680, 1050}, |
232 | {1680, 1050}, |
233 | {1600, 1200}, |
233 | {1600, 1200}, |
234 | {1920, 1080}, |
234 | {1920, 1080}, |
235 | {1920, 1200} |
235 | {1920, 1200} |
236 | }; |
236 | }; |
237 | 237 | ||
238 | for (i = 0; i < 17; i++) { |
238 | for (i = 0; i < 17; i++) { |
239 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
239 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
240 | if (common_modes[i].w > native_mode->panel_xres || |
240 | if (common_modes[i].w > native_mode->panel_xres || |
241 | common_modes[i].h > native_mode->panel_yres || |
241 | common_modes[i].h > native_mode->panel_yres || |
242 | (common_modes[i].w == native_mode->panel_xres && |
242 | (common_modes[i].w == native_mode->panel_xres && |
243 | common_modes[i].h == native_mode->panel_yres)) |
243 | common_modes[i].h == native_mode->panel_yres)) |
244 | continue; |
244 | continue; |
245 | } |
245 | } |
246 | if (common_modes[i].w < 320 || common_modes[i].h < 200) |
246 | if (common_modes[i].w < 320 || common_modes[i].h < 200) |
247 | continue; |
247 | continue; |
248 | 248 | ||
249 | mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); |
249 | mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); |
250 | drm_mode_probed_add(connector, mode); |
250 | drm_mode_probed_add(connector, mode); |
251 | } |
251 | } |
252 | } |
252 | } |
253 | 253 | ||
254 | int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property, |
254 | int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property, |
255 | uint64_t val) |
255 | uint64_t val) |
256 | { |
256 | { |
257 | struct drm_device *dev = connector->dev; |
257 | struct drm_device *dev = connector->dev; |
258 | struct radeon_device *rdev = dev->dev_private; |
258 | struct radeon_device *rdev = dev->dev_private; |
259 | struct drm_encoder *encoder; |
259 | struct drm_encoder *encoder; |
260 | struct radeon_encoder *radeon_encoder; |
260 | struct radeon_encoder *radeon_encoder; |
261 | 261 | ||
262 | if (property == rdev->mode_info.coherent_mode_property) { |
262 | if (property == rdev->mode_info.coherent_mode_property) { |
263 | struct radeon_encoder_atom_dig *dig; |
263 | struct radeon_encoder_atom_dig *dig; |
264 | 264 | ||
265 | /* need to find digital encoder on connector */ |
265 | /* need to find digital encoder on connector */ |
266 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
266 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
267 | if (!encoder) |
267 | if (!encoder) |
268 | return 0; |
268 | return 0; |
269 | 269 | ||
270 | radeon_encoder = to_radeon_encoder(encoder); |
270 | radeon_encoder = to_radeon_encoder(encoder); |
271 | 271 | ||
272 | if (!radeon_encoder->enc_priv) |
272 | if (!radeon_encoder->enc_priv) |
273 | return 0; |
273 | return 0; |
274 | 274 | ||
275 | dig = radeon_encoder->enc_priv; |
275 | dig = radeon_encoder->enc_priv; |
276 | dig->coherent_mode = val ? true : false; |
276 | dig->coherent_mode = val ? true : false; |
277 | radeon_property_change_mode(&radeon_encoder->base); |
277 | radeon_property_change_mode(&radeon_encoder->base); |
278 | } |
278 | } |
279 | 279 | ||
280 | if (property == rdev->mode_info.tv_std_property) { |
280 | if (property == rdev->mode_info.tv_std_property) { |
281 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); |
281 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); |
282 | if (!encoder) { |
282 | if (!encoder) { |
283 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC); |
283 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC); |
284 | } |
284 | } |
285 | 285 | ||
286 | if (!encoder) |
286 | if (!encoder) |
287 | return 0; |
287 | return 0; |
288 | 288 | ||
289 | radeon_encoder = to_radeon_encoder(encoder); |
289 | radeon_encoder = to_radeon_encoder(encoder); |
290 | if (!radeon_encoder->enc_priv) |
290 | if (!radeon_encoder->enc_priv) |
291 | return 0; |
291 | return 0; |
292 | if (rdev->is_atom_bios) { |
292 | if (rdev->is_atom_bios) { |
293 | struct radeon_encoder_atom_dac *dac_int; |
293 | struct radeon_encoder_atom_dac *dac_int; |
294 | dac_int = radeon_encoder->enc_priv; |
294 | dac_int = radeon_encoder->enc_priv; |
295 | dac_int->tv_std = val; |
295 | dac_int->tv_std = val; |
296 | } else { |
296 | } else { |
297 | struct radeon_encoder_tv_dac *dac_int; |
297 | struct radeon_encoder_tv_dac *dac_int; |
298 | dac_int = radeon_encoder->enc_priv; |
298 | dac_int = radeon_encoder->enc_priv; |
299 | dac_int->tv_std = val; |
299 | dac_int->tv_std = val; |
300 | } |
300 | } |
301 | radeon_property_change_mode(&radeon_encoder->base); |
301 | radeon_property_change_mode(&radeon_encoder->base); |
302 | } |
302 | } |
303 | 303 | ||
304 | if (property == rdev->mode_info.load_detect_property) { |
304 | if (property == rdev->mode_info.load_detect_property) { |
305 | struct radeon_connector *radeon_connector = |
305 | struct radeon_connector *radeon_connector = |
306 | to_radeon_connector(connector); |
306 | to_radeon_connector(connector); |
307 | 307 | ||
308 | if (val == 0) |
308 | if (val == 0) |
309 | radeon_connector->dac_load_detect = false; |
309 | radeon_connector->dac_load_detect = false; |
310 | else |
310 | else |
311 | radeon_connector->dac_load_detect = true; |
311 | radeon_connector->dac_load_detect = true; |
312 | } |
312 | } |
313 | 313 | ||
314 | if (property == rdev->mode_info.tmds_pll_property) { |
314 | if (property == rdev->mode_info.tmds_pll_property) { |
315 | struct radeon_encoder_int_tmds *tmds = NULL; |
315 | struct radeon_encoder_int_tmds *tmds = NULL; |
316 | bool ret = false; |
316 | bool ret = false; |
317 | /* need to find digital encoder on connector */ |
317 | /* need to find digital encoder on connector */ |
318 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
318 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
319 | if (!encoder) |
319 | if (!encoder) |
320 | return 0; |
320 | return 0; |
321 | 321 | ||
322 | radeon_encoder = to_radeon_encoder(encoder); |
322 | radeon_encoder = to_radeon_encoder(encoder); |
323 | 323 | ||
324 | tmds = radeon_encoder->enc_priv; |
324 | tmds = radeon_encoder->enc_priv; |
325 | if (!tmds) |
325 | if (!tmds) |
326 | return 0; |
326 | return 0; |
327 | 327 | ||
328 | if (val == 0) { |
328 | if (val == 0) { |
329 | if (rdev->is_atom_bios) |
329 | if (rdev->is_atom_bios) |
330 | ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds); |
330 | ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds); |
331 | else |
331 | else |
332 | ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds); |
332 | ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds); |
333 | } |
333 | } |
334 | if (val == 1 || ret == false) { |
334 | if (val == 1 || ret == false) { |
335 | radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds); |
335 | radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds); |
336 | } |
336 | } |
337 | radeon_property_change_mode(&radeon_encoder->base); |
337 | radeon_property_change_mode(&radeon_encoder->base); |
338 | } |
338 | } |
339 | 339 | ||
340 | return 0; |
340 | return 0; |
341 | } |
341 | } |
342 | 342 | ||
343 | static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, |
343 | static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, |
344 | struct drm_connector *connector) |
344 | struct drm_connector *connector) |
345 | { |
345 | { |
346 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
346 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
347 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
347 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
348 | 348 | ||
349 | /* Try to get native mode details from EDID if necessary */ |
349 | /* Try to get native mode details from EDID if necessary */ |
350 | if (!native_mode->dotclock) { |
350 | if (!native_mode->dotclock) { |
351 | struct drm_display_mode *t, *mode; |
351 | struct drm_display_mode *t, *mode; |
352 | 352 | ||
353 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { |
353 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { |
354 | if (mode->hdisplay == native_mode->panel_xres && |
354 | if (mode->hdisplay == native_mode->panel_xres && |
355 | mode->vdisplay == native_mode->panel_yres) { |
355 | mode->vdisplay == native_mode->panel_yres) { |
356 | native_mode->hblank = mode->htotal - mode->hdisplay; |
356 | native_mode->hblank = mode->htotal - mode->hdisplay; |
357 | native_mode->hoverplus = mode->hsync_start - mode->hdisplay; |
357 | native_mode->hoverplus = mode->hsync_start - mode->hdisplay; |
358 | native_mode->hsync_width = mode->hsync_end - mode->hsync_start; |
358 | native_mode->hsync_width = mode->hsync_end - mode->hsync_start; |
359 | native_mode->vblank = mode->vtotal - mode->vdisplay; |
359 | native_mode->vblank = mode->vtotal - mode->vdisplay; |
360 | native_mode->voverplus = mode->vsync_start - mode->vdisplay; |
360 | native_mode->voverplus = mode->vsync_start - mode->vdisplay; |
361 | native_mode->vsync_width = mode->vsync_end - mode->vsync_start; |
361 | native_mode->vsync_width = mode->vsync_end - mode->vsync_start; |
362 | native_mode->dotclock = mode->clock; |
362 | native_mode->dotclock = mode->clock; |
363 | DRM_INFO("Determined LVDS native mode details from EDID\n"); |
363 | DRM_INFO("Determined LVDS native mode details from EDID\n"); |
364 | break; |
364 | break; |
365 | } |
365 | } |
366 | } |
366 | } |
367 | } |
367 | } |
368 | if (!native_mode->dotclock) { |
368 | if (!native_mode->dotclock) { |
369 | DRM_INFO("No LVDS native mode details, disabling RMX\n"); |
369 | DRM_INFO("No LVDS native mode details, disabling RMX\n"); |
370 | radeon_encoder->rmx_type = RMX_OFF; |
370 | radeon_encoder->rmx_type = RMX_OFF; |
371 | } |
371 | } |
372 | } |
372 | } |
373 | 373 | ||
374 | static int radeon_lvds_get_modes(struct drm_connector *connector) |
374 | static int radeon_lvds_get_modes(struct drm_connector *connector) |
375 | { |
375 | { |
376 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
376 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
377 | struct drm_encoder *encoder; |
377 | struct drm_encoder *encoder; |
378 | int ret = 0; |
378 | int ret = 0; |
379 | struct drm_display_mode *mode; |
379 | struct drm_display_mode *mode; |
380 | 380 | ||
381 | if (radeon_connector->ddc_bus) { |
381 | if (radeon_connector->ddc_bus) { |
382 | ret = radeon_ddc_get_modes(radeon_connector); |
382 | ret = radeon_ddc_get_modes(radeon_connector); |
383 | if (ret > 0) { |
383 | if (ret > 0) { |
384 | encoder = radeon_best_single_encoder(connector); |
384 | encoder = radeon_best_single_encoder(connector); |
385 | if (encoder) { |
385 | if (encoder) { |
386 | radeon_fixup_lvds_native_mode(encoder, connector); |
386 | radeon_fixup_lvds_native_mode(encoder, connector); |
387 | /* add scaled modes */ |
387 | /* add scaled modes */ |
388 | radeon_add_common_modes(encoder, connector); |
388 | radeon_add_common_modes(encoder, connector); |
389 | } |
389 | } |
390 | return ret; |
390 | return ret; |
391 | } |
391 | } |
392 | } |
392 | } |
393 | 393 | ||
394 | encoder = radeon_best_single_encoder(connector); |
394 | encoder = radeon_best_single_encoder(connector); |
395 | if (!encoder) |
395 | if (!encoder) |
396 | return 0; |
396 | return 0; |
397 | 397 | ||
398 | /* we have no EDID modes */ |
398 | /* we have no EDID modes */ |
399 | mode = radeon_fp_native_mode(encoder); |
399 | mode = radeon_fp_native_mode(encoder); |
400 | if (mode) { |
400 | if (mode) { |
401 | ret = 1; |
401 | ret = 1; |
402 | drm_mode_probed_add(connector, mode); |
402 | drm_mode_probed_add(connector, mode); |
403 | /* add scaled modes */ |
403 | /* add scaled modes */ |
404 | radeon_add_common_modes(encoder, connector); |
404 | radeon_add_common_modes(encoder, connector); |
405 | } |
405 | } |
406 | 406 | ||
407 | return ret; |
407 | return ret; |
408 | } |
408 | } |
409 | 409 | ||
410 | static int radeon_lvds_mode_valid(struct drm_connector *connector, |
410 | static int radeon_lvds_mode_valid(struct drm_connector *connector, |
411 | struct drm_display_mode *mode) |
411 | struct drm_display_mode *mode) |
412 | { |
412 | { |
413 | return MODE_OK; |
413 | return MODE_OK; |
414 | } |
414 | } |
415 | 415 | ||
416 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) |
416 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) |
417 | { |
417 | { |
418 | enum drm_connector_status ret = connector_status_connected; |
418 | enum drm_connector_status ret = connector_status_connected; |
419 | /* check acpi lid status ??? */ |
419 | /* check acpi lid status ??? */ |
420 | radeon_connector_update_scratch_regs(connector, ret); |
420 | radeon_connector_update_scratch_regs(connector, ret); |
421 | return ret; |
421 | return ret; |
422 | } |
422 | } |
423 | 423 | ||
424 | static void radeon_connector_destroy(struct drm_connector *connector) |
424 | static void radeon_connector_destroy(struct drm_connector *connector) |
425 | { |
425 | { |
426 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
426 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
427 | 427 | ||
428 | if (radeon_connector->ddc_bus) |
428 | if (radeon_connector->ddc_bus) |
429 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
429 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
430 | kfree(radeon_connector->con_priv); |
430 | kfree(radeon_connector->con_priv); |
431 | drm_sysfs_connector_remove(connector); |
431 | drm_sysfs_connector_remove(connector); |
432 | drm_connector_cleanup(connector); |
432 | drm_connector_cleanup(connector); |
433 | kfree(connector); |
433 | kfree(connector); |
434 | } |
434 | } |
435 | 435 | ||
436 | static int radeon_lvds_set_property(struct drm_connector *connector, |
436 | static int radeon_lvds_set_property(struct drm_connector *connector, |
437 | struct drm_property *property, |
437 | struct drm_property *property, |
438 | uint64_t value) |
438 | uint64_t value) |
439 | { |
439 | { |
440 | struct drm_device *dev = connector->dev; |
440 | struct drm_device *dev = connector->dev; |
441 | struct radeon_encoder *radeon_encoder; |
441 | struct radeon_encoder *radeon_encoder; |
442 | enum radeon_rmx_type rmx_type; |
442 | enum radeon_rmx_type rmx_type; |
443 | 443 | ||
444 | DRM_DEBUG("\n"); |
444 | DRM_DEBUG("\n"); |
445 | if (property != dev->mode_config.scaling_mode_property) |
445 | if (property != dev->mode_config.scaling_mode_property) |
446 | return 0; |
446 | return 0; |
447 | 447 | ||
448 | if (connector->encoder) |
448 | if (connector->encoder) |
449 | radeon_encoder = to_radeon_encoder(connector->encoder); |
449 | radeon_encoder = to_radeon_encoder(connector->encoder); |
450 | else { |
450 | else { |
451 | struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; |
451 | struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; |
452 | radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector)); |
452 | radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector)); |
453 | } |
453 | } |
454 | 454 | ||
455 | switch (value) { |
455 | switch (value) { |
456 | case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break; |
456 | case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break; |
457 | case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break; |
457 | case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break; |
458 | case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break; |
458 | case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break; |
459 | default: |
459 | default: |
460 | case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break; |
460 | case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break; |
461 | } |
461 | } |
462 | if (radeon_encoder->rmx_type == rmx_type) |
462 | if (radeon_encoder->rmx_type == rmx_type) |
463 | return 0; |
463 | return 0; |
464 | 464 | ||
465 | radeon_encoder->rmx_type = rmx_type; |
465 | radeon_encoder->rmx_type = rmx_type; |
466 | 466 | ||
467 | radeon_property_change_mode(&radeon_encoder->base); |
467 | radeon_property_change_mode(&radeon_encoder->base); |
468 | return 0; |
468 | return 0; |
469 | } |
469 | } |
470 | 470 | ||
471 | 471 | ||
472 | struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = { |
472 | struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = { |
473 | .get_modes = radeon_lvds_get_modes, |
473 | .get_modes = radeon_lvds_get_modes, |
474 | .mode_valid = radeon_lvds_mode_valid, |
474 | .mode_valid = radeon_lvds_mode_valid, |
475 | .best_encoder = radeon_best_single_encoder, |
475 | .best_encoder = radeon_best_single_encoder, |
476 | }; |
476 | }; |
477 | 477 | ||
478 | struct drm_connector_funcs radeon_lvds_connector_funcs = { |
478 | struct drm_connector_funcs radeon_lvds_connector_funcs = { |
479 | .dpms = drm_helper_connector_dpms, |
479 | .dpms = drm_helper_connector_dpms, |
480 | .detect = radeon_lvds_detect, |
480 | .detect = radeon_lvds_detect, |
481 | .fill_modes = drm_helper_probe_single_connector_modes, |
481 | .fill_modes = drm_helper_probe_single_connector_modes, |
482 | .destroy = radeon_connector_destroy, |
482 | .destroy = radeon_connector_destroy, |
483 | .set_property = radeon_lvds_set_property, |
483 | .set_property = radeon_lvds_set_property, |
484 | }; |
484 | }; |
485 | 485 | ||
486 | static int radeon_vga_get_modes(struct drm_connector *connector) |
486 | static int radeon_vga_get_modes(struct drm_connector *connector) |
487 | { |
487 | { |
488 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
488 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
489 | int ret; |
489 | int ret; |
490 | 490 | ||
491 | ret = radeon_ddc_get_modes(radeon_connector); |
491 | ret = radeon_ddc_get_modes(radeon_connector); |
492 | 492 | ||
493 | return ret; |
493 | return ret; |
494 | } |
494 | } |
495 | 495 | ||
496 | static int radeon_vga_mode_valid(struct drm_connector *connector, |
496 | static int radeon_vga_mode_valid(struct drm_connector *connector, |
497 | struct drm_display_mode *mode) |
497 | struct drm_display_mode *mode) |
498 | { |
498 | { |
499 | return MODE_OK; |
499 | return MODE_OK; |
500 | } |
500 | } |
501 | 501 | ||
502 | static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) |
502 | static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) |
503 | { |
503 | { |
504 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
504 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
505 | struct drm_encoder *encoder; |
505 | struct drm_encoder *encoder; |
506 | struct drm_encoder_helper_funcs *encoder_funcs; |
506 | struct drm_encoder_helper_funcs *encoder_funcs; |
507 | bool dret; |
507 | bool dret; |
508 | enum drm_connector_status ret = connector_status_disconnected; |
508 | enum drm_connector_status ret = connector_status_disconnected; |
509 | 509 | ||
510 | encoder = radeon_best_single_encoder(connector); |
510 | encoder = radeon_best_single_encoder(connector); |
511 | if (!encoder) |
511 | if (!encoder) |
512 | ret = connector_status_disconnected; |
512 | ret = connector_status_disconnected; |
513 | 513 | ||
514 | radeon_i2c_do_lock(radeon_connector, 1); |
514 | radeon_i2c_do_lock(radeon_connector, 1); |
515 | dret = radeon_ddc_probe(radeon_connector); |
515 | dret = radeon_ddc_probe(radeon_connector); |
516 | radeon_i2c_do_lock(radeon_connector, 0); |
516 | radeon_i2c_do_lock(radeon_connector, 0); |
517 | if (dret) |
517 | if (dret) |
518 | ret = connector_status_connected; |
518 | ret = connector_status_connected; |
519 | else { |
519 | else { |
520 | if (radeon_connector->dac_load_detect) { |
520 | if (radeon_connector->dac_load_detect) { |
521 | encoder_funcs = encoder->helper_private; |
521 | encoder_funcs = encoder->helper_private; |
522 | ret = encoder_funcs->detect(encoder, connector); |
522 | ret = encoder_funcs->detect(encoder, connector); |
523 | } |
523 | } |
524 | } |
524 | } |
525 | 525 | ||
526 | if (ret == connector_status_connected) |
526 | if (ret == connector_status_connected) |
527 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
527 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
528 | radeon_connector_update_scratch_regs(connector, ret); |
528 | radeon_connector_update_scratch_regs(connector, ret); |
529 | return ret; |
529 | return ret; |
530 | } |
530 | } |
531 | 531 | ||
532 | struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = { |
532 | struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = { |
533 | .get_modes = radeon_vga_get_modes, |
533 | .get_modes = radeon_vga_get_modes, |
534 | .mode_valid = radeon_vga_mode_valid, |
534 | .mode_valid = radeon_vga_mode_valid, |
535 | .best_encoder = radeon_best_single_encoder, |
535 | .best_encoder = radeon_best_single_encoder, |
536 | }; |
536 | }; |
537 | 537 | ||
538 | struct drm_connector_funcs radeon_vga_connector_funcs = { |
538 | struct drm_connector_funcs radeon_vga_connector_funcs = { |
539 | .dpms = drm_helper_connector_dpms, |
539 | .dpms = drm_helper_connector_dpms, |
540 | .detect = radeon_vga_detect, |
540 | .detect = radeon_vga_detect, |
541 | .fill_modes = drm_helper_probe_single_connector_modes, |
541 | .fill_modes = drm_helper_probe_single_connector_modes, |
542 | .destroy = radeon_connector_destroy, |
542 | .destroy = radeon_connector_destroy, |
543 | .set_property = radeon_connector_set_property, |
543 | .set_property = radeon_connector_set_property, |
544 | }; |
544 | }; |
545 | 545 | ||
546 | static int radeon_tv_get_modes(struct drm_connector *connector) |
546 | static int radeon_tv_get_modes(struct drm_connector *connector) |
547 | { |
547 | { |
548 | struct drm_device *dev = connector->dev; |
548 | struct drm_device *dev = connector->dev; |
549 | struct radeon_device *rdev = dev->dev_private; |
549 | struct radeon_device *rdev = dev->dev_private; |
550 | struct drm_display_mode *tv_mode; |
550 | struct drm_display_mode *tv_mode; |
551 | struct drm_encoder *encoder; |
551 | struct drm_encoder *encoder; |
552 | 552 | ||
553 | encoder = radeon_best_single_encoder(connector); |
553 | encoder = radeon_best_single_encoder(connector); |
554 | if (!encoder) |
554 | if (!encoder) |
555 | return 0; |
555 | return 0; |
556 | 556 | ||
557 | /* avivo chips can scale any mode */ |
557 | /* avivo chips can scale any mode */ |
558 | if (rdev->family >= CHIP_RS600) |
558 | if (rdev->family >= CHIP_RS600) |
559 | /* add scaled modes */ |
559 | /* add scaled modes */ |
560 | radeon_add_common_modes(encoder, connector); |
560 | radeon_add_common_modes(encoder, connector); |
561 | else { |
561 | else { |
562 | /* only 800x600 is supported right now on pre-avivo chips */ |
562 | /* only 800x600 is supported right now on pre-avivo chips */ |
563 | tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false); |
563 | tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false); |
564 | tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; |
564 | tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; |
565 | drm_mode_probed_add(connector, tv_mode); |
565 | drm_mode_probed_add(connector, tv_mode); |
566 | } |
566 | } |
567 | return 1; |
567 | return 1; |
568 | } |
568 | } |
569 | 569 | ||
570 | static int radeon_tv_mode_valid(struct drm_connector *connector, |
570 | static int radeon_tv_mode_valid(struct drm_connector *connector, |
571 | struct drm_display_mode *mode) |
571 | struct drm_display_mode *mode) |
572 | { |
572 | { |
573 | return MODE_OK; |
573 | return MODE_OK; |
574 | } |
574 | } |
575 | 575 | ||
576 | static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) |
576 | static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) |
577 | { |
577 | { |
578 | struct drm_encoder *encoder; |
578 | struct drm_encoder *encoder; |
579 | struct drm_encoder_helper_funcs *encoder_funcs; |
579 | struct drm_encoder_helper_funcs *encoder_funcs; |
580 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
580 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
581 | enum drm_connector_status ret = connector_status_disconnected; |
581 | enum drm_connector_status ret = connector_status_disconnected; |
582 | 582 | ||
583 | if (!radeon_connector->dac_load_detect) |
583 | if (!radeon_connector->dac_load_detect) |
584 | return ret; |
584 | return ret; |
585 | 585 | ||
586 | encoder = radeon_best_single_encoder(connector); |
586 | encoder = radeon_best_single_encoder(connector); |
587 | if (!encoder) |
587 | if (!encoder) |
588 | ret = connector_status_disconnected; |
588 | ret = connector_status_disconnected; |
589 | else { |
589 | else { |
590 | encoder_funcs = encoder->helper_private; |
590 | encoder_funcs = encoder->helper_private; |
591 | ret = encoder_funcs->detect(encoder, connector); |
591 | ret = encoder_funcs->detect(encoder, connector); |
592 | } |
592 | } |
593 | if (ret == connector_status_connected) |
593 | if (ret == connector_status_connected) |
594 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); |
594 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); |
595 | radeon_connector_update_scratch_regs(connector, ret); |
595 | radeon_connector_update_scratch_regs(connector, ret); |
596 | return ret; |
596 | return ret; |
597 | } |
597 | } |
598 | 598 | ||
599 | struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = { |
599 | struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = { |
600 | .get_modes = radeon_tv_get_modes, |
600 | .get_modes = radeon_tv_get_modes, |
601 | .mode_valid = radeon_tv_mode_valid, |
601 | .mode_valid = radeon_tv_mode_valid, |
602 | .best_encoder = radeon_best_single_encoder, |
602 | .best_encoder = radeon_best_single_encoder, |
603 | }; |
603 | }; |
604 | 604 | ||
605 | struct drm_connector_funcs radeon_tv_connector_funcs = { |
605 | struct drm_connector_funcs radeon_tv_connector_funcs = { |
606 | .dpms = drm_helper_connector_dpms, |
606 | .dpms = drm_helper_connector_dpms, |
607 | .detect = radeon_tv_detect, |
607 | .detect = radeon_tv_detect, |
608 | .fill_modes = drm_helper_probe_single_connector_modes, |
608 | .fill_modes = drm_helper_probe_single_connector_modes, |
609 | .destroy = radeon_connector_destroy, |
609 | .destroy = radeon_connector_destroy, |
610 | .set_property = radeon_connector_set_property, |
610 | .set_property = radeon_connector_set_property, |
611 | }; |
611 | }; |
612 | 612 | ||
613 | static int radeon_dvi_get_modes(struct drm_connector *connector) |
613 | static int radeon_dvi_get_modes(struct drm_connector *connector) |
614 | { |
614 | { |
615 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
615 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
616 | int ret; |
616 | int ret; |
617 | 617 | ||
618 | ret = radeon_ddc_get_modes(radeon_connector); |
618 | ret = radeon_ddc_get_modes(radeon_connector); |
619 | return ret; |
619 | return ret; |
620 | } |
620 | } |
621 | 621 | ||
622 | /* |
622 | /* |
623 | * DVI is complicated |
623 | * DVI is complicated |
624 | * Do a DDC probe, if DDC probe passes, get the full EDID so |
624 | * Do a DDC probe, if DDC probe passes, get the full EDID so |
625 | * we can do analog/digital monitor detection at this point. |
625 | * we can do analog/digital monitor detection at this point. |
626 | * If the monitor is an analog monitor or we got no DDC, |
626 | * If the monitor is an analog monitor or we got no DDC, |
627 | * we need to find the DAC encoder object for this connector. |
627 | * we need to find the DAC encoder object for this connector. |
628 | * If we got no DDC, we do load detection on the DAC encoder object. |
628 | * If we got no DDC, we do load detection on the DAC encoder object. |
629 | * If we got analog DDC or load detection passes on the DAC encoder |
629 | * If we got analog DDC or load detection passes on the DAC encoder |
630 | * we have to check if this analog encoder is shared with anyone else (TV) |
630 | * we have to check if this analog encoder is shared with anyone else (TV) |
631 | * if its shared we have to set the other connector to disconnected. |
631 | * if its shared we have to set the other connector to disconnected. |
632 | */ |
632 | */ |
633 | static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) |
633 | static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) |
634 | { |
634 | { |
635 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
635 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
636 | struct drm_encoder *encoder = NULL; |
636 | struct drm_encoder *encoder = NULL; |
637 | struct drm_encoder_helper_funcs *encoder_funcs; |
637 | struct drm_encoder_helper_funcs *encoder_funcs; |
638 | struct drm_mode_object *obj; |
638 | struct drm_mode_object *obj; |
639 | int i; |
639 | int i; |
640 | enum drm_connector_status ret = connector_status_disconnected; |
640 | enum drm_connector_status ret = connector_status_disconnected; |
641 | bool dret; |
641 | bool dret; |
642 | 642 | ||
643 | radeon_i2c_do_lock(radeon_connector, 1); |
643 | radeon_i2c_do_lock(radeon_connector, 1); |
644 | dret = radeon_ddc_probe(radeon_connector); |
644 | dret = radeon_ddc_probe(radeon_connector); |
645 | radeon_i2c_do_lock(radeon_connector, 0); |
645 | radeon_i2c_do_lock(radeon_connector, 0); |
646 | if (dret) { |
646 | if (dret) { |
647 | radeon_i2c_do_lock(radeon_connector, 1); |
647 | radeon_i2c_do_lock(radeon_connector, 1); |
648 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); |
648 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); |
649 | radeon_i2c_do_lock(radeon_connector, 0); |
649 | radeon_i2c_do_lock(radeon_connector, 0); |
650 | 650 | ||
651 | if (!radeon_connector->edid) { |
651 | if (!radeon_connector->edid) { |
652 | DRM_ERROR("DDC responded but not EDID found for %s\n", |
652 | DRM_ERROR("DDC responded but not EDID found for %s\n", |
653 | drm_get_connector_name(connector)); |
653 | drm_get_connector_name(connector)); |
654 | } else { |
654 | } else { |
655 | radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); |
655 | radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); |
656 | 656 | ||
657 | /* if this isn't a digital monitor |
657 | /* if this isn't a digital monitor |
658 | then we need to make sure we don't have any |
658 | then we need to make sure we don't have any |
659 | TV conflicts */ |
659 | TV conflicts */ |
660 | ret = connector_status_connected; |
660 | ret = connector_status_connected; |
661 | } |
661 | } |
662 | } |
662 | } |
663 | 663 | ||
664 | if ((ret == connector_status_connected) && (radeon_connector->use_digital == true)) |
664 | if ((ret == connector_status_connected) && (radeon_connector->use_digital == true)) |
665 | goto out; |
665 | goto out; |
666 | 666 | ||
667 | /* find analog encoder */ |
667 | /* find analog encoder */ |
668 | if (radeon_connector->dac_load_detect) { |
668 | if (radeon_connector->dac_load_detect) { |
669 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
669 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
670 | if (connector->encoder_ids[i] == 0) |
670 | if (connector->encoder_ids[i] == 0) |
671 | break; |
671 | break; |
672 | 672 | ||
673 | obj = drm_mode_object_find(connector->dev, |
673 | obj = drm_mode_object_find(connector->dev, |
674 | connector->encoder_ids[i], |
674 | connector->encoder_ids[i], |
675 | DRM_MODE_OBJECT_ENCODER); |
675 | DRM_MODE_OBJECT_ENCODER); |
676 | if (!obj) |
676 | if (!obj) |
677 | continue; |
677 | continue; |
678 | 678 | ||
679 | encoder = obj_to_encoder(obj); |
679 | encoder = obj_to_encoder(obj); |
680 | 680 | ||
681 | encoder_funcs = encoder->helper_private; |
681 | encoder_funcs = encoder->helper_private; |
682 | if (encoder_funcs->detect) { |
682 | if (encoder_funcs->detect) { |
683 | if (ret != connector_status_connected) { |
683 | if (ret != connector_status_connected) { |
684 | ret = encoder_funcs->detect(encoder, connector); |
684 | ret = encoder_funcs->detect(encoder, connector); |
685 | if (ret == connector_status_connected) { |
685 | if (ret == connector_status_connected) { |
686 | radeon_connector->use_digital = false; |
686 | radeon_connector->use_digital = false; |
687 | } |
687 | } |
688 | } |
688 | } |
689 | break; |
689 | break; |
690 | } |
690 | } |
691 | } |
691 | } |
692 | } |
692 | } |
693 | 693 | ||
694 | if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) && |
694 | if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) && |
695 | encoder) { |
695 | encoder) { |
696 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
696 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
697 | } |
697 | } |
698 | 698 | ||
699 | out: |
699 | out: |
700 | /* updated in get modes as well since we need to know if it's analog or digital */ |
700 | /* updated in get modes as well since we need to know if it's analog or digital */ |
701 | radeon_connector_update_scratch_regs(connector, ret); |
701 | radeon_connector_update_scratch_regs(connector, ret); |
702 | return ret; |
702 | return ret; |
703 | } |
703 | } |
704 | 704 | ||
705 | /* okay need to be smart in here about which encoder to pick */ |
705 | /* okay need to be smart in here about which encoder to pick */ |
706 | struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) |
706 | struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) |
707 | { |
707 | { |
708 | int enc_id = connector->encoder_ids[0]; |
708 | int enc_id = connector->encoder_ids[0]; |
709 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
709 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
710 | struct drm_mode_object *obj; |
710 | struct drm_mode_object *obj; |
711 | struct drm_encoder *encoder; |
711 | struct drm_encoder *encoder; |
712 | int i; |
712 | int i; |
713 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
713 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
714 | if (connector->encoder_ids[i] == 0) |
714 | if (connector->encoder_ids[i] == 0) |
715 | break; |
715 | break; |
716 | 716 | ||
717 | obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
717 | obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
718 | if (!obj) |
718 | if (!obj) |
719 | continue; |
719 | continue; |
720 | 720 | ||
721 | encoder = obj_to_encoder(obj); |
721 | encoder = obj_to_encoder(obj); |
722 | 722 | ||
723 | if (radeon_connector->use_digital == true) { |
723 | if (radeon_connector->use_digital == true) { |
724 | if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) |
724 | if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) |
725 | return encoder; |
725 | return encoder; |
726 | } else { |
726 | } else { |
727 | if (encoder->encoder_type == DRM_MODE_ENCODER_DAC || |
727 | if (encoder->encoder_type == DRM_MODE_ENCODER_DAC || |
728 | encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) |
728 | encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) |
729 | return encoder; |
729 | return encoder; |
730 | } |
730 | } |
731 | } |
731 | } |
732 | 732 | ||
733 | /* see if we have a default encoder TODO */ |
733 | /* see if we have a default encoder TODO */ |
734 | 734 | ||
735 | /* then check use digitial */ |
735 | /* then check use digitial */ |
736 | /* pick the first one */ |
736 | /* pick the first one */ |
737 | if (enc_id) { |
737 | if (enc_id) { |
738 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); |
738 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); |
739 | if (!obj) |
739 | if (!obj) |
740 | return NULL; |
740 | return NULL; |
741 | encoder = obj_to_encoder(obj); |
741 | encoder = obj_to_encoder(obj); |
742 | return encoder; |
742 | return encoder; |
743 | } |
743 | } |
744 | return NULL; |
744 | return NULL; |
745 | } |
745 | } |
746 | 746 | ||
747 | static void radeon_dvi_force(struct drm_connector *connector) |
747 | static void radeon_dvi_force(struct drm_connector *connector) |
748 | { |
748 | { |
749 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
749 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
750 | if (connector->force == DRM_FORCE_ON) |
750 | if (connector->force == DRM_FORCE_ON) |
751 | radeon_connector->use_digital = false; |
751 | radeon_connector->use_digital = false; |
752 | if (connector->force == DRM_FORCE_ON_DIGITAL) |
752 | if (connector->force == DRM_FORCE_ON_DIGITAL) |
753 | radeon_connector->use_digital = true; |
753 | radeon_connector->use_digital = true; |
754 | } |
754 | } |
755 | 755 | ||
756 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { |
756 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { |
757 | .get_modes = radeon_dvi_get_modes, |
757 | .get_modes = radeon_dvi_get_modes, |
758 | .mode_valid = radeon_vga_mode_valid, |
758 | .mode_valid = radeon_vga_mode_valid, |
759 | .best_encoder = radeon_dvi_encoder, |
759 | .best_encoder = radeon_dvi_encoder, |
760 | }; |
760 | }; |
761 | 761 | ||
762 | struct drm_connector_funcs radeon_dvi_connector_funcs = { |
762 | struct drm_connector_funcs radeon_dvi_connector_funcs = { |
763 | .dpms = drm_helper_connector_dpms, |
763 | .dpms = drm_helper_connector_dpms, |
764 | .detect = radeon_dvi_detect, |
764 | .detect = radeon_dvi_detect, |
765 | .fill_modes = drm_helper_probe_single_connector_modes, |
765 | .fill_modes = drm_helper_probe_single_connector_modes, |
766 | .set_property = radeon_connector_set_property, |
766 | .set_property = radeon_connector_set_property, |
767 | .destroy = radeon_connector_destroy, |
767 | .destroy = radeon_connector_destroy, |
768 | .force = radeon_dvi_force, |
768 | .force = radeon_dvi_force, |
769 | }; |
769 | }; |
770 | 770 | ||
771 | void |
771 | void |
772 | radeon_add_atom_connector(struct drm_device *dev, |
772 | radeon_add_atom_connector(struct drm_device *dev, |
773 | uint32_t connector_id, |
773 | uint32_t connector_id, |
774 | uint32_t supported_device, |
774 | uint32_t supported_device, |
775 | int connector_type, |
775 | int connector_type, |
776 | struct radeon_i2c_bus_rec *i2c_bus, |
776 | struct radeon_i2c_bus_rec *i2c_bus, |
777 | bool linkb, |
777 | bool linkb, |
778 | uint32_t igp_lane_info) |
778 | uint32_t igp_lane_info) |
779 | { |
779 | { |
780 | struct radeon_device *rdev = dev->dev_private; |
780 | struct radeon_device *rdev = dev->dev_private; |
781 | struct drm_connector *connector; |
781 | struct drm_connector *connector; |
782 | struct radeon_connector *radeon_connector; |
782 | struct radeon_connector *radeon_connector; |
783 | struct radeon_connector_atom_dig *radeon_dig_connector; |
783 | struct radeon_connector_atom_dig *radeon_dig_connector; |
784 | uint32_t subpixel_order = SubPixelNone; |
784 | uint32_t subpixel_order = SubPixelNone; |
785 | int ret; |
785 | int ret; |
786 | 786 | ||
787 | /* fixme - tv/cv/din */ |
787 | /* fixme - tv/cv/din */ |
788 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
788 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
789 | return; |
789 | return; |
790 | 790 | ||
791 | /* see if we already added it */ |
791 | /* see if we already added it */ |
792 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
792 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
793 | radeon_connector = to_radeon_connector(connector); |
793 | radeon_connector = to_radeon_connector(connector); |
794 | if (radeon_connector->connector_id == connector_id) { |
794 | if (radeon_connector->connector_id == connector_id) { |
795 | radeon_connector->devices |= supported_device; |
795 | radeon_connector->devices |= supported_device; |
796 | return; |
796 | return; |
797 | } |
797 | } |
798 | } |
798 | } |
799 | 799 | ||
800 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
800 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
801 | if (!radeon_connector) |
801 | if (!radeon_connector) |
802 | return; |
802 | return; |
803 | 803 | ||
804 | connector = &radeon_connector->base; |
804 | connector = &radeon_connector->base; |
805 | 805 | ||
806 | radeon_connector->connector_id = connector_id; |
806 | radeon_connector->connector_id = connector_id; |
807 | radeon_connector->devices = supported_device; |
807 | radeon_connector->devices = supported_device; |
808 | switch (connector_type) { |
808 | switch (connector_type) { |
809 | case DRM_MODE_CONNECTOR_VGA: |
809 | case DRM_MODE_CONNECTOR_VGA: |
810 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
810 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
811 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
811 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
812 | if (ret) |
812 | if (ret) |
813 | goto failed; |
813 | goto failed; |
814 | if (i2c_bus->valid) { |
814 | if (i2c_bus->valid) { |
815 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
815 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
816 | if (!radeon_connector->ddc_bus) |
816 | if (!radeon_connector->ddc_bus) |
817 | goto failed; |
817 | goto failed; |
818 | } |
818 | } |
819 | radeon_connector->dac_load_detect = true; |
819 | radeon_connector->dac_load_detect = true; |
820 | drm_connector_attach_property(&radeon_connector->base, |
820 | drm_connector_attach_property(&radeon_connector->base, |
821 | rdev->mode_info.load_detect_property, |
821 | rdev->mode_info.load_detect_property, |
822 | 1); |
822 | 1); |
823 | break; |
823 | break; |
824 | case DRM_MODE_CONNECTOR_DVIA: |
824 | case DRM_MODE_CONNECTOR_DVIA: |
825 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
825 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
826 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
826 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
827 | if (ret) |
827 | if (ret) |
828 | goto failed; |
828 | goto failed; |
829 | if (i2c_bus->valid) { |
829 | if (i2c_bus->valid) { |
830 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
830 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
831 | if (!radeon_connector->ddc_bus) |
831 | if (!radeon_connector->ddc_bus) |
832 | goto failed; |
832 | goto failed; |
833 | } |
833 | } |
834 | radeon_connector->dac_load_detect = true; |
834 | radeon_connector->dac_load_detect = true; |
835 | drm_connector_attach_property(&radeon_connector->base, |
835 | drm_connector_attach_property(&radeon_connector->base, |
836 | rdev->mode_info.load_detect_property, |
836 | rdev->mode_info.load_detect_property, |
837 | 1); |
837 | 1); |
838 | break; |
838 | break; |
839 | case DRM_MODE_CONNECTOR_DVII: |
839 | case DRM_MODE_CONNECTOR_DVII: |
840 | case DRM_MODE_CONNECTOR_DVID: |
840 | case DRM_MODE_CONNECTOR_DVID: |
841 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
841 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
842 | if (!radeon_dig_connector) |
842 | if (!radeon_dig_connector) |
843 | goto failed; |
843 | goto failed; |
844 | radeon_dig_connector->linkb = linkb; |
844 | radeon_dig_connector->linkb = linkb; |
845 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
845 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
846 | radeon_connector->con_priv = radeon_dig_connector; |
846 | radeon_connector->con_priv = radeon_dig_connector; |
847 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
847 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
848 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
848 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
849 | if (ret) |
849 | if (ret) |
850 | goto failed; |
850 | goto failed; |
851 | if (i2c_bus->valid) { |
851 | if (i2c_bus->valid) { |
852 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
852 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
853 | if (!radeon_connector->ddc_bus) |
853 | if (!radeon_connector->ddc_bus) |
854 | goto failed; |
854 | goto failed; |
855 | } |
855 | } |
856 | subpixel_order = SubPixelHorizontalRGB; |
856 | subpixel_order = SubPixelHorizontalRGB; |
857 | drm_connector_attach_property(&radeon_connector->base, |
857 | drm_connector_attach_property(&radeon_connector->base, |
858 | rdev->mode_info.coherent_mode_property, |
858 | rdev->mode_info.coherent_mode_property, |
859 | 1); |
859 | 1); |
860 | radeon_connector->dac_load_detect = true; |
860 | radeon_connector->dac_load_detect = true; |
861 | drm_connector_attach_property(&radeon_connector->base, |
861 | drm_connector_attach_property(&radeon_connector->base, |
862 | rdev->mode_info.load_detect_property, |
862 | rdev->mode_info.load_detect_property, |
863 | 1); |
863 | 1); |
864 | break; |
864 | break; |
865 | case DRM_MODE_CONNECTOR_HDMIA: |
865 | case DRM_MODE_CONNECTOR_HDMIA: |
866 | case DRM_MODE_CONNECTOR_HDMIB: |
866 | case DRM_MODE_CONNECTOR_HDMIB: |
867 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
867 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
868 | if (!radeon_dig_connector) |
868 | if (!radeon_dig_connector) |
869 | goto failed; |
869 | goto failed; |
870 | radeon_dig_connector->linkb = linkb; |
870 | radeon_dig_connector->linkb = linkb; |
871 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
871 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
872 | radeon_connector->con_priv = radeon_dig_connector; |
872 | radeon_connector->con_priv = radeon_dig_connector; |
873 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
873 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
874 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
874 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
875 | if (ret) |
875 | if (ret) |
876 | goto failed; |
876 | goto failed; |
877 | if (i2c_bus->valid) { |
877 | if (i2c_bus->valid) { |
878 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); |
878 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); |
879 | if (!radeon_connector->ddc_bus) |
879 | if (!radeon_connector->ddc_bus) |
880 | goto failed; |
880 | goto failed; |
881 | } |
881 | } |
882 | drm_connector_attach_property(&radeon_connector->base, |
882 | drm_connector_attach_property(&radeon_connector->base, |
883 | rdev->mode_info.coherent_mode_property, |
883 | rdev->mode_info.coherent_mode_property, |
884 | 1); |
884 | 1); |
885 | subpixel_order = SubPixelHorizontalRGB; |
885 | subpixel_order = SubPixelHorizontalRGB; |
886 | break; |
886 | break; |
887 | case DRM_MODE_CONNECTOR_DisplayPort: |
887 | case DRM_MODE_CONNECTOR_DisplayPort: |
888 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
888 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
889 | if (!radeon_dig_connector) |
889 | if (!radeon_dig_connector) |
890 | goto failed; |
890 | goto failed; |
891 | radeon_dig_connector->linkb = linkb; |
891 | radeon_dig_connector->linkb = linkb; |
892 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
892 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
893 | radeon_connector->con_priv = radeon_dig_connector; |
893 | radeon_connector->con_priv = radeon_dig_connector; |
894 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
894 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
895 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
895 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
896 | if (ret) |
896 | if (ret) |
897 | goto failed; |
897 | goto failed; |
898 | if (i2c_bus->valid) { |
898 | if (i2c_bus->valid) { |
899 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); |
899 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); |
900 | if (!radeon_connector->ddc_bus) |
900 | if (!radeon_connector->ddc_bus) |
901 | goto failed; |
901 | goto failed; |
902 | } |
902 | } |
903 | subpixel_order = SubPixelHorizontalRGB; |
903 | subpixel_order = SubPixelHorizontalRGB; |
904 | break; |
904 | break; |
905 | case DRM_MODE_CONNECTOR_SVIDEO: |
905 | case DRM_MODE_CONNECTOR_SVIDEO: |
906 | case DRM_MODE_CONNECTOR_Composite: |
906 | case DRM_MODE_CONNECTOR_Composite: |
907 | case DRM_MODE_CONNECTOR_9PinDIN: |
907 | case DRM_MODE_CONNECTOR_9PinDIN: |
908 | if (radeon_tv == 1) { |
908 | if (radeon_tv == 1) { |
909 | drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
909 | drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
910 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
910 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
911 | if (ret) |
911 | if (ret) |
912 | goto failed; |
912 | goto failed; |
913 | radeon_connector->dac_load_detect = true; |
913 | radeon_connector->dac_load_detect = true; |
914 | drm_connector_attach_property(&radeon_connector->base, |
914 | drm_connector_attach_property(&radeon_connector->base, |
915 | rdev->mode_info.load_detect_property, |
915 | rdev->mode_info.load_detect_property, |
916 | 1); |
916 | 1); |
917 | } |
917 | } |
918 | break; |
918 | break; |
919 | case DRM_MODE_CONNECTOR_LVDS: |
919 | case DRM_MODE_CONNECTOR_LVDS: |
920 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
920 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
921 | if (!radeon_dig_connector) |
921 | if (!radeon_dig_connector) |
922 | goto failed; |
922 | goto failed; |
923 | radeon_dig_connector->linkb = linkb; |
923 | radeon_dig_connector->linkb = linkb; |
924 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
924 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
925 | radeon_connector->con_priv = radeon_dig_connector; |
925 | radeon_connector->con_priv = radeon_dig_connector; |
926 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
926 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
927 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
927 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
928 | if (ret) |
928 | if (ret) |
929 | goto failed; |
929 | goto failed; |
930 | if (i2c_bus->valid) { |
930 | if (i2c_bus->valid) { |
931 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
931 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
932 | if (!radeon_connector->ddc_bus) |
932 | if (!radeon_connector->ddc_bus) |
933 | goto failed; |
933 | goto failed; |
934 | } |
934 | } |
935 | drm_mode_create_scaling_mode_property(dev); |
935 | drm_mode_create_scaling_mode_property(dev); |
936 | drm_connector_attach_property(&radeon_connector->base, |
936 | drm_connector_attach_property(&radeon_connector->base, |
937 | dev->mode_config.scaling_mode_property, |
937 | dev->mode_config.scaling_mode_property, |
938 | DRM_MODE_SCALE_FULLSCREEN); |
938 | DRM_MODE_SCALE_FULLSCREEN); |
939 | subpixel_order = SubPixelHorizontalRGB; |
939 | subpixel_order = SubPixelHorizontalRGB; |
940 | break; |
940 | break; |
941 | } |
941 | } |
942 | 942 | ||
943 | connector->display_info.subpixel_order = subpixel_order; |
943 | connector->display_info.subpixel_order = subpixel_order; |
944 | drm_sysfs_connector_add(connector); |
944 | drm_sysfs_connector_add(connector); |
945 | return; |
945 | return; |
946 | 946 | ||
947 | failed: |
947 | failed: |
948 | if (radeon_connector->ddc_bus) |
948 | if (radeon_connector->ddc_bus) |
949 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
949 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
950 | drm_connector_cleanup(connector); |
950 | drm_connector_cleanup(connector); |
951 | kfree(connector); |
951 | kfree(connector); |
952 | } |
952 | } |
953 | 953 | ||
954 | void |
954 | void |
955 | radeon_add_legacy_connector(struct drm_device *dev, |
955 | radeon_add_legacy_connector(struct drm_device *dev, |
956 | uint32_t connector_id, |
956 | uint32_t connector_id, |
957 | uint32_t supported_device, |
957 | uint32_t supported_device, |
958 | int connector_type, |
958 | int connector_type, |
959 | struct radeon_i2c_bus_rec *i2c_bus) |
959 | struct radeon_i2c_bus_rec *i2c_bus) |
960 | { |
960 | { |
961 | struct radeon_device *rdev = dev->dev_private; |
961 | struct radeon_device *rdev = dev->dev_private; |
962 | struct drm_connector *connector; |
962 | struct drm_connector *connector; |
963 | struct radeon_connector *radeon_connector; |
963 | struct radeon_connector *radeon_connector; |
964 | uint32_t subpixel_order = SubPixelNone; |
964 | uint32_t subpixel_order = SubPixelNone; |
965 | int ret; |
965 | int ret; |
- | 966 | ||
- | 967 | ENTER(); |
|
- | 968 | ||
- | 969 | dbgprintf("id %d device %x type %x i2c %x\n", |
|
966 | 970 | connector_id, supported_device, connector_type, i2c_bus); |
|
967 | /* fixme - tv/cv/din */ |
971 | /* fixme - tv/cv/din */ |
968 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
972 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
969 | return; |
973 | return; |
970 | 974 | ||
971 | /* see if we already added it */ |
975 | /* see if we already added it */ |
972 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
976 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
973 | radeon_connector = to_radeon_connector(connector); |
977 | radeon_connector = to_radeon_connector(connector); |
974 | if (radeon_connector->connector_id == connector_id) { |
978 | if (radeon_connector->connector_id == connector_id) { |
975 | radeon_connector->devices |= supported_device; |
979 | radeon_connector->devices |= supported_device; |
- | 980 | LEAVE(); |
|
976 | return; |
981 | return; |
977 | } |
982 | } |
978 | } |
983 | } |
979 | 984 | ||
980 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
985 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
981 | if (!radeon_connector) |
986 | if (!radeon_connector) |
982 | return; |
987 | return; |
983 | 988 | ||
984 | connector = &radeon_connector->base; |
989 | connector = &radeon_connector->base; |
985 | 990 | ||
986 | radeon_connector->connector_id = connector_id; |
991 | radeon_connector->connector_id = connector_id; |
987 | radeon_connector->devices = supported_device; |
992 | radeon_connector->devices = supported_device; |
988 | switch (connector_type) { |
993 | switch (connector_type) { |
989 | case DRM_MODE_CONNECTOR_VGA: |
994 | case DRM_MODE_CONNECTOR_VGA: |
990 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
995 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
991 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
996 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
992 | if (ret) |
997 | if (ret) |
993 | goto failed; |
998 | goto failed; |
994 | if (i2c_bus->valid) { |
999 | if (i2c_bus->valid) { |
995 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
1000 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
996 | if (!radeon_connector->ddc_bus) |
1001 | if (!radeon_connector->ddc_bus) |
997 | goto failed; |
1002 | goto failed; |
998 | } |
1003 | } |
999 | radeon_connector->dac_load_detect = true; |
1004 | radeon_connector->dac_load_detect = true; |
1000 | drm_connector_attach_property(&radeon_connector->base, |
1005 | drm_connector_attach_property(&radeon_connector->base, |
1001 | rdev->mode_info.load_detect_property, |
1006 | rdev->mode_info.load_detect_property, |
1002 | 1); |
1007 | 1); |
1003 | break; |
1008 | break; |
1004 | case DRM_MODE_CONNECTOR_DVIA: |
1009 | case DRM_MODE_CONNECTOR_DVIA: |
1005 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1010 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1006 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1011 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1007 | if (ret) |
1012 | if (ret) |
1008 | goto failed; |
1013 | goto failed; |
1009 | if (i2c_bus->valid) { |
1014 | if (i2c_bus->valid) { |
1010 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
1015 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
1011 | if (!radeon_connector->ddc_bus) |
1016 | if (!radeon_connector->ddc_bus) |
1012 | goto failed; |
1017 | goto failed; |
1013 | } |
1018 | } |
1014 | radeon_connector->dac_load_detect = true; |
1019 | radeon_connector->dac_load_detect = true; |
1015 | drm_connector_attach_property(&radeon_connector->base, |
1020 | drm_connector_attach_property(&radeon_connector->base, |
1016 | rdev->mode_info.load_detect_property, |
1021 | rdev->mode_info.load_detect_property, |
1017 | 1); |
1022 | 1); |
1018 | break; |
1023 | break; |
1019 | case DRM_MODE_CONNECTOR_DVII: |
1024 | case DRM_MODE_CONNECTOR_DVII: |
1020 | case DRM_MODE_CONNECTOR_DVID: |
1025 | case DRM_MODE_CONNECTOR_DVID: |
1021 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1026 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1022 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1027 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1023 | if (ret) |
1028 | if (ret) |
1024 | goto failed; |
1029 | goto failed; |
1025 | if (i2c_bus->valid) { |
1030 | if (i2c_bus->valid) { |
1026 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
1031 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
1027 | if (!radeon_connector->ddc_bus) |
1032 | if (!radeon_connector->ddc_bus) |
1028 | goto failed; |
1033 | goto failed; |
1029 | radeon_connector->dac_load_detect = true; |
1034 | radeon_connector->dac_load_detect = true; |
1030 | drm_connector_attach_property(&radeon_connector->base, |
1035 | drm_connector_attach_property(&radeon_connector->base, |
1031 | rdev->mode_info.load_detect_property, |
1036 | rdev->mode_info.load_detect_property, |
1032 | 1); |
1037 | 1); |
1033 | } |
1038 | } |
1034 | subpixel_order = SubPixelHorizontalRGB; |
1039 | subpixel_order = SubPixelHorizontalRGB; |
1035 | break; |
1040 | break; |
1036 | case DRM_MODE_CONNECTOR_SVIDEO: |
1041 | case DRM_MODE_CONNECTOR_SVIDEO: |
1037 | case DRM_MODE_CONNECTOR_Composite: |
1042 | case DRM_MODE_CONNECTOR_Composite: |
1038 | case DRM_MODE_CONNECTOR_9PinDIN: |
1043 | case DRM_MODE_CONNECTOR_9PinDIN: |
1039 | if (radeon_tv == 1) { |
1044 | if (radeon_tv == 1) { |
1040 | drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
1045 | drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
1041 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
1046 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
1042 | if (ret) |
1047 | if (ret) |
1043 | goto failed; |
1048 | goto failed; |
1044 | radeon_connector->dac_load_detect = true; |
1049 | radeon_connector->dac_load_detect = true; |
1045 | drm_connector_attach_property(&radeon_connector->base, |
1050 | drm_connector_attach_property(&radeon_connector->base, |
1046 | rdev->mode_info.load_detect_property, |
1051 | rdev->mode_info.load_detect_property, |
1047 | 1); |
1052 | 1); |
1048 | } |
1053 | } |
1049 | break; |
1054 | break; |
1050 | case DRM_MODE_CONNECTOR_LVDS: |
1055 | case DRM_MODE_CONNECTOR_LVDS: |
1051 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
1056 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
1052 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
1057 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
1053 | if (ret) |
1058 | if (ret) |
1054 | goto failed; |
1059 | goto failed; |
1055 | if (i2c_bus->valid) { |
1060 | if (i2c_bus->valid) { |
1056 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
1061 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
1057 | if (!radeon_connector->ddc_bus) |
1062 | if (!radeon_connector->ddc_bus) |
1058 | goto failed; |
1063 | goto failed; |
1059 | } |
1064 | } |
1060 | drm_connector_attach_property(&radeon_connector->base, |
1065 | drm_connector_attach_property(&radeon_connector->base, |
1061 | dev->mode_config.scaling_mode_property, |
1066 | dev->mode_config.scaling_mode_property, |
1062 | DRM_MODE_SCALE_FULLSCREEN); |
1067 | DRM_MODE_SCALE_FULLSCREEN); |
1063 | subpixel_order = SubPixelHorizontalRGB; |
1068 | subpixel_order = SubPixelHorizontalRGB; |
1064 | break; |
1069 | break; |
1065 | } |
1070 | } |
1066 | 1071 | ||
1067 | connector->display_info.subpixel_order = subpixel_order; |
1072 | connector->display_info.subpixel_order = subpixel_order; |
1068 | drm_sysfs_connector_add(connector); |
1073 | drm_sysfs_connector_add(connector); |
- | 1074 | LEAVE(); |
|
1069 | return; |
1075 | return; |
1070 | 1076 | ||
1071 | failed: |
1077 | failed: |
1072 | if (radeon_connector->ddc_bus) |
1078 | if (radeon_connector->ddc_bus) |
1073 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
1079 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
1074 | drm_connector_cleanup(connector); |
1080 | drm_connector_cleanup(connector); |
1075 | kfree(connector); |
1081 | kfree(connector); |
- | 1082 | LEAVE(); |
|
1076 | }>>>>>>>> |
1083 | }>>>>>>>> |