Rev 2330 | Rev 2342 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2330 | Serge | 1 | /* |
2 | * Copyright 2006 Dave Airlie |
||
3 | * Copyright © 2006-2007 Intel Corporation |
||
4 | * Jesse Barnes |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice (including the next |
||
14 | * paragraph) shall be included in all copies or substantial portions of the |
||
15 | * Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
23 | * DEALINGS IN THE SOFTWARE. |
||
24 | * |
||
25 | * Authors: |
||
26 | * Eric Anholt |
||
27 | */ |
||
28 | #include |
||
29 | #include |
||
30 | //#include |
||
31 | #include "drmP.h" |
||
32 | #include "drm.h" |
||
33 | #include "drm_crtc.h" |
||
34 | #include "drm_edid.h" |
||
35 | #include "intel_drv.h" |
||
36 | #include "i915_drm.h" |
||
37 | #include "i915_drv.h" |
||
38 | #include "intel_sdvo_regs.h" |
||
39 | |||
40 | unsigned int hweight16(unsigned int w) |
||
41 | { |
||
42 | unsigned int res = w - ((w >> 1) & 0x5555); |
||
43 | res = (res & 0x3333) + ((res >> 2) & 0x3333); |
||
44 | res = (res + (res >> 4)) & 0x0F0F; |
||
45 | return (res + (res >> 8)) & 0x00FF; |
||
46 | } |
||
47 | |||
48 | |||
49 | #define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1) |
||
50 | #define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1) |
||
51 | #define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1) |
||
52 | #define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0) |
||
53 | |||
54 | #define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\ |
||
55 | SDVO_TV_MASK) |
||
56 | |||
57 | #define IS_TV(c) (c->output_flag & SDVO_TV_MASK) |
||
58 | #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) |
||
59 | #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) |
||
60 | #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) |
||
61 | |||
62 | |||
63 | static const char *tv_format_names[] = { |
||
64 | "NTSC_M" , "NTSC_J" , "NTSC_443", |
||
65 | "PAL_B" , "PAL_D" , "PAL_G" , |
||
66 | "PAL_H" , "PAL_I" , "PAL_M" , |
||
67 | "PAL_N" , "PAL_NC" , "PAL_60" , |
||
68 | "SECAM_B" , "SECAM_D" , "SECAM_G" , |
||
69 | "SECAM_K" , "SECAM_K1", "SECAM_L" , |
||
70 | "SECAM_60" |
||
71 | }; |
||
72 | |||
73 | #define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names)) |
||
74 | |||
75 | struct intel_sdvo { |
||
76 | struct intel_encoder base; |
||
77 | |||
78 | struct i2c_adapter *i2c; |
||
79 | u8 slave_addr; |
||
80 | |||
81 | struct i2c_adapter ddc; |
||
82 | |||
83 | /* Register for the SDVO device: SDVOB or SDVOC */ |
||
84 | int sdvo_reg; |
||
85 | |||
86 | /* Active outputs controlled by this SDVO output */ |
||
87 | uint16_t controlled_output; |
||
88 | |||
89 | /* |
||
90 | * Capabilities of the SDVO device returned by |
||
91 | * i830_sdvo_get_capabilities() |
||
92 | */ |
||
93 | struct intel_sdvo_caps caps; |
||
94 | |||
95 | /* Pixel clock limitations reported by the SDVO device, in kHz */ |
||
96 | int pixel_clock_min, pixel_clock_max; |
||
97 | |||
98 | /* |
||
99 | * For multiple function SDVO device, |
||
100 | * this is for current attached outputs. |
||
101 | */ |
||
102 | uint16_t attached_output; |
||
103 | |||
104 | /** |
||
105 | * This is used to select the color range of RBG outputs in HDMI mode. |
||
106 | * It is only valid when using TMDS encoding and 8 bit per color mode. |
||
107 | */ |
||
108 | uint32_t color_range; |
||
109 | |||
110 | /** |
||
111 | * This is set if we're going to treat the device as TV-out. |
||
112 | * |
||
113 | * While we have these nice friendly flags for output types that ought |
||
114 | * to decide this for us, the S-Video output on our HDMI+S-Video card |
||
115 | * shows up as RGB1 (VGA). |
||
116 | */ |
||
117 | bool is_tv; |
||
118 | |||
119 | /* This is for current tv format name */ |
||
120 | int tv_format_index; |
||
121 | |||
122 | /** |
||
123 | * This is set if we treat the device as HDMI, instead of DVI. |
||
124 | */ |
||
125 | bool is_hdmi; |
||
126 | bool has_hdmi_monitor; |
||
127 | bool has_hdmi_audio; |
||
128 | |||
129 | /** |
||
130 | * This is set if we detect output of sdvo device as LVDS and |
||
131 | * have a valid fixed mode to use with the panel. |
||
132 | */ |
||
133 | bool is_lvds; |
||
134 | |||
135 | /** |
||
136 | * This is sdvo fixed pannel mode pointer |
||
137 | */ |
||
138 | struct drm_display_mode *sdvo_lvds_fixed_mode; |
||
139 | |||
140 | /* DDC bus used by this SDVO encoder */ |
||
141 | uint8_t ddc_bus; |
||
142 | |||
143 | /* Input timings for adjusted_mode */ |
||
144 | struct intel_sdvo_dtd input_dtd; |
||
145 | }; |
||
146 | |||
147 | struct intel_sdvo_connector { |
||
148 | struct intel_connector base; |
||
149 | |||
150 | /* Mark the type of connector */ |
||
151 | uint16_t output_flag; |
||
152 | |||
153 | int force_audio; |
||
154 | |||
155 | /* This contains all current supported TV format */ |
||
156 | u8 tv_format_supported[TV_FORMAT_NUM]; |
||
157 | int format_supported_num; |
||
158 | struct drm_property *tv_format; |
||
159 | |||
160 | /* add the property for the SDVO-TV */ |
||
161 | struct drm_property *left; |
||
162 | struct drm_property *right; |
||
163 | struct drm_property *top; |
||
164 | struct drm_property *bottom; |
||
165 | struct drm_property *hpos; |
||
166 | struct drm_property *vpos; |
||
167 | struct drm_property *contrast; |
||
168 | struct drm_property *saturation; |
||
169 | struct drm_property *hue; |
||
170 | struct drm_property *sharpness; |
||
171 | struct drm_property *flicker_filter; |
||
172 | struct drm_property *flicker_filter_adaptive; |
||
173 | struct drm_property *flicker_filter_2d; |
||
174 | struct drm_property *tv_chroma_filter; |
||
175 | struct drm_property *tv_luma_filter; |
||
176 | struct drm_property *dot_crawl; |
||
177 | |||
178 | /* add the property for the SDVO-TV/LVDS */ |
||
179 | struct drm_property *brightness; |
||
180 | |||
181 | /* Add variable to record current setting for the above property */ |
||
182 | u32 left_margin, right_margin, top_margin, bottom_margin; |
||
183 | |||
184 | /* this is to get the range of margin.*/ |
||
185 | u32 max_hscan, max_vscan; |
||
186 | u32 max_hpos, cur_hpos; |
||
187 | u32 max_vpos, cur_vpos; |
||
188 | u32 cur_brightness, max_brightness; |
||
189 | u32 cur_contrast, max_contrast; |
||
190 | u32 cur_saturation, max_saturation; |
||
191 | u32 cur_hue, max_hue; |
||
192 | u32 cur_sharpness, max_sharpness; |
||
193 | u32 cur_flicker_filter, max_flicker_filter; |
||
194 | u32 cur_flicker_filter_adaptive, max_flicker_filter_adaptive; |
||
195 | u32 cur_flicker_filter_2d, max_flicker_filter_2d; |
||
196 | u32 cur_tv_chroma_filter, max_tv_chroma_filter; |
||
197 | u32 cur_tv_luma_filter, max_tv_luma_filter; |
||
198 | u32 cur_dot_crawl, max_dot_crawl; |
||
199 | }; |
||
200 | |||
201 | static struct intel_sdvo *to_intel_sdvo(struct drm_encoder *encoder) |
||
202 | { |
||
203 | return container_of(encoder, struct intel_sdvo, base.base); |
||
204 | } |
||
205 | |||
206 | static struct intel_sdvo *intel_attached_sdvo(struct drm_connector *connector) |
||
207 | { |
||
208 | return container_of(intel_attached_encoder(connector), |
||
209 | struct intel_sdvo, base); |
||
210 | } |
||
211 | |||
212 | static struct intel_sdvo_connector *to_intel_sdvo_connector(struct drm_connector *connector) |
||
213 | { |
||
214 | return container_of(to_intel_connector(connector), struct intel_sdvo_connector, base); |
||
215 | } |
||
216 | |||
217 | static bool |
||
218 | intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags); |
||
219 | static bool |
||
220 | intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, |
||
221 | struct intel_sdvo_connector *intel_sdvo_connector, |
||
222 | int type); |
||
223 | static bool |
||
224 | intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, |
||
225 | struct intel_sdvo_connector *intel_sdvo_connector); |
||
226 | |||
227 | /** |
||
228 | * Writes the SDVOB or SDVOC with the given value, but always writes both |
||
229 | * SDVOB and SDVOC to work around apparent hardware issues (according to |
||
230 | * comments in the BIOS). |
||
231 | */ |
||
232 | static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) |
||
233 | { |
||
234 | struct drm_device *dev = intel_sdvo->base.base.dev; |
||
235 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
236 | u32 bval = val, cval = val; |
||
237 | int i; |
||
238 | |||
239 | if (intel_sdvo->sdvo_reg == PCH_SDVOB) { |
||
240 | I915_WRITE(intel_sdvo->sdvo_reg, val); |
||
241 | I915_READ(intel_sdvo->sdvo_reg); |
||
242 | return; |
||
243 | } |
||
244 | |||
245 | if (intel_sdvo->sdvo_reg == SDVOB) { |
||
246 | cval = I915_READ(SDVOC); |
||
247 | } else { |
||
248 | bval = I915_READ(SDVOB); |
||
249 | } |
||
250 | /* |
||
251 | * Write the registers twice for luck. Sometimes, |
||
252 | * writing them only once doesn't appear to 'stick'. |
||
253 | * The BIOS does this too. Yay, magic |
||
254 | */ |
||
255 | for (i = 0; i < 2; i++) |
||
256 | { |
||
257 | I915_WRITE(SDVOB, bval); |
||
258 | I915_READ(SDVOB); |
||
259 | I915_WRITE(SDVOC, cval); |
||
260 | I915_READ(SDVOC); |
||
261 | } |
||
262 | } |
||
263 | |||
264 | static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) |
||
265 | { |
||
266 | struct i2c_msg msgs[] = { |