drm/amd/display: Fix i2c write flag.
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm_helpers.c
1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
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  * Authors: AMD
23  *
24  */
25
26 #include <linux/string.h>
27 #include <linux/acpi.h>
28 #include <linux/version.h>
29 #include <linux/i2c.h>
30
31 #include <drm/drmP.h>
32 #include <drm/drm_crtc_helper.h>
33 #include <drm/amdgpu_drm.h>
34 #include <drm/drm_edid.h>
35
36 #include "dm_services.h"
37 #include "amdgpu.h"
38 #include "dc.h"
39 #include "amdgpu_dm.h"
40 #include "amdgpu_dm_irq.h"
41 #include "amdgpu_dm_types.h"
42
43 #include "dm_helpers.h"
44
45 /* dm_helpers_parse_edid_caps
46  *
47  * Parse edid caps
48  *
49  * @edid:       [in] pointer to edid
50  *  edid_caps:  [in] pointer to edid caps
51  * @return
52  *      void
53  * */
54 enum dc_edid_status dm_helpers_parse_edid_caps(
55                 struct dc_context *ctx,
56                 const struct dc_edid *edid,
57                 struct dc_edid_caps *edid_caps)
58 {
59         struct edid *edid_buf = (struct edid *) edid->raw_edid;
60         struct cea_sad *sads;
61         int sad_count = -1;
62         int sadb_count = -1;
63         int i = 0;
64         int j = 0;
65         uint8_t *sadb = NULL;
66
67         enum dc_edid_status result = EDID_OK;
68
69         if (!edid_caps || !edid)
70                 return EDID_BAD_INPUT;
71
72         if (!drm_edid_is_valid(edid_buf))
73                 result = EDID_BAD_CHECKSUM;
74
75         edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] |
76                                         ((uint16_t) edid_buf->mfg_id[1])<<8;
77         edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] |
78                                         ((uint16_t) edid_buf->prod_code[1])<<8;
79         edid_caps->serial_number = edid_buf->serial;
80         edid_caps->manufacture_week = edid_buf->mfg_week;
81         edid_caps->manufacture_year = edid_buf->mfg_year;
82
83         /* One of the four detailed_timings stores the monitor name. It's
84          * stored in an array of length 13. */
85         for (i = 0; i < 4; i++) {
86                 if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) {
87                         while (j < 13 && edid_buf->detailed_timings[i].data.other_data.data.str.str[j]) {
88                                 if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n')
89                                         break;
90
91                                 edid_caps->display_name[j] =
92                                         edid_buf->detailed_timings[i].data.other_data.data.str.str[j];
93                                 j++;
94                         }
95                 }
96         }
97
98         edid_caps->edid_hdmi = drm_detect_hdmi_monitor(
99                         (struct edid *) edid->raw_edid);
100
101         sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
102         if (sad_count <= 0) {
103                 DRM_INFO("SADs count is: %d, don't need to read it\n",
104                                 sad_count);
105                 return result;
106         }
107
108         edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT;
109         for (i = 0; i < edid_caps->audio_mode_count; ++i) {
110                 struct cea_sad *sad = &sads[i];
111
112                 edid_caps->audio_modes[i].format_code = sad->format;
113                 edid_caps->audio_modes[i].channel_count = sad->channels;
114                 edid_caps->audio_modes[i].sample_rate = sad->freq;
115                 edid_caps->audio_modes[i].sample_size = sad->byte2;
116         }
117
118         sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb);
119
120         if (sadb_count < 0) {
121                 DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count);
122                 sadb_count = 0;
123         }
124
125         if (sadb_count)
126                 edid_caps->speaker_flags = sadb[0];
127         else
128                 edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
129
130         kfree(sads);
131         kfree(sadb);
132
133         return result;
134 }
135
136 static void get_payload_table(
137                 struct amdgpu_connector *aconnector,
138                 struct dp_mst_stream_allocation_table *proposed_table)
139 {
140         int i;
141         struct drm_dp_mst_topology_mgr *mst_mgr =
142                         &aconnector->mst_port->mst_mgr;
143
144         mutex_lock(&mst_mgr->payload_lock);
145
146         proposed_table->stream_count = 0;
147
148         /* number of active streams */
149         for (i = 0; i < mst_mgr->max_payloads; i++) {
150                 if (mst_mgr->payloads[i].num_slots == 0)
151                         break; /* end of vcp_id table */
152
153                 ASSERT(mst_mgr->payloads[i].payload_state !=
154                                 DP_PAYLOAD_DELETE_LOCAL);
155
156                 if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL ||
157                         mst_mgr->payloads[i].payload_state ==
158                                         DP_PAYLOAD_REMOTE) {
159
160                         struct dp_mst_stream_allocation *sa =
161                                         &proposed_table->stream_allocations[
162                                                 proposed_table->stream_count];
163
164                         sa->slot_count = mst_mgr->payloads[i].num_slots;
165                         sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
166                         proposed_table->stream_count++;
167                 }
168         }
169
170         mutex_unlock(&mst_mgr->payload_lock);
171 }
172
173 /*
174  * Writes payload allocation table in immediate downstream device.
175  */
176 bool dm_helpers_dp_mst_write_payload_allocation_table(
177                 struct dc_context *ctx,
178                 const struct dc_stream *stream,
179                 struct dp_mst_stream_allocation_table *proposed_table,
180                 bool enable)
181 {
182         struct amdgpu_connector *aconnector;
183         struct drm_dp_mst_topology_mgr *mst_mgr;
184         struct drm_dp_mst_port *mst_port;
185         int slots = 0;
186         bool ret;
187         int clock;
188         int bpp = 0;
189         int pbn = 0;
190
191         aconnector = stream->sink->priv;
192
193         if (!aconnector || !aconnector->mst_port)
194                 return false;
195
196         mst_mgr = &aconnector->mst_port->mst_mgr;
197
198         if (!mst_mgr->mst_state)
199                 return false;
200
201         mst_port = aconnector->port;
202
203         if (enable) {
204                 clock = stream->timing.pix_clk_khz;
205
206                 switch (stream->timing.display_color_depth) {
207
208                 case COLOR_DEPTH_666:
209                         bpp = 6;
210                         break;
211                 case COLOR_DEPTH_888:
212                         bpp = 8;
213                         break;
214                 case COLOR_DEPTH_101010:
215                         bpp = 10;
216                         break;
217                 case COLOR_DEPTH_121212:
218                         bpp = 12;
219                         break;
220                 case COLOR_DEPTH_141414:
221                         bpp = 14;
222                         break;
223                 case COLOR_DEPTH_161616:
224                         bpp = 16;
225                         break;
226                 default:
227                         ASSERT(bpp != 0);
228                         break;
229                 }
230
231                 bpp = bpp * 3;
232
233                 /* TODO need to know link rate */
234
235                 pbn = drm_dp_calc_pbn_mode(clock, bpp);
236
237                 slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
238                 ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
239
240                 if (!ret)
241                         return false;
242
243         } else {
244                 drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
245         }
246
247         ret = drm_dp_update_payload_part1(mst_mgr);
248
249         /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
250          * AUX message. The sequence is slot 1-63 allocated sequence for each
251          * stream. AMD ASIC stream slot allocation should follow the same
252          * sequence. copy DRM MST allocation to dc */
253
254         get_payload_table(aconnector, proposed_table);
255
256         if (ret)
257                 return false;
258
259         return true;
260 }
261
262 /*
263  * Polls for ACT (allocation change trigger) handled and sends
264  * ALLOCATE_PAYLOAD message.
265  */
266 bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
267                 struct dc_context *ctx,
268                 const struct dc_stream *stream)
269 {
270         struct amdgpu_connector *aconnector;
271         struct drm_dp_mst_topology_mgr *mst_mgr;
272         int ret;
273
274         aconnector = stream->sink->priv;
275
276         if (!aconnector || !aconnector->mst_port)
277                 return false;
278
279         mst_mgr = &aconnector->mst_port->mst_mgr;
280
281         if (!mst_mgr->mst_state)
282                 return false;
283
284         ret = drm_dp_check_act_status(mst_mgr);
285
286         if (ret)
287                 return false;
288
289         return true;
290 }
291
292 bool dm_helpers_dp_mst_send_payload_allocation(
293                 struct dc_context *ctx,
294                 const struct dc_stream *stream,
295                 bool enable)
296 {
297         struct amdgpu_connector *aconnector;
298         struct drm_dp_mst_topology_mgr *mst_mgr;
299         struct drm_dp_mst_port *mst_port;
300         int ret;
301
302         aconnector = stream->sink->priv;
303
304         if (!aconnector || !aconnector->mst_port)
305                 return false;
306
307         mst_port = aconnector->port;
308
309         mst_mgr = &aconnector->mst_port->mst_mgr;
310
311         if (!mst_mgr->mst_state)
312                 return false;
313
314         ret = drm_dp_update_payload_part2(mst_mgr);
315
316         if (ret)
317                 return false;
318
319         if (!enable)
320                 drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
321
322         return true;
323 }
324
325 bool dm_helpers_dp_mst_start_top_mgr(
326                 struct dc_context *ctx,
327                 const struct dc_link *link,
328                 bool boot)
329 {
330         struct amdgpu_connector *aconnector = link->priv;
331
332         if (!aconnector) {
333                         DRM_ERROR("Failed to found connector for link!");
334                         return false;
335         }
336
337         if (boot) {
338                 DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n",
339                                         aconnector, aconnector->base.base.id);
340                 return true;
341         }
342
343         DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
344                         aconnector, aconnector->base.base.id);
345
346         return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0);
347 }
348
349 void dm_helpers_dp_mst_stop_top_mgr(
350                 struct dc_context *ctx,
351                 const struct dc_link *link)
352 {
353         struct amdgpu_connector *aconnector = link->priv;
354
355         if (!aconnector) {
356                         DRM_ERROR("Failed to found connector for link!");
357                         return;
358         }
359
360         DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n",
361                         aconnector, aconnector->base.base.id);
362
363         if (aconnector->mst_mgr.mst_state == true)
364                 drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false);
365 }
366
367 bool dm_helpers_dp_read_dpcd(
368                 struct dc_context *ctx,
369                 const struct dc_link *link,
370                 uint32_t address,
371                 uint8_t *data,
372                 uint32_t size)
373 {
374
375         struct amdgpu_connector *aconnector = link->priv;
376
377         if (!aconnector) {
378                 DRM_ERROR("Failed to found connector for link!");
379                 return false;
380         }
381
382         return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address,
383                         data, size) > 0;
384 }
385
386 bool dm_helpers_dp_write_dpcd(
387                 struct dc_context *ctx,
388                 const struct dc_link *link,
389                 uint32_t address,
390                 const uint8_t *data,
391                 uint32_t size)
392 {
393         struct amdgpu_connector *aconnector = link->priv;
394
395         if (!aconnector) {
396                 DRM_ERROR("Failed to found connector for link!");
397                 return false;
398         }
399
400         return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux,
401                         address, (uint8_t *)data, size) > 0;
402 }
403
404 bool dm_helpers_submit_i2c(
405                 struct dc_context *ctx,
406                 const struct dc_link *link,
407                 struct i2c_command *cmd)
408 {
409         struct amdgpu_connector *aconnector = link->priv;
410         struct i2c_msg *msgs;
411         int i = 0;
412         int num = cmd->number_of_payloads;
413         bool result;
414
415         if (!aconnector) {
416                 DRM_ERROR("Failed to found connector for link!");
417                 return false;
418         }
419
420         msgs = kzalloc(num * sizeof(struct i2c_msg), GFP_KERNEL);
421
422         if (!msgs)
423                 return false;
424
425         for (i = 0; i < num; i++) {
426                 msgs[i].flags = cmd->payloads[i].write ? 0 : I2C_M_RD;
427                 msgs[i].addr = cmd->payloads[i].address;
428                 msgs[i].len = cmd->payloads[i].length;
429                 msgs[i].buf = cmd->payloads[i].data;
430         }
431
432         result = i2c_transfer(&aconnector->i2c->base, msgs, num) == num;
433
434         kfree(msgs);
435
436         return result;
437 }