1 /* $NetBSD: amdgpu_dc_dmub_srv.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $ */ 2 3 /* 4 * Copyright 2019 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dc_dmub_srv.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $"); 30 31 #include "dc.h" 32 #include "dc_dmub_srv.h" 33 #include "../dmub/inc/dmub_srv.h" 34 35 static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc, 36 struct dmub_srv *dmub) 37 { 38 dc_srv->dmub = dmub; 39 dc_srv->ctx = dc->ctx; 40 } 41 42 struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub) 43 { 44 struct dc_dmub_srv *dc_srv = 45 kzalloc(sizeof(struct dc_dmub_srv), GFP_KERNEL); 46 47 if (dc_srv == NULL) { 48 BREAK_TO_DEBUGGER(); 49 return NULL; 50 } 51 52 dc_dmub_srv_construct(dc_srv, dc, dmub); 53 54 return dc_srv; 55 } 56 57 void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv) 58 { 59 if (*dmub_srv) { 60 kfree(*dmub_srv); 61 *dmub_srv = NULL; 62 } 63 } 64 65 void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv, 66 struct dmub_cmd_header *cmd) 67 { 68 struct dmub_srv *dmub = dc_dmub_srv->dmub; 69 struct dc_context *dc_ctx = dc_dmub_srv->ctx; 70 enum dmub_status status; 71 72 status = dmub_srv_cmd_queue(dmub, cmd); 73 if (status == DMUB_STATUS_OK) 74 return; 75 76 if (status != DMUB_STATUS_QUEUE_FULL) 77 goto error; 78 79 /* Execute and wait for queue to become empty again. */ 80 dc_dmub_srv_cmd_execute(dc_dmub_srv); 81 dc_dmub_srv_wait_idle(dc_dmub_srv); 82 83 /* Requeue the command. */ 84 status = dmub_srv_cmd_queue(dmub, cmd); 85 if (status == DMUB_STATUS_OK) 86 return; 87 88 error: 89 DC_ERROR("Error queuing DMUB command: status=%d\n", status); 90 } 91 92 void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) 93 { 94 struct dmub_srv *dmub = dc_dmub_srv->dmub; 95 struct dc_context *dc_ctx = dc_dmub_srv->ctx; 96 enum dmub_status status; 97 98 status = dmub_srv_cmd_execute(dmub); 99 if (status != DMUB_STATUS_OK) 100 DC_ERROR("Error starting DMUB execution: status=%d\n", status); 101 } 102 103 void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) 104 { 105 struct dmub_srv *dmub = dc_dmub_srv->dmub; 106 struct dc_context *dc_ctx = dc_dmub_srv->ctx; 107 enum dmub_status status; 108 109 status = dmub_srv_wait_for_idle(dmub, 100000); 110 if (status != DMUB_STATUS_OK) 111 DC_ERROR("Error waiting for DMUB idle: status=%d\n", status); 112 } 113 114 void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv) 115 { 116 struct dmub_srv *dmub = dc_dmub_srv->dmub; 117 struct dc_context *dc_ctx = dc_dmub_srv->ctx; 118 enum dmub_status status; 119 120 for (;;) { 121 /* Wait up to a second for PHY init. */ 122 status = dmub_srv_wait_for_phy_init(dmub, 1000000); 123 if (status == DMUB_STATUS_OK) 124 /* Initialization OK */ 125 break; 126 127 DC_ERROR("DMCUB PHY init failed: status=%d\n", status); 128 ASSERT(0); 129 130 if (status != DMUB_STATUS_TIMEOUT) 131 /* 132 * Server likely initialized or we don't have 133 * DMCUB HW support - this won't end. 134 */ 135 break; 136 137 /* Continue spinning so we don't hang the ASIC. */ 138 } 139 } 140