Rev 1963 | Rev 2160 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1963 | Rev 1986 | ||
---|---|---|---|
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_crtc_helper.h" |
27 | #include "drm_crtc_helper.h" |
28 | #include "radeon_drm.h" |
28 | #include "radeon_drm.h" |
29 | #include "radeon.h" |
29 | #include "radeon.h" |
30 | #include "atom.h" |
30 | #include "atom.h" |
31 | 31 | ||
32 | extern int atom_debug; |
32 | extern int atom_debug; |
33 | 33 | ||
34 | /* evil but including atombios.h is much worse */ |
34 | /* evil but including atombios.h is much worse */ |
35 | bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, |
35 | bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, |
36 | struct drm_display_mode *mode); |
36 | struct drm_display_mode *mode); |
37 | 37 | ||
38 | static uint32_t radeon_encoder_clones(struct drm_encoder *encoder) |
38 | static uint32_t radeon_encoder_clones(struct drm_encoder *encoder) |
39 | { |
39 | { |
40 | struct drm_device *dev = encoder->dev; |
40 | struct drm_device *dev = encoder->dev; |
41 | struct radeon_device *rdev = dev->dev_private; |
41 | struct radeon_device *rdev = dev->dev_private; |
42 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
42 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
43 | struct drm_encoder *clone_encoder; |
43 | struct drm_encoder *clone_encoder; |
44 | uint32_t index_mask = 0; |
44 | uint32_t index_mask = 0; |
45 | int count; |
45 | int count; |
46 | 46 | ||
47 | /* DIG routing gets problematic */ |
47 | /* DIG routing gets problematic */ |
48 | if (rdev->family >= CHIP_R600) |
48 | if (rdev->family >= CHIP_R600) |
49 | return index_mask; |
49 | return index_mask; |
50 | /* LVDS/TV are too wacky */ |
50 | /* LVDS/TV are too wacky */ |
51 | if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) |
51 | if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) |
52 | return index_mask; |
52 | return index_mask; |
53 | /* DVO requires 2x ppll clocks depending on tmds chip */ |
53 | /* DVO requires 2x ppll clocks depending on tmds chip */ |
54 | if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) |
54 | if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) |
55 | return index_mask; |
55 | return index_mask; |
56 | 56 | ||
57 | count = -1; |
57 | count = -1; |
58 | list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) { |
58 | list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) { |
59 | struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder); |
59 | struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder); |
60 | count++; |
60 | count++; |
61 | 61 | ||
62 | if (clone_encoder == encoder) |
62 | if (clone_encoder == encoder) |
63 | continue; |
63 | continue; |
64 | if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) |
64 | if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) |
65 | continue; |
65 | continue; |
66 | if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT) |
66 | if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT) |
67 | continue; |
67 | continue; |
68 | else |
68 | else |
69 | index_mask |= (1 << count); |
69 | index_mask |= (1 << count); |
70 | } |
70 | } |
71 | return index_mask; |
71 | return index_mask; |
72 | } |
72 | } |
73 | 73 | ||
74 | void radeon_setup_encoder_clones(struct drm_device *dev) |
74 | void radeon_setup_encoder_clones(struct drm_device *dev) |
75 | { |
75 | { |
76 | struct drm_encoder *encoder; |
76 | struct drm_encoder *encoder; |
77 | 77 | ||
78 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
78 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
79 | encoder->possible_clones = radeon_encoder_clones(encoder); |
79 | encoder->possible_clones = radeon_encoder_clones(encoder); |
80 | } |
80 | } |
81 | } |
81 | } |
82 | 82 | ||
83 | uint32_t |
83 | uint32_t |
84 | radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac) |
84 | radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac) |
85 | { |
85 | { |
86 | struct radeon_device *rdev = dev->dev_private; |
86 | struct radeon_device *rdev = dev->dev_private; |
87 | uint32_t ret = 0; |
87 | uint32_t ret = 0; |
88 | 88 | ||
89 | switch (supported_device) { |
89 | switch (supported_device) { |
90 | case ATOM_DEVICE_CRT1_SUPPORT: |
90 | case ATOM_DEVICE_CRT1_SUPPORT: |
91 | case ATOM_DEVICE_TV1_SUPPORT: |
91 | case ATOM_DEVICE_TV1_SUPPORT: |
92 | case ATOM_DEVICE_TV2_SUPPORT: |
92 | case ATOM_DEVICE_TV2_SUPPORT: |
93 | case ATOM_DEVICE_CRT2_SUPPORT: |
93 | case ATOM_DEVICE_CRT2_SUPPORT: |
94 | case ATOM_DEVICE_CV_SUPPORT: |
94 | case ATOM_DEVICE_CV_SUPPORT: |
95 | switch (dac) { |
95 | switch (dac) { |
96 | case 1: /* dac a */ |
96 | case 1: /* dac a */ |
97 | if ((rdev->family == CHIP_RS300) || |
97 | if ((rdev->family == CHIP_RS300) || |
98 | (rdev->family == CHIP_RS400) || |
98 | (rdev->family == CHIP_RS400) || |
99 | (rdev->family == CHIP_RS480)) |
99 | (rdev->family == CHIP_RS480)) |
100 | ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; |
100 | ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; |
101 | else if (ASIC_IS_AVIVO(rdev)) |
101 | else if (ASIC_IS_AVIVO(rdev)) |
102 | ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; |
102 | ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; |
103 | else |
103 | else |
104 | ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; |
104 | ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; |
105 | break; |
105 | break; |
106 | case 2: /* dac b */ |
106 | case 2: /* dac b */ |
107 | if (ASIC_IS_AVIVO(rdev)) |
107 | if (ASIC_IS_AVIVO(rdev)) |
108 | ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; |
108 | ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; |
109 | else { |
109 | else { |
110 | /*if (rdev->family == CHIP_R200) |
110 | /*if (rdev->family == CHIP_R200) |
111 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
111 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
112 | else*/ |
112 | else*/ |
113 | ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; |
113 | ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; |
114 | } |
114 | } |
115 | break; |
115 | break; |
116 | case 3: /* external dac */ |
116 | case 3: /* external dac */ |
117 | if (ASIC_IS_AVIVO(rdev)) |
117 | if (ASIC_IS_AVIVO(rdev)) |
118 | ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; |
118 | ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; |
119 | else |
119 | else |
120 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
120 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
121 | break; |
121 | break; |
122 | } |
122 | } |
123 | break; |
123 | break; |
124 | case ATOM_DEVICE_LCD1_SUPPORT: |
124 | case ATOM_DEVICE_LCD1_SUPPORT: |
125 | if (ASIC_IS_AVIVO(rdev)) |
125 | if (ASIC_IS_AVIVO(rdev)) |
126 | ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; |
126 | ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; |
127 | else |
127 | else |
128 | ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; |
128 | ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; |
129 | break; |
129 | break; |
130 | case ATOM_DEVICE_DFP1_SUPPORT: |
130 | case ATOM_DEVICE_DFP1_SUPPORT: |
131 | if ((rdev->family == CHIP_RS300) || |
131 | if ((rdev->family == CHIP_RS300) || |
132 | (rdev->family == CHIP_RS400) || |
132 | (rdev->family == CHIP_RS400) || |
133 | (rdev->family == CHIP_RS480)) |
133 | (rdev->family == CHIP_RS480)) |
134 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
134 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
135 | else if (ASIC_IS_AVIVO(rdev)) |
135 | else if (ASIC_IS_AVIVO(rdev)) |
136 | ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; |
136 | ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; |
137 | else |
137 | else |
138 | ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; |
138 | ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; |
139 | break; |
139 | break; |
140 | case ATOM_DEVICE_LCD2_SUPPORT: |
140 | case ATOM_DEVICE_LCD2_SUPPORT: |
141 | case ATOM_DEVICE_DFP2_SUPPORT: |
141 | case ATOM_DEVICE_DFP2_SUPPORT: |
142 | if ((rdev->family == CHIP_RS600) || |
142 | if ((rdev->family == CHIP_RS600) || |
143 | (rdev->family == CHIP_RS690) || |
143 | (rdev->family == CHIP_RS690) || |
144 | (rdev->family == CHIP_RS740)) |
144 | (rdev->family == CHIP_RS740)) |
145 | ret = ENCODER_INTERNAL_DDI_ENUM_ID1; |
145 | ret = ENCODER_INTERNAL_DDI_ENUM_ID1; |
146 | else if (ASIC_IS_AVIVO(rdev)) |
146 | else if (ASIC_IS_AVIVO(rdev)) |
147 | ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; |
147 | ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; |
148 | else |
148 | else |
149 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
149 | ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; |
150 | break; |
150 | break; |
151 | case ATOM_DEVICE_DFP3_SUPPORT: |
151 | case ATOM_DEVICE_DFP3_SUPPORT: |
152 | ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; |
152 | ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; |
153 | break; |
153 | break; |
154 | } |
154 | } |
155 | 155 | ||
156 | return ret; |
156 | return ret; |
157 | } |
157 | } |
158 | 158 | ||
159 | static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) |
159 | static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) |
160 | { |
160 | { |
161 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
161 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
162 | switch (radeon_encoder->encoder_id) { |
162 | switch (radeon_encoder->encoder_id) { |
163 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: |
163 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: |
164 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: |
164 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: |
165 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: |
165 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: |
166 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: |
166 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: |
167 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
167 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
168 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
168 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
169 | case ENCODER_OBJECT_ID_INTERNAL_DDI: |
169 | case ENCODER_OBJECT_ID_INTERNAL_DDI: |
170 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
170 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
171 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
171 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
172 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
172 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
173 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
173 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
174 | return true; |
174 | return true; |
175 | default: |
175 | default: |
176 | return false; |
176 | return false; |
177 | } |
177 | } |
178 | } |
178 | } |
179 | 179 | ||
180 | void |
180 | void |
181 | radeon_link_encoder_connector(struct drm_device *dev) |
181 | radeon_link_encoder_connector(struct drm_device *dev) |
182 | { |
182 | { |
183 | struct drm_connector *connector; |
183 | struct drm_connector *connector; |
184 | struct radeon_connector *radeon_connector; |
184 | struct radeon_connector *radeon_connector; |
185 | struct drm_encoder *encoder; |
185 | struct drm_encoder *encoder; |
186 | struct radeon_encoder *radeon_encoder; |
186 | struct radeon_encoder *radeon_encoder; |
187 | 187 | ||
188 | /* walk the list and link encoders to connectors */ |
188 | /* walk the list and link encoders to connectors */ |
189 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
189 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
190 | radeon_connector = to_radeon_connector(connector); |
190 | radeon_connector = to_radeon_connector(connector); |
191 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
191 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
192 | radeon_encoder = to_radeon_encoder(encoder); |
192 | radeon_encoder = to_radeon_encoder(encoder); |
193 | if (radeon_encoder->devices & radeon_connector->devices) |
193 | if (radeon_encoder->devices & radeon_connector->devices) |
194 | drm_mode_connector_attach_encoder(connector, encoder); |
194 | drm_mode_connector_attach_encoder(connector, encoder); |
195 | } |
195 | } |
196 | } |
196 | } |
197 | } |
197 | } |
198 | 198 | ||
199 | void radeon_encoder_set_active_device(struct drm_encoder *encoder) |
199 | void radeon_encoder_set_active_device(struct drm_encoder *encoder) |
200 | { |
200 | { |
201 | struct drm_device *dev = encoder->dev; |
201 | struct drm_device *dev = encoder->dev; |
202 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
202 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
203 | struct drm_connector *connector; |
203 | struct drm_connector *connector; |
204 |