]> Git Repo - J-linux.git/blob - drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
Merge remote-tracking branch 'asoc/for-5.10' into asoc-linus
[J-linux.git] / drivers / gpu / drm / amd / display / dc / dc_dmub_srv.c
1 /*
2  * Copyright 2019 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 "dc.h"
27 #include "dc_dmub_srv.h"
28 #include "../dmub/dmub_srv.h"
29
30 static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
31                                   struct dmub_srv *dmub)
32 {
33         dc_srv->dmub = dmub;
34         dc_srv->ctx = dc->ctx;
35 }
36
37 struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub)
38 {
39         struct dc_dmub_srv *dc_srv =
40                 kzalloc(sizeof(struct dc_dmub_srv), GFP_KERNEL);
41
42         if (dc_srv == NULL) {
43                 BREAK_TO_DEBUGGER();
44                 return NULL;
45         }
46
47         dc_dmub_srv_construct(dc_srv, dc, dmub);
48
49         return dc_srv;
50 }
51
52 void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv)
53 {
54         if (*dmub_srv) {
55                 kfree(*dmub_srv);
56                 *dmub_srv = NULL;
57         }
58 }
59
60 void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv,
61                            union dmub_rb_cmd *cmd)
62 {
63         struct dmub_srv *dmub = dc_dmub_srv->dmub;
64         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
65         enum dmub_status status;
66
67         status = dmub_srv_cmd_queue(dmub, cmd);
68         if (status == DMUB_STATUS_OK)
69                 return;
70
71         if (status != DMUB_STATUS_QUEUE_FULL)
72                 goto error;
73
74         /* Execute and wait for queue to become empty again. */
75         dc_dmub_srv_cmd_execute(dc_dmub_srv);
76         dc_dmub_srv_wait_idle(dc_dmub_srv);
77
78         /* Requeue the command. */
79         status = dmub_srv_cmd_queue(dmub, cmd);
80         if (status == DMUB_STATUS_OK)
81                 return;
82
83 error:
84         DC_ERROR("Error queuing DMUB command: status=%d\n", status);
85 }
86
87 void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv)
88 {
89         struct dmub_srv *dmub = dc_dmub_srv->dmub;
90         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
91         enum dmub_status status;
92
93         status = dmub_srv_cmd_execute(dmub);
94         if (status != DMUB_STATUS_OK)
95                 DC_ERROR("Error starting DMUB execution: status=%d\n", status);
96 }
97
98 void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
99 {
100         struct dmub_srv *dmub = dc_dmub_srv->dmub;
101         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
102         enum dmub_status status;
103
104         status = dmub_srv_wait_for_idle(dmub, 100000);
105         if (status != DMUB_STATUS_OK)
106                 DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
107 }
108
109 void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv)
110 {
111         struct dmub_srv *dmub = dc_dmub_srv->dmub;
112         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
113         enum dmub_status status;
114
115         for (;;) {
116                 /* Wait up to a second for PHY init. */
117                 status = dmub_srv_wait_for_phy_init(dmub, 1000000);
118                 if (status == DMUB_STATUS_OK)
119                         /* Initialization OK */
120                         break;
121
122                 DC_ERROR("DMCUB PHY init failed: status=%d\n", status);
123                 ASSERT(0);
124
125                 if (status != DMUB_STATUS_TIMEOUT)
126                         /*
127                          * Server likely initialized or we don't have
128                          * DMCUB HW support - this won't end.
129                          */
130                         break;
131
132                 /* Continue spinning so we don't hang the ASIC. */
133         }
134 }
135
136 bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
137                                     unsigned int stream_mask)
138 {
139         struct dmub_srv *dmub;
140         const uint32_t timeout = 30;
141
142         if (!dc_dmub_srv || !dc_dmub_srv->dmub)
143                 return false;
144
145         dmub = dc_dmub_srv->dmub;
146
147         return dmub_srv_send_gpint_command(
148                        dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK,
149                        stream_mask, timeout) == DMUB_STATUS_OK;
150 }
This page took 0.037545 seconds and 4 git commands to generate.