]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
Merge tag 'soundwire-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
[linux.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm_crc.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 <drm/drm_crtc.h>
27 #include <drm/drm_vblank.h>
28
29 #include "amdgpu.h"
30 #include "amdgpu_dm.h"
31 #include "dc.h"
32 #include "amdgpu_securedisplay.h"
33 #include "amdgpu_dm_psr.h"
34
35 static const char *const pipe_crc_sources[] = {
36         "none",
37         "crtc",
38         "crtc dither",
39         "dprx",
40         "dprx dither",
41         "auto",
42 };
43
44 static enum amdgpu_dm_pipe_crc_source dm_parse_crc_source(const char *source)
45 {
46         if (!source || !strcmp(source, "none"))
47                 return AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
48         if (!strcmp(source, "auto") || !strcmp(source, "crtc"))
49                 return AMDGPU_DM_PIPE_CRC_SOURCE_CRTC;
50         if (!strcmp(source, "dprx"))
51                 return AMDGPU_DM_PIPE_CRC_SOURCE_DPRX;
52         if (!strcmp(source, "crtc dither"))
53                 return AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER;
54         if (!strcmp(source, "dprx dither"))
55                 return AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER;
56
57         return AMDGPU_DM_PIPE_CRC_SOURCE_INVALID;
58 }
59
60 static bool dm_is_crc_source_crtc(enum amdgpu_dm_pipe_crc_source src)
61 {
62         return (src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) ||
63                (src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER);
64 }
65
66 static bool dm_is_crc_source_dprx(enum amdgpu_dm_pipe_crc_source src)
67 {
68         return (src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX) ||
69                (src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER);
70 }
71
72 static bool dm_need_crc_dither(enum amdgpu_dm_pipe_crc_source src)
73 {
74         return (src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER) ||
75                (src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER) ||
76                (src == AMDGPU_DM_PIPE_CRC_SOURCE_NONE);
77 }
78
79 const char *const *amdgpu_dm_crtc_get_crc_sources(struct drm_crtc *crtc,
80                                                   size_t *count)
81 {
82         *count = ARRAY_SIZE(pipe_crc_sources);
83         return pipe_crc_sources;
84 }
85
86 #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
87 static void update_phy_id_mapping(struct amdgpu_device *adev)
88 {
89         struct drm_device *ddev = adev_to_drm(adev);
90         struct amdgpu_display_manager *dm = &adev->dm;
91         struct drm_connector *connector;
92         struct amdgpu_dm_connector *aconnector;
93         struct amdgpu_dm_connector *sort_connector[AMDGPU_DM_MAX_CRTC] = {NULL};
94         struct drm_connector_list_iter iter;
95         uint8_t idx = 0, idx_2 = 0, connector_cnt = 0;
96
97         dm->secure_display_ctx.phy_mapping_updated = false;
98
99         mutex_lock(&ddev->mode_config.mutex);
100         drm_connector_list_iter_begin(ddev, &iter);
101         drm_for_each_connector_iter(connector, &iter) {
102
103                 if (connector->status != connector_status_connected)
104                         continue;
105
106                 if (idx >= AMDGPU_DM_MAX_CRTC) {
107                         DRM_WARN("%s connected connectors exceed max crtc\n", __func__);
108                         mutex_unlock(&ddev->mode_config.mutex);
109                         return;
110                 }
111
112                 aconnector = to_amdgpu_dm_connector(connector);
113
114                 sort_connector[idx] = aconnector;
115                 idx++;
116                 connector_cnt++;
117         }
118         drm_connector_list_iter_end(&iter);
119
120         /* sort connectors by link_enc_hw_instance first */
121         for (idx = connector_cnt; idx > 1 ; idx--) {
122                 for (idx_2 = 0; idx_2 < (idx - 1); idx_2++) {
123                         if (sort_connector[idx_2]->dc_link->link_enc_hw_inst >
124                             sort_connector[idx_2 + 1]->dc_link->link_enc_hw_inst)
125                                 swap(sort_connector[idx_2], sort_connector[idx_2 + 1]);
126                 }
127         }
128
129         /*
130          * Sort mst connectors by RAD. mst connectors with the same enc_hw_instance are already
131          * sorted together above.
132          */
133         for (idx = 0; idx < connector_cnt; /*Do nothing*/) {
134                 if (sort_connector[idx]->mst_root) {
135                         uint8_t i, j, k;
136                         uint8_t mst_con_cnt = 1;
137
138                         for (idx_2 = (idx + 1); idx_2 < connector_cnt; idx_2++) {
139                                 if (sort_connector[idx_2]->mst_root == sort_connector[idx]->mst_root)
140                                         mst_con_cnt++;
141                                 else
142                                         break;
143                         }
144
145                         for (i = mst_con_cnt; i > 1; i--) {
146                                 for (j = idx; j < (idx + i - 2); j++) {
147                                         int mstb_lct = sort_connector[j]->mst_output_port->parent->lct;
148                                         int next_mstb_lct = sort_connector[j + 1]->mst_output_port->parent->lct;
149                                         u8 *rad;
150                                         u8 *next_rad;
151                                         bool swap = false;
152
153                                         /* Sort by mst tree depth first. Then compare RAD if depth is the same*/
154                                         if (mstb_lct > next_mstb_lct) {
155                                                 swap = true;
156                                         } else if (mstb_lct == next_mstb_lct) {
157                                                 if (mstb_lct == 1) {
158                                                         if (sort_connector[j]->mst_output_port->port_num > sort_connector[j + 1]->mst_output_port->port_num)
159                                                                 swap = true;
160                                                 } else if (mstb_lct > 1) {
161                                                         rad = sort_connector[j]->mst_output_port->parent->rad;
162                                                         next_rad = sort_connector[j + 1]->mst_output_port->parent->rad;
163
164                                                         for (k = 0; k < mstb_lct - 1; k++) {
165                                                                 int shift = (k % 2) ? 0 : 4;
166                                                                 int port_num = (rad[k / 2] >> shift) & 0xf;
167                                                                 int next_port_num = (next_rad[k / 2] >> shift) & 0xf;
168
169                                                                 if (port_num > next_port_num) {
170                                                                         swap = true;
171                                                                         break;
172                                                                 }
173                                                         }
174                                                 } else {
175                                                         DRM_ERROR("MST LCT shouldn't be set as < 1");
176                                                         mutex_unlock(&ddev->mode_config.mutex);
177                                                         return;
178                                                 }
179                                         }
180
181                                         if (swap)
182                                                 swap(sort_connector[j], sort_connector[j + 1]);
183                                 }
184                         }
185
186                         idx += mst_con_cnt;
187                 } else {
188                         idx++;
189                 }
190         }
191
192         /* Complete sorting. Assign relavant result to dm->secure_display_ctx.phy_id_mapping[]*/
193         memset(dm->secure_display_ctx.phy_id_mapping, 0, sizeof(dm->secure_display_ctx.phy_id_mapping));
194         for (idx = 0; idx < connector_cnt; idx++) {
195                 aconnector = sort_connector[idx];
196
197                 dm->secure_display_ctx.phy_id_mapping[idx].assigned = true;
198                 dm->secure_display_ctx.phy_id_mapping[idx].is_mst = false;
199                 dm->secure_display_ctx.phy_id_mapping[idx].enc_hw_inst = aconnector->dc_link->link_enc_hw_inst;
200
201                 if (sort_connector[idx]->mst_root) {
202                         dm->secure_display_ctx.phy_id_mapping[idx].is_mst = true;
203                         dm->secure_display_ctx.phy_id_mapping[idx].lct = aconnector->mst_output_port->parent->lct;
204                         dm->secure_display_ctx.phy_id_mapping[idx].port_num = aconnector->mst_output_port->port_num;
205                         memcpy(dm->secure_display_ctx.phy_id_mapping[idx].rad,
206                                 aconnector->mst_output_port->parent->rad, sizeof(aconnector->mst_output_port->parent->rad));
207                 }
208         }
209         mutex_unlock(&ddev->mode_config.mutex);
210
211         dm->secure_display_ctx.phy_id_mapping_cnt = connector_cnt;
212         dm->secure_display_ctx.phy_mapping_updated = true;
213 }
214
215 static bool get_phy_id(struct amdgpu_display_manager *dm,
216                         struct amdgpu_dm_connector *aconnector, uint8_t *phy_id)
217 {
218         int idx, idx_2;
219         bool found = false;
220
221         /*
222          * Assume secure display start after all connectors are probed. The connection
223          * config is static as well
224          */
225         if (!dm->secure_display_ctx.phy_mapping_updated) {
226                 DRM_WARN("%s Should update the phy id table before get it's value", __func__);
227                 return false;
228         }
229
230         for (idx = 0; idx < dm->secure_display_ctx.phy_id_mapping_cnt; idx++) {
231                 if (!dm->secure_display_ctx.phy_id_mapping[idx].assigned) {
232                         DRM_ERROR("phy_id_mapping[%d] should be assigned", idx);
233                         return false;
234                 }
235
236                 if (aconnector->dc_link->link_enc_hw_inst ==
237                                 dm->secure_display_ctx.phy_id_mapping[idx].enc_hw_inst) {
238                         if (!dm->secure_display_ctx.phy_id_mapping[idx].is_mst) {
239                                 found = true;
240                                 goto out;
241                         } else {
242                                 /* Could caused by wrongly pass mst root connector */
243                                 if (!aconnector->mst_output_port) {
244                                         DRM_ERROR("%s Check mst case but connector without a port assigned", __func__);
245                                         return false;
246                                 }
247
248                                 if (aconnector->mst_root &&
249                                         aconnector->mst_root->mst_mgr.mst_primary == NULL) {
250                                         DRM_WARN("%s pass in a stale mst connector", __func__);
251                                 }
252
253                                 if (aconnector->mst_output_port->parent->lct == dm->secure_display_ctx.phy_id_mapping[idx].lct &&
254                                         aconnector->mst_output_port->port_num == dm->secure_display_ctx.phy_id_mapping[idx].port_num) {
255                                         if (aconnector->mst_output_port->parent->lct == 1) {
256                                                 found = true;
257                                                 goto out;
258                                         } else if (aconnector->mst_output_port->parent->lct > 1) {
259                                                 /* Check RAD */
260                                                 for (idx_2 = 0; idx_2 < aconnector->mst_output_port->parent->lct - 1; idx_2++) {
261                                                         int shift = (idx_2 % 2) ? 0 : 4;
262                                                         int port_num = (aconnector->mst_output_port->parent->rad[idx_2 / 2] >> shift) & 0xf;
263                                                         int port_num2 = (dm->secure_display_ctx.phy_id_mapping[idx].rad[idx_2 / 2] >> shift) & 0xf;
264
265                                                         if (port_num != port_num2)
266                                                                 break;
267                                                 }
268
269                                                 if (idx_2 == aconnector->mst_output_port->parent->lct - 1) {
270                                                         found = true;
271                                                         goto out;
272                                                 }
273                                         } else {
274                                                 DRM_ERROR("lCT should be >= 1");
275                                                 return false;
276                                         }
277                                 }
278                         }
279                 }
280         }
281
282 out:
283         if (found) {
284                 DRM_DEBUG_DRIVER("Associated secure display PHY ID as %d", idx);
285                 *phy_id = idx;
286         } else {
287                 DRM_WARN("Can't find associated phy ID");
288                 return false;
289         }
290
291         return true;
292 }
293
294 static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc, struct dc_stream_state *stream)
295 {
296         struct drm_device *drm_dev = crtc->dev;
297         struct amdgpu_display_manager *dm = &drm_to_adev(drm_dev)->dm;
298         struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
299         struct amdgpu_dm_connector *aconnector;
300         bool was_activated;
301         uint8_t phy_id;
302         unsigned long flags;
303         int i;
304
305         spin_lock_irqsave(&drm_dev->event_lock, flags);
306         was_activated = acrtc->dm_irq_params.crc_window_activated;
307         for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
308                 acrtc->dm_irq_params.window_param[i].x_start = 0;
309                 acrtc->dm_irq_params.window_param[i].y_start = 0;
310                 acrtc->dm_irq_params.window_param[i].x_end = 0;
311                 acrtc->dm_irq_params.window_param[i].y_end = 0;
312                 acrtc->dm_irq_params.window_param[i].enable = false;
313                 acrtc->dm_irq_params.window_param[i].update_win = false;
314                 acrtc->dm_irq_params.window_param[i].skip_frame_cnt = 0;
315         }
316         acrtc->dm_irq_params.crc_window_activated = false;
317         spin_unlock_irqrestore(&drm_dev->event_lock, flags);
318
319         /* Disable secure_display if it was enabled */
320         if (was_activated && dm->secure_display_ctx.op_mode == LEGACY_MODE) {
321                 /* stop ROI update on this crtc */
322                 flush_work(&dm->secure_display_ctx.crtc_ctx[crtc->index].notify_ta_work);
323                 flush_work(&dm->secure_display_ctx.crtc_ctx[crtc->index].forward_roi_work);
324                 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
325
326                 if (aconnector && get_phy_id(dm, aconnector, &phy_id)) {
327                         if (dm->secure_display_ctx.support_mul_roi)
328                                 dc_stream_forward_multiple_crc_window(stream, NULL, phy_id, true);
329                         else
330                                 dc_stream_forward_crc_window(stream, NULL, phy_id, true);
331                 } else {
332                         DRM_DEBUG_DRIVER("%s Can't find matching phy id", __func__);
333                 }
334         }
335 }
336
337 static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
338 {
339         struct secure_display_crtc_context *crtc_ctx;
340         struct psp_context *psp;
341         struct ta_securedisplay_cmd *securedisplay_cmd;
342         struct drm_crtc *crtc;
343         struct dc_stream_state *stream;
344         struct amdgpu_dm_connector *aconnector;
345         uint8_t phy_inst;
346         struct amdgpu_display_manager *dm;
347         struct crc_data crc_cpy[MAX_CRC_WINDOW_NUM];
348         unsigned long flags;
349         uint8_t roi_idx = 0;
350         int ret;
351         int i;
352
353         crtc_ctx = container_of(work, struct secure_display_crtc_context, notify_ta_work);
354         crtc = crtc_ctx->crtc;
355
356         if (!crtc)
357                 return;
358
359         psp = &drm_to_adev(crtc->dev)->psp;
360
361         if (!psp->securedisplay_context.context.initialized) {
362                 DRM_DEBUG_DRIVER("Secure Display fails to notify PSP TA\n");
363                 return;
364         }
365
366         dm = &drm_to_adev(crtc->dev)->dm;
367         stream = to_amdgpu_crtc(crtc)->dm_irq_params.stream;
368         aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
369         if (!aconnector)
370                 return;
371
372         mutex_lock(&crtc->dev->mode_config.mutex);
373         if (!get_phy_id(dm, aconnector, &phy_inst)) {
374                 DRM_WARN("%s Can't find mapping phy id!", __func__);
375                 mutex_unlock(&crtc->dev->mode_config.mutex);
376                 return;
377         }
378         mutex_unlock(&crtc->dev->mode_config.mutex);
379
380         spin_lock_irqsave(&crtc->dev->event_lock, flags);
381         memcpy(crc_cpy, crtc_ctx->crc_info.crc, sizeof(struct crc_data) * MAX_CRC_WINDOW_NUM);
382         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
383
384         /* need lock for multiple crtcs to use the command buffer */
385         mutex_lock(&psp->securedisplay_context.mutex);
386         /* PSP TA is expected to finish data transmission over I2C within current frame,
387          * even there are up to 4 crtcs request to send in this frame.
388          */
389         if (dm->secure_display_ctx.support_mul_roi) {
390                 psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
391                                                         TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC_V2);
392
393                 securedisplay_cmd->securedisplay_in_message.send_roi_crc_v2.phy_id = phy_inst;
394
395                 for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
396                         if (crc_cpy[i].crc_ready)
397                                 roi_idx |= 1 << i;
398                 }
399                 securedisplay_cmd->securedisplay_in_message.send_roi_crc_v2.roi_idx = roi_idx;
400
401                 ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC_V2);
402         } else {
403                 psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
404                                                         TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
405
406                 securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_inst;
407
408                 ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
409         }
410
411         if (!ret) {
412                 if (securedisplay_cmd->status != TA_SECUREDISPLAY_STATUS__SUCCESS)
413                         psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
414         }
415
416         mutex_unlock(&psp->securedisplay_context.mutex);
417 }
418
419 static void
420 amdgpu_dm_forward_crc_window(struct work_struct *work)
421 {
422         struct secure_display_crtc_context *crtc_ctx;
423         struct amdgpu_display_manager *dm;
424         struct drm_crtc *crtc;
425         struct dc_stream_state *stream;
426         struct amdgpu_dm_connector *aconnector;
427         struct crc_window roi_cpy[MAX_CRC_WINDOW_NUM];
428         unsigned long flags;
429         uint8_t phy_id;
430
431         crtc_ctx = container_of(work, struct secure_display_crtc_context, forward_roi_work);
432         crtc = crtc_ctx->crtc;
433
434         if (!crtc)
435                 return;
436
437         dm = &drm_to_adev(crtc->dev)->dm;
438         stream = to_amdgpu_crtc(crtc)->dm_irq_params.stream;
439         aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
440
441         if (!aconnector)
442                 return;
443
444         mutex_lock(&crtc->dev->mode_config.mutex);
445         if (!get_phy_id(dm, aconnector, &phy_id)) {
446                 DRM_WARN("%s Can't find mapping phy id!", __func__);
447                 mutex_unlock(&crtc->dev->mode_config.mutex);
448                 return;
449         }
450         mutex_unlock(&crtc->dev->mode_config.mutex);
451
452         spin_lock_irqsave(&crtc->dev->event_lock, flags);
453         memcpy(roi_cpy, crtc_ctx->roi, sizeof(struct crc_window) * MAX_CRC_WINDOW_NUM);
454         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
455
456         mutex_lock(&dm->dc_lock);
457         if (dm->secure_display_ctx.support_mul_roi)
458                 dc_stream_forward_multiple_crc_window(stream, roi_cpy,
459                         phy_id, false);
460         else
461                 dc_stream_forward_crc_window(stream, &roi_cpy[0].rect,
462                         phy_id, false);
463         mutex_unlock(&dm->dc_lock);
464 }
465
466 bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc)
467 {
468         struct drm_device *drm_dev = crtc->dev;
469         struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
470         bool ret = false;
471
472         spin_lock_irq(&drm_dev->event_lock);
473         ret = acrtc->dm_irq_params.crc_window_activated;
474         spin_unlock_irq(&drm_dev->event_lock);
475
476         return ret;
477 }
478 #endif
479
480 int
481 amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
482                                  size_t *values_cnt)
483 {
484         enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
485
486         if (source < 0) {
487                 DRM_DEBUG_DRIVER("Unknown CRC source %s for CRTC%d\n",
488                                  src_name, crtc->index);
489                 return -EINVAL;
490         }
491
492         *values_cnt = 3;
493         return 0;
494 }
495
496 int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
497                                         struct dm_crtc_state *dm_crtc_state,
498                                         enum amdgpu_dm_pipe_crc_source source)
499 {
500         struct amdgpu_device *adev = drm_to_adev(crtc->dev);
501         struct dc_stream_state *stream_state = dm_crtc_state->stream;
502         bool enable = amdgpu_dm_is_valid_crc_source(source);
503         int ret = 0;
504
505         /* Configuration will be deferred to stream enable. */
506         if (!stream_state)
507                 return -EINVAL;
508
509         mutex_lock(&adev->dm.dc_lock);
510
511         /* For PSR1, check that the panel has exited PSR */
512         if (stream_state->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1)
513                 amdgpu_dm_psr_wait_disable(stream_state);
514
515         /* Enable or disable CRTC CRC generation */
516         if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
517                 if (!dc_stream_configure_crc(stream_state->ctx->dc,
518                                              stream_state, NULL, enable, enable, 0, true)) {
519                         ret = -EINVAL;
520                         goto unlock;
521                 }
522         }
523
524         /* Configure dithering */
525         if (!dm_need_crc_dither(source)) {
526                 dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
527                 dc_stream_set_dyn_expansion(stream_state->ctx->dc, stream_state,
528                                             DYN_EXPANSION_DISABLE);
529         } else {
530                 dc_stream_set_dither_option(stream_state,
531                                             DITHER_OPTION_DEFAULT);
532                 dc_stream_set_dyn_expansion(stream_state->ctx->dc, stream_state,
533                                             DYN_EXPANSION_AUTO);
534         }
535
536 unlock:
537         mutex_unlock(&adev->dm.dc_lock);
538
539         return ret;
540 }
541
542 int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
543 {
544         enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
545         enum amdgpu_dm_pipe_crc_source cur_crc_src;
546         struct drm_crtc_commit *commit;
547         struct dm_crtc_state *crtc_state;
548         struct drm_device *drm_dev = crtc->dev;
549 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
550         struct amdgpu_device *adev = drm_to_adev(drm_dev);
551         struct amdgpu_display_manager *dm = &adev->dm;
552 #endif
553         struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
554         struct drm_dp_aux *aux = NULL;
555         bool enable = false;
556         bool enabled = false;
557         int ret = 0;
558
559         if (source < 0) {
560                 DRM_DEBUG_DRIVER("Unknown CRC source %s for CRTC%d\n",
561                                  src_name, crtc->index);
562                 return -EINVAL;
563         }
564
565         ret = drm_modeset_lock(&crtc->mutex, NULL);
566         if (ret)
567                 return ret;
568
569         spin_lock(&crtc->commit_lock);
570         commit = list_first_entry_or_null(&crtc->commit_list,
571                                           struct drm_crtc_commit, commit_entry);
572         if (commit)
573                 drm_crtc_commit_get(commit);
574         spin_unlock(&crtc->commit_lock);
575
576         if (commit) {
577                 /*
578                  * Need to wait for all outstanding programming to complete
579                  * in commit tail since it can modify CRC related fields and
580                  * hardware state. Since we're holding the CRTC lock we're
581                  * guaranteed that no other commit work can be queued off
582                  * before we modify the state below.
583                  */
584                 ret = wait_for_completion_interruptible_timeout(
585                         &commit->hw_done, 10 * HZ);
586                 if (ret)
587                         goto cleanup;
588         }
589
590         enable = amdgpu_dm_is_valid_crc_source(source);
591         crtc_state = to_dm_crtc_state(crtc->state);
592         spin_lock_irq(&drm_dev->event_lock);
593         cur_crc_src = acrtc->dm_irq_params.crc_src;
594         spin_unlock_irq(&drm_dev->event_lock);
595
596         /*
597          * USER REQ SRC | CURRENT SRC | BEHAVIOR
598          * -----------------------------
599          * None         | None        | Do nothing
600          * None         | CRTC        | Disable CRTC CRC, set default to dither
601          * None         | DPRX        | Disable DPRX CRC, need 'aux', set default to dither
602          * None         | CRTC DITHER | Disable CRTC CRC
603          * None         | DPRX DITHER | Disable DPRX CRC, need 'aux'
604          * CRTC         | XXXX        | Enable CRTC CRC, no dither
605          * DPRX         | XXXX        | Enable DPRX CRC, need 'aux', no dither
606          * CRTC DITHER  | XXXX        | Enable CRTC CRC, set dither
607          * DPRX DITHER  | XXXX        | Enable DPRX CRC, need 'aux', set dither
608          */
609         if (dm_is_crc_source_dprx(source) ||
610             (source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE &&
611              dm_is_crc_source_dprx(cur_crc_src))) {
612                 struct amdgpu_dm_connector *aconn = NULL;
613                 struct drm_connector *connector;
614                 struct drm_connector_list_iter conn_iter;
615
616                 drm_connector_list_iter_begin(crtc->dev, &conn_iter);
617                 drm_for_each_connector_iter(connector, &conn_iter) {
618                         if (!connector->state || connector->state->crtc != crtc)
619                                 continue;
620
621                         if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
622                                 continue;
623
624                         aconn = to_amdgpu_dm_connector(connector);
625                         break;
626                 }
627                 drm_connector_list_iter_end(&conn_iter);
628
629                 if (!aconn) {
630                         DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", crtc->index);
631                         ret = -EINVAL;
632                         goto cleanup;
633                 }
634
635                 aux = (aconn->mst_output_port) ? &aconn->mst_output_port->aux : &aconn->dm_dp_aux.aux;
636
637                 if (!aux) {
638                         DRM_DEBUG_DRIVER("No dp aux for amd connector\n");
639                         ret = -EINVAL;
640                         goto cleanup;
641                 }
642
643                 if ((aconn->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) &&
644                                 (aconn->base.connector_type != DRM_MODE_CONNECTOR_eDP)) {
645                         DRM_DEBUG_DRIVER("No DP connector available for CRC source\n");
646                         ret = -EINVAL;
647                         goto cleanup;
648                 }
649
650         }
651
652         /*
653          * Reading the CRC requires the vblank interrupt handler to be
654          * enabled. Keep a reference until CRC capture stops.
655          */
656         enabled = amdgpu_dm_is_valid_crc_source(cur_crc_src);
657         if (!enabled && enable) {
658                 ret = drm_crtc_vblank_get(crtc);
659                 if (ret)
660                         goto cleanup;
661         }
662
663 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
664         /* Reset secure_display when we change crc source from debugfs */
665         amdgpu_dm_set_crc_window_default(crtc, crtc_state->stream);
666 #endif
667
668         if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source)) {
669                 ret = -EINVAL;
670                 goto cleanup;
671         }
672
673         if (!enabled && enable) {
674                 if (dm_is_crc_source_dprx(source)) {
675                         if (drm_dp_start_crc(aux, crtc)) {
676                                 DRM_DEBUG_DRIVER("dp start crc failed\n");
677                                 ret = -EINVAL;
678                                 goto cleanup;
679                         }
680                 }
681         } else if (enabled && !enable) {
682                 drm_crtc_vblank_put(crtc);
683                 if (dm_is_crc_source_dprx(source)) {
684                         if (drm_dp_stop_crc(aux)) {
685                                 DRM_DEBUG_DRIVER("dp stop crc failed\n");
686                                 ret = -EINVAL;
687                                 goto cleanup;
688                         }
689                 }
690         }
691
692         spin_lock_irq(&drm_dev->event_lock);
693         acrtc->dm_irq_params.crc_src = source;
694         spin_unlock_irq(&drm_dev->event_lock);
695
696         /* Reset crc_skipped on dm state */
697         crtc_state->crc_skip_count = 0;
698
699 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
700         /* Initialize phy id mapping table for secure display*/
701         if (dm->secure_display_ctx.op_mode == LEGACY_MODE &&
702                 !dm->secure_display_ctx.phy_mapping_updated)
703                 update_phy_id_mapping(adev);
704 #endif
705
706 cleanup:
707         if (commit)
708                 drm_crtc_commit_put(commit);
709
710         drm_modeset_unlock(&crtc->mutex);
711
712         return ret;
713 }
714
715 /**
716  * amdgpu_dm_crtc_handle_crc_irq: Report to DRM the CRC on given CRTC.
717  * @crtc: DRM CRTC object.
718  *
719  * This function should be called at the end of a vblank, when the fb has been
720  * fully processed through the pipe.
721  */
722 void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc)
723 {
724         struct dm_crtc_state *crtc_state;
725         struct dc_stream_state *stream_state;
726         struct drm_device *drm_dev = NULL;
727         enum amdgpu_dm_pipe_crc_source cur_crc_src;
728         struct amdgpu_crtc *acrtc = NULL;
729         uint32_t crcs[3];
730         unsigned long flags;
731
732         if (crtc == NULL)
733                 return;
734
735         crtc_state = to_dm_crtc_state(crtc->state);
736         stream_state = crtc_state->stream;
737         acrtc = to_amdgpu_crtc(crtc);
738         drm_dev = crtc->dev;
739
740         spin_lock_irqsave(&drm_dev->event_lock, flags);
741         cur_crc_src = acrtc->dm_irq_params.crc_src;
742         spin_unlock_irqrestore(&drm_dev->event_lock, flags);
743
744         /* Early return if CRC capture is not enabled. */
745         if (!amdgpu_dm_is_valid_crc_source(cur_crc_src))
746                 return;
747
748         /*
749          * Since flipping and crc enablement happen asynchronously, we - more
750          * often than not - will be returning an 'uncooked' crc on first frame.
751          * Probably because hw isn't ready yet. For added security, skip the
752          * first two CRC values.
753          */
754         if (crtc_state->crc_skip_count < 2) {
755                 crtc_state->crc_skip_count += 1;
756                 return;
757         }
758
759         if (dm_is_crc_source_crtc(cur_crc_src)) {
760                 if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state, 0,
761                                        &crcs[0], &crcs[1], &crcs[2]))
762                         return;
763
764                 drm_crtc_add_crc_entry(crtc, true,
765                                        drm_crtc_accurate_vblank_count(crtc), crcs);
766         }
767 }
768
769 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
770 void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
771 {
772         struct drm_device *drm_dev = NULL;
773         enum amdgpu_dm_pipe_crc_source cur_crc_src;
774         struct amdgpu_crtc *acrtc = NULL;
775         struct amdgpu_device *adev = NULL;
776         struct secure_display_crtc_context *crtc_ctx = NULL;
777         bool reset_crc_frame_count[MAX_CRC_WINDOW_NUM] = {false};
778         uint32_t crc_r[MAX_CRC_WINDOW_NUM] = {0};
779         uint32_t crc_g[MAX_CRC_WINDOW_NUM] = {0};
780         uint32_t crc_b[MAX_CRC_WINDOW_NUM] = {0};
781         unsigned long flags1;
782         bool forward_roi_change = false;
783         bool notify_ta = false;
784         bool all_crc_ready = true;
785         struct dc_stream_state *stream_state;
786         int i;
787
788         if (crtc == NULL)
789                 return;
790
791         acrtc = to_amdgpu_crtc(crtc);
792         adev = drm_to_adev(crtc->dev);
793         drm_dev = crtc->dev;
794         stream_state = to_dm_crtc_state(crtc->state)->stream;
795
796         spin_lock_irqsave(&drm_dev->event_lock, flags1);
797         cur_crc_src = acrtc->dm_irq_params.crc_src;
798
799         /* Early return if CRC capture is not enabled. */
800         if (!amdgpu_dm_is_valid_crc_source(cur_crc_src) ||
801             !dm_is_crc_source_crtc(cur_crc_src)) {
802                 spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
803                 return;
804         }
805
806         if (!acrtc->dm_irq_params.crc_window_activated) {
807                 spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
808                 return;
809         }
810
811         crtc_ctx = &adev->dm.secure_display_ctx.crtc_ctx[acrtc->crtc_id];
812         if (WARN_ON(crtc_ctx->crtc != crtc)) {
813                 /* We have set the crtc when creating secure_display_crtc_context,
814                  * don't expect it to be changed here.
815                  */
816                 crtc_ctx->crtc = crtc;
817         }
818
819         for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
820                 struct crc_params crc_window = {
821                         .windowa_x_start = acrtc->dm_irq_params.window_param[i].x_start,
822                         .windowa_y_start = acrtc->dm_irq_params.window_param[i].y_start,
823                         .windowa_x_end = acrtc->dm_irq_params.window_param[i].x_end,
824                         .windowa_y_end = acrtc->dm_irq_params.window_param[i].y_end,
825                         .windowb_x_start = acrtc->dm_irq_params.window_param[i].x_start,
826                         .windowb_y_start = acrtc->dm_irq_params.window_param[i].y_start,
827                         .windowb_x_end = acrtc->dm_irq_params.window_param[i].x_end,
828                         .windowb_y_end = acrtc->dm_irq_params.window_param[i].y_end,
829                 };
830
831                 crtc_ctx->roi[i].enable = acrtc->dm_irq_params.window_param[i].enable;
832
833                 if (!acrtc->dm_irq_params.window_param[i].enable) {
834                         crtc_ctx->crc_info.crc[i].crc_ready = false;
835                         continue;
836                 }
837
838                 if (acrtc->dm_irq_params.window_param[i].skip_frame_cnt) {
839                         acrtc->dm_irq_params.window_param[i].skip_frame_cnt -= 1;
840                         crtc_ctx->crc_info.crc[i].crc_ready = false;
841                         continue;
842                 }
843
844                 if (acrtc->dm_irq_params.window_param[i].update_win) {
845                         crtc_ctx->roi[i].rect.x = crc_window.windowa_x_start;
846                         crtc_ctx->roi[i].rect.y = crc_window.windowa_y_start;
847                         crtc_ctx->roi[i].rect.width = crc_window.windowa_x_end -
848                                                 crc_window.windowa_x_start;
849                         crtc_ctx->roi[i].rect.height = crc_window.windowa_y_end -
850                                                 crc_window.windowa_y_start;
851
852                         if (adev->dm.secure_display_ctx.op_mode == LEGACY_MODE)
853                                 /* forward task to dmub to update ROI */
854                                 forward_roi_change = true;
855                         else if (adev->dm.secure_display_ctx.op_mode == DISPLAY_CRC_MODE)
856                                 /* update ROI via dm*/
857                                 dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
858                                         &crc_window, true, true, i, false);
859
860                         reset_crc_frame_count[i] = true;
861
862                         acrtc->dm_irq_params.window_param[i].update_win = false;
863
864                         /* Statically skip 1 frame, because we may need to wait below things
865                          * before sending ROI to dmub:
866                          * 1. We defer the work by using system workqueue.
867                          * 2. We may need to wait for dc_lock before accessing dmub.
868                          */
869                         acrtc->dm_irq_params.window_param[i].skip_frame_cnt = 1;
870                         crtc_ctx->crc_info.crc[i].crc_ready = false;
871                 } else {
872                         if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state, i,
873                                                 &crc_r[i], &crc_g[i], &crc_b[i]))
874                                 DRM_ERROR("Secure Display: fail to get crc from engine %d\n", i);
875
876                         if (adev->dm.secure_display_ctx.op_mode == LEGACY_MODE)
877                                 /* forward task to psp to read ROI/CRC and output via I2C */
878                                 notify_ta = true;
879                         else if (adev->dm.secure_display_ctx.op_mode == DISPLAY_CRC_MODE)
880                                 /* Avoid ROI window get changed, keep overwriting. */
881                                 dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
882                                                 &crc_window, true, true, i, false);
883
884                         /* crc ready for psp to read out */
885                         crtc_ctx->crc_info.crc[i].crc_ready = true;
886                 }
887         }
888
889         spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
890
891         if (forward_roi_change)
892                 schedule_work(&crtc_ctx->forward_roi_work);
893
894         if (notify_ta)
895                 schedule_work(&crtc_ctx->notify_ta_work);
896
897         spin_lock_irqsave(&crtc_ctx->crc_info.lock, flags1);
898         for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
899                 crtc_ctx->crc_info.crc[i].crc_R = crc_r[i];
900                 crtc_ctx->crc_info.crc[i].crc_G = crc_g[i];
901                 crtc_ctx->crc_info.crc[i].crc_B = crc_b[i];
902
903                 if (!crtc_ctx->roi[i].enable) {
904                         crtc_ctx->crc_info.crc[i].frame_count = 0;
905                         continue;
906                 }
907
908                 if (!crtc_ctx->crc_info.crc[i].crc_ready)
909                         all_crc_ready = false;
910
911                 if (reset_crc_frame_count[i] || crtc_ctx->crc_info.crc[i].frame_count == UINT_MAX)
912                         /* Reset the reference frame count after user update the ROI
913                          * or it reaches the maximum value.
914                          */
915                         crtc_ctx->crc_info.crc[i].frame_count = 0;
916                 else
917                         crtc_ctx->crc_info.crc[i].frame_count += 1;
918         }
919         spin_unlock_irqrestore(&crtc_ctx->crc_info.lock, flags1);
920
921         if (all_crc_ready)
922                 complete_all(&crtc_ctx->crc_info.completion);
923 }
924
925 void amdgpu_dm_crtc_secure_display_create_contexts(struct amdgpu_device *adev)
926 {
927         struct secure_display_crtc_context *crtc_ctx = NULL;
928         int i;
929
930         crtc_ctx = kcalloc(adev->mode_info.num_crtc,
931                                       sizeof(struct secure_display_crtc_context),
932                                       GFP_KERNEL);
933
934         if (!crtc_ctx) {
935                 adev->dm.secure_display_ctx.crtc_ctx = NULL;
936                 return;
937         }
938
939         for (i = 0; i < adev->mode_info.num_crtc; i++) {
940                 INIT_WORK(&crtc_ctx[i].forward_roi_work, amdgpu_dm_forward_crc_window);
941                 INIT_WORK(&crtc_ctx[i].notify_ta_work, amdgpu_dm_crtc_notify_ta_to_read);
942                 crtc_ctx[i].crtc = &adev->mode_info.crtcs[i]->base;
943                 spin_lock_init(&crtc_ctx[i].crc_info.lock);
944         }
945
946         adev->dm.secure_display_ctx.crtc_ctx = crtc_ctx;
947
948         adev->dm.secure_display_ctx.op_mode = DISPLAY_CRC_MODE;
949 }
950 #endif
This page took 0.089147 seconds and 4 git commands to generate.