Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: Add helper for DP++ adaptors

Add a helper which aids in the identification of DP dual mode
(aka. DP++) adaptors. There are several types of adaptors
specified: type 1 DVI, type 1 HDMI, type 2 DVI, type 2 HDMI

Type 1 adaptors have a max TMDS clock limit of 165MHz, type 2 adaptors
may go as high as 300MHz and they provide a register informing the
source device what the actual limit is. Supposedly also type 1 adaptors
may optionally implement this register. This TMDS clock limit is the
main reason why we need to identify these adaptors.

Type 1 adaptors provide access to their internal registers and the sink
DDC bus through I2C. Type 2 adaptors provide this access both via I2C
and I2C-over-AUX. A type 2 source device may choose to implement either
of these methods. If a source device implements the I2C-over-AUX
method, then the driver will obviously need specific support for such
adaptors since the port is driven like an HDMI port, but DDC
communication happes over the AUX channel.

This helper should be enough to identify the adaptor type (some
type 1 DVI adaptors may be a slight exception) and the maximum TMDS
clock limit. Another feature that may be available is control over
the TMDS output buffers on the adaptor, possibly allowing for some
power saving when the TMDS link is down.

Other user controllable features that may be available in the adaptors
are downstream i2c bus speed control when using i2c-over-aux, and
some control over the CEC pin. I chose not to provide any helper
functions for those since I have no use for them in i915 at this time.
The rest of the registers in the adaptor are mostly just information,
eg. IEEE OUI, hardware and firmware revision, etc.

v2: Pass adaptor type to helper functions to ease driver implementation
Fix a bunch of typoes (Paulo)
Add DRM_DP_DUAL_MODE_UNKNOWN for the case where we don't (yet) know
the type (Paulo)
Reject 0x00 and 0xff DP_DUAL_MODE_MAX_TMDS_CLOCK values (Paulo)
Adjust drm_dp_dual_mode_detect() type2 vs. type1 detection to
ease future LSPCON enabling
Remove the unused DP_DUAL_MODE_LAST_RESERVED define
v3: Fix kernel doc function argument descriptions (Jani)
s/NONE/UNKNOWN/ in drm_dp_dual_mode_detect() docs
Add kernel doc for enum drm_dp_dual_mode_type
Actually build the docs
Fix more typoes
v4: Adjust code indentation of type2 adaptor detection (Shashank)
Add debug messages for failurs cases (Shashank)
v5: EXPORT_SYMBOL(drm_dp_dual_mode_read) (Paulo)

Cc: stable@vger.kernel.org
Cc: Tore Anderson <tore@fud.no>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Shashank Sharma <shashank.sharma@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Shashank Sharma <shashank.sharma@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Shashank Sharma <shashank.sharma@intel.com> (v4)
Link: http://patchwork.freedesktop.org/patch/msgid/1462542412-25533-1-git-send-email-ville.syrjala@linux.intel.com
(cherry picked from commit ede53344dbfd1dd43bfd73eb6af743d37c56a7c3)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>

authored by

Ville Syrjälä and committed by
Jani Nikula
b3daa5ef 5b4fd5b1

