Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,50 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_CDNS_DSI
tristate "Cadence DPI/DSI bridge"
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL_BRIDGE
select GENERIC_PHY
select GENERIC_PHY_MIPI_DPHY
select VIDEOMODE_HELPERS
depends on OF
help
Support Cadence DPI to DSI bridge. This is an internal
bridge and is meant to be directly embedded in a SoC.
if DRM_CDNS_DSI
config DRM_CDNS_DSI_J721E
bool "J721E Cadence DSI wrapper support"
default y
help
Support J721E Cadence DSI wrapper. The wrapper manages
the routing of the DSS DPI signal to the Cadence DSI.
endif
config DRM_CDNS_MHDP8546
tristate "Cadence DPI/DP bridge"
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER
select DRM_PANEL_BRIDGE
depends on OF
help
Support Cadence DPI to DP bridge. This is an internal
bridge and is meant to be directly embedded in a SoC.
It takes a DPI stream as input and outputs it encoded
in DP format.
if DRM_CDNS_MHDP8546
config DRM_CDNS_MHDP8546_J721E
depends on ARCH_K3 || COMPILE_TEST
bool "J721E Cadence DPI/DP wrapper support"
default y
help
Support J721E Cadence DPI/DP wrapper. This is a wrapper
which adds support for J721E related platform ops. It
initializes the J721E Display Port and sets up the
clock and data muxes.
endif
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
cdns-dsi-y := cdns-dsi-core.o
cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o
obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o
cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o
cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright: 2017 Cadence Design Systems, Inc.
*
* Author: Boris Brezillon <boris.brezillon@bootlin.com>
*/
#ifndef __CDNS_DSI_H__
#define __CDNS_DSI_H__
#include <drm/drm_bridge.h>
#include <drm/drm_mipi_dsi.h>
#include <linux/bits.h>
#include <linux/completion.h>
#include <linux/phy/phy.h>
struct clk;
struct reset_control;
struct cdns_dsi_output {
struct mipi_dsi_device *dev;
struct drm_bridge *bridge;
union phy_configure_opts phy_opts;
};
enum cdns_dsi_input_id {
CDNS_SDI_INPUT,
CDNS_DPI_INPUT,
CDNS_DSC_INPUT,
};
struct cdns_dsi_cfg {
unsigned int hfp;
unsigned int hsa;
unsigned int hbp;
unsigned int hact;
unsigned int htotal;
};
struct cdns_dsi_input {
enum cdns_dsi_input_id id;
struct drm_bridge bridge;
};
struct cdns_dsi;
/**
* struct cdns_dsi_platform_ops - CDNS DSI Platform operations
* @init: Called in the CDNS DSI probe
* @deinit: Called in the CDNS DSI remove
* @enable: Called at the beginning of CDNS DSI bridge enable
* @disable: Called at the end of CDNS DSI bridge disable
*/
struct cdns_dsi_platform_ops {
int (*init)(struct cdns_dsi *dsi);
void (*deinit)(struct cdns_dsi *dsi);
void (*enable)(struct cdns_dsi *dsi);
void (*disable)(struct cdns_dsi *dsi);
};
struct cdns_dsi {
struct mipi_dsi_host base;
void __iomem *regs;
#ifdef CONFIG_DRM_CDNS_DSI_J721E
void __iomem *j721e_regs;
#endif
const struct cdns_dsi_platform_ops *platform_ops;
struct cdns_dsi_input input;
struct cdns_dsi_output output;
unsigned int direct_cmd_fifo_depth;
unsigned int rx_fifo_depth;
struct completion direct_cmd_comp;
struct clk *dsi_p_clk;
struct reset_control *dsi_p_rst;
struct clk *dsi_sys_clk;
bool link_initialized;
bool phy_initialized;
struct phy *dphy;
};
#endif /* !__CDNS_DSI_H__ */
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0
/*
* TI j721e Cadence DSI wrapper
*
* Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
* Author: Rahul T R <r-ravikumar@ti.com>
*/
#include <linux/io.h>
#include <linux/platform_device.h>
#include "cdns-dsi-j721e.h"
#define DSI_WRAP_REVISION 0x0
#define DSI_WRAP_DPI_CONTROL 0x4
#define DSI_WRAP_DSC_CONTROL 0x8
#define DSI_WRAP_DPI_SECURE 0xc
#define DSI_WRAP_DSI_0_ASF_STATUS 0x10
#define DSI_WRAP_DPI_0_EN BIT(0)
#define DSI_WRAP_DSI2_MUX_SEL BIT(4)
static int cdns_dsi_j721e_init(struct cdns_dsi *dsi)
{
struct platform_device *pdev = to_platform_device(dsi->base.dev);
dsi->j721e_regs = devm_platform_ioremap_resource(pdev, 1);
return PTR_ERR_OR_ZERO(dsi->j721e_regs);
}
static void cdns_dsi_j721e_enable(struct cdns_dsi *dsi)
{
/*
* Enable DPI0 as its input. DSS0 DPI2 is connected
* to DSI DPI0. This is the only supported configuration on
* J721E.
*/
writel(DSI_WRAP_DPI_0_EN, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL);
}
static void cdns_dsi_j721e_disable(struct cdns_dsi *dsi)
{
/* Put everything to defaults */
writel(0, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL);
}
const struct cdns_dsi_platform_ops dsi_ti_j721e_ops = {
.init = cdns_dsi_j721e_init,
.enable = cdns_dsi_j721e_enable,
.disable = cdns_dsi_j721e_disable,
};
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* TI j721e Cadence DSI wrapper
*
* Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
* Author: Rahul T R <r-ravikumar@ti.com>
*/
#ifndef __CDNS_DSI_J721E_H__
#define __CDNS_DSI_J721E_H__
#include "cdns-dsi-core.h"
extern const struct cdns_dsi_platform_ops dsi_ti_j721e_ops;
#endif /* !__CDNS_DSI_J721E_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,422 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Cadence MHDP8546 DP bridge driver.
*
* Copyright (C) 2020 Cadence Design Systems, Inc.
*
* Author: Quentin Schulz <quentin.schulz@free-electrons.com>
* Swapnil Jakhade <sjakhade@cadence.com>
*/
#ifndef CDNS_MHDP8546_CORE_H
#define CDNS_MHDP8546_CORE_H
#include <linux/bits.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_connector.h>
struct clk;
struct device;
struct phy;
/* Register offsets */
#define CDNS_APB_CTRL 0x00000
#define CDNS_CPU_STALL BIT(3)
#define CDNS_MAILBOX_FULL 0x00008
#define CDNS_MAILBOX_EMPTY 0x0000c
#define CDNS_MAILBOX_TX_DATA 0x00010
#define CDNS_MAILBOX_RX_DATA 0x00014
#define CDNS_KEEP_ALIVE 0x00018
#define CDNS_KEEP_ALIVE_MASK GENMASK(7, 0)
#define CDNS_VER_L 0x0001C
#define CDNS_VER_H 0x00020
#define CDNS_LIB_L_ADDR 0x00024
#define CDNS_LIB_H_ADDR 0x00028
#define CDNS_MB_INT_MASK 0x00034
#define CDNS_MB_INT_STATUS 0x00038
#define CDNS_SW_CLK_L 0x0003c
#define CDNS_SW_CLK_H 0x00040
#define CDNS_SW_EVENT0 0x00044
#define CDNS_DPTX_HPD BIT(0)
#define CDNS_HDCP_TX_STATUS BIT(4)
#define CDNS_HDCP2_TX_IS_KM_STORED BIT(5)
#define CDNS_HDCP2_TX_STORE_KM BIT(6)
#define CDNS_HDCP_TX_IS_RCVR_ID_VALID BIT(7)
#define CDNS_SW_EVENT1 0x00048
#define CDNS_SW_EVENT2 0x0004c
#define CDNS_SW_EVENT3 0x00050
#define CDNS_APB_INT_MASK 0x0006C
#define CDNS_APB_INT_MASK_MAILBOX_INT BIT(0)
#define CDNS_APB_INT_MASK_SW_EVENT_INT BIT(1)
#define CDNS_APB_INT_STATUS 0x00070
#define CDNS_DPTX_CAR 0x00904
#define CDNS_VIF_CLK_EN BIT(0)
#define CDNS_VIF_CLK_RSTN BIT(1)
#define CDNS_SOURCE_VIDEO_IF(s) (0x00b00 + ((s) * 0x20))
#define CDNS_BND_HSYNC2VSYNC(s) (CDNS_SOURCE_VIDEO_IF(s) + \
0x00)
#define CDNS_IP_DTCT_WIN GENMASK(11, 0)
#define CDNS_IP_DET_INTERLACE_FORMAT BIT(12)
#define CDNS_IP_BYPASS_V_INTERFACE BIT(13)
#define CDNS_HSYNC2VSYNC_POL_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + \
0x10)
#define CDNS_H2V_HSYNC_POL_ACTIVE_LOW BIT(1)
#define CDNS_H2V_VSYNC_POL_ACTIVE_LOW BIT(2)
#define CDNS_DPTX_PHY_CONFIG 0x02000
#define CDNS_PHY_TRAINING_EN BIT(0)
#define CDNS_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1)
#define CDNS_PHY_SCRAMBLER_BYPASS BIT(5)
#define CDNS_PHY_ENCODER_BYPASS BIT(6)
#define CDNS_PHY_SKEW_BYPASS BIT(7)
#define CDNS_PHY_TRAINING_AUTO BIT(8)
#define CDNS_PHY_LANE0_SKEW(x) (((x) & GENMASK(2, 0)) << 9)
#define CDNS_PHY_LANE1_SKEW(x) (((x) & GENMASK(2, 0)) << 12)
#define CDNS_PHY_LANE2_SKEW(x) (((x) & GENMASK(2, 0)) << 15)
#define CDNS_PHY_LANE3_SKEW(x) (((x) & GENMASK(2, 0)) << 18)
#define CDNS_PHY_COMMON_CONFIG (CDNS_PHY_LANE1_SKEW(1) | \
CDNS_PHY_LANE2_SKEW(2) | \
CDNS_PHY_LANE3_SKEW(3))
#define CDNS_PHY_10BIT_EN BIT(21)
#define CDNS_DP_FRAMER_GLOBAL_CONFIG 0x02200
#define CDNS_DP_NUM_LANES(x) ((x) - 1)
#define CDNS_DP_MST_EN BIT(2)
#define CDNS_DP_FRAMER_EN BIT(3)
#define CDNS_DP_RATE_GOVERNOR_EN BIT(4)
#define CDNS_DP_NO_VIDEO_MODE BIT(5)
#define CDNS_DP_DISABLE_PHY_RST BIT(6)
#define CDNS_DP_WR_FAILING_EDGE_VSYNC BIT(7)
#define CDNS_DP_FRAMER_TU 0x02208
#define CDNS_DP_FRAMER_TU_SIZE(x) (((x) & GENMASK(6, 0)) << 8)
#define CDNS_DP_FRAMER_TU_VS(x) ((x) & GENMASK(5, 0))
#define CDNS_DP_FRAMER_TU_CNT_RST_EN BIT(15)
#define CDNS_DP_MTPH_CONTROL 0x02264
#define CDNS_DP_MTPH_ECF_EN BIT(0)
#define CDNS_DP_MTPH_ACT_EN BIT(1)
#define CDNS_DP_MTPH_LVP_EN BIT(2)
#define CDNS_DP_MTPH_STATUS 0x0226C
#define CDNS_DP_MTPH_ACT_STATUS BIT(0)
#define CDNS_DP_LANE_EN 0x02300
#define CDNS_DP_LANE_EN_LANES(x) GENMASK((x) - 1, 0)
#define CDNS_DP_ENHNCD 0x02304
#define CDNS_DPTX_STREAM(s) (0x03000 + (s) * 0x80)
#define CDNS_DP_MSA_HORIZONTAL_0(s) (CDNS_DPTX_STREAM(s) + 0x00)
#define CDNS_DP_MSAH0_H_TOTAL(x) (x)
#define CDNS_DP_MSAH0_HSYNC_START(x) ((x) << 16)
#define CDNS_DP_MSA_HORIZONTAL_1(s) (CDNS_DPTX_STREAM(s) + 0x04)
#define CDNS_DP_MSAH1_HSYNC_WIDTH(x) (x)
#define CDNS_DP_MSAH1_HSYNC_POL_LOW BIT(15)
#define CDNS_DP_MSAH1_HDISP_WIDTH(x) ((x) << 16)
#define CDNS_DP_MSA_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x08)
#define CDNS_DP_MSAV0_V_TOTAL(x) (x)
#define CDNS_DP_MSAV0_VSYNC_START(x) ((x) << 16)
#define CDNS_DP_MSA_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x0c)
#define CDNS_DP_MSAV1_VSYNC_WIDTH(x) (x)
#define CDNS_DP_MSAV1_VSYNC_POL_LOW BIT(15)
#define CDNS_DP_MSAV1_VDISP_WIDTH(x) ((x) << 16)
#define CDNS_DP_MSA_MISC(s) (CDNS_DPTX_STREAM(s) + 0x10)
#define CDNS_DP_STREAM_CONFIG(s) (CDNS_DPTX_STREAM(s) + 0x14)
#define CDNS_DP_STREAM_CONFIG_2(s) (CDNS_DPTX_STREAM(s) + 0x2c)
#define CDNS_DP_SC2_TU_VS_DIFF(x) ((x) << 8)
#define CDNS_DP_HORIZONTAL(s) (CDNS_DPTX_STREAM(s) + 0x30)
#define CDNS_DP_H_HSYNC_WIDTH(x) (x)
#define CDNS_DP_H_H_TOTAL(x) ((x) << 16)
#define CDNS_DP_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x34)
#define CDNS_DP_V0_VHEIGHT(x) (x)
#define CDNS_DP_V0_VSTART(x) ((x) << 16)
#define CDNS_DP_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x38)
#define CDNS_DP_V1_VTOTAL(x) (x)
#define CDNS_DP_V1_VTOTAL_EVEN BIT(16)
#define CDNS_DP_MST_SLOT_ALLOCATE(s) (CDNS_DPTX_STREAM(s) + 0x44)
#define CDNS_DP_S_ALLOC_START_SLOT(x) (x)
#define CDNS_DP_S_ALLOC_END_SLOT(x) ((x) << 8)
#define CDNS_DP_RATE_GOVERNING(s) (CDNS_DPTX_STREAM(s) + 0x48)
#define CDNS_DP_RG_TARG_AV_SLOTS_Y(x) (x)
#define CDNS_DP_RG_TARG_AV_SLOTS_X(x) ((x) << 4)
#define CDNS_DP_RG_ENABLE BIT(10)
#define CDNS_DP_FRAMER_PXL_REPR(s) (CDNS_DPTX_STREAM(s) + 0x4c)
#define CDNS_DP_FRAMER_6_BPC BIT(0)
#define CDNS_DP_FRAMER_8_BPC BIT(1)
#define CDNS_DP_FRAMER_10_BPC BIT(2)
#define CDNS_DP_FRAMER_12_BPC BIT(3)
#define CDNS_DP_FRAMER_16_BPC BIT(4)
#define CDNS_DP_FRAMER_PXL_FORMAT 0x8
#define CDNS_DP_FRAMER_RGB BIT(0)
#define CDNS_DP_FRAMER_YCBCR444 BIT(1)
#define CDNS_DP_FRAMER_YCBCR422 BIT(2)
#define CDNS_DP_FRAMER_YCBCR420 BIT(3)
#define CDNS_DP_FRAMER_Y_ONLY BIT(4)
#define CDNS_DP_FRAMER_SP(s) (CDNS_DPTX_STREAM(s) + 0x50)
#define CDNS_DP_FRAMER_VSYNC_POL_LOW BIT(0)
#define CDNS_DP_FRAMER_HSYNC_POL_LOW BIT(1)
#define CDNS_DP_FRAMER_INTERLACE BIT(2)
#define CDNS_DP_LINE_THRESH(s) (CDNS_DPTX_STREAM(s) + 0x64)
#define CDNS_DP_ACTIVE_LINE_THRESH(x) (x)
#define CDNS_DP_VB_ID(s) (CDNS_DPTX_STREAM(s) + 0x68)
#define CDNS_DP_VB_ID_INTERLACED BIT(2)
#define CDNS_DP_VB_ID_COMPRESSED BIT(6)
#define CDNS_DP_FRONT_BACK_PORCH(s) (CDNS_DPTX_STREAM(s) + 0x78)
#define CDNS_DP_BACK_PORCH(x) (x)
#define CDNS_DP_FRONT_PORCH(x) ((x) << 16)
#define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c)
#define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16
/* mailbox */
#define MAILBOX_RETRY_US 1000
#define MAILBOX_TIMEOUT_US 2000000
#define MB_OPCODE_ID 0
#define MB_MODULE_ID 1
#define MB_SIZE_MSB_ID 2
#define MB_SIZE_LSB_ID 3
#define MB_DATA_ID 4
#define MB_MODULE_ID_DP_TX 0x01
#define MB_MODULE_ID_HDCP_TX 0x07
#define MB_MODULE_ID_HDCP_RX 0x08
#define MB_MODULE_ID_HDCP_GENERAL 0x09
#define MB_MODULE_ID_GENERAL 0x0a
/* firmware and opcodes */
#define FW_NAME "cadence/mhdp8546.bin"
#define CDNS_MHDP_IMEM 0x10000
#define GENERAL_MAIN_CONTROL 0x01
#define GENERAL_TEST_ECHO 0x02
#define GENERAL_BUS_SETTINGS 0x03
#define GENERAL_TEST_ACCESS 0x04
#define GENERAL_REGISTER_READ 0x07
#define DPTX_SET_POWER_MNG 0x00
#define DPTX_GET_EDID 0x02
#define DPTX_READ_DPCD 0x03
#define DPTX_WRITE_DPCD 0x04
#define DPTX_ENABLE_EVENT 0x05
#define DPTX_WRITE_REGISTER 0x06
#define DPTX_READ_REGISTER 0x07
#define DPTX_WRITE_FIELD 0x08
#define DPTX_READ_EVENT 0x0a
#define DPTX_GET_LAST_AUX_STAUS 0x0e
#define DPTX_HPD_STATE 0x11
#define DPTX_ADJUST_LT 0x12
#define FW_STANDBY 0
#define FW_ACTIVE 1
/* HPD */
#define DPTX_READ_EVENT_HPD_TO_HIGH BIT(0)
#define DPTX_READ_EVENT_HPD_TO_LOW BIT(1)
#define DPTX_READ_EVENT_HPD_PULSE BIT(2)
#define DPTX_READ_EVENT_HPD_STATE BIT(3)
/* general */
#define CDNS_DP_TRAINING_PATTERN_4 0x7
#define CDNS_KEEP_ALIVE_TIMEOUT 2000
#define CDNS_VOLT_SWING(x) ((x) & GENMASK(1, 0))
#define CDNS_FORCE_VOLT_SWING BIT(2)
#define CDNS_PRE_EMPHASIS(x) ((x) & GENMASK(1, 0))
#define CDNS_FORCE_PRE_EMPHASIS BIT(2)
#define CDNS_SUPPORT_TPS(x) BIT((x) - 1)
#define CDNS_FAST_LINK_TRAINING BIT(0)
#define CDNS_LANE_MAPPING_TYPE_C_LANE_0(x) ((x) & GENMASK(1, 0))
#define CDNS_LANE_MAPPING_TYPE_C_LANE_1(x) ((x) & GENMASK(3, 2))
#define CDNS_LANE_MAPPING_TYPE_C_LANE_2(x) ((x) & GENMASK(5, 4))
#define CDNS_LANE_MAPPING_TYPE_C_LANE_3(x) ((x) & GENMASK(7, 6))
#define CDNS_LANE_MAPPING_NORMAL 0xe4
#define CDNS_LANE_MAPPING_FLIPPED 0x1b
#define CDNS_DP_MAX_NUM_LANES 4
#define CDNS_DP_TEST_VSC_SDP BIT(6) /* 1.3+ */
#define CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY BIT(7)
#define CDNS_MHDP_MAX_STREAMS 4
#define DP_LINK_CAP_ENHANCED_FRAMING BIT(0)
struct cdns_mhdp_link {
unsigned char revision;
unsigned int rate;
unsigned int num_lanes;
unsigned long capabilities;
};
struct cdns_mhdp_host {
unsigned int link_rate;
u8 lanes_cnt;
u8 volt_swing;
u8 pre_emphasis;
u8 pattern_supp;
u8 lane_mapping;
bool fast_link;
bool enhanced;
bool scrambler;
bool ssc;
};
struct cdns_mhdp_sink {
unsigned int link_rate;
u8 lanes_cnt;
u8 pattern_supp;
bool fast_link;
bool enhanced;
bool ssc;
};
struct cdns_mhdp_display_fmt {
enum drm_output_color_format color_format;
u32 bpc;
bool y_only;
};
/*
* These enums present MHDP hw initialization state
* Legal state transitions are:
* MHDP_HW_READY <-> MHDP_HW_STOPPED
*/
enum mhdp_hw_state {
MHDP_HW_READY = 1, /* HW ready, FW active */
MHDP_HW_STOPPED /* Driver removal FW to be stopped */
};
struct cdns_mhdp_device;
struct mhdp_platform_ops {
int (*init)(struct cdns_mhdp_device *mhdp);
void (*exit)(struct cdns_mhdp_device *mhdp);
void (*enable)(struct cdns_mhdp_device *mhdp);
void (*disable)(struct cdns_mhdp_device *mhdp);
};
struct cdns_mhdp_bridge_state {
struct drm_bridge_state base;
struct drm_display_mode *current_mode;
};
struct cdns_mhdp_platform_info {
const u32 *input_bus_flags;
const struct mhdp_platform_ops *ops;
};
#define to_cdns_mhdp_bridge_state(s) \
container_of(s, struct cdns_mhdp_bridge_state, base)
struct cdns_mhdp_hdcp {
struct delayed_work check_work;
struct work_struct prop_work;
struct mutex mutex; /* mutex to protect hdcp.value */
u32 value;
u8 hdcp_content_type;
};
struct cdns_mhdp_device {
void __iomem *regs;
void __iomem *sapb_regs;
void __iomem *j721e_regs;
struct device *dev;
struct clk *clk;
struct phy *phy;
const struct cdns_mhdp_platform_info *info;
/* This is to protect mailbox communications with the firmware */
struct mutex mbox_mutex;
/*
* "link_mutex" protects the access to all the link parameters
* including the link training process. Link training will be
* invoked both from threaded interrupt handler and from atomic
* callbacks when link_up is not set. So this mutex protects
* flags such as link_up, bridge_enabled, link.num_lanes,
* link.rate etc.
*/
struct mutex link_mutex;
struct drm_connector *connector;
struct drm_bridge bridge;
struct cdns_mhdp_link link;
struct drm_dp_aux aux;
struct cdns_mhdp_host host;
struct cdns_mhdp_sink sink;
struct cdns_mhdp_display_fmt display_fmt;
u8 stream_id;
bool link_up;
bool plugged;
/*
* "start_lock" protects the access to bridge_attached and
* hw_state data members that control the delayed firmware
* loading and attaching the bridge. They are accessed from
* both the DRM core and cdns_mhdp_fw_cb(). In most cases just
* protecting the data members is enough, but the irq mask
* setting needs to be protected when enabling the FW.
*/
spinlock_t start_lock;
bool bridge_attached;
bool bridge_enabled;
enum mhdp_hw_state hw_state;
wait_queue_head_t fw_load_wq;
/* Work struct to schedule a uevent on link train failure */
struct work_struct modeset_retry_work;
struct work_struct hpd_work;
wait_queue_head_t sw_events_wq;
u32 sw_events;
struct cdns_mhdp_hdcp hdcp;
bool hdcp_supported;
};
#define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector)
#define bridge_to_mhdp(x) container_of(x, struct cdns_mhdp_device, bridge)
u32 cdns_mhdp_wait_for_sw_event(struct cdns_mhdp_device *mhdp, uint32_t event);
#endif
@@ -0,0 +1,553 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Cadence MHDP8546 DP bridge driver.
*
* Copyright (C) 2020 Cadence Design Systems, Inc.
*
*/
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/unaligned.h>
#include <drm/display/drm_hdcp_helper.h>
#include "cdns-mhdp8546-hdcp.h"
static int cdns_mhdp_secure_mailbox_read(struct cdns_mhdp_device *mhdp)
{
int ret, empty;
WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_EMPTY,
empty, !empty, MAILBOX_RETRY_US,
MAILBOX_TIMEOUT_US);
if (ret < 0)
return ret;
return readl(mhdp->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff;
}
static int cdns_mhdp_secure_mailbox_write(struct cdns_mhdp_device *mhdp,
u8 val)
{
int ret, full;
WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_FULL,
full, !full, MAILBOX_RETRY_US,
MAILBOX_TIMEOUT_US);
if (ret < 0)
return ret;
writel(val, mhdp->sapb_regs + CDNS_MAILBOX_TX_DATA);
return 0;
}
static int cdns_mhdp_secure_mailbox_recv_header(struct cdns_mhdp_device *mhdp,
u8 module_id,
u8 opcode,
u16 req_size)
{
u32 mbox_size, i;
u8 header[4];
int ret;
/* read the header of the message */
for (i = 0; i < sizeof(header); i++) {
ret = cdns_mhdp_secure_mailbox_read(mhdp);
if (ret < 0)
return ret;
header[i] = ret;
}
mbox_size = get_unaligned_be16(header + 2);
if (opcode != header[0] || module_id != header[1] ||
(opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) {
for (i = 0; i < mbox_size; i++)
if (cdns_mhdp_secure_mailbox_read(mhdp) < 0)
break;
return -EINVAL;
}
return 0;
}
static int cdns_mhdp_secure_mailbox_recv_data(struct cdns_mhdp_device *mhdp,
u8 *buff, u16 buff_size)
{
int ret;
u32 i;
for (i = 0; i < buff_size; i++) {
ret = cdns_mhdp_secure_mailbox_read(mhdp);
if (ret < 0)
return ret;
buff[i] = ret;
}
return 0;
}
static int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_device *mhdp,
u8 module_id,
u8 opcode,
u16 size,
u8 *message)
{
u8 header[4];
int ret;
u32 i;
header[0] = opcode;
header[1] = module_id;
put_unaligned_be16(size, header + 2);
for (i = 0; i < sizeof(header); i++) {
ret = cdns_mhdp_secure_mailbox_write(mhdp, header[i]);
if (ret)
return ret;
}
for (i = 0; i < size; i++) {
ret = cdns_mhdp_secure_mailbox_write(mhdp, message[i]);
if (ret)
return ret;
}
return 0;
}
static int cdns_mhdp_hdcp_get_status(struct cdns_mhdp_device *mhdp,
u16 *hdcp_port_status)
{
u8 hdcp_status[HDCP_STATUS_SIZE];
int ret;
mutex_lock(&mhdp->mbox_mutex);
ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP_TRAN_STATUS_CHANGE, 0, NULL);
if (ret)
goto err_get_hdcp_status;
ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP_TRAN_STATUS_CHANGE,
sizeof(hdcp_status));
if (ret)
goto err_get_hdcp_status;
ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_status,
sizeof(hdcp_status));
if (ret)
goto err_get_hdcp_status;
*hdcp_port_status = ((u16)(hdcp_status[0] << 8) | hdcp_status[1]);
err_get_hdcp_status:
mutex_unlock(&mhdp->mbox_mutex);
return ret;
}
static u8 cdns_mhdp_hdcp_handle_status(struct cdns_mhdp_device *mhdp,
u16 status)
{
u8 err = GET_HDCP_PORT_STS_LAST_ERR(status);
if (err)
dev_dbg(mhdp->dev, "HDCP Error = %d", err);
return err;
}
static int cdns_mhdp_hdcp_rx_id_valid_response(struct cdns_mhdp_device *mhdp,
u8 valid)
{
int ret;
mutex_lock(&mhdp->mbox_mutex);
ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
1, &valid);
mutex_unlock(&mhdp->mbox_mutex);
return ret;
}
static int cdns_mhdp_hdcp_rx_id_valid(struct cdns_mhdp_device *mhdp,
u8 *recv_num, u8 *hdcp_rx_id)
{
u8 rec_id_hdr[2];
u8 status;
int ret;
mutex_lock(&mhdp->mbox_mutex);
ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP_TRAN_IS_REC_ID_VALID, 0, NULL);
if (ret)
goto err_rx_id_valid;
ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP_TRAN_IS_REC_ID_VALID,
sizeof(status));
if (ret)
goto err_rx_id_valid;
ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, rec_id_hdr, 2);
if (ret)
goto err_rx_id_valid;
*recv_num = rec_id_hdr[0];
ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_rx_id, 5 * *recv_num);
err_rx_id_valid:
mutex_unlock(&mhdp->mbox_mutex);
return ret;
}
static int cdns_mhdp_hdcp_km_stored_resp(struct cdns_mhdp_device *mhdp,
u32 size, u8 *km)
{
int ret;
mutex_lock(&mhdp->mbox_mutex);
ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP2X_TX_RESPOND_KM, size, km);
mutex_unlock(&mhdp->mbox_mutex);
return ret;
}
static int cdns_mhdp_hdcp_tx_is_km_stored(struct cdns_mhdp_device *mhdp,
u8 *resp, u32 size)
{
int ret;
mutex_lock(&mhdp->mbox_mutex);
ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP2X_TX_IS_KM_STORED, 0, NULL);
if (ret)
goto err_is_km_stored;
ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP2X_TX_IS_KM_STORED,
size);
if (ret)
goto err_is_km_stored;
ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, resp, size);
err_is_km_stored:
mutex_unlock(&mhdp->mbox_mutex);
return ret;
}
static int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp,
u8 hdcp_cfg)
{
int ret;
mutex_lock(&mhdp->mbox_mutex);
ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg);
mutex_unlock(&mhdp->mbox_mutex);
return ret;
}
static int cdns_mhdp_hdcp_set_config(struct cdns_mhdp_device *mhdp,
u8 hdcp_config, bool enable)
{
u16 hdcp_port_status;
u32 ret_event;
u8 hdcp_cfg;
int ret;
hdcp_cfg = hdcp_config | (enable ? 0x04 : 0) |
(HDCP_CONTENT_TYPE_0 << 3);
cdns_mhdp_hdcp_tx_config(mhdp, hdcp_cfg);
ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS);
if (!ret_event)
return -1;
ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
return -1;
return 0;
}
static int cdns_mhdp_hdcp_auth_check(struct cdns_mhdp_device *mhdp)
{
u16 hdcp_port_status;
u32 ret_event;
int ret;
ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS);
if (!ret_event)
return -1;
ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
return -1;
if (hdcp_port_status & 1) {
dev_dbg(mhdp->dev, "Authentication completed successfully!\n");
return 0;
}
dev_dbg(mhdp->dev, "Authentication failed\n");
return -1;
}
static int cdns_mhdp_hdcp_check_receviers(struct cdns_mhdp_device *mhdp)
{
u8 hdcp_rec_id[HDCP_MAX_RECEIVERS][HDCP_RECEIVER_ID_SIZE_BYTES];
u8 hdcp_num_rec;
u32 ret_event;
ret_event = cdns_mhdp_wait_for_sw_event(mhdp,
CDNS_HDCP_TX_IS_RCVR_ID_VALID);
if (!ret_event)
return -1;
hdcp_num_rec = 0;
memset(&hdcp_rec_id, 0, sizeof(hdcp_rec_id));
cdns_mhdp_hdcp_rx_id_valid(mhdp, &hdcp_num_rec, (u8 *)hdcp_rec_id);
cdns_mhdp_hdcp_rx_id_valid_response(mhdp, 1);
return 0;
}
static int cdns_mhdp_hdcp_auth_22(struct cdns_mhdp_device *mhdp)
{
u8 resp[HDCP_STATUS_SIZE];
u16 hdcp_port_status;
u32 ret_event;
int ret;
dev_dbg(mhdp->dev, "HDCP: Start 2.2 Authentication\n");
ret_event = cdns_mhdp_wait_for_sw_event(mhdp,
CDNS_HDCP2_TX_IS_KM_STORED);
if (!ret_event)
return -1;
if (ret_event & CDNS_HDCP_TX_STATUS) {
mhdp->sw_events &= ~CDNS_HDCP_TX_STATUS;
ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status))
return -1;
}
cdns_mhdp_hdcp_tx_is_km_stored(mhdp, resp, sizeof(resp));
cdns_mhdp_hdcp_km_stored_resp(mhdp, 0, NULL);
if (cdns_mhdp_hdcp_check_receviers(mhdp))
return -1;
return 0;
}
static inline int cdns_mhdp_hdcp_auth_14(struct cdns_mhdp_device *mhdp)
{
dev_dbg(mhdp->dev, "HDCP: Starting 1.4 Authentication\n");
return cdns_mhdp_hdcp_check_receviers(mhdp);
}
static int cdns_mhdp_hdcp_auth(struct cdns_mhdp_device *mhdp,
u8 hdcp_config)
{
int ret;
ret = cdns_mhdp_hdcp_set_config(mhdp, hdcp_config, true);
if (ret)
goto auth_failed;
if (hdcp_config == HDCP_TX_1)
ret = cdns_mhdp_hdcp_auth_14(mhdp);
else
ret = cdns_mhdp_hdcp_auth_22(mhdp);
if (ret)
goto auth_failed;
ret = cdns_mhdp_hdcp_auth_check(mhdp);
if (ret)
ret = cdns_mhdp_hdcp_auth_check(mhdp);
auth_failed:
return ret;
}
static int _cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
{
int ret;
dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n",
mhdp->connector->name, mhdp->connector->base.id);
ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false);
return ret;
}
static int _cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
{
int ret = -EINVAL;
int tries = 3;
u32 i;
for (i = 0; i < tries; i++) {
if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0 ||
content_type == DRM_MODE_HDCP_CONTENT_TYPE1) {
ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_2);
if (!ret)
return 0;
_cdns_mhdp_hdcp_disable(mhdp);
}
if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_1);
if (!ret)
return 0;
_cdns_mhdp_hdcp_disable(mhdp);
}
}
dev_err(mhdp->dev, "HDCP authentication failed (%d tries/%d)\n",
tries, ret);
return ret;
}
static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
{
u16 hdcp_port_status;
int ret = 0;
mutex_lock(&mhdp->hdcp.mutex);
if (!mhdp->connector)
goto out;
if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
goto out;
ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
if (!ret && hdcp_port_status & HDCP_PORT_STS_AUTH)
goto out;
dev_err(mhdp->dev,
"[%s:%d] HDCP link failed, retrying authentication\n",
mhdp->connector->name, mhdp->connector->base.id);
ret = _cdns_mhdp_hdcp_disable(mhdp);
if (ret) {
mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
schedule_work(&mhdp->hdcp.prop_work);
goto out;
}
ret = _cdns_mhdp_hdcp_enable(mhdp, mhdp->hdcp.hdcp_content_type);
if (ret) {
mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
schedule_work(&mhdp->hdcp.prop_work);
}
out:
mutex_unlock(&mhdp->hdcp.mutex);
return ret;
}
static void cdns_mhdp_hdcp_check_work(struct work_struct *work)
{
struct delayed_work *d_work = to_delayed_work(work);
struct cdns_mhdp_hdcp *hdcp = container_of(d_work,
struct cdns_mhdp_hdcp,
check_work);
struct cdns_mhdp_device *mhdp = container_of(hdcp,
struct cdns_mhdp_device,
hdcp);
if (!cdns_mhdp_hdcp_check_link(mhdp))
schedule_delayed_work(&hdcp->check_work,
DRM_HDCP_CHECK_PERIOD_MS);
}
static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
{
struct cdns_mhdp_hdcp *hdcp = container_of(work,
struct cdns_mhdp_hdcp,
prop_work);
struct cdns_mhdp_device *mhdp = container_of(hdcp,
struct cdns_mhdp_device,
hdcp);
struct drm_device *dev = NULL;
struct drm_connector_state *state;
if (mhdp->connector)
dev = mhdp->connector->dev;
if (!dev)
return;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
mutex_lock(&mhdp->hdcp.mutex);
if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
state = mhdp->connector->state;
state->content_protection = mhdp->hdcp.value;
}
mutex_unlock(&mhdp->hdcp.mutex);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
int cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type)
{
int ret;
mutex_lock(&mhdp->hdcp.mutex);
ret = _cdns_mhdp_hdcp_enable(mhdp, content_type);
if (ret)
goto out;
mhdp->hdcp.hdcp_content_type = content_type;
mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
schedule_work(&mhdp->hdcp.prop_work);
schedule_delayed_work(&mhdp->hdcp.check_work,
DRM_HDCP_CHECK_PERIOD_MS);
out:
mutex_unlock(&mhdp->hdcp.mutex);
return ret;
}
int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
{
int ret = 0;
mutex_lock(&mhdp->hdcp.mutex);
if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
schedule_work(&mhdp->hdcp.prop_work);
ret = _cdns_mhdp_hdcp_disable(mhdp);
}
mutex_unlock(&mhdp->hdcp.mutex);
cancel_delayed_work_sync(&mhdp->hdcp.check_work);
return ret;
}
void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp)
{
INIT_DELAYED_WORK(&mhdp->hdcp.check_work, cdns_mhdp_hdcp_check_work);
INIT_WORK(&mhdp->hdcp.prop_work, cdns_mhdp_hdcp_prop_work);
mutex_init(&mhdp->hdcp.mutex);
}
@@ -0,0 +1,89 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Cadence MHDP8546 DP bridge driver.
*
* Copyright (C) 2020 Cadence Design Systems, Inc.
*
*/
#ifndef CDNS_MHDP8546_HDCP_H
#define CDNS_MHDP8546_HDCP_H
#include "cdns-mhdp8546-core.h"
#define HDCP_MAX_RECEIVERS 32
#define HDCP_RECEIVER_ID_SIZE_BYTES 5
#define HDCP_STATUS_SIZE 0x5
#define HDCP_PORT_STS_AUTH 0x1
#define HDCP_PORT_STS_LAST_ERR_SHIFT 0x5
#define HDCP_PORT_STS_LAST_ERR_MASK (0x0F << 5)
#define GET_HDCP_PORT_STS_LAST_ERR(__sts__) \
(((__sts__) & HDCP_PORT_STS_LAST_ERR_MASK) >> \
HDCP_PORT_STS_LAST_ERR_SHIFT)
#define HDCP_CONFIG_1_4 BIT(0) /* use HDCP 1.4 only */
#define HDCP_CONFIG_2_2 BIT(1) /* use HDCP 2.2 only */
/* use All HDCP versions */
#define HDCP_CONFIG_ALL (BIT(0) | BIT(1))
#define HDCP_CONFIG_NONE 0
enum {
HDCP_GENERAL_SET_LC_128,
HDCP_SET_SEED,
};
enum {
HDCP_TRAN_CONFIGURATION,
HDCP2X_TX_SET_PUBLIC_KEY_PARAMS,
HDCP2X_TX_SET_DEBUG_RANDOM_NUMBERS,
HDCP2X_TX_RESPOND_KM,
HDCP1_TX_SEND_KEYS,
HDCP1_TX_SEND_RANDOM_AN,
HDCP_TRAN_STATUS_CHANGE,
HDCP2X_TX_IS_KM_STORED,
HDCP2X_TX_STORE_KM,
HDCP_TRAN_IS_REC_ID_VALID,
HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
HDCP_TRAN_TEST_KEYS,
HDCP2X_TX_SET_KM_KEY_PARAMS,
HDCP_NUM_OF_SUPPORTED_MESSAGES
};
enum {
HDCP_CONTENT_TYPE_0,
HDCP_CONTENT_TYPE_1,
};
#define DRM_HDCP_CHECK_PERIOD_MS (128 * 16)
#define HDCP_PAIRING_R_ID 5
#define HDCP_PAIRING_M_LEN 16
#define HDCP_KM_LEN 16
#define HDCP_PAIRING_M_EKH 16
struct cdns_hdcp_pairing_data {
u8 receiver_id[HDCP_PAIRING_R_ID];
u8 m[HDCP_PAIRING_M_LEN];
u8 km[HDCP_KM_LEN];
u8 ekh[HDCP_PAIRING_M_EKH];
};
enum {
HDCP_TX_2,
HDCP_TX_1,
HDCP_TX_BOTH,
};
#define DLP_MODULUS_N 384
#define DLP_E 3
struct cdns_hdcp_tx_public_key_param {
u8 N[DLP_MODULUS_N];
u8 E[DLP_E];
};
int cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type);
int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp);
void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp);
#endif
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-2.0
/*
* TI j721e Cadence MHDP8546 DP wrapper
*
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
* Author: Jyri Sarha <jsarha@ti.com>
*/
#include <linux/io.h>
#include <linux/platform_device.h>
#include "cdns-mhdp8546-j721e.h"
#define REVISION 0x00
#define DPTX_IPCFG 0x04
#define ECC_MEM_CFG 0x08
#define DPTX_DSC_CFG 0x0c
#define DPTX_SRC_CFG 0x10
#define DPTX_VIF_SECURE_MODE_CFG 0x14
#define DPTX_VIF_CONN_STATUS 0x18
#define PHY_CLK_STATUS 0x1c
#define DPTX_SRC_AIF_EN BIT(16)
#define DPTX_SRC_VIF_3_IN30B BIT(11)
#define DPTX_SRC_VIF_2_IN30B BIT(10)
#define DPTX_SRC_VIF_1_IN30B BIT(9)
#define DPTX_SRC_VIF_0_IN30B BIT(8)
#define DPTX_SRC_VIF_3_SEL_DPI5 BIT(7)
#define DPTX_SRC_VIF_3_SEL_DPI3 0
#define DPTX_SRC_VIF_2_SEL_DPI4 BIT(6)
#define DPTX_SRC_VIF_2_SEL_DPI2 0
#define DPTX_SRC_VIF_1_SEL_DPI3 BIT(5)
#define DPTX_SRC_VIF_1_SEL_DPI1 0
#define DPTX_SRC_VIF_0_SEL_DPI2 BIT(4)
#define DPTX_SRC_VIF_0_SEL_DPI0 0
#define DPTX_SRC_VIF_3_EN BIT(3)
#define DPTX_SRC_VIF_2_EN BIT(2)
#define DPTX_SRC_VIF_1_EN BIT(1)
#define DPTX_SRC_VIF_0_EN BIT(0)
/* TODO turn DPTX_IPCFG fw_mem_clk_en at pm_runtime_suspend. */
static int cdns_mhdp_j721e_init(struct cdns_mhdp_device *mhdp)
{
struct platform_device *pdev = to_platform_device(mhdp->dev);
mhdp->j721e_regs = devm_platform_ioremap_resource(pdev, 1);
return PTR_ERR_OR_ZERO(mhdp->j721e_regs);
}
static void cdns_mhdp_j721e_enable(struct cdns_mhdp_device *mhdp)
{
/*
* Enable VIF_0 and select DPI2 as its input. DSS0 DPI0 is connected
* to eDP DPI2. This is the only supported SST configuration on
* J721E.
*/
writel(DPTX_SRC_VIF_0_EN | DPTX_SRC_VIF_0_SEL_DPI2,
mhdp->j721e_regs + DPTX_SRC_CFG);
}
static void cdns_mhdp_j721e_disable(struct cdns_mhdp_device *mhdp)
{
/* Put everything to defaults */
writel(0, mhdp->j721e_regs + DPTX_DSC_CFG);
}
const struct mhdp_platform_ops mhdp_ti_j721e_ops = {
.init = cdns_mhdp_j721e_init,
.enable = cdns_mhdp_j721e_enable,
.disable = cdns_mhdp_j721e_disable,
};
const u32
mhdp_ti_j721e_bridge_input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE |
DRM_BUS_FLAG_DE_HIGH;
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* TI j721e Cadence MHDP8546 DP wrapper
*
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
* Author: Jyri Sarha <jsarha@ti.com>
*/
#ifndef CDNS_MHDP8546_J721E_H
#define CDNS_MHDP8546_J721E_H
#include "cdns-mhdp8546-core.h"
struct mhdp_platform_ops;
extern const struct mhdp_platform_ops mhdp_ti_j721e_ops;
extern const u32 mhdp_ti_j721e_bridge_input_bus_flags;
#endif /* !CDNS_MHDP8546_J721E_H */