xref: /openbsd-src/sys/dev/pci/drm/apple/dcp-internal.h (revision 48fd60f3bd8da3cf27db0a8496339846134c8aa1)
15dd0baa8Skettenis // SPDX-License-Identifier: GPL-2.0-only OR MIT
25dd0baa8Skettenis /* Copyright 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io> */
35dd0baa8Skettenis 
45dd0baa8Skettenis #ifndef __APPLE_DCP_INTERNAL_H__
55dd0baa8Skettenis #define __APPLE_DCP_INTERNAL_H__
65dd0baa8Skettenis 
75dd0baa8Skettenis #include <linux/backlight.h>
85dd0baa8Skettenis #include <linux/device.h>
95dd0baa8Skettenis #include <linux/ioport.h>
105dd0baa8Skettenis #include <linux/mutex.h>
115dd0baa8Skettenis #include <linux/mux/consumer.h>
125dd0baa8Skettenis #include <linux/phy/phy.h>
135dd0baa8Skettenis #include <linux/platform_device.h>
145dd0baa8Skettenis #include <linux/scatterlist.h>
155dd0baa8Skettenis 
165dd0baa8Skettenis #include "dptxep.h"
175dd0baa8Skettenis #include "iomfb.h"
185dd0baa8Skettenis #include "iomfb_v12_3.h"
195dd0baa8Skettenis #include "iomfb_v13_3.h"
205dd0baa8Skettenis 
215dd0baa8Skettenis #define DCP_MAX_PLANES 2
225dd0baa8Skettenis 
235dd0baa8Skettenis struct apple_dcp;
245dd0baa8Skettenis struct apple_dcp_afkep;
255dd0baa8Skettenis 
265dd0baa8Skettenis enum dcp_firmware_version {
275dd0baa8Skettenis 	DCP_FIRMWARE_UNKNOWN,
285dd0baa8Skettenis 	DCP_FIRMWARE_V_12_3,
295dd0baa8Skettenis 	DCP_FIRMWARE_V_13_5,
305dd0baa8Skettenis };
315dd0baa8Skettenis 
325dd0baa8Skettenis enum {
335dd0baa8Skettenis 	SYSTEM_ENDPOINT = 0x20,
345dd0baa8Skettenis 	TEST_ENDPOINT = 0x21,
355dd0baa8Skettenis 	DCP_EXPERT_ENDPOINT = 0x22,
365dd0baa8Skettenis 	DISP0_ENDPOINT = 0x23,
375dd0baa8Skettenis 	DPTX_ENDPOINT = 0x2a,
385dd0baa8Skettenis 	HDCP_ENDPOINT = 0x2b,
395dd0baa8Skettenis 	REMOTE_ALLOC_ENDPOINT = 0x2d,
405dd0baa8Skettenis 	IOMFB_ENDPOINT = 0x37,
415dd0baa8Skettenis };
425dd0baa8Skettenis 
435dd0baa8Skettenis /* Temporary backing for a chunked transfer via setDCPAVPropStart/Chunk/End */
445dd0baa8Skettenis struct dcp_chunks {
455dd0baa8Skettenis 	size_t length;
465dd0baa8Skettenis 	void *data;
475dd0baa8Skettenis };
485dd0baa8Skettenis 
495dd0baa8Skettenis #define DCP_MAX_MAPPINGS (128) /* should be enough */
505dd0baa8Skettenis #define MAX_DISP_REGISTERS (7)
515dd0baa8Skettenis 
525dd0baa8Skettenis struct dcp_mem_descriptor {
535dd0baa8Skettenis 	size_t size;
545dd0baa8Skettenis 	void *buf;
555dd0baa8Skettenis 	dma_addr_t dva;
565dd0baa8Skettenis 	struct sg_table map;
575dd0baa8Skettenis 	u64 reg;
585dd0baa8Skettenis };
595dd0baa8Skettenis 
605dd0baa8Skettenis /* Limit on call stack depth (arbitrary). Some nesting is required */
615dd0baa8Skettenis #define DCP_MAX_CALL_DEPTH 8
625dd0baa8Skettenis 
635dd0baa8Skettenis typedef void (*dcp_callback_t)(struct apple_dcp *, void *, void *);
645dd0baa8Skettenis 
655dd0baa8Skettenis struct dcp_channel {
665dd0baa8Skettenis 	dcp_callback_t callbacks[DCP_MAX_CALL_DEPTH];
675dd0baa8Skettenis 	void *cookies[DCP_MAX_CALL_DEPTH];
685dd0baa8Skettenis 	void *output[DCP_MAX_CALL_DEPTH];
695dd0baa8Skettenis 	u16 end[DCP_MAX_CALL_DEPTH];
705dd0baa8Skettenis 
715dd0baa8Skettenis 	/* Current depth of the call stack. Less than DCP_MAX_CALL_DEPTH */
725dd0baa8Skettenis 	u8 depth;
735dd0baa8Skettenis };
745dd0baa8Skettenis 
755dd0baa8Skettenis struct dcp_fb_reference {
765dd0baa8Skettenis 	struct list_head head;
775dd0baa8Skettenis 	struct drm_framebuffer *fb;
785dd0baa8Skettenis 	u32 swap_id;
795dd0baa8Skettenis };
805dd0baa8Skettenis 
815dd0baa8Skettenis #define MAX_NOTCH_HEIGHT 160
825dd0baa8Skettenis 
835dd0baa8Skettenis struct dcp_brightness {
845dd0baa8Skettenis 	struct backlight_device *bl_dev;
855dd0baa8Skettenis 	u32 maximum;
865dd0baa8Skettenis 	u32 dac;
875dd0baa8Skettenis 	int nits;
885dd0baa8Skettenis 	int scale;
895dd0baa8Skettenis 	bool update;
905dd0baa8Skettenis };
915dd0baa8Skettenis 
925dd0baa8Skettenis /** laptop/AiO integrated panel parameters from DT */
935dd0baa8Skettenis struct dcp_panel {
945dd0baa8Skettenis 	/// panel width in millimeter
955dd0baa8Skettenis 	int width_mm;
965dd0baa8Skettenis 	/// panel height in millimeter
975dd0baa8Skettenis 	int height_mm;
98172aa44cSkettenis 	/// panel has a mini-LED backlight
995dd0baa8Skettenis 	bool has_mini_led;
1005dd0baa8Skettenis };
1015dd0baa8Skettenis 
1025dd0baa8Skettenis struct apple_dcp_hw_data {
1035dd0baa8Skettenis 	u32 num_dptx_ports;
1045dd0baa8Skettenis };
1055dd0baa8Skettenis 
1065dd0baa8Skettenis /* TODO: move IOMFB members to its own struct */
1075dd0baa8Skettenis struct apple_dcp {
1085dd0baa8Skettenis 	struct device *dev;
1095dd0baa8Skettenis 	struct platform_device *piodma;
1105dd0baa8Skettenis 	struct iommu_domain *iommu_dom;
1115dd0baa8Skettenis 	struct apple_rtkit *rtk;
1125dd0baa8Skettenis 	struct apple_crtc *crtc;
1135dd0baa8Skettenis 	struct apple_connector *connector;
1145dd0baa8Skettenis 
1155dd0baa8Skettenis 	struct apple_dcp_hw_data hw;
1165dd0baa8Skettenis 
1175dd0baa8Skettenis 	/* firmware version and compatible firmware version */
1185dd0baa8Skettenis 	enum dcp_firmware_version fw_compat;
1195dd0baa8Skettenis 
1205dd0baa8Skettenis 	/* Coprocessor control register */
1215dd0baa8Skettenis 	void __iomem *coproc_reg;
1225dd0baa8Skettenis 
1235dd0baa8Skettenis 	/* DCP has crashed */
1245dd0baa8Skettenis 	bool crashed;
1255dd0baa8Skettenis 
1265dd0baa8Skettenis 	/************* IOMFB **************************************************
1275dd0baa8Skettenis 	 * everything below is mostly used inside IOMFB but it could make     *
1285dd0baa8Skettenis 	 * sense keep some of the the members in apple_dcp.                   *
1295dd0baa8Skettenis 	 **********************************************************************/
1305dd0baa8Skettenis 
1315dd0baa8Skettenis 	/* clock rate request by dcp in */
1325dd0baa8Skettenis 	struct clk *clk;
1335dd0baa8Skettenis 
1345dd0baa8Skettenis 	/* DCP shared memory */
1355dd0baa8Skettenis 	void *shmem;
1365dd0baa8Skettenis 
1375dd0baa8Skettenis 	/* Display registers mappable to the DCP */
1385dd0baa8Skettenis 	struct resource *disp_registers[MAX_DISP_REGISTERS];
1395dd0baa8Skettenis 	unsigned int nr_disp_registers;
1405dd0baa8Skettenis 
1415dd0baa8Skettenis 	struct resource disp_bw_scratch_res;
1425dd0baa8Skettenis 	struct resource disp_bw_doorbell_res;
1435dd0baa8Skettenis 	u32 disp_bw_scratch_index;
1445dd0baa8Skettenis 	u32 disp_bw_scratch_offset;
1455dd0baa8Skettenis 	u32 disp_bw_doorbell_index;
1465dd0baa8Skettenis 	u32 disp_bw_doorbell_offset;
1475dd0baa8Skettenis 
1485dd0baa8Skettenis 	u32 index;
1495dd0baa8Skettenis 
1505dd0baa8Skettenis 	/* Bitmap of memory descriptors used for mappings made by the DCP */
1515dd0baa8Skettenis 	DECLARE_BITMAP(memdesc_map, DCP_MAX_MAPPINGS);
1525dd0baa8Skettenis 
1535dd0baa8Skettenis 	/* Indexed table of memory descriptors */
1545dd0baa8Skettenis 	struct dcp_mem_descriptor memdesc[DCP_MAX_MAPPINGS];
1555dd0baa8Skettenis 
1565dd0baa8Skettenis 	struct dcp_channel ch_cmd, ch_oobcmd;
1575dd0baa8Skettenis 	struct dcp_channel ch_cb, ch_oobcb, ch_async, ch_oobasync;
1585dd0baa8Skettenis 
1595dd0baa8Skettenis 	/* iomfb EP callback handlers */
1605dd0baa8Skettenis 	const iomfb_cb_handler *cb_handlers;
1615dd0baa8Skettenis 
1625dd0baa8Skettenis 	/* Active chunked transfer. There can only be one at a time. */
1635dd0baa8Skettenis 	struct dcp_chunks chunks;
1645dd0baa8Skettenis 
1655dd0baa8Skettenis 	/* Queued swap. Owned by the DCP to avoid per-swap memory allocation */
1665dd0baa8Skettenis 	union {
1675dd0baa8Skettenis 		struct dcp_swap_submit_req_v12_3 v12_3;
1685dd0baa8Skettenis 		struct dcp_swap_submit_req_v13_3 v13_3;
1695dd0baa8Skettenis 	} swap;
1705dd0baa8Skettenis 
1715dd0baa8Skettenis 	/* swap id of the last completed swap */
1725dd0baa8Skettenis 	u32 last_swap_id;
1735dd0baa8Skettenis 
1745dd0baa8Skettenis 	/* Current display mode */
1755dd0baa8Skettenis 	bool during_modeset;
1765dd0baa8Skettenis 	bool valid_mode;
1775dd0baa8Skettenis 	struct dcp_set_digital_out_mode_req mode;
1785dd0baa8Skettenis 
1795dd0baa8Skettenis 	/* completion for active turning true */
1805dd0baa8Skettenis 	struct completion start_done;
1815dd0baa8Skettenis 
1825dd0baa8Skettenis 	/* Is the DCP booted? */
1835dd0baa8Skettenis 	bool active;
1845dd0baa8Skettenis 
1855dd0baa8Skettenis 	/* eDP display without DP-HDMI conversion */
1865dd0baa8Skettenis 	bool main_display;
1875dd0baa8Skettenis 
1885dd0baa8Skettenis 	/* clear all surfaces on init */
1895dd0baa8Skettenis 	bool surfaces_cleared;
1905dd0baa8Skettenis 
1915dd0baa8Skettenis 	/* Modes valid for the connected display */
1925dd0baa8Skettenis 	struct dcp_display_mode *modes;
1935dd0baa8Skettenis 	unsigned int nr_modes;
1945dd0baa8Skettenis 
1955dd0baa8Skettenis 	/* Attributes of the connector */
1965dd0baa8Skettenis 	int connector_type;
1975dd0baa8Skettenis 
1985dd0baa8Skettenis 	/* Attributes of the connected display */
1995dd0baa8Skettenis 	int width_mm, height_mm;
2005dd0baa8Skettenis 
2015dd0baa8Skettenis 	unsigned notch_height;
2025dd0baa8Skettenis 
2035dd0baa8Skettenis 	/* Workqueue for sending vblank events when a dcp swap is not possible */
2045dd0baa8Skettenis 	struct work_struct vblank_wq;
2055dd0baa8Skettenis 
2065dd0baa8Skettenis 	/* List of referenced drm_framebuffers which can be unreferenced
2075dd0baa8Skettenis 	 * on the next successfully completed swap.
2085dd0baa8Skettenis 	 */
2095dd0baa8Skettenis 	struct list_head swapped_out_fbs;
2105dd0baa8Skettenis 
2115dd0baa8Skettenis 	struct dcp_brightness brightness;
2125dd0baa8Skettenis 	/* Workqueue for updating the initial initial brightness */
2135dd0baa8Skettenis 	struct work_struct bl_register_wq;
2145dd0baa8Skettenis 	struct rwlock bl_register_mutex;
215*48fd60f3Skettenis 	/* Workqueue for updating the brightness */
216*48fd60f3Skettenis 	struct work_struct bl_update_wq;
2175dd0baa8Skettenis 
2185dd0baa8Skettenis 	/* integrated panel if present */
2195dd0baa8Skettenis 	struct dcp_panel panel;
2205dd0baa8Skettenis 
2215dd0baa8Skettenis 	struct apple_dcp_afkep *systemep;
2225dd0baa8Skettenis 	struct completion systemep_done;
2235dd0baa8Skettenis 
2245dd0baa8Skettenis 	struct apple_dcp_afkep *ibootep;
2255dd0baa8Skettenis 
2265dd0baa8Skettenis 	struct apple_dcp_afkep *dptxep;
2275dd0baa8Skettenis 
2285dd0baa8Skettenis 	struct dptx_port dptxport[2];
2295dd0baa8Skettenis 
2305dd0baa8Skettenis 	/* these fields are output port specific */
2315dd0baa8Skettenis 	struct phy *phy;
2325dd0baa8Skettenis 	struct mux_control *xbar;
2335dd0baa8Skettenis 
2345dd0baa8Skettenis 	struct gpio_desc *hdmi_hpd;
2355dd0baa8Skettenis 	struct gpio_desc *hdmi_pwren;
2365dd0baa8Skettenis 	struct gpio_desc *dp2hdmi_pwren;
2375dd0baa8Skettenis 
2385dd0baa8Skettenis 	struct rwlock hpd_mutex;
2395dd0baa8Skettenis 
2405dd0baa8Skettenis 	u32 dptx_phy;
2415dd0baa8Skettenis 	u32 dptx_die;
2425dd0baa8Skettenis 	int hdmi_hpd_irq;
2435dd0baa8Skettenis };
2445dd0baa8Skettenis 
2455dd0baa8Skettenis int dcp_backlight_register(struct apple_dcp *dcp);
246*48fd60f3Skettenis int dcp_backlight_update(struct apple_dcp *dcp);
2475dd0baa8Skettenis bool dcp_has_panel(struct apple_dcp *dcp);
2485dd0baa8Skettenis 
2495dd0baa8Skettenis #define DCP_AUDIO_MAX_CHANS 15
2505dd0baa8Skettenis 
2515dd0baa8Skettenis #endif /* __APPLE_DCP_INTERNAL_H__ */
252