This source file includes following definitions.
- drm_scdc_read
- drm_scdc_write
- drm_scdc_get_scrambling_status
- drm_scdc_set_scrambling
- drm_scdc_set_high_tmds_clock_ratio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <linux/slab.h>
25 #include <linux/delay.h>
26
27 #include <drm/drm_print.h>
28 #include <drm/drm_scdc_helper.h>
29
30
31
32
33
34
35
36
37
38
39 #define SCDC_I2C_SLAVE_ADDRESS 0x54
40
41
42
43
44
45
46
47
48
49
50
51
52
53 ssize_t drm_scdc_read(struct i2c_adapter *adapter, u8 offset, void *buffer,
54 size_t size)
55 {
56 int ret;
57 struct i2c_msg msgs[2] = {
58 {
59 .addr = SCDC_I2C_SLAVE_ADDRESS,
60 .flags = 0,
61 .len = 1,
62 .buf = &offset,
63 }, {
64 .addr = SCDC_I2C_SLAVE_ADDRESS,
65 .flags = I2C_M_RD,
66 .len = size,
67 .buf = buffer,
68 }
69 };
70
71 ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
72 if (ret < 0)
73 return ret;
74 if (ret != ARRAY_SIZE(msgs))
75 return -EPROTO;
76
77 return 0;
78 }
79 EXPORT_SYMBOL(drm_scdc_read);
80
81
82
83
84
85
86
87
88
89
90
91
92
93 ssize_t drm_scdc_write(struct i2c_adapter *adapter, u8 offset,
94 const void *buffer, size_t size)
95 {
96 struct i2c_msg msg = {
97 .addr = SCDC_I2C_SLAVE_ADDRESS,
98 .flags = 0,
99 .len = 1 + size,
100 .buf = NULL,
101 };
102 void *data;
103 int err;
104
105 data = kmalloc(1 + size, GFP_KERNEL);
106 if (!data)
107 return -ENOMEM;
108
109 msg.buf = data;
110
111 memcpy(data, &offset, sizeof(offset));
112 memcpy(data + 1, buffer, size);
113
114 err = i2c_transfer(adapter, &msg, 1);
115
116 kfree(data);
117
118 if (err < 0)
119 return err;
120 if (err != 1)
121 return -EPROTO;
122
123 return 0;
124 }
125 EXPORT_SYMBOL(drm_scdc_write);
126
127
128
129
130
131
132
133
134
135
136
137 bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter)
138 {
139 u8 status;
140 int ret;
141
142 ret = drm_scdc_readb(adapter, SCDC_SCRAMBLER_STATUS, &status);
143 if (ret < 0) {
144 DRM_DEBUG_KMS("Failed to read scrambling status: %d\n", ret);
145 return false;
146 }
147
148 return status & SCDC_SCRAMBLING_STATUS;
149 }
150 EXPORT_SYMBOL(drm_scdc_get_scrambling_status);
151
152
153
154
155
156
157
158
159
160
161
162
163
164 bool drm_scdc_set_scrambling(struct i2c_adapter *adapter, bool enable)
165 {
166 u8 config;
167 int ret;
168
169 ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
170 if (ret < 0) {
171 DRM_DEBUG_KMS("Failed to read TMDS config: %d\n", ret);
172 return false;
173 }
174
175 if (enable)
176 config |= SCDC_SCRAMBLING_ENABLE;
177 else
178 config &= ~SCDC_SCRAMBLING_ENABLE;
179
180 ret = drm_scdc_writeb(adapter, SCDC_TMDS_CONFIG, config);
181 if (ret < 0) {
182 DRM_DEBUG_KMS("Failed to enable scrambling: %d\n", ret);
183 return false;
184 }
185
186 return true;
187 }
188 EXPORT_SYMBOL(drm_scdc_set_scrambling);
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 bool drm_scdc_set_high_tmds_clock_ratio(struct i2c_adapter *adapter, bool set)
220 {
221 u8 config;
222 int ret;
223
224 ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
225 if (ret < 0) {
226 DRM_DEBUG_KMS("Failed to read TMDS config: %d\n", ret);
227 return false;
228 }
229
230 if (set)
231 config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40;
232 else
233 config &= ~SCDC_TMDS_BIT_CLOCK_RATIO_BY_40;
234
235 ret = drm_scdc_writeb(adapter, SCDC_TMDS_CONFIG, config);
236 if (ret < 0) {
237 DRM_DEBUG_KMS("Failed to set TMDS clock ratio: %d\n", ret);
238 return false;
239 }
240
241
242
243
244
245
246 usleep_range(1000, 2000);
247 return true;
248 }
249 EXPORT_SYMBOL(drm_scdc_set_high_tmds_clock_ratio);