13a1627b0SNicholas Kazlauskas /*
23a1627b0SNicholas Kazlauskas  * Copyright 2019 Advanced Micro Devices, Inc.
33a1627b0SNicholas Kazlauskas  *
43a1627b0SNicholas Kazlauskas  * Permission is hereby granted, free of charge, to any person obtaining a
53a1627b0SNicholas Kazlauskas  * copy of this software and associated documentation files (the "Software"),
63a1627b0SNicholas Kazlauskas  * to deal in the Software without restriction, including without limitation
73a1627b0SNicholas Kazlauskas  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83a1627b0SNicholas Kazlauskas  * and/or sell copies of the Software, and to permit persons to whom the
93a1627b0SNicholas Kazlauskas  * Software is furnished to do so, subject to the following conditions:
103a1627b0SNicholas Kazlauskas  *
113a1627b0SNicholas Kazlauskas  * The above copyright notice and this permission notice shall be included in
123a1627b0SNicholas Kazlauskas  * all copies or substantial portions of the Software.
133a1627b0SNicholas Kazlauskas  *
143a1627b0SNicholas Kazlauskas  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
153a1627b0SNicholas Kazlauskas  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
163a1627b0SNicholas Kazlauskas  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
173a1627b0SNicholas Kazlauskas  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
183a1627b0SNicholas Kazlauskas  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
193a1627b0SNicholas Kazlauskas  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
203a1627b0SNicholas Kazlauskas  * OTHER DEALINGS IN THE SOFTWARE.
213a1627b0SNicholas Kazlauskas  *
223a1627b0SNicholas Kazlauskas  * Authors: AMD
233a1627b0SNicholas Kazlauskas  *
243a1627b0SNicholas Kazlauskas  */
253a1627b0SNicholas Kazlauskas 
263a1627b0SNicholas Kazlauskas #include "dc.h"
273a1627b0SNicholas Kazlauskas #include "dc_dmub_srv.h"
283a1627b0SNicholas Kazlauskas #include "../dmub/inc/dmub_srv.h"
293a1627b0SNicholas Kazlauskas 
303a1627b0SNicholas Kazlauskas static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
313a1627b0SNicholas Kazlauskas 				  struct dmub_srv *dmub)
323a1627b0SNicholas Kazlauskas {
333a1627b0SNicholas Kazlauskas 	dc_srv->dmub = dmub;
343a1627b0SNicholas Kazlauskas 	dc_srv->ctx = dc->ctx;
353a1627b0SNicholas Kazlauskas }
363a1627b0SNicholas Kazlauskas 
373a1627b0SNicholas Kazlauskas struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub)
383a1627b0SNicholas Kazlauskas {
393a1627b0SNicholas Kazlauskas 	struct dc_dmub_srv *dc_srv =
403a1627b0SNicholas Kazlauskas 		kzalloc(sizeof(struct dc_dmub_srv), GFP_KERNEL);
413a1627b0SNicholas Kazlauskas 
423a1627b0SNicholas Kazlauskas 	if (dc_srv == NULL) {
433a1627b0SNicholas Kazlauskas 		BREAK_TO_DEBUGGER();
443a1627b0SNicholas Kazlauskas 		return NULL;
453a1627b0SNicholas Kazlauskas 	}
463a1627b0SNicholas Kazlauskas 
473a1627b0SNicholas Kazlauskas 	dc_dmub_srv_construct(dc_srv, dc, dmub);
483a1627b0SNicholas Kazlauskas 
493a1627b0SNicholas Kazlauskas 	return dc_srv;
503a1627b0SNicholas Kazlauskas }
513a1627b0SNicholas Kazlauskas 
523a1627b0SNicholas Kazlauskas void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv)
533a1627b0SNicholas Kazlauskas {
543a1627b0SNicholas Kazlauskas 	if (*dmub_srv) {
553a1627b0SNicholas Kazlauskas 		kfree(*dmub_srv);
563a1627b0SNicholas Kazlauskas 		*dmub_srv = NULL;
573a1627b0SNicholas Kazlauskas 	}
583a1627b0SNicholas Kazlauskas }
593a1627b0SNicholas Kazlauskas 
603a1627b0SNicholas Kazlauskas void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv,
613a1627b0SNicholas Kazlauskas 			   struct dmub_cmd_header *cmd)
623a1627b0SNicholas Kazlauskas {
633a1627b0SNicholas Kazlauskas 	struct dmub_srv *dmub = dc_dmub_srv->dmub;
643a1627b0SNicholas Kazlauskas 	struct dc_context *dc_ctx = dc_dmub_srv->ctx;
653a1627b0SNicholas Kazlauskas 	enum dmub_status status;
663a1627b0SNicholas Kazlauskas 
673a1627b0SNicholas Kazlauskas 	status = dmub_srv_cmd_queue(dmub, cmd);
683a1627b0SNicholas Kazlauskas 	if (status == DMUB_STATUS_OK)
693a1627b0SNicholas Kazlauskas 		return;
703a1627b0SNicholas Kazlauskas 
713a1627b0SNicholas Kazlauskas 	if (status != DMUB_STATUS_QUEUE_FULL)
723a1627b0SNicholas Kazlauskas 		goto error;
733a1627b0SNicholas Kazlauskas 
743a1627b0SNicholas Kazlauskas 	/* Execute and wait for queue to become empty again. */
753a1627b0SNicholas Kazlauskas 	dc_dmub_srv_cmd_execute(dc_dmub_srv);
763a1627b0SNicholas Kazlauskas 	dc_dmub_srv_wait_idle(dc_dmub_srv);
773a1627b0SNicholas Kazlauskas 
783a1627b0SNicholas Kazlauskas 	/* Requeue the command. */
793a1627b0SNicholas Kazlauskas 	status = dmub_srv_cmd_queue(dmub, cmd);
803a1627b0SNicholas Kazlauskas 	if (status == DMUB_STATUS_OK)
813a1627b0SNicholas Kazlauskas 		return;
823a1627b0SNicholas Kazlauskas 
833a1627b0SNicholas Kazlauskas error:
843a1627b0SNicholas Kazlauskas 	DC_ERROR("Error queuing DMUB command: status=%d\n", status);
853a1627b0SNicholas Kazlauskas }
863a1627b0SNicholas Kazlauskas 
873a1627b0SNicholas Kazlauskas void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv)
883a1627b0SNicholas Kazlauskas {
893a1627b0SNicholas Kazlauskas 	struct dmub_srv *dmub = dc_dmub_srv->dmub;
903a1627b0SNicholas Kazlauskas 	struct dc_context *dc_ctx = dc_dmub_srv->ctx;
913a1627b0SNicholas Kazlauskas 	enum dmub_status status;
923a1627b0SNicholas Kazlauskas 
933a1627b0SNicholas Kazlauskas 	status = dmub_srv_cmd_execute(dmub);
943a1627b0SNicholas Kazlauskas 	if (status != DMUB_STATUS_OK)
95243a8f41SColin Ian King 		DC_ERROR("Error starting DMUB execution: status=%d\n", status);
963a1627b0SNicholas Kazlauskas }
973a1627b0SNicholas Kazlauskas 
983a1627b0SNicholas Kazlauskas void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
993a1627b0SNicholas Kazlauskas {
1003a1627b0SNicholas Kazlauskas 	struct dmub_srv *dmub = dc_dmub_srv->dmub;
1013a1627b0SNicholas Kazlauskas 	struct dc_context *dc_ctx = dc_dmub_srv->ctx;
1023a1627b0SNicholas Kazlauskas 	enum dmub_status status;
1033a1627b0SNicholas Kazlauskas 
1043a1627b0SNicholas Kazlauskas 	status = dmub_srv_wait_for_idle(dmub, 100000);
1053a1627b0SNicholas Kazlauskas 	if (status != DMUB_STATUS_OK)
1063a1627b0SNicholas Kazlauskas 		DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
1073a1627b0SNicholas Kazlauskas }
1083a1627b0SNicholas Kazlauskas 
1093a1627b0SNicholas Kazlauskas void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv)
1103a1627b0SNicholas Kazlauskas {
1113a1627b0SNicholas Kazlauskas 	struct dmub_srv *dmub = dc_dmub_srv->dmub;
1123a1627b0SNicholas Kazlauskas 	struct dc_context *dc_ctx = dc_dmub_srv->ctx;
1133a1627b0SNicholas Kazlauskas 	enum dmub_status status;
1143a1627b0SNicholas Kazlauskas 
11556fc13feSNicholas Kazlauskas 	status = dmub_srv_wait_for_phy_init(dmub, 10000000);
11656fc13feSNicholas Kazlauskas 	if (status != DMUB_STATUS_OK) {
1173a1627b0SNicholas Kazlauskas 		DC_ERROR("Error waiting for DMUB phy init: status=%d\n",
1183a1627b0SNicholas Kazlauskas 			 status);
11956fc13feSNicholas Kazlauskas 		ASSERT(0);
12056fc13feSNicholas Kazlauskas 	}
1213a1627b0SNicholas Kazlauskas }
122