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 #ifndef _DMUB_SRV_H_
27 #define _DMUB_SRV_H_
28 
29 /**
30  * DOC: DMUB interface and operation
31  *
32  * DMUB is the interface to the display DMCUB microcontroller on DCN hardware.
33  * It delegates hardware initialization and command submission to the
34  * microcontroller. DMUB is the shortname for DMCUB.
35  *
36  * This interface is not thread-safe. Ensure that all access to the interface
37  * is properly synchronized by the caller.
38  *
39  * Initialization and usage of the DMUB service should be done in the
40  * steps given below:
41  *
42  * 1. dmub_srv_create()
43  * 2. dmub_srv_has_hw_support()
44  * 3. dmub_srv_calc_region_info()
45  * 4. dmub_srv_hw_init()
46  *
47  * The call to dmub_srv_create() is required to use the server.
48  *
49  * The calls to dmub_srv_has_hw_support() and dmub_srv_calc_region_info()
50  * are helpers to query cache window size and allocate framebuffer(s)
51  * for the cache windows.
52  *
53  * The call to dmub_srv_hw_init() programs the DMCUB registers to prepare
54  * for command submission. Commands can be queued via dmub_srv_cmd_queue()
55  * and executed via dmub_srv_cmd_execute().
56  *
57  * If the queue is full the dmub_srv_wait_for_idle() call can be used to
58  * wait until the queue has been cleared.
59  *
60  * Destroying the DMUB service can be done by calling dmub_srv_destroy().
61  * This does not clear DMUB hardware state, only software state.
62  *
63  * The interface is intended to be standalone and should not depend on any
64  * other component within DAL.
65  */
66 
67 #include "inc/dmub_cmd.h"
68 
69 #if defined(__cplusplus)
70 extern "C" {
71 #endif
72 
73 /* Forward declarations */
74 struct dmub_srv;
75 struct dmub_srv_common_regs;
76 
77 /* enum dmub_status - return code for dmcub functions */
78 enum dmub_status {
79 	DMUB_STATUS_OK = 0,
80 	DMUB_STATUS_NO_CTX,
81 	DMUB_STATUS_QUEUE_FULL,
82 	DMUB_STATUS_TIMEOUT,
83 	DMUB_STATUS_INVALID,
84 };
85 
86 /* enum dmub_asic - dmub asic identifier */
87 enum dmub_asic {
88 	DMUB_ASIC_NONE = 0,
89 	DMUB_ASIC_DCN20,
90 	DMUB_ASIC_DCN21,
91 	DMUB_ASIC_DCN30,
92 	DMUB_ASIC_DCN301,
93 	DMUB_ASIC_DCN302,
94 	DMUB_ASIC_MAX,
95 };
96 
97 /* enum dmub_window_id - dmub window identifier */
98 enum dmub_window_id {
99 	DMUB_WINDOW_0_INST_CONST = 0,
100 	DMUB_WINDOW_1_STACK,
101 	DMUB_WINDOW_2_BSS_DATA,
102 	DMUB_WINDOW_3_VBIOS,
103 	DMUB_WINDOW_4_MAILBOX,
104 	DMUB_WINDOW_5_TRACEBUFF,
105 	DMUB_WINDOW_6_FW_STATE,
106 	DMUB_WINDOW_7_SCRATCH_MEM,
107 	DMUB_WINDOW_TOTAL,
108 };
109 
110 /**
111  * struct dmub_region - dmub hw memory region
112  * @base: base address for region, must be 256 byte aligned
113  * @top: top address for region
114  */
115 struct dmub_region {
116 	uint32_t base;
117 	uint32_t top;
118 };
119 
120 /**
121  * struct dmub_window - dmub hw cache window
122  * @off: offset to the fb memory in gpu address space
123  * @r: region in uc address space for cache window
124  */
125 struct dmub_window {
126 	union dmub_addr offset;
127 	struct dmub_region region;
128 };
129 
130 /**
131  * struct dmub_fb - defines a dmub framebuffer memory region
132  * @cpu_addr: cpu virtual address for the region, NULL if invalid
133  * @gpu_addr: gpu virtual address for the region, NULL if invalid
134  * @size: size of the region in bytes, zero if invalid
135  */
136 struct dmub_fb {
137 	void *cpu_addr;
138 	uint64_t gpu_addr;
139 	uint32_t size;
140 };
141 
142 /**
143  * struct dmub_srv_region_params - params used for calculating dmub regions
144  * @inst_const_size: size of the fw inst const section
145  * @bss_data_size: size of the fw bss data section
146  * @vbios_size: size of the vbios data
147  * @fw_bss_data: raw firmware bss data section
148  */
149 struct dmub_srv_region_params {
150 	uint32_t inst_const_size;
151 	uint32_t bss_data_size;
152 	uint32_t vbios_size;
153 	const uint8_t *fw_inst_const;
154 	const uint8_t *fw_bss_data;
155 };
156 
157 /**
158  * struct dmub_srv_region_info - output region info from the dmub service
159  * @fb_size: required minimum fb size for all regions, aligned to 4096 bytes
160  * @num_regions: number of regions used by the dmub service
161  * @regions: region info
162  *
163  * The regions are aligned such that they can be all placed within the
164  * same framebuffer but they can also be placed into different framebuffers.
165  *
166  * The size of each region can be calculated by the caller:
167  * size = reg.top - reg.base
168  *
169  * Care must be taken when performing custom allocations to ensure that each
170  * region base address is 256 byte aligned.
171  */
172 struct dmub_srv_region_info {
173 	uint32_t fb_size;
174 	uint8_t num_regions;
175 	struct dmub_region regions[DMUB_WINDOW_TOTAL];
176 };
177 
178 /**
179  * struct dmub_srv_fb_params - parameters used for driver fb setup
180  * @region_info: region info calculated by dmub service
181  * @cpu_addr: base cpu address for the framebuffer
182  * @gpu_addr: base gpu virtual address for the framebuffer
183  */
184 struct dmub_srv_fb_params {
185 	const struct dmub_srv_region_info *region_info;
186 	void *cpu_addr;
187 	uint64_t gpu_addr;
188 };
189 
190 /**
191  * struct dmub_srv_fb_info - output fb info from the dmub service
192  * @num_fbs: number of required dmub framebuffers
193  * @fbs: fb data for each region
194  *
195  * Output from the dmub service helper that can be used by the
196  * driver to prepare dmub_fb that can be passed into the dmub
197  * hw init service.
198  *
199  * Assumes that all regions are within the same framebuffer
200  * and have been setup according to the region_info generated
201  * by the dmub service.
202  */
203 struct dmub_srv_fb_info {
204 	uint8_t num_fb;
205 	struct dmub_fb fb[DMUB_WINDOW_TOTAL];
206 };
207 
208 /**
209  * struct dmub_srv_base_funcs - Driver specific base callbacks
210  */
211 struct dmub_srv_base_funcs {
212 	/**
213 	 * @reg_read:
214 	 *
215 	 * Hook for reading a register.
216 	 *
217 	 * Return: The 32-bit register value from the given address.
218 	 */
219 	uint32_t (*reg_read)(void *ctx, uint32_t address);
220 
221 	/**
222 	 * @reg_write:
223 	 *
224 	 * Hook for writing a value to the register specified by address.
225 	 */
226 	void (*reg_write)(void *ctx, uint32_t address, uint32_t value);
227 };
228 
229 /**
230  * struct dmub_srv_hw_funcs - hardware sequencer funcs for dmub
231  */
232 struct dmub_srv_hw_funcs {
233 	/* private: internal use only */
234 
235 	void (*init)(struct dmub_srv *dmub);
236 
237 	void (*reset)(struct dmub_srv *dmub);
238 
239 	void (*reset_release)(struct dmub_srv *dmub);
240 
241 	void (*backdoor_load)(struct dmub_srv *dmub,
242 			      const struct dmub_window *cw0,
243 			      const struct dmub_window *cw1);
244 
245 	void (*setup_windows)(struct dmub_srv *dmub,
246 			      const struct dmub_window *cw2,
247 			      const struct dmub_window *cw3,
248 			      const struct dmub_window *cw4,
249 			      const struct dmub_window *cw5,
250 			      const struct dmub_window *cw6);
251 
252 	void (*setup_mailbox)(struct dmub_srv *dmub,
253 			      const struct dmub_region *inbox1);
254 
255 	uint32_t (*get_inbox1_rptr)(struct dmub_srv *dmub);
256 
257 	void (*set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
258 
259 	uint32_t (*emul_get_inbox1_rptr)(struct dmub_srv *dmub);
260 
261 	void (*emul_set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
262 
263 	bool (*is_supported)(struct dmub_srv *dmub);
264 
265 	bool (*is_hw_init)(struct dmub_srv *dmub);
266 
267 	bool (*is_phy_init)(struct dmub_srv *dmub);
268 	void (*enable_dmub_boot_options)(struct dmub_srv *dmub);
269 
270 	void (*skip_dmub_panel_power_sequence)(struct dmub_srv *dmub, bool skip);
271 
272 	union dmub_fw_boot_status (*get_fw_status)(struct dmub_srv *dmub);
273 
274 
275 	void (*set_gpint)(struct dmub_srv *dmub,
276 			  union dmub_gpint_data_register reg);
277 
278 	bool (*is_gpint_acked)(struct dmub_srv *dmub,
279 			       union dmub_gpint_data_register reg);
280 
281 	uint32_t (*get_gpint_response)(struct dmub_srv *dmub);
282 };
283 
284 /**
285  * struct dmub_srv_create_params - params for dmub service creation
286  * @base_funcs: driver supplied base routines
287  * @hw_funcs: optional overrides for hw funcs
288  * @user_ctx: context data for callback funcs
289  * @asic: driver supplied asic
290  * @fw_version: the current firmware version, if any
291  * @is_virtual: false for hw support only
292  */
293 struct dmub_srv_create_params {
294 	struct dmub_srv_base_funcs funcs;
295 	struct dmub_srv_hw_funcs *hw_funcs;
296 	void *user_ctx;
297 	enum dmub_asic asic;
298 	uint32_t fw_version;
299 	bool is_virtual;
300 };
301 
302 /*
303  * struct dmub_srv_hw_params - params for dmub hardware initialization
304  * @fb: framebuffer info for each region
305  * @fb_base: base of the framebuffer aperture
306  * @fb_offset: offset of the framebuffer aperture
307  * @psp_version: psp version to pass for DMCU init
308  * @load_inst_const: true if DMUB should load inst const fw
309  */
310 struct dmub_srv_hw_params {
311 	struct dmub_fb *fb[DMUB_WINDOW_TOTAL];
312 	uint64_t fb_base;
313 	uint64_t fb_offset;
314 	uint32_t psp_version;
315 	bool load_inst_const;
316 	bool skip_panel_power_sequence;
317 };
318 
319 /**
320  * struct dmub_srv - software state for dmcub
321  * @asic: dmub asic identifier
322  * @user_ctx: user provided context for the dmub_srv
323  * @fw_version: the current firmware version, if any
324  * @is_virtual: false if hardware support only
325  * @fw_state: dmub firmware state pointer
326  */
327 struct dmub_srv {
328 	enum dmub_asic asic;
329 	void *user_ctx;
330 	uint32_t fw_version;
331 	bool is_virtual;
332 	struct dmub_fb scratch_mem_fb;
333 	volatile const struct dmub_fw_state *fw_state;
334 
335 	/* private: internal use only */
336 	const struct dmub_srv_common_regs *regs;
337 
338 	struct dmub_srv_base_funcs funcs;
339 	struct dmub_srv_hw_funcs hw_funcs;
340 	struct dmub_rb inbox1_rb;
341 
342 	bool sw_init;
343 	bool hw_init;
344 
345 	uint64_t fb_base;
346 	uint64_t fb_offset;
347 	uint32_t psp_version;
348 
349 	/* Feature capabilities reported by fw */
350 	struct dmub_feature_caps feature_caps;
351 };
352 
353 /**
354  * DMUB firmware version helper macro - useful for checking if the version
355  * of a firmware to know if feature or functionality is supported or present.
356  */
357 #define DMUB_FW_VERSION(major, minor, revision) \
358 	((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | ((revision) & 0xFFFF))
359 
360 /**
361  * dmub_srv_create() - creates the DMUB service.
362  * @dmub: the dmub service
363  * @params: creation parameters for the service
364  *
365  * Return:
366  *   DMUB_STATUS_OK - success
367  *   DMUB_STATUS_INVALID - unspecified error
368  */
369 enum dmub_status dmub_srv_create(struct dmub_srv *dmub,
370 				 const struct dmub_srv_create_params *params);
371 
372 /**
373  * dmub_srv_destroy() - destroys the DMUB service.
374  * @dmub: the dmub service
375  */
376 void dmub_srv_destroy(struct dmub_srv *dmub);
377 
378 /**
379  * dmub_srv_calc_region_info() - retreives region info from the dmub service
380  * @dmub: the dmub service
381  * @params: parameters used to calculate region locations
382  * @info_out: the output region info from dmub
383  *
384  * Calculates the base and top address for all relevant dmub regions
385  * using the parameters given (if any).
386  *
387  * Return:
388  *   DMUB_STATUS_OK - success
389  *   DMUB_STATUS_INVALID - unspecified error
390  */
391 enum dmub_status
392 dmub_srv_calc_region_info(struct dmub_srv *dmub,
393 			  const struct dmub_srv_region_params *params,
394 			  struct dmub_srv_region_info *out);
395 
396 /**
397  * dmub_srv_calc_region_info() - retreives fb info from the dmub service
398  * @dmub: the dmub service
399  * @params: parameters used to calculate fb locations
400  * @info_out: the output fb info from dmub
401  *
402  * Calculates the base and top address for all relevant dmub regions
403  * using the parameters given (if any).
404  *
405  * Return:
406  *   DMUB_STATUS_OK - success
407  *   DMUB_STATUS_INVALID - unspecified error
408  */
409 enum dmub_status dmub_srv_calc_fb_info(struct dmub_srv *dmub,
410 				       const struct dmub_srv_fb_params *params,
411 				       struct dmub_srv_fb_info *out);
412 
413 /**
414  * dmub_srv_has_hw_support() - returns hw support state for dmcub
415  * @dmub: the dmub service
416  * @is_supported: hw support state
417  *
418  * Queries the hardware for DMCUB support and returns the result.
419  *
420  * Can be called before dmub_srv_hw_init().
421  *
422  * Return:
423  *   DMUB_STATUS_OK - success
424  *   DMUB_STATUS_INVALID - unspecified error
425  */
426 enum dmub_status dmub_srv_has_hw_support(struct dmub_srv *dmub,
427 					 bool *is_supported);
428 
429 /**
430  * dmub_srv_is_hw_init() - returns hardware init state
431  *
432  * Return:
433  *   DMUB_STATUS_OK - success
434  *   DMUB_STATUS_INVALID - unspecified error
435  */
436 enum dmub_status dmub_srv_is_hw_init(struct dmub_srv *dmub, bool *is_hw_init);
437 
438 /**
439  * dmub_srv_hw_init() - initializes the underlying DMUB hardware
440  * @dmub: the dmub service
441  * @params: params for hardware initialization
442  *
443  * Resets the DMUB hardware and performs backdoor loading of the
444  * required cache regions based on the input framebuffer regions.
445  *
446  * Return:
447  *   DMUB_STATUS_OK - success
448  *   DMUB_STATUS_NO_CTX - dmcub context not initialized
449  *   DMUB_STATUS_INVALID - unspecified error
450  */
451 enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
452 				  const struct dmub_srv_hw_params *params);
453 
454 /**
455  * dmub_srv_hw_reset() - puts the DMUB hardware in reset state if initialized
456  * @dmub: the dmub service
457  *
458  * Before destroying the DMUB service or releasing the backing framebuffer
459  * memory we'll need to put the DMCUB into reset first.
460  *
461  * A subsequent call to dmub_srv_hw_init() will re-enable the DMCUB.
462  *
463  * Return:
464  *   DMUB_STATUS_OK - success
465  *   DMUB_STATUS_INVALID - unspecified error
466  */
467 enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub);
468 
469 /**
470  * dmub_srv_cmd_queue() - queues a command to the DMUB
471  * @dmub: the dmub service
472  * @cmd: the command to queue
473  *
474  * Queues a command to the DMUB service but does not begin execution
475  * immediately.
476  *
477  * Return:
478  *   DMUB_STATUS_OK - success
479  *   DMUB_STATUS_QUEUE_FULL - no remaining room in queue
480  *   DMUB_STATUS_INVALID - unspecified error
481  */
482 enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub,
483 				    const union dmub_rb_cmd *cmd);
484 
485 /**
486  * dmub_srv_cmd_execute() - Executes a queued sequence to the dmub
487  * @dmub: the dmub service
488  *
489  * Begins execution of queued commands on the dmub.
490  *
491  * Return:
492  *   DMUB_STATUS_OK - success
493  *   DMUB_STATUS_INVALID - unspecified error
494  */
495 enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub);
496 
497 /**
498  * dmub_srv_wait_for_auto_load() - Waits for firmware auto load to complete
499  * @dmub: the dmub service
500  * @timeout_us: the maximum number of microseconds to wait
501  *
502  * Waits until firmware has been autoloaded by the DMCUB. The maximum
503  * wait time is given in microseconds to prevent spinning forever.
504  *
505  * On ASICs without firmware autoload support this function will return
506  * immediately.
507  *
508  * Return:
509  *   DMUB_STATUS_OK - success
510  *   DMUB_STATUS_TIMEOUT - wait for phy init timed out
511  *   DMUB_STATUS_INVALID - unspecified error
512  */
513 enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
514 					     uint32_t timeout_us);
515 
516 /**
517  * dmub_srv_wait_for_phy_init() - Waits for DMUB PHY init to complete
518  * @dmub: the dmub service
519  * @timeout_us: the maximum number of microseconds to wait
520  *
521  * Waits until the PHY has been initialized by the DMUB. The maximum
522  * wait time is given in microseconds to prevent spinning forever.
523  *
524  * On ASICs without PHY init support this function will return
525  * immediately.
526  *
527  * Return:
528  *   DMUB_STATUS_OK - success
529  *   DMUB_STATUS_TIMEOUT - wait for phy init timed out
530  *   DMUB_STATUS_INVALID - unspecified error
531  */
532 enum dmub_status dmub_srv_wait_for_phy_init(struct dmub_srv *dmub,
533 					    uint32_t timeout_us);
534 
535 /**
536  * dmub_srv_wait_for_idle() - Waits for the DMUB to be idle
537  * @dmub: the dmub service
538  * @timeout_us: the maximum number of microseconds to wait
539  *
540  * Waits until the DMUB buffer is empty and all commands have
541  * finished processing. The maximum wait time is given in
542  * microseconds to prevent spinning forever.
543  *
544  * Return:
545  *   DMUB_STATUS_OK - success
546  *   DMUB_STATUS_TIMEOUT - wait for buffer to flush timed out
547  *   DMUB_STATUS_INVALID - unspecified error
548  */
549 enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub,
550 					uint32_t timeout_us);
551 
552 /**
553  * dmub_srv_send_gpint_command() - Sends a GPINT based command.
554  * @dmub: the dmub service
555  * @command_code: the command code to send
556  * @param: the command parameter to send
557  * @timeout_us: the maximum number of microseconds to wait
558  *
559  * Sends a command via the general purpose interrupt (GPINT).
560  * Waits for the number of microseconds specified by timeout_us
561  * for the command ACK before returning.
562  *
563  * Can be called after software initialization.
564  *
565  * Return:
566  *   DMUB_STATUS_OK - success
567  *   DMUB_STATUS_TIMEOUT - wait for ACK timed out
568  *   DMUB_STATUS_INVALID - unspecified error
569  */
570 enum dmub_status
571 dmub_srv_send_gpint_command(struct dmub_srv *dmub,
572 			    enum dmub_gpint_command command_code,
573 			    uint16_t param, uint32_t timeout_us);
574 
575 /**
576  * dmub_srv_get_gpint_response() - Queries the GPINT response.
577  * @dmub: the dmub service
578  * @response: the response for the last GPINT
579  *
580  * Returns the response code for the last GPINT interrupt.
581  *
582  * Can be called after software initialization.
583  *
584  * Return:
585  *   DMUB_STATUS_OK - success
586  *   DMUB_STATUS_INVALID - unspecified error
587  */
588 enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,
589 					     uint32_t *response);
590 
591 /**
592  * dmub_flush_buffer_mem() - Read back entire frame buffer region.
593  * This ensures that the write from x86 has been flushed and will not
594  * hang the DMCUB.
595  * @fb: frame buffer to flush
596  *
597  * Can be called after software initialization.
598  */
599 void dmub_flush_buffer_mem(const struct dmub_fb *fb);
600 
601 /**
602  * dmub_srv_get_fw_boot_status() - Returns the DMUB boot status bits.
603  *
604  * @dmub: the dmub service
605  * @status: out pointer for firmware status
606  *
607  * Return:
608  *   DMUB_STATUS_OK - success
609  *   DMUB_STATUS_INVALID - unspecified error, unsupported
610  */
611 enum dmub_status dmub_srv_get_fw_boot_status(struct dmub_srv *dmub,
612 					     union dmub_fw_boot_status *status);
613 
614 enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub,
615 					      union dmub_rb_cmd *cmd);
616 
617 #if defined(__cplusplus)
618 }
619 #endif
620 
621 #endif /* _DMUB_SRV_H_ */
622