+465 -1
+6
Documentation/DocBook/gpu.tmpl
··· 1623 1623 !Edrivers/gpu/drm/drm_dp_helper.c 1624 1624 </sect2> 1625 1625 <sect2> 1626 + <title>Display Port Dual Mode Adaptor Helper Functions Reference</title> 1627 + !Pdrivers/gpu/drm/drm_dp_dual_mode_helper.c dp dual mode helpers 1628 + !Iinclude/drm/drm_dp_dual_mode_helper.h 1629 + !Edrivers/gpu/drm/drm_dp_dual_mode_helper.c 1630 + </sect2> 1631 + <sect2> 1626 1632 <title>Display Port MST Helper Functions Reference</title> 1627 1633 !Pdrivers/gpu/drm/drm_dp_mst_topology.c dp mst helper 1628 1634 !Iinclude/drm/drm_dp_mst_helper.h
+1 -1
drivers/gpu/drm/Makefile
··· 23 23 24 24 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ 25 25 drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ 26 - drm_kms_helper_common.o 26 + drm_kms_helper_common.o drm_dp_dual_mode_helper.o 27 27 28 28 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o 29 29 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
+366
drivers/gpu/drm/drm_dp_dual_mode_helper.c
··· 1 + /* 2 + * Copyright © 2016 Intel Corporation 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + 23 + #include <linux/errno.h> 24 + #include <linux/export.h> 25 + #include <linux/i2c.h> 26 + #include <linux/slab.h> 27 + #include <linux/string.h> 28 + #include <drm/drm_dp_dual_mode_helper.h> 29 + #include <drm/drmP.h> 30 + 31 + /** 32 + * DOC: dp dual mode helpers 33 + * 34 + * Helper functions to deal with DP dual mode (aka. DP++) adaptors. 35 + * 36 + * Type 1: 37 + * Adaptor registers (if any) and the sink DDC bus may be accessed via I2C. 38 + * 39 + * Type 2: 40 + * Adaptor registers and sink DDC bus can be accessed either via I2C or 41 + * I2C-over-AUX. Source devices may choose to implement either of these 42 + * access methods. 43 + */ 44 + 45 + #define DP_DUAL_MODE_SLAVE_ADDRESS 0x40 46 + 47 + /** 48 + * drm_dp_dual_mode_read - Read from the DP dual mode adaptor register(s) 49 + * @adapter: I2C adapter for the DDC bus 50 + * @offset: register offset 51 + * @buffer: buffer for return data 52 + * @size: sizo of the buffer 53 + * 54 + * Reads @size bytes from the DP dual mode adaptor registers 55 + * starting at @offset. 56 + * 57 + * Returns: 58 + * 0 on success, negative error code on failure 59 + */ 60 + ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter, 61 + u8 offset, void *buffer, size_t size) 62 + { 63 + struct i2c_msg msgs[] = { 64 + { 65 + .addr = DP_DUAL_MODE_SLAVE_ADDRESS, 66 + .flags = 0, 67 + .len = 1, 68 + .buf = &offset, 69 + }, 70 + { 71 + .addr = DP_DUAL_MODE_SLAVE_ADDRESS, 72 + .flags = I2C_M_RD, 73 + .len = size, 74 + .buf = buffer, 75 + }, 76 + }; 77 + int ret; 78 + 79 + ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs)); 80 + if (ret < 0) 81 + return ret; 82 + if (ret != ARRAY_SIZE(msgs)) 83 + return -EPROTO; 84 + 85 + return 0; 86 + } 87 + EXPORT_SYMBOL(drm_dp_dual_mode_read); 88 + 89 + /** 90 + * drm_dp_dual_mode_write - Write to the DP dual mode adaptor register(s) 91 + * @adapter: I2C adapter for the DDC bus 92 + * @offset: register offset 93 + * @buffer: buffer for write data 94 + * @size: sizo of the buffer 95 + * 96 + * Writes @size bytes to the DP dual mode adaptor registers 97 + * starting at @offset. 98 + * 99 + * Returns: 100 + * 0 on success, negative error code on failure 101 + */ 102 + ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter, 103 + u8 offset, const void *buffer, size_t size) 104 + { 105 + struct i2c_msg msg = { 106 + .addr = DP_DUAL_MODE_SLAVE_ADDRESS, 107 + .flags = 0, 108 + .len = 1 + size, 109 + .buf = NULL, 110 + }; 111 + void *data; 112 + int ret; 113 + 114 + data = kmalloc(msg.len, GFP_TEMPORARY); 115 + if (!data) 116 + return -ENOMEM; 117 + 118 + msg.buf = data; 119 + 120 + memcpy(data, &offset, 1); 121 + memcpy(data + 1, buffer, size); 122 + 123 + ret = i2c_transfer(adapter, &msg, 1); 124 + 125 + kfree(data); 126 + 127 + if (ret < 0) 128 + return ret; 129 + if (ret != 1) 130 + return -EPROTO; 131 + 132 + return 0; 133 + } 134 + EXPORT_SYMBOL(drm_dp_dual_mode_write); 135 + 136 + static bool is_hdmi_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN]) 137 + { 138 + static const char dp_dual_mode_hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN] = 139 + "DP-HDMI ADAPTOR\x04"; 140 + 141 + return memcmp(hdmi_id, dp_dual_mode_hdmi_id, 142 + sizeof(dp_dual_mode_hdmi_id)) == 0; 143 + } 144 + 145 + static bool is_type2_adaptor(uint8_t adaptor_id) 146 + { 147 + return adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 | 148 + DP_DUAL_MODE_REV_TYPE2); 149 + } 150 + 151 + /** 152 + * drm_dp_dual_mode_detect - Identify the DP dual mode adaptor 153 + * @adapter: I2C adapter for the DDC bus 154 + * 155 + * Attempt to identify the type of the DP dual mode adaptor used. 156 + * 157 + * Note that when the answer is @DRM_DP_DUAL_MODE_UNKNOWN it's not 158 + * certain whether we're dealing with a native HDMI port or 159 + * a type 1 DVI dual mode adaptor. The driver will have to use 160 + * some other hardware/driver specific mechanism to make that 161 + * distinction. 162 + * 163 + * Returns: 164 + * The type of the DP dual mode adaptor used 165 + */ 166 + enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter) 167 + { 168 + char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN] = {}; 169 + uint8_t adaptor_id = 0x00; 170 + ssize_t ret; 171 + 172 + /* 173 + * Let's see if the adaptor is there the by reading the 174 + * HDMI ID registers. 175 + * 176 + * Note that type 1 DVI adaptors are not required to implemnt 177 + * any registers, and that presents a problem for detection. 178 + * If the i2c transfer is nacked, we may or may not be dealing 179 + * with a type 1 DVI adaptor. Some other mechanism of detecting 180 + * the presence of the adaptor is required. One way would be 181 + * to check the state of the CONFIG1 pin, Another method would 182 + * simply require the driver to know whether the port is a DP++ 183 + * port or a native HDMI port. Both of these methods are entirely 184 + * hardware/driver specific so we can't deal with them here. 185 + */ 186 + ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_HDMI_ID, 187 + hdmi_id, sizeof(hdmi_id)); 188 + if (ret) 189 + return DRM_DP_DUAL_MODE_UNKNOWN; 190 + 191 + /* 192 + * Sigh. Some (maybe all?) type 1 adaptors are broken and ack 193 + * the offset but ignore it, and instead they just always return 194 + * data from the start of the HDMI ID buffer. So for a broken 195 + * type 1 HDMI adaptor a single byte read will always give us 196 + * 0x44, and for a type 1 DVI adaptor it should give 0x00 197 + * (assuming it implements any registers). Fortunately neither 198 + * of those values will match the type 2 signature of the 199 + * DP_DUAL_MODE_ADAPTOR_ID register so we can proceed with 200 + * the type 2 adaptor detection safely even in the presence 201 + * of broken type 1 adaptors. 202 + */ 203 + ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID, 204 + &adaptor_id, sizeof(adaptor_id)); 205 + if (ret == 0) { 206 + if (is_type2_adaptor(adaptor_id)) { 207 + if (is_hdmi_adaptor(hdmi_id)) 208 + return DRM_DP_DUAL_MODE_TYPE2_HDMI; 209 + else 210 + return DRM_DP_DUAL_MODE_TYPE2_DVI; 211 + } 212 + } 213 + 214 + if (is_hdmi_adaptor(hdmi_id)) 215 + return DRM_DP_DUAL_MODE_TYPE1_HDMI; 216 + else 217 + return DRM_DP_DUAL_MODE_TYPE1_DVI; 218 + } 219 + EXPORT_SYMBOL(drm_dp_dual_mode_detect); 220 + 221 + /** 222 + * drm_dp_dual_mode_max_tmds_clock - Max TMDS clock for DP dual mode adaptor 223 + * @type: DP dual mode adaptor type 224 + * @adapter: I2C adapter for the DDC bus 225 + * 226 + * Determine the max TMDS clock the adaptor supports based on the 227 + * type of the dual mode adaptor and the DP_DUAL_MODE_MAX_TMDS_CLOCK 228 + * register (on type2 adaptors). As some type 1 adaptors have 229 + * problems with registers (see comments in drm_dp_dual_mode_detect()) 230 + * we don't read the register on those, instead we simply assume 231 + * a 165 MHz limit based on the specification. 232 + * 233 + * Returns: 234 + * Maximum supported TMDS clock rate for the DP dual mode adaptor in kHz. 235 + */ 236 + int drm_dp_dual_mode_max_tmds_clock(enum drm_dp_dual_mode_type type, 237 + struct i2c_adapter *adapter) 238 + { 239 + uint8_t max_tmds_clock; 240 + ssize_t ret; 241 + 242 + /* native HDMI so no limit */ 243 + if (type == DRM_DP_DUAL_MODE_NONE) 244 + return 0; 245 + 246 + /* 247 + * Type 1 adaptors are limited to 165MHz 248 + * Type 2 adaptors can tells us their limit 249 + */ 250 + if (type < DRM_DP_DUAL_MODE_TYPE2_DVI) 251 + return 165000; 252 + 253 + ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_MAX_TMDS_CLOCK, 254 + &max_tmds_clock, sizeof(max_tmds_clock)); 255 + if (ret || max_tmds_clock == 0x00 || max_tmds_clock == 0xff) { 256 + DRM_DEBUG_KMS("Failed to query max TMDS clock\n"); 257 + return 165000; 258 + } 259 + 260 + return max_tmds_clock * 5000 / 2; 261 + } 262 + EXPORT_SYMBOL(drm_dp_dual_mode_max_tmds_clock); 263 + 264 + /** 265 + * drm_dp_dual_mode_get_tmds_output - Get the state of the TMDS output buffers in the DP dual mode adaptor 266 + * @type: DP dual mode adaptor type 267 + * @adapter: I2C adapter for the DDC bus 268 + * @enabled: current state of the TMDS output buffers 269 + * 270 + * Get the state of the TMDS output buffers in the adaptor. For 271 + * type2 adaptors this is queried from the DP_DUAL_MODE_TMDS_OEN 272 + * register. As some type 1 adaptors have problems with registers 273 + * (see comments in drm_dp_dual_mode_detect()) we don't read the 274 + * register on those, instead we simply assume that the buffers 275 + * are always enabled. 276 + * 277 + * Returns: 278 + * 0 on success, negative error code on failure 279 + */ 280 + int drm_dp_dual_mode_get_tmds_output(enum drm_dp_dual_mode_type type, 281 + struct i2c_adapter *adapter, 282 + bool *enabled) 283 + { 284 + uint8_t tmds_oen; 285 + ssize_t ret; 286 + 287 + if (type < DRM_DP_DUAL_MODE_TYPE2_DVI) { 288 + *enabled = true; 289 + return 0; 290 + } 291 + 292 + ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_TMDS_OEN, 293 + &tmds_oen, sizeof(tmds_oen)); 294 + if (ret) { 295 + DRM_DEBUG_KMS("Failed to query state of TMDS output buffers\n"); 296 + return ret; 297 + } 298 + 299 + *enabled = !(tmds_oen & DP_DUAL_MODE_TMDS_DISABLE); 300 + 301 + return 0; 302 + } 303 + EXPORT_SYMBOL(drm_dp_dual_mode_get_tmds_output); 304 + 305 + /** 306 + * drm_dp_dual_mode_set_tmds_output - Enable/disable TMDS output buffers in the DP dual mode adaptor 307 + * @type: DP dual mode adaptor type 308 + * @adapter: I2C adapter for the DDC bus 309 + * @enable: enable (as opposed to disable) the TMDS output buffers 310 + * 311 + * Set the state of the TMDS output buffers in the adaptor. For 312 + * type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. As 313 + * some type 1 adaptors have problems with registers (see comments 314 + * in drm_dp_dual_mode_detect()) we avoid touching the register, 315 + * making this function a no-op on type 1 adaptors. 316 + * 317 + * Returns: 318 + * 0 on success, negative error code on failure 319 + */ 320 + int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type, 321 + struct i2c_adapter *adapter, bool enable) 322 + { 323 + uint8_t tmds_oen = enable ? 0 : DP_DUAL_MODE_TMDS_DISABLE; 324 + ssize_t ret; 325 + 326 + if (type < DRM_DP_DUAL_MODE_TYPE2_DVI) 327 + return 0; 328 + 329 + ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN, 330 + &tmds_oen, sizeof(tmds_oen)); 331 + if (ret) { 332 + DRM_DEBUG_KMS("Failed to %s TMDS output buffers\n", 333 + enable ? "enable" : "disable"); 334 + return ret; 335 + } 336 + 337 + return 0; 338 + } 339 + EXPORT_SYMBOL(drm_dp_dual_mode_set_tmds_output); 340 + 341 + /** 342 + * drm_dp_get_dual_mode_type_name - Get the name of the DP dual mode adaptor type as a string 343 + * @type: DP dual mode adaptor type 344 + * 345 + * Returns: 346 + * String representation of the DP dual mode adaptor type 347 + */ 348 + const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type) 349 + { 350 + switch (type) { 351 + case DRM_DP_DUAL_MODE_NONE: 352 + return "none"; 353 + case DRM_DP_DUAL_MODE_TYPE1_DVI: 354 + return "type 1 DVI"; 355 + case DRM_DP_DUAL_MODE_TYPE1_HDMI: 356 + return "type 1 HDMI"; 357 + case DRM_DP_DUAL_MODE_TYPE2_DVI: 358 + return "type 2 DVI"; 359 + case DRM_DP_DUAL_MODE_TYPE2_HDMI: 360 + return "type 2 HDMI"; 361 + default: 362 + WARN_ON(type != DRM_DP_DUAL_MODE_UNKNOWN); 363 + return "unknown"; 364 + } 365 + } 366 + EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
+92
include/drm/drm_dp_dual_mode_helper.h
··· 1 + /* 2 + * Copyright © 2016 Intel Corporation 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + 23 + #ifndef DRM_DP_DUAL_MODE_HELPER_H 24 + #define DRM_DP_DUAL_MODE_HELPER_H 25 + 26 + #include <linux/types.h> 27 + 28 + /* 29 + * Optional for type 1 DVI adaptors 30 + * Mandatory for type 1 HDMI and type 2 adaptors 31 + */ 32 + #define DP_DUAL_MODE_HDMI_ID 0x00 /* 00-0f */ 33 + #define DP_DUAL_MODE_HDMI_ID_LEN 16 34 + /* 35 + * Optional for type 1 adaptors 36 + * Mandatory for type 2 adaptors 37 + */ 38 + #define DP_DUAL_MODE_ADAPTOR_ID 0x10 39 + #define DP_DUAL_MODE_REV_MASK 0x07 40 + #define DP_DUAL_MODE_REV_TYPE2 0x00 41 + #define DP_DUAL_MODE_TYPE_MASK 0xf0 42 + #define DP_DUAL_MODE_TYPE_TYPE2 0xa0 43 + #define DP_DUAL_MODE_IEEE_OUI 0x11 /* 11-13*/ 44 + #define DP_DUAL_IEEE_OUI_LEN 3 45 + #define DP_DUAL_DEVICE_ID 0x14 /* 14-19 */ 46 + #define DP_DUAL_DEVICE_ID_LEN 6 47 + #define DP_DUAL_MODE_HARDWARE_REV 0x1a 48 + #define DP_DUAL_MODE_FIRMWARE_MAJOR_REV 0x1b 49 + #define DP_DUAL_MODE_FIRMWARE_MINOR_REV 0x1c 50 + #define DP_DUAL_MODE_MAX_TMDS_CLOCK 0x1d 51 + #define DP_DUAL_MODE_I2C_SPEED_CAP 0x1e 52 + #define DP_DUAL_MODE_TMDS_OEN 0x20 53 + #define DP_DUAL_MODE_TMDS_DISABLE 0x01 54 + #define DP_DUAL_MODE_HDMI_PIN_CTRL 0x21 55 + #define DP_DUAL_MODE_CEC_ENABLE 0x01 56 + #define DP_DUAL_MODE_I2C_SPEED_CTRL 0x22 57 + 58 + struct i2c_adapter; 59 + 60 + ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter, 61 + u8 offset, void *buffer, size_t size); 62 + ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter, 63 + u8 offset, const void *buffer, size_t size); 64 + 65 + /** 66 + * enum drm_dp_dual_mode_type - Type of the DP dual mode adaptor 67 + * @DRM_DP_DUAL_MODE_NONE: No DP dual mode adaptor 68 + * @DRM_DP_DUAL_MODE_UNKNOWN: Could be either none or type 1 DVI adaptor 69 + * @DRM_DP_DUAL_MODE_TYPE1_DVI: Type 1 DVI adaptor 70 + * @DRM_DP_DUAL_MODE_TYPE1_HDMI: Type 1 HDMI adaptor 71 + * @DRM_DP_DUAL_MODE_TYPE2_DVI: Type 2 DVI adaptor 72 + * @DRM_DP_DUAL_MODE_TYPE2_HDMI: Type 2 HDMI adaptor 73 + */ 74 + enum drm_dp_dual_mode_type { 75 + DRM_DP_DUAL_MODE_NONE, 76 + DRM_DP_DUAL_MODE_UNKNOWN, 77 + DRM_DP_DUAL_MODE_TYPE1_DVI, 78 + DRM_DP_DUAL_MODE_TYPE1_HDMI, 79 + DRM_DP_DUAL_MODE_TYPE2_DVI, 80 + DRM_DP_DUAL_MODE_TYPE2_HDMI, 81 + }; 82 + 83 + enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter); 84 + int drm_dp_dual_mode_max_tmds_clock(enum drm_dp_dual_mode_type type, 85 + struct i2c_adapter *adapter); 86 + int drm_dp_dual_mode_get_tmds_output(enum drm_dp_dual_mode_type type, 87 + struct i2c_adapter *adapter, bool *enabled); 88 + int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type, 89 + struct i2c_adapter *adapter, bool enable); 90 + const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type); 91 + 92 + #endif