src/sys/dev/pci/drm/apple/dcp-internal.h

251 lines
5.8 KiB
C

// SPDX-License-Identifier: GPL-2.0-only OR MIT
/* Copyright 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io> */
#ifndef __APPLE_DCP_INTERNAL_H__
#define __APPLE_DCP_INTERNAL_H__
#include <linux/backlight.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/mutex.h>
#include <linux/mux/consumer.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
#include "dptxep.h"
#include "iomfb.h"
#include "iomfb_v12_3.h"
#include "iomfb_v13_3.h"
#define DCP_MAX_PLANES 2
struct apple_dcp;
struct apple_dcp_afkep;
enum dcp_firmware_version {
DCP_FIRMWARE_UNKNOWN,
DCP_FIRMWARE_V_12_3,
DCP_FIRMWARE_V_13_5,
};
enum {
SYSTEM_ENDPOINT = 0x20,
TEST_ENDPOINT = 0x21,
DCP_EXPERT_ENDPOINT = 0x22,
DISP0_ENDPOINT = 0x23,
DPTX_ENDPOINT = 0x2a,
HDCP_ENDPOINT = 0x2b,
REMOTE_ALLOC_ENDPOINT = 0x2d,
IOMFB_ENDPOINT = 0x37,
};
/* Temporary backing for a chunked transfer via setDCPAVPropStart/Chunk/End */
struct dcp_chunks {
size_t length;
void *data;
};
#define DCP_MAX_MAPPINGS (128) /* should be enough */
#define MAX_DISP_REGISTERS (7)
struct dcp_mem_descriptor {
size_t size;
void *buf;
dma_addr_t dva;
struct sg_table map;
u64 reg;
};
/* Limit on call stack depth (arbitrary). Some nesting is required */
#define DCP_MAX_CALL_DEPTH 8
typedef void (*dcp_callback_t)(struct apple_dcp *, void *, void *);
struct dcp_channel {
dcp_callback_t callbacks[DCP_MAX_CALL_DEPTH];
void *cookies[DCP_MAX_CALL_DEPTH];
void *output[DCP_MAX_CALL_DEPTH];
u16 end[DCP_MAX_CALL_DEPTH];
/* Current depth of the call stack. Less than DCP_MAX_CALL_DEPTH */
u8 depth;
};
struct dcp_fb_reference {
struct list_head head;
struct drm_framebuffer *fb;
u32 swap_id;
};
#define MAX_NOTCH_HEIGHT 160
struct dcp_brightness {
struct backlight_device *bl_dev;
u32 maximum;
u32 dac;
int nits;
int scale;
bool update;
};
/** laptop/AiO integrated panel parameters from DT */
struct dcp_panel {
/// panel width in millimeter
int width_mm;
/// panel height in millimeter
int height_mm;
/// panel has a mini-LED backlight
bool has_mini_led;
};
struct apple_dcp_hw_data {
u32 num_dptx_ports;
};
/* TODO: move IOMFB members to its own struct */
struct apple_dcp {
struct device *dev;
struct platform_device *piodma;
struct iommu_domain *iommu_dom;
struct apple_rtkit *rtk;
struct apple_crtc *crtc;
struct apple_connector *connector;
struct apple_dcp_hw_data hw;
/* firmware version and compatible firmware version */
enum dcp_firmware_version fw_compat;
/* Coprocessor control register */
void __iomem *coproc_reg;
/* DCP has crashed */
bool crashed;
/************* IOMFB **************************************************
* everything below is mostly used inside IOMFB but it could make *
* sense keep some of the the members in apple_dcp. *
**********************************************************************/
/* clock rate request by dcp in */
struct clk *clk;
/* DCP shared memory */
void *shmem;
/* Display registers mappable to the DCP */
struct resource *disp_registers[MAX_DISP_REGISTERS];
unsigned int nr_disp_registers;
struct resource disp_bw_scratch_res;
struct resource disp_bw_doorbell_res;
u32 disp_bw_scratch_index;
u32 disp_bw_scratch_offset;
u32 disp_bw_doorbell_index;
u32 disp_bw_doorbell_offset;
u32 index;
/* Bitmap of memory descriptors used for mappings made by the DCP */
DECLARE_BITMAP(memdesc_map, DCP_MAX_MAPPINGS);
/* Indexed table of memory descriptors */
struct dcp_mem_descriptor memdesc[DCP_MAX_MAPPINGS];
struct dcp_channel ch_cmd, ch_oobcmd;
struct dcp_channel ch_cb, ch_oobcb, ch_async, ch_oobasync;
/* iomfb EP callback handlers */
const iomfb_cb_handler *cb_handlers;
/* Active chunked transfer. There can only be one at a time. */
struct dcp_chunks chunks;
/* Queued swap. Owned by the DCP to avoid per-swap memory allocation */
union {
struct dcp_swap_submit_req_v12_3 v12_3;
struct dcp_swap_submit_req_v13_3 v13_3;
} swap;
/* swap id of the last completed swap */
u32 last_swap_id;
/* Current display mode */
bool during_modeset;
bool valid_mode;
struct dcp_set_digital_out_mode_req mode;
/* completion for active turning true */
struct completion start_done;
/* Is the DCP booted? */
bool active;
/* eDP display without DP-HDMI conversion */
bool main_display;
/* clear all surfaces on init */
bool surfaces_cleared;
/* Modes valid for the connected display */
struct dcp_display_mode *modes;
unsigned int nr_modes;
/* Attributes of the connector */
int connector_type;
/* Attributes of the connected display */
int width_mm, height_mm;
unsigned notch_height;
/* Workqueue for sending vblank events when a dcp swap is not possible */
struct work_struct vblank_wq;
/* List of referenced drm_framebuffers which can be unreferenced
* on the next successfully completed swap.
*/
struct list_head swapped_out_fbs;
struct dcp_brightness brightness;
/* Workqueue for updating the initial initial brightness */
struct work_struct bl_register_wq;
struct rwlock bl_register_mutex;
/* Workqueue for updating the brightness */
struct work_struct bl_update_wq;
/* integrated panel if present */
struct dcp_panel panel;
struct apple_dcp_afkep *systemep;
struct completion systemep_done;
struct apple_dcp_afkep *ibootep;
struct apple_dcp_afkep *dptxep;
struct dptx_port dptxport[2];
/* these fields are output port specific */
struct phy *phy;
struct mux_control *xbar;
struct gpio_desc *hdmi_hpd;
struct gpio_desc *hdmi_pwren;
struct gpio_desc *dp2hdmi_pwren;
struct rwlock hpd_mutex;
u32 dptx_phy;
u32 dptx_die;
int hdmi_hpd_irq;
};
int dcp_backlight_register(struct apple_dcp *dcp);
int dcp_backlight_update(struct apple_dcp *dcp);
bool dcp_has_panel(struct apple_dcp *dcp);
#define DCP_AUDIO_MAX_CHANS 15
#endif /* __APPLE_DCP_INTERNAL_H__ */