Bug Summary

File:dev/pci/drm/i915/display/intel_dvo.c
Warning:line 510, column 4
Value stored to 'encoder_type' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name intel_dvo.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/drm/i915/display/intel_dvo.c
1/*
2 * Copyright 2006 Dave Airlie <airlied@linux.ie>
3 * Copyright © 2006-2007 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
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
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Eric Anholt <eric@anholt.net>
26 */
27
28#include <linux/i2c.h>
29#include <linux/slab.h>
30
31#include <drm/drm_atomic_helper.h>
32#include <drm/drm_crtc.h>
33
34#include "i915_drv.h"
35#include "intel_connector.h"
36#include "intel_de.h"
37#include "intel_display_types.h"
38#include "intel_dvo.h"
39#include "intel_dvo_dev.h"
40#include "intel_gmbus.h"
41#include "intel_panel.h"
42
43#define INTEL_DVO_CHIP_NONE0 0
44#define INTEL_DVO_CHIP_LVDS1 1
45#define INTEL_DVO_CHIP_TMDS2 2
46#define INTEL_DVO_CHIP_TVOUT4 4
47#define INTEL_DVO_CHIP_LVDS_NO_FIXED5 5
48
49#define SIL164_ADDR0x38 0x38
50#define CH7xxx_ADDR0x76 0x76
51#define TFP410_ADDR0x38 0x38
52#define NS2501_ADDR0x38 0x38
53
54static const struct intel_dvo_device intel_dvo_devices[] = {
55 {
56 .type = INTEL_DVO_CHIP_TMDS2,
57 .name = "sil164",
58 .dvo_reg = DVOC((const i915_reg_t){ .reg = (0x61160) }),
59 .dvo_srcdim_reg = DVOC_SRCDIM((const i915_reg_t){ .reg = (0x61164) }),
60 .slave_addr = SIL164_ADDR0x38,
61 .dev_ops = &sil164_ops,
62 },
63 {
64 .type = INTEL_DVO_CHIP_TMDS2,
65 .name = "ch7xxx",
66 .dvo_reg = DVOC((const i915_reg_t){ .reg = (0x61160) }),
67 .dvo_srcdim_reg = DVOC_SRCDIM((const i915_reg_t){ .reg = (0x61164) }),
68 .slave_addr = CH7xxx_ADDR0x76,
69 .dev_ops = &ch7xxx_ops,
70 },
71 {
72 .type = INTEL_DVO_CHIP_TMDS2,
73 .name = "ch7xxx",
74 .dvo_reg = DVOC((const i915_reg_t){ .reg = (0x61160) }),
75 .dvo_srcdim_reg = DVOC_SRCDIM((const i915_reg_t){ .reg = (0x61164) }),
76 .slave_addr = 0x75, /* For some ch7010 */
77 .dev_ops = &ch7xxx_ops,
78 },
79 {
80 .type = INTEL_DVO_CHIP_LVDS1,
81 .name = "ivch",
82 .dvo_reg = DVOA((const i915_reg_t){ .reg = (0x61120) }),
83 .dvo_srcdim_reg = DVOA_SRCDIM((const i915_reg_t){ .reg = (0x61124) }),
84 .slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */
85 .dev_ops = &ivch_ops,
86 },
87 {
88 .type = INTEL_DVO_CHIP_TMDS2,
89 .name = "tfp410",
90 .dvo_reg = DVOC((const i915_reg_t){ .reg = (0x61160) }),
91 .dvo_srcdim_reg = DVOC_SRCDIM((const i915_reg_t){ .reg = (0x61164) }),
92 .slave_addr = TFP410_ADDR0x38,
93 .dev_ops = &tfp410_ops,
94 },
95 {
96 .type = INTEL_DVO_CHIP_LVDS1,
97 .name = "ch7017",
98 .dvo_reg = DVOC((const i915_reg_t){ .reg = (0x61160) }),
99 .dvo_srcdim_reg = DVOC_SRCDIM((const i915_reg_t){ .reg = (0x61164) }),
100 .slave_addr = 0x75,
101 .gpio = GMBUS_PIN_DPB5,
102 .dev_ops = &ch7017_ops,
103 },
104 {
105 .type = INTEL_DVO_CHIP_LVDS_NO_FIXED5,
106 .name = "ns2501",
107 .dvo_reg = DVOB((const i915_reg_t){ .reg = (0x61140) }),
108 .dvo_srcdim_reg = DVOB_SRCDIM((const i915_reg_t){ .reg = (0x61144) }),
109 .slave_addr = NS2501_ADDR0x38,
110 .dev_ops = &ns2501_ops,
111 },
112};
113
114struct intel_dvo {
115 struct intel_encoder base;
116
117 struct intel_dvo_device dev;
118
119 struct intel_connector *attached_connector;
120
121 bool_Bool panel_wants_dither;
122};
123
124static struct intel_dvo *enc_to_dvo(struct intel_encoder *encoder)
125{
126 return container_of(encoder, struct intel_dvo, base)({ const __typeof( ((struct intel_dvo *)0)->base ) *__mptr
= (encoder); (struct intel_dvo *)( (char *)__mptr - __builtin_offsetof
(struct intel_dvo, base) );})
;
127}
128
129static struct intel_dvo *intel_attached_dvo(struct intel_connector *connector)
130{
131 return enc_to_dvo(intel_attached_encoder(connector));
132}
133
134static bool_Bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
135{
136 struct drm_device *dev = connector->base.dev;
137 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
138 struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
139 u32 tmp;
140
141 tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg);
142
143 if (!(tmp & DVO_ENABLE(1 << 31)))
144 return false0;
145
146 return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev);
147}
148
149static bool_Bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
150 enum pipe *pipe)
151{
152 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
153 struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
154 u32 tmp;
155
156 tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg);
157
158 *pipe = (tmp & DVO_PIPE_SEL_MASK(1 << 30)) >> DVO_PIPE_SEL_SHIFT30;
159
160 return tmp & DVO_ENABLE(1 << 31);
161}
162
163static void intel_dvo_get_config(struct intel_encoder *encoder,
164 struct intel_crtc_state *pipe_config)
165{
166 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
167 struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
168 u32 tmp, flags = 0;
169
170 pipe_config->output_types |= BIT(INTEL_OUTPUT_DVO)(1UL << (INTEL_OUTPUT_DVO));
171
172 tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg);
173 if (tmp & DVO_HSYNC_ACTIVE_HIGH(1 << 3))
174 flags |= DRM_MODE_FLAG_PHSYNC(1<<0);
175 else
176 flags |= DRM_MODE_FLAG_NHSYNC(1<<1);
177 if (tmp & DVO_VSYNC_ACTIVE_HIGH(1 << 4))
178 flags |= DRM_MODE_FLAG_PVSYNC(1<<2);
179 else
180 flags |= DRM_MODE_FLAG_NVSYNC(1<<3);
181
182 pipe_config->hw.adjusted_mode.flags |= flags;
183
184 pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock;
185}
186
187static void intel_disable_dvo(struct intel_atomic_state *state,
188 struct intel_encoder *encoder,
189 const struct intel_crtc_state *old_crtc_state,
190 const struct drm_connector_state *old_conn_state)
191{
192 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
193 struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
194 i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
195 u32 temp = intel_de_read(dev_priv, dvo_reg);
196
197 intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false0);
198 intel_de_write(dev_priv, dvo_reg, temp & ~DVO_ENABLE(1 << 31));
199 intel_de_read(dev_priv, dvo_reg);
200}
201
202static void intel_enable_dvo(struct intel_atomic_state *state,
203 struct intel_encoder *encoder,
204 const struct intel_crtc_state *pipe_config,
205 const struct drm_connector_state *conn_state)
206{
207 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
208 struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
209 i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
210 u32 temp = intel_de_read(dev_priv, dvo_reg);
211
212 intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev,
213 &pipe_config->hw.mode,
214 &pipe_config->hw.adjusted_mode);
215
216 intel_de_write(dev_priv, dvo_reg, temp | DVO_ENABLE(1 << 31));
217 intel_de_read(dev_priv, dvo_reg);
218
219 intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true1);
220}
221
222static enum drm_mode_status
223intel_dvo_mode_valid(struct drm_connector *connector,
224 struct drm_display_mode *mode)
225{
226 struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) *
__mptr = (connector); (struct intel_connector *)( (char *)__mptr
- __builtin_offsetof(struct intel_connector, base) );})
;
227 struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector);
228 struct drm_i915_privateinteldrm_softc *i915 = to_i915(intel_connector->base.dev);
229 const struct drm_display_mode *fixed_mode =
230 intel_panel_fixed_mode(intel_connector, mode);
231 int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
232 int target_clock = mode->clock;
233 enum drm_mode_status status;
234
235 status = intel_cpu_transcoder_mode_valid(i915, mode);
236 if (status != MODE_OK)
237 return status;
238
239 if (mode->flags & DRM_MODE_FLAG_DBLSCAN(1<<5))
240 return MODE_NO_DBLESCAN;
241
242 /* XXX: Validate clock range */
243
244 if (fixed_mode) {
245 enum drm_mode_status status;
246
247 status = intel_panel_mode_valid(intel_connector, mode);
248 if (status != MODE_OK)
249 return status;
250
251 target_clock = fixed_mode->clock;
252 }
253
254 if (target_clock > max_dotclk)
255 return MODE_CLOCK_HIGH;
256
257 return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode);
258}
259
260static int intel_dvo_compute_config(struct intel_encoder *encoder,
261 struct intel_crtc_state *pipe_config,
262 struct drm_connector_state *conn_state)
263{
264 struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
265 struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) *
__mptr = (conn_state->connector); (struct intel_connector *
)( (char *)__mptr - __builtin_offsetof(struct intel_connector
, base) );})
;
266 struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
267 const struct drm_display_mode *fixed_mode =
268 intel_panel_fixed_mode(intel_dvo->attached_connector, adjusted_mode);
269
270 /*
271 * If we have timings from the BIOS for the panel, put them in
272 * to the adjusted mode. The CRTC will be set up for this mode,
273 * with the panel scaling set up to source from the H/VDisplay
274 * of the original mode.
275 */
276 if (fixed_mode) {
277 int ret;
278
279 ret = intel_panel_compute_config(connector, adjusted_mode);
280 if (ret)
281 return ret;
282 }
283
284 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN(1<<5))
285 return -EINVAL22;
286
287 pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
288
289 return 0;
290}
291
292static void intel_dvo_pre_enable(struct intel_atomic_state *state,
293 struct intel_encoder *encoder,
294 const struct intel_crtc_state *pipe_config,
295 const struct drm_connector_state *conn_state)
296{
297 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
298 struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr
= (pipe_config->uapi.crtc); (struct intel_crtc *)( (char *
)__mptr - __builtin_offsetof(struct intel_crtc, base) );})
;
299 const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
300 struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
301 enum pipe pipe = crtc->pipe;
302 u32 dvo_val;
303 i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
304 i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg;
305
306 /* Save the data order, since I don't know what it should be set to. */
307 dvo_val = intel_de_read(dev_priv, dvo_reg) &
308 (DVO_PRESERVE_MASK(0x7 << 24) | DVO_DATA_ORDER_GBRG(1 << 6));
309 dvo_val |= DVO_DATA_ORDER_FP(1 << 14) | DVO_BORDER_ENABLE(1 << 7) |
310 DVO_BLANK_ACTIVE_HIGH(1 << 2);
311
312 dvo_val |= DVO_PIPE_SEL(pipe)((pipe) << 30);
313 dvo_val |= DVO_PIPE_STALL(1 << 28);
314 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC(1<<0))
315 dvo_val |= DVO_HSYNC_ACTIVE_HIGH(1 << 3);
316 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC(1<<2))
317 dvo_val |= DVO_VSYNC_ACTIVE_HIGH(1 << 4);
318
319 intel_de_write(dev_priv, dvo_srcdim_reg,
320 (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT12) | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT0));
321 intel_de_write(dev_priv, dvo_reg, dvo_val);
322}
323
324static enum drm_connector_status
325intel_dvo_detect(struct drm_connector *connector, bool_Bool force)
326{
327 struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev);
328 struct intel_dvo *intel_dvo = intel_attached_dvo(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) *
__mptr = (connector); (struct intel_connector *)( (char *)__mptr
- __builtin_offsetof(struct intel_connector, base) );})
);
329
330 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",___drm_dbg(((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s]\n", connector
->base.id, connector->name)
331 connector->base.id, connector->name)___drm_dbg(((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s]\n", connector
->base.id, connector->name)
;
332
333 if (!INTEL_DISPLAY_ENABLED(i915)(({ int __ret = !!((!((&(i915)->__runtime)->pipe_mask
!= 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string
(((&(i915)->drm))->dev), "", "drm_WARN_ON(" "!((&(i915)->__runtime)->pipe_mask != 0)"
")"); __builtin_expect(!!(__ret), 0); }), !(i915)->params
.disable_display && !intel_opregion_headless_sku(i915
))
)
334 return connector_status_disconnected;
335
336 return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
337}
338
339static int intel_dvo_get_modes(struct drm_connector *connector)
340{
341 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev);
342 int num_modes;
343
344 /*
345 * We should probably have an i2c driver get_modes function for those
346 * devices which will have a fixed set of modes determined by the chip
347 * (TV-out, for example), but for now with just TMDS and LVDS,
348 * that's not the case.
349 */
350 num_modes = intel_ddc_get_modes(connector,
351 intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC4));
352 if (num_modes)
353 return num_modes;
354
355 return intel_panel_get_modes(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) *
__mptr = (connector); (struct intel_connector *)( (char *)__mptr
- __builtin_offsetof(struct intel_connector, base) );})
);
356}
357
358static const struct drm_connector_funcs intel_dvo_connector_funcs = {
359 .detect = intel_dvo_detect,
360 .late_register = intel_connector_register,
361 .early_unregister = intel_connector_unregister,
362 .destroy = intel_connector_destroy,
363 .fill_modes = drm_helper_probe_single_connector_modes,
364 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
365 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
366};
367
368static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
369 .mode_valid = intel_dvo_mode_valid,
370 .get_modes = intel_dvo_get_modes,
371};
372
373static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
374{
375 struct intel_dvo *intel_dvo = enc_to_dvo(to_intel_encoder(encoder)({ const __typeof( ((struct intel_encoder *)0)->base ) *__mptr
= (encoder); (struct intel_encoder *)( (char *)__mptr - __builtin_offsetof
(struct intel_encoder, base) );})
);
376
377 if (intel_dvo->dev.dev_ops->destroy)
378 intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev);
379
380 intel_encoder_destroy(encoder);
381}
382
383static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
384 .destroy = intel_dvo_enc_destroy,
385};
386
387static enum port intel_dvo_port(i915_reg_t dvo_reg)
388{
389 if (i915_mmio_reg_equal(dvo_reg, DVOA((const i915_reg_t){ .reg = (0x61120) })))
390 return PORT_A;
391 else if (i915_mmio_reg_equal(dvo_reg, DVOB((const i915_reg_t){ .reg = (0x61140) })))
392 return PORT_B;
393 else
394 return PORT_C;
395}
396
397void intel_dvo_init(struct drm_i915_privateinteldrm_softc *dev_priv)
398{
399 struct intel_encoder *intel_encoder;
400 struct intel_dvo *intel_dvo;
401 struct intel_connector *intel_connector;
402 int i;
403 int encoder_type = DRM_MODE_ENCODER_NONE0;
404
405 intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL(0x0001 | 0x0004));
406 if (!intel_dvo)
407 return;
408
409 intel_connector = intel_connector_alloc();
410 if (!intel_connector) {
411 kfree(intel_dvo);
412 return;
413 }
414
415 intel_dvo->attached_connector = intel_connector;
416
417 intel_encoder = &intel_dvo->base;
418
419 intel_encoder->disable = intel_disable_dvo;
420 intel_encoder->enable = intel_enable_dvo;
421 intel_encoder->get_hw_state = intel_dvo_get_hw_state;
422 intel_encoder->get_config = intel_dvo_get_config;
423 intel_encoder->compute_config = intel_dvo_compute_config;
424 intel_encoder->pre_enable = intel_dvo_pre_enable;
425 intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
426
427 /* Now, try to find a controller */
428 for (i = 0; i < ARRAY_SIZE(intel_dvo_devices)(sizeof((intel_dvo_devices)) / sizeof((intel_dvo_devices)[0])
)
; i++) {
429 struct drm_connector *connector = &intel_connector->base;
430 const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
431 struct i2c_adapter *i2c;
432 int gpio;
433 bool_Bool dvoinit;
434 enum pipe pipe;
435 u32 dpll[I915_MAX_PIPES];
436 enum port port;
437
438 /*
439 * Allow the I2C driver info to specify the GPIO to be used in
440 * special cases, but otherwise default to what's defined
441 * in the spec.
442 */
443 if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio))
444 gpio = dvo->gpio;
445 else if (dvo->type == INTEL_DVO_CHIP_LVDS1)
446 gpio = GMBUS_PIN_SSC1;
447 else
448 gpio = GMBUS_PIN_DPB5;
449
450 /*
451 * Set up the I2C bus necessary for the chip we're probing.
452 * It appears that everything is on GPIOE except for panels
453 * on i830 laptops, which are on GPIOB (DVOA).
454 */
455 i2c = intel_gmbus_get_adapter(dev_priv, gpio);
456
457 intel_dvo->dev = *dvo;
458
459 /*
460 * GMBUS NAK handling seems to be unstable, hence let the
461 * transmitter detection run in bit banging mode for now.
462 */
463 intel_gmbus_force_bit(i2c, true1);
464
465 /*
466 * ns2501 requires the DVO 2x clock before it will
467 * respond to i2c accesses, so make sure we have
468 * have the clock enabled before we attempt to
469 * initialize the device.
470 */
471 for_each_pipe(dev_priv, pipe)for ((pipe) = 0; (pipe) < I915_MAX_PIPES; (pipe)++) if (!(
(&(dev_priv)->__runtime)->pipe_mask & (1UL <<
(pipe)))) {} else
{
472 dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6014), (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6018), (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6030) })[(pipe)]))
})
);
473 intel_de_write(dev_priv, DPLL(pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6014), (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6018), (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6030) })[(pipe)]))
})
,
474 dpll[pipe] | DPLL_DVO_2X_MODE(1 << 30));
475 }
476
477 dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c);
478
479 /* restore the DVO 2x clock state to original */
480 for_each_pipe(dev_priv, pipe)for ((pipe) = 0; (pipe) < I915_MAX_PIPES; (pipe)++) if (!(
(&(dev_priv)->__runtime)->pipe_mask & (1UL <<
(pipe)))) {} else
{
481 intel_de_write(dev_priv, DPLL(pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6014), (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6018), (((&(dev_priv
)->__info)->display.mmio_offset) + 0x6030) })[(pipe)]))
})
, dpll[pipe]);
482 }
483
484 intel_gmbus_force_bit(i2c, false0);
485
486 if (!dvoinit)
487 continue;
488
489 port = intel_dvo_port(dvo->dvo_reg);
490 drm_encoder_init(&dev_priv->drm, &intel_encoder->base,
491 &intel_dvo_enc_funcs, encoder_type,
492 "DVO %c", port_name(port)((port) + 'A'));
493
494 intel_encoder->type = INTEL_OUTPUT_DVO;
495 intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
496 intel_encoder->port = port;
497 intel_encoder->pipe_mask = ~0;
498
499 if (dvo->type != INTEL_DVO_CHIP_LVDS1)
500 intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) |
501 (1 << INTEL_OUTPUT_DVO);
502
503 switch (dvo->type) {
504 case INTEL_DVO_CHIP_TMDS2:
505 intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT(1 << 1) |
506 DRM_CONNECTOR_POLL_DISCONNECT(1 << 2);
507 drm_connector_init(&dev_priv->drm, connector,
508 &intel_dvo_connector_funcs,
509 DRM_MODE_CONNECTOR_DVII2);
510 encoder_type = DRM_MODE_ENCODER_TMDS2;
Value stored to 'encoder_type' is never read
511 break;
512 case INTEL_DVO_CHIP_LVDS_NO_FIXED5:
513 case INTEL_DVO_CHIP_LVDS1:
514 drm_connector_init(&dev_priv->drm, connector,
515 &intel_dvo_connector_funcs,
516 DRM_MODE_CONNECTOR_LVDS7);
517 encoder_type = DRM_MODE_ENCODER_LVDS3;
518 break;
519 }
520
521 drm_connector_helper_add(connector,
522 &intel_dvo_connector_helper_funcs);
523 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
524 connector->interlace_allowed = false0;
525 connector->doublescan_allowed = false0;
526
527 intel_connector_attach_encoder(intel_connector, intel_encoder);
528 if (dvo->type == INTEL_DVO_CHIP_LVDS1) {
529 /*
530 * For our LVDS chipsets, we should hopefully be able
531 * to dig the fixed panel mode out of the BIOS data.
532 * However, it's in a different format from the BIOS
533 * data on chipsets with integrated LVDS (stored in AIM
534 * headers, likely), so for now, just get the current
535 * mode being output through DVO.
536 */
537 intel_panel_add_encoder_fixed_mode(intel_connector,
538 intel_encoder);
539
540 intel_panel_init(intel_connector);
541
542 intel_dvo->panel_wants_dither = true1;
543 }
544
545 return;
546 }
547
548 kfree(intel_dvo);
549 kfree(intel_connector);
550}