xref: /linux/include/drm/display/drm_scdc_helper.h (revision f57c2198380fcf475404c159c784d0ee70fa091b)
1 /*
2  * Copyright (c) 2015 NVIDIA Corporation. All rights reserved.
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, sub license,
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 (including the
12  * next paragraph) shall be included in all copies or substantial portions
13  * of the Software.
14  *
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,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #ifndef DRM_SCDC_HELPER_H
25 #define DRM_SCDC_HELPER_H
26 
27 #include <linux/errno.h>
28 #include <linux/types.h>
29 
30 #include <drm/display/drm_scdc.h>
31 
32 struct drm_connector;
33 struct i2c_adapter;
34 struct dentry;
35 
36 struct drm_scdc_status_flags {
37 	/* Status Register 0 */
38 	bool clock_detected;
39 	bool ch0_locked;
40 	bool ch1_locked;
41 	bool ch2_locked;
42 	bool ln3_locked;
43 	bool flt_ready;
44 	bool dsc_fail;
45 
46 	/* Status Register 1 */
47 	u8 ln0_training_pattern : 4;
48 	u8 ln1_training_pattern : 4;
49 
50 	/* Status Register 2 */
51 	u8 ln2_training_pattern : 4;
52 	u8 ln3_training_pattern : 4;
53 };
54 
55 enum drm_scdc_frl_rate {
56 	SCDC_FRL_RATE_OFF = 0,
57 	SCDC_FRL_RATE_3X3 = 1,
58 	SCDC_FRL_RATE_6X3 = 2,
59 	SCDC_FRL_RATE_6X4 = 3,
60 	SCDC_FRL_RATE_8X4 = 4,
61 	SCDC_FRL_RATE_10X4 = 5,
62 	SCDC_FRL_RATE_12X4 = 6,
63 	SCDC_FRL_RATE_RESV_7 = 7,
64 	SCDC_FRL_RATE_RESV_8 = 8,
65 	SCDC_FRL_RATE_RESV_9 = 9,
66 	SCDC_FRL_RATE_RESV_10 = 10,
67 	SCDC_FRL_RATE_RESV_11 = 11,
68 	SCDC_FRL_RATE_RESV_12 = 12,
69 	SCDC_FRL_RATE_RESV_13 = 13,
70 	SCDC_FRL_RATE_RESV_14 = 14,
71 	SCDC_FRL_RATE_RESV_15 = 15
72 };
73 
74 /**
75  * drm_scdc_num_frl_lanes - get number of lanes for a given FRL rate
76  * @rate: one of &enum drm_scdc_frl_rate
77  *
78  * For a given @rate, return the number of lanes it uses.
79  *
80  * Returns: %-EINVAL if @rate is not a valid FRL rate, or the number of lanes
81  * for a given &enum drm_scdc_frl_rate on success (including %0 for "off")
82  */
83 static inline __pure int drm_scdc_num_frl_lanes(enum drm_scdc_frl_rate rate)
84 {
85 	switch (rate) {
86 	case SCDC_FRL_RATE_OFF:
87 		return 0;
88 	case SCDC_FRL_RATE_3X3:
89 	case SCDC_FRL_RATE_6X3:
90 		return 3;
91 	case SCDC_FRL_RATE_6X4:
92 	case SCDC_FRL_RATE_8X4:
93 	case SCDC_FRL_RATE_10X4:
94 	case SCDC_FRL_RATE_12X4:
95 		return 4;
96 	default:
97 		return -EINVAL;
98 	}
99 }
100 
101 struct drm_scdc_state {
102 	/** @stf: contents of the status flag registers */
103 	struct drm_scdc_status_flags stf;
104 	/** @scramling_enabled: true if TMDS scrambling is on */
105 	bool scrambling_enabled;
106 	/** @scrambling_detected: true if the sink actually detected scrambling */
107 	bool scrambling_detected;
108 	/**
109 	 * @tmds_bclk_x40: true if TMDS bit period is 1/40th of the TMDS
110 	 * clock period, false if it's 1/10th of the clock period.
111 	 */
112 	bool tmds_bclk_x40;
113 	/** @rate: FRL rate set by the source */
114 	enum drm_scdc_frl_rate rate : 4;
115 	/** @ffe_levels: The FFE levels for @rate set by the source */
116 	u8 ffe_levels : 4;
117 	/** @error_count: character error counts for each channel/link */
118 	u16 error_count[4];
119 	/** @rs_corrections: number of Reed-Solomon Corrections */
120 	u16 rs_corrections;
121 	/** @scdc: raw SCDC data buffer */
122 	u8 scdc[256];
123 };
124 
125 int drm_scdc_read(struct i2c_adapter *adapter, u8 offset, void *buffer,
126 		  size_t size);
127 int drm_scdc_write(struct i2c_adapter *adapter, u8 offset, const void *buffer,
128 		   size_t size);
129 
130 /**
131  * drm_scdc_readb - read a single byte from SCDC
132  * @adapter: I2C adapter
133  * @offset: offset of register to read
134  * @value: return location for the register value
135  *
136  * Reads a single byte from SCDC. This is a convenience wrapper around the
137  * drm_scdc_read() function.
138  *
139  * Returns:
140  * 0 on success or a negative error code on failure.
141  */
142 static inline int drm_scdc_readb(struct i2c_adapter *adapter, u8 offset,
143 				 u8 *value)
144 {
145 	return drm_scdc_read(adapter, offset, value, sizeof(*value));
146 }
147 
148 /**
149  * drm_scdc_writeb - write a single byte to SCDC
150  * @adapter: I2C adapter
151  * @offset: offset of register to read
152  * @value: return location for the register value
153  *
154  * Writes a single byte to SCDC. This is a convenience wrapper around the
155  * drm_scdc_write() function.
156  *
157  * Returns:
158  * 0 on success or a negative error code on failure.
159  */
160 static inline int drm_scdc_writeb(struct i2c_adapter *adapter, u8 offset,
161 				  u8 value)
162 {
163 	return drm_scdc_write(adapter, offset, &value, sizeof(value));
164 }
165 
166 bool drm_scdc_get_scrambling_status(struct drm_connector *connector);
167 
168 bool drm_scdc_set_scrambling(struct drm_connector *connector, bool enable);
169 bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector, bool set);
170 
171 int drm_scdc_set_source_version(struct drm_connector *connector, u8 ver);
172 
173 int drm_scdc_read_state(struct drm_connector *connector,
174 			struct drm_scdc_state *state);
175 void drm_scdc_debugfs_init(struct drm_connector *connector, struct dentry *root);
176 
177 #endif
178