ANDROID: drm: kirin: Introduce kirin960

Add initial kirin960 support files.

Signed-off-by: Xu YiPing <xuyiping@hisilicon.com>
[jstultz: Fold in some minor cleanups]
[jstultz: Folded in a export symbol fix by Greg Kroah-Hartman]
Signed-off-by: John Stultz <john.stultz@linaro.org>
Bug: 146450171
Change-Id: I934004f4a15e1bba341807f6c63c13bf6c661698
This commit is contained in:
John Stultz 2019-01-10 22:59:16 +08:00 committed by Todd Kjos
parent 5cf9a844f6
commit 34ebaf13be
11 changed files with 2440 additions and 163 deletions

View File

@ -6,7 +6,37 @@ config DRM_HISI_KIRIN
select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
help
Choose this option if you have a hisilicon Kirin chipsets(hi6220).
Choose this option if you have a hisilicon Kirin chipsets.
If M is selected the module will be called kirin-drm.
if DRM_HISI_KIRIN
config DRM_HISI_KIRIN620
bool "DRM Support for Hisilicon Kirin620 Platform"
default n
depends on DRM_HISI_KIRIN
select DRM_KMS_HELPER
select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
help
Choose this option if you have hisilicon Kirin Chipset(kirin620).
It includes kirin620 ade and dsi drivers.
If y is to build kirin620 drm into kirin drm drivers.
config DRM_HISI_KIRIN960
bool "DRM Support for Hisilicon Kirin960 Platform"
default n
depends on DRM_HISI_KIRIN
select DRM_KMS_HELPER
select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
help
Choose this option if you have hisilicon Kirin Chipset(kirin960), such
as hikey board. It includes kirin620 dpe and dsi drivers.
If y is to build kirin960 drm into kirin drm drivers.
endif

View File

@ -1,6 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
kirin-drm-y := kirin_drm_drv.o \
kirin_drm_ade.o
EXTRA_CFLAGS += \
-Iinclude/drm
obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o dw_drm_dsi.o
kirin-drm-y := kirin_drm_drv.o
kirin-drm-$(CONFIG_DRM_HISI_KIRIN620) += kirin_drm_ade.o
kirin-dsi-y := kirin_drm_dsi.o
kirin-dsi-$(CONFIG_DRM_HISI_KIRIN620) += kirin/dw_drm_dsi.o
kirin-dsi-$(CONFIG_DRM_HISI_KIRIN960) += kirin960/dw_drm_dsi.o
obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o kirin-dsi.o

View File

@ -8,7 +8,7 @@
#define __DW_DSI_REG_H__
#define MASK(x) (BIT(x) - 1)
#define DEFAULT_MAX_TX_ESC_CLK (10 * 1000000UL) //for hikey960
/*
* regs
*/
@ -52,6 +52,50 @@
#define VID_VACTIVE_LINES 0x60 /* Vertical resolution */
#define VID_PKT_SIZE 0x3C /* Video packet size */
#define VID_MODE_CFG 0x38 /* Video mode configuration */
/***************************for hikey960***********************************/
#define GEN_HDR 0x6c
#define GEN_HDATA(data) (((data) & 0xffff) << 8)
#define GEN_HDATA_MASK (0xffff << 8)
#define GEN_HTYPE(type) (((type) & 0xff) << 0)
#define GEN_HTYPE_MASK 0xff
#define GEN_PLD_DATA 0x70
#define CMD_PKT_STATUS 0x74
#define GEN_CMD_EMPTY BIT(0)
#define GEN_CMD_FULL BIT(1)
#define GEN_PLD_W_EMPTY BIT(2)
#define GEN_PLD_W_FULL BIT(3)
#define GEN_PLD_R_EMPTY BIT(4)
#define GEN_PLD_R_FULL BIT(5)
#define GEN_RD_CMD_BUSY BIT(6)
#define CMD_MODE_CFG 0x68
#define MAX_RD_PKT_SIZE_LP BIT(24)
#define DCS_LW_TX_LP BIT(19)
#define DCS_SR_0P_TX_LP BIT(18)
#define DCS_SW_1P_TX_LP BIT(17)
#define DCS_SW_0P_TX_LP BIT(16)
#define GEN_LW_TX_LP BIT(14)
#define GEN_SR_2P_TX_LP BIT(13)
#define GEN_SR_1P_TX_LP BIT(12)
#define GEN_SR_0P_TX_LP BIT(11)
#define GEN_SW_2P_TX_LP BIT(10)
#define GEN_SW_1P_TX_LP BIT(9)
#define GEN_SW_0P_TX_LP BIT(8)
#define EN_ACK_RQST BIT(1)
#define EN_TEAR_FX BIT(0)
#define CMD_PKT_STATUS_TIMEOUT_US 20000
#define CMD_MODE_ALL_LP (MAX_RD_PKT_SIZE_LP | \
DCS_LW_TX_LP | \
DCS_SR_0P_TX_LP | \
DCS_SW_1P_TX_LP | \
DCS_SW_0P_TX_LP | \
GEN_LW_TX_LP | \
GEN_SR_2P_TX_LP | \
GEN_SR_1P_TX_LP | \
GEN_SR_0P_TX_LP | \
GEN_SW_2P_TX_LP | \
GEN_SW_1P_TX_LP | \
GEN_SW_0P_TX_LP)
/***************************for hikey960***********************************/
#define PHY_TMR_CFG 0x9C /* Data lanes timing configuration */
#define BTA_TO_CNT 0x8C /* Response timeout definition */
#define PHY_TMR_LPCLK_CFG 0x98 /* clock lane timing configuration */

View File

@ -9,6 +9,7 @@
* Xinliang Liu <z.liuxinliang@hisilicon.com>
* Xinliang Liu <xinliang.liu@linaro.org>
* Xinwei Kong <kong.kongxinwei@hisilicon.com>
* Da Lv <lvda3@hisilicon.com>
*/
#include <linux/clk.h>
@ -26,97 +27,10 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include "dw_dsi_reg.h"
#include "../kirin_drm_dsi.h"
#include "../dw_dsi_reg.h"
#define MAX_TX_ESC_CLK 10
#define ROUND(x, y) ((x) / (y) + \
((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
#define PHY_REF_CLK_RATE 19200000
#define PHY_REF_CLK_PERIOD_PS (1000000000 / (PHY_REF_CLK_RATE / 1000))
#define encoder_to_dsi(encoder) \
container_of(encoder, struct dw_dsi, encoder)
#define host_to_dsi(host) \
container_of(host, struct dw_dsi, host)
struct mipi_phy_params {
u32 clk_t_lpx;
u32 clk_t_hs_prepare;
u32 clk_t_hs_zero;
u32 clk_t_hs_trial;
u32 clk_t_wakeup;
u32 data_t_lpx;
u32 data_t_hs_prepare;
u32 data_t_hs_zero;
u32 data_t_hs_trial;
u32 data_t_ta_go;
u32 data_t_ta_get;
u32 data_t_wakeup;
u32 hstx_ckg_sel;
u32 pll_fbd_div5f;
u32 pll_fbd_div1f;
u32 pll_fbd_2p;
u32 pll_enbwt;
u32 pll_fbd_p;
u32 pll_fbd_s;
u32 pll_pre_div1p;
u32 pll_pre_p;
u32 pll_vco_750M;
u32 pll_lpf_rs;
u32 pll_lpf_cs;
u32 clklp2hs_time;
u32 clkhs2lp_time;
u32 lp2hs_time;
u32 hs2lp_time;
u32 clk_to_data_delay;
u32 data_to_clk_delay;
u32 lane_byte_clk_kHz;
u32 clk_division;
};
struct dsi_hw_ctx {
void __iomem *base;
struct clk *pclk;
};
struct dw_dsi {
struct drm_encoder encoder;
struct drm_bridge *bridge;
struct mipi_dsi_host host;
struct drm_display_mode cur_mode;
struct dsi_hw_ctx *ctx;
struct mipi_phy_params phy;
u32 lanes;
enum mipi_dsi_pixel_format format;
unsigned long mode_flags;
bool enable;
};
struct dsi_data {
struct dw_dsi dsi;
struct dsi_hw_ctx ctx;
};
struct dsi_phy_range {
u32 min_range_kHz;
u32 max_range_kHz;
u32 pll_vco_750M;
u32 hstx_ckg_sel;
};
static const struct dsi_phy_range dphy_range_info[] = {
{ 46875, 62500, 1, 7 },
{ 62500, 93750, 0, 7 },
{ 93750, 125000, 1, 6 },
{ 125000, 187500, 0, 6 },
{ 187500, 250000, 1, 5 },
{ 250000, 375000, 0, 5 },
{ 375000, 500000, 1, 4 },
{ 500000, 750000, 0, 4 },
{ 750000, 1000000, 1, 0 },
{ 1000000, 1500000, 0, 0 }
};
static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy)
{
@ -568,24 +482,7 @@ static void dsi_mipi_init(struct dw_dsi *dsi)
dsi->lanes, mode->clock, phy->lane_byte_clk_kHz);
}
static void dsi_encoder_disable(struct drm_encoder *encoder)
{
struct dw_dsi *dsi = encoder_to_dsi(encoder);
struct dsi_hw_ctx *ctx = dsi->ctx;
void __iomem *base = ctx->base;
if (!dsi->enable)
return;
writel(0, base + PWR_UP);
writel(0, base + LPCLK_CTRL);
writel(0, base + PHY_RSTZ);
clk_disable_unprepare(ctx->pclk);
dsi->enable = false;
}
static void dsi_encoder_enable(struct drm_encoder *encoder)
static void dsi_encoder_enable_sub(struct drm_encoder *encoder)
{
struct dw_dsi *dsi = encoder_to_dsi(encoder);
struct dsi_hw_ctx *ctx = dsi->ctx;
@ -601,8 +498,6 @@ static void dsi_encoder_enable(struct drm_encoder *encoder)
}
dsi_mipi_init(dsi);
dsi->enable = true;
}
static enum drm_mode_status dsi_encoder_phy_mode_valid(
@ -844,54 +739,13 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
return 0;
}
static int dsi_probe(struct platform_device *pdev)
{
struct dsi_data *data;
struct dw_dsi *dsi;
struct dsi_hw_ctx *ctx;
int ret;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
DRM_ERROR("failed to allocate dsi data.\n");
return -ENOMEM;
}
dsi = &data->dsi;
ctx = &data->ctx;
dsi->ctx = ctx;
ret = dsi_parse_dt(pdev, dsi);
if (ret)
return ret;
platform_set_drvdata(pdev, data);
return component_add(&pdev->dev, &dsi_ops);
}
static int dsi_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &dsi_ops);
return 0;
}
static const struct of_device_id dsi_of_match[] = {
{.compatible = "hisilicon,hi6220-dsi"},
{ }
const struct kirin_dsi_ops kirin_dsi_620 = {
.version = KIRIN620_DSI,
.parse_dt = dsi_parse_dt,
.host_init = dsi_host_init,
.encoder_enable = dsi_encoder_enable_sub,
.encoder_valid = dsi_encoder_mode_valid
};
MODULE_DEVICE_TABLE(of, dsi_of_match);
static struct platform_driver dsi_driver = {
.probe = dsi_probe,
.remove = dsi_remove,
.driver = {
.name = "dw-dsi",
.of_match_table = dsi_of_match,
},
};
module_platform_driver(dsi_driver);
MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016 Linaro Limited.
* Copyright (c) 2014-2016 Hisilicon Limited.
* Copyright (c) 2016,2019 Linaro Limited.
* Copyright (c) 2014-2016,2019 Hisilicon Limited.
*/
#ifndef __KIRIN_ADE_REG_H__

View File

@ -0,0 +1,393 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* Copyright (c) 2016 Linaro Limited.
* Copyright (c) 2014-2016 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef __KIRIN_DPE_REG_H__
#define __KIRIN_DPE_REG_H__
#define BIT_MMU_IRPT_NS BIT(28)
#define BIT_ITF0_INTS BIT(16)
#define BIT_DPP_INTS BIT(15)
#define BIT_VACTIVE0_END BIT(8)
#define BIT_VACTIVE0_START BIT(7)
#define BIT_VSYNC BIT(4)
#define BIT_LDI_UNFLOW BIT(2)
#define DFS_TIME (80)
#define DFS_TIME_MIN (50)
#define DFS_TIME_MIN_4K (10)
#define DBUF0_DEPTH (1408)
#define DBUF_WIDTH_BIT (144)
#define PERRSTDIS3 (0x088)
#define DPE_GLB0_OFFSET (0x12000)
#define DPE_DBG_OFFSET (0x11000)
#define DPE_CMDLIST_OFFSET (0x02000)
#define DPE_SMMU_OFFSET (0x08000)
#define DPE_MIF_OFFSET (0x0A000)
#define DPE_MCTRL_SYS_OFFSET (0x10000)
#define DPE_MCTRL_CTL0_OFFSET (0x10800)
#define DPE_RCH_VG0_DMA_OFFSET (0x20000)
#define DPE_RCH_VG0_SCL_OFFSET (0x20200)
#define DPE_RCH_VG0_ARSR_OFFSET (0x20300)
#define DPE_RCH_VG1_DMA_OFFSET (0x28000)
#define DPE_RCH_VG1_SCL_OFFSET (0x28200)
#define DPE_RCH_VG2_DMA_OFFSET (0x30000)
#define DPE_RCH_VG2_SCL_OFFSET (0x30200)
#define DPE_RCH_G0_DMA_OFFSET (0x38000)
#define DPE_RCH_G0_SCL_OFFSET (0x38200)
#define DPE_RCH_G1_DMA_OFFSET (0x40000)
#define DPE_RCH_G1_SCL_OFFSET (0x40200)
#define DPE_RCH_D2_DMA_OFFSET (0x50000)
#define DPE_RCH_D3_DMA_OFFSET (0x51000)
#define DPE_RCH_D0_DMA_OFFSET (0x52000)
#define DPE_RCH_D0_DFC_OFFSET (0x52100)
#define DPE_RCH_D1_DMA_OFFSET (0x53000)
#define DPE_WCH0_DMA_OFFSET (0x5A000)
#define DPE_WCH1_DMA_OFFSET (0x5C000)
#define DPE_WCH2_DMA_OFFSET (0x5E000)
#define DPE_WCH2_DFC_OFFSET (0x5E100)
#define DPE_OVL0_OFFSET (0x60000)
#define DPE_DBUF0_OFFSET (0x6D000)
#define DPE_DPP_OFFSET (0x70000)
#define DPE_DPP_DITHER_OFFSET (0x70200)
#define DPE_LDI0_OFFSET (0x7D000)
#define DPE_IFBC_OFFSET (0x7D800)
#define DPE_DSC_OFFSET (0x7DC00)
#define GLB_CPU_PDP_INTS (DPE_GLB0_OFFSET + 0x224)
#define GLB_CPU_PDP_INT_MSK (DPE_GLB0_OFFSET + 0x228)
#define GLB_CPU_SDP_INTS (DPE_GLB0_OFFSET + 0x22C)
#define GLB_CPU_SDP_INT_MSK (DPE_GLB0_OFFSET + 0x230)
#define DBG_MCTL_INTS (0x023C)
#define DBG_MCTL_INT_MSK (0x0240)
#define DBG_WCH0_INTS (0x0244)
#define DBG_WCH0_INT_MSK (0x0248)
#define DBG_WCH1_INTS (0x024C)
#define DBG_WCH1_INT_MSK (0x0250)
#define DBG_RCH0_INTS (0x0254)
#define DBG_RCH0_INT_MSK (0x0258)
#define DBG_RCH1_INTS (0x025C)
#define DBG_RCH1_INT_MSK (0x0260)
#define DBG_RCH2_INTS (0x0264)
#define DBG_RCH2_INT_MSK (0x0268)
#define DBG_RCH3_INTS (0x026C)
#define DBG_RCH3_INT_MSK (0x0270)
#define DBG_RCH4_INTS (0x0274)
#define DBG_RCH4_INT_MSK (0x0278)
#define DBG_RCH5_INTS (0x027C)
#define DBG_RCH5_INT_MSK (0x0280)
#define DBG_RCH6_INTS (0x0284)
#define DBG_RCH6_INT_MSK (0x0288)
#define DBG_RCH7_INTS (0x028C)
#define DBG_RCH7_INT_MSK (0x0290)
#define DBG_DPE_GLB_INTS (0x0294)
#define DBG_DPE_GLB_INT_MSK (0x0298)
#define AIF0_CH0_OFFSET (0x7000)
#define AIF0_CH0_ADD_OFFSET (0x7004)
#define MIF_ENABLE (0x0000)
#define MIF_MEM_CTRL (0x0004)
#define MIF_CTRL0 (0x0000)
#define MIF_CTRL1 (0x0004)
#define MIF_CTRL2 (0x0008)
#define MIF_CTRL3 (0x000C)
#define MIF_CTRL4 (0x0010)
#define MIF_CTRL5 (0x0014)
#define MIF_CTRL_OFFSET (0x0020)
#define MIF_CH0_OFFSET (DPE_MIF_OFFSET + MIF_CTRL_OFFSET * 1)
#define SMMU_SCR (0x0000)
#define SMMU_MEMCTRL (0x0004)
#define SMMU_LP_CTRL (0x0008)
#define SMMU_INTMASK_NS (0x0010)
#define SMMU_INTRAW_NS (0x0014)
#define SMMU_INTSTAT_NS (0x0018)
#define SMMU_INTCLR_NS (0x001C)
#define SMMU_SMRx_NS (0x0020)
#define DMA_OFT_X0 (0x0000)
#define DMA_OFT_Y0 (0x0004)
#define DMA_OFT_X1 (0x0008)
#define DMA_OFT_Y1 (0x000C)
#define DMA_MASK0 (0x0010)
#define DMA_MASK1 (0x0014)
#define DMA_STRETCH_SIZE_VRT (0x0018)
#define DMA_CTRL (0x001C)
#define DMA_TILE_SCRAM (0x0020)
#define DMA_PULSE (0x0028)
#define DMA_CORE_GT (0x002C)
#define DMA_DATA_ADDR0 (0x0060)
#define DMA_STRIDE0 (0x0064)
#define DMA_STRETCH_STRIDE0 (0x0068)
#define DMA_DATA_NUM0 (0x006C)
#define DMA_CH_CTL (0x00D4)
#define DMA_CH_REG_DEFAULT (0x0A00)
#define DMA_ALIGN_BYTES (128 / BITS_PER_BYTE)
#define DMA_ADDR_ALIGN (128 / BITS_PER_BYTE)
#define DMA_STRIDE_ALIGN (128 / BITS_PER_BYTE)
#define DFC_DISP_SIZE (0x0000)
#define DFC_PIX_IN_NUM (0x0004)
#define DFC_GLB_ALPHA (0x0008)
#define DFC_DISP_FMT (0x000C)
#define DFC_CLIP_CTL_HRZ (0x0010)
#define DFC_CLIP_CTL_VRZ (0x0014)
#define DFC_CTL_CLIP_EN (0x0018)
#define DFC_ICG_MODULE (0x001C)
#define DFC_DITHER_ENABLE (0x0020)
#define DFC_PADDING_CTL (0x0024)
#define MCTL_CTL_EN (0x0000)
#define MCTL_CTL_MUTEX (0x0004)
#define MCTL_CTL_MUTEX_STATUS (0x0008)
#define MCTL_CTL_MUTEX_ITF (0x000C)
#define MCTL_CTL_MUTEX_DBUF (0x0010)
#define MCTL_CTL_MUTEX_SCF (0x0014)
#define MCTL_CTL_MUTEX_OV (0x0018)
#define MCTL_CTL_MUTEX_WCH0 (0x0020)
#define MCTL_CTL_MUTEX_RCH0 (0x0030)
#define MCTL_CTL_TOP (0x0050)
#define MCTL_CTL_DBG (0x00E0)
#define MCTL_RCH0_FLUSH_EN (0x0100)
#define MCTL_OV0_FLUSH_EN (0x0128)
#define MCTL_RCH0_OV_OEN (0x0160)
#define MCTL_RCH_OV0_SEL (0x0180)
#define OVL_SIZE (0x0000)
#define OVL_BG_COLOR (0x0004)
#define OVL_DST_STARTPOS (0x0008)
#define OVL_DST_ENDPOS (0x000C)
#define OVL_GCFG (0x0010)
#define OVL_LAYER0_POS (0x0014)
#define OVL_LAYER0_SIZE (0x0018)
#define OVL_LAYER0_ALPHA (0x0030)
#define OVL_LAYER0_CFG (0x0034)
#define OVL6_REG_DEFAULT (0x01A8)
#define DBUF_FRM_SIZE (0x0000)
#define DBUF_FRM_HSIZE (0x0004)
#define DBUF_SRAM_VALID_NUM (0x0008)
#define DBUF_WBE_EN (0x000C)
#define DBUF_THD_FILL_LEV0 (0x0010)
#define DBUF_DFS_FILL_LEV1 (0x0014)
#define DBUF_THD_RQOS (0x0018)
#define DBUF_THD_WQOS (0x001C)
#define DBUF_THD_CG (0x0020)
#define DBUF_THD_OTHER (0x0024)
#define DBUF_ONLINE_FILL_LEVEL (0x003C)
#define DBUF_WB_FILL_LEVEL (0x0040)
#define DBUF_DFS_STATUS (0x0044)
#define DBUF_THD_FLUX_REQ_BEF (0x0048)
#define DBUF_DFS_LP_CTRL (0x004C)
#define DBUF_RD_SHADOW_SEL (0x0050)
#define DBUF_MEM_CTRL (0x0054)
#define DBUF_THD_FLUX_REQ_AFT (0x0064)
#define DBUF_THD_DFS_OK (0x0068)
#define DBUF_FLUX_REQ_CTRL (0x006C)
#define DBUF_REG_DEFAULT (0x00A4)
#define DPP_IMG_SIZE_BEF_SR (0x000C)
#define DPP_IMG_SIZE_AFT_SR (0x0010)
#define DPP_INTS (0x0040)
#define DPP_INT_MSK (0x0044)
#define SCF_COEF_MEM_CTRL (0x0018)
#define IFBC_MEM_CTRL (0x001C)
#define DITHER_MEM_CTRL (0x002C)
#define DSC_MEM_CTRL (0x0084)
#define ARSR2P_LB_MEM_CTRL (0x0084)
#define SCF_LB_MEM_CTRL (0x0090)
#define ROT_MEM_CTRL (0x0538)
#define VPP_MEM_CTRL (0x0704)
#define CMD_MEM_CTRL (0x073C)
#define DMA_BUF_MEM_CTRL (0x0854)
#define AFBCD_MEM_CTRL (0x093C)
#define AFBCE_MEM_CTRL (0x0924)
#define LDI_DPI0_HRZ_CTRL0 (0x0000)
#define LDI_DPI0_HRZ_CTRL1 (0x0004)
#define LDI_DPI0_HRZ_CTRL2 (0x0008)
#define LDI_VRT_CTRL0 (0x000C)
#define LDI_VRT_CTRL1 (0x0010)
#define LDI_VRT_CTRL2 (0x0014)
#define LDI_PLR_CTRL (0x0018)
#define LDI_CTRL (0x0024)
#define LDI_WORK_MODE (0x0028)
#define LDI_DSI_CMD_MOD_CTRL (0x0030)
#define LDI_VINACT_MSK_LEN (0x0050)
#define LDI_CMD_EVENT_SEL (0x0060)
#define LDI_MEM_CTRL (0x0100)
#define LDI_PXL0_DIV2_GT_EN (0x0210)
#define LDI_PXL0_DIV4_GT_EN (0x0214)
#define LDI_PXL0_GT_EN (0x0218)
#define LDI_PXL0_DSI_GT_EN (0x021C)
#define LDI_PXL0_DIVXCFG (0x0220)
#define LDI_VESA_CLK_SEL (0x0228)
#define LDI_CPU_ITF_INTS (0x0248)
#define LDI_CPU_ITF_INT_MSK (0x024C)
#define MIPIDSI_VERSION_OFFSET (0x0000)
#define MIPIDSI_PWR_UP_OFFSET (0x0004)
#define MIPIDSI_CLKMGR_CFG_OFFSET (0x0008)
#define MIPIDSI_DPI_VCID_OFFSET (0x000c)
#define MIPIDSI_DPI_COLOR_CODING_OFFSET (0x0010)
#define MIPIDSI_DPI_CFG_POL_OFFSET (0x0014)
#define MIPIDSI_DPI_LP_CMD_TIM_OFFSET (0x0018)
#define MIPIDSI_PCKHDL_CFG_OFFSET (0x002c)
#define MIPIDSI_GEN_VCID_OFFSET (0x0030)
#define MIPIDSI_MODE_CFG_OFFSET (0x0034)
#define MIPIDSI_VID_MODE_CFG_OFFSET (0x0038)
#define MIPIDSI_VID_PKT_SIZE_OFFSET (0x003c)
#define MIPIDSI_VID_NUM_CHUNKS_OFFSET (0x0040)
#define MIPIDSI_VID_NULL_SIZE_OFFSET (0x0044)
#define MIPIDSI_VID_HSA_TIME_OFFSET (0x0048)
#define MIPIDSI_VID_HBP_TIME_OFFSET (0x004c)
#define MIPIDSI_VID_HLINE_TIME_OFFSET (0x0050)
#define MIPIDSI_VID_VSA_LINES_OFFSET (0x0054)
#define MIPIDSI_VID_VBP_LINES_OFFSET (0x0058)
#define MIPIDSI_VID_VFP_LINES_OFFSET (0x005c)
#define MIPIDSI_VID_VACTIVE_LINES_OFFSET (0x0060)
#define MIPIDSI_EDPI_CMD_SIZE_OFFSET (0x0064)
#define MIPIDSI_CMD_MODE_CFG_OFFSET (0x0068)
#define MIPIDSI_GEN_HDR_OFFSET (0x006c)
#define MIPIDSI_GEN_PLD_DATA_OFFSET (0x0070)
#define MIPIDSI_CMD_PKT_STATUS_OFFSET (0x0074)
#define MIPIDSI_TO_CNT_CFG_OFFSET (0x0078)
#define MIPIDSI_BTA_TO_CNT_OFFSET (0x008C)
#define MIPIDSI_SDF_3D_OFFSET (0x0090)
#define MIPIDSI_LPCLK_CTRL_OFFSET (0x0094)
#define MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET (0x0098)
#define MIPIDSI_PHY_TMR_CFG_OFFSET (0x009c)
#define MIPIDSI_PHY_RSTZ_OFFSET (0x00a0)
#define MIPIDSI_PHY_IF_CFG_OFFSET (0x00a4)
#define MIPIDSI_PHY_ULPS_CTRL_OFFSET (0x00a8)
#define MIPIDSI_PHY_TX_TRIGGERS_OFFSET (0x00ac)
#define MIPIDSI_PHY_STATUS_OFFSET (0x00b0)
#define MIPIDSI_PHY_TST_CTRL0_OFFSET (0x00b4)
#define MIPIDSI_PHY_TST_CTRL1_OFFSET (0x00b8)
#define MIPIDSI_PHY_TMR_RD_CFG_OFFSET (0x00f4)
enum XRES_DIV {
XRES_DIV_1 = 1,
XRES_DIV_2,
};
enum YRES_DIV {
YRES_DIV_1 = 1,
YRES_DIV_2,
};
enum PXL0_DIVCFG {
PXL0_DIVCFG_0 = 0,
PXL0_DIVCFG_1,
};
enum PXL0_DIV2_GT_EN {
PXL0_DIV2_GT_EN_CLOSE = 0,
PXL0_DIV2_GT_EN_OPEN,
};
enum PXL0_DIV4_GT_EN {
PXL0_DIV4_GT_EN_CLOSE = 0,
PXL0_DIV4_GT_EN_OPEN,
};
enum PXL0_DSI_GT_EN {
PXL0_DSI_GT_EN_0 = 0,
PXL0_DSI_GT_EN_1,
};
enum lcd_format {
LCD_RGB888 = 0,
LCD_RGB101010,
LCD_RGB565,
};
enum lcd_rgb_order {
LCD_RGB = 0,
LCD_BGR,
};
enum dpe_dfc_format {
DFC_PIXEL_FORMAT_RGB_565 = 0,
DFC_PIXEL_FORMAT_XRGB_4444,
DFC_PIXEL_FORMAT_ARGB_4444,
DFC_PIXEL_FORMAT_XRGB_5551,
DFC_PIXEL_FORMAT_ARGB_5551,
DFC_PIXEL_FORMAT_XRGB_8888,
DFC_PIXEL_FORMAT_ARGB_8888,
DFC_PIXEL_FORMAT_BGR_565,
DFC_PIXEL_FORMAT_XBGR_4444,
DFC_PIXEL_FORMAT_ABGR_4444,
DFC_PIXEL_FORMAT_XBGR_5551,
DFC_PIXEL_FORMAT_ABGR_5551,
DFC_PIXEL_FORMAT_XBGR_8888,
DFC_PIXEL_FORMAT_ABGR_8888,
DFC_PIXEL_FORMAT_YUV444,
DFC_PIXEL_FORMAT_YVU444,
DFC_PIXEL_FORMAT_YUYV422,
DFC_PIXEL_FORMAT_YVYU422,
DFC_PIXEL_FORMAT_VYUY422,
DFC_PIXEL_FORMAT_UYVY422,
};
enum dpe_dma_format {
DMA_PIXEL_FORMAT_RGB_565 = 0,
DMA_PIXEL_FORMAT_ARGB_4444,
DMA_PIXEL_FORMAT_XRGB_4444,
DMA_PIXEL_FORMAT_ARGB_5551,
DMA_PIXEL_FORMAT_XRGB_5551,
DMA_PIXEL_FORMAT_ARGB_8888,
DMA_PIXEL_FORMAT_XRGB_8888,
DMA_PIXEL_FORMAT_RESERVED0,
DMA_PIXEL_FORMAT_YUYV_422_Pkg,
DMA_PIXEL_FORMAT_YUV_420_SP_HP,
DMA_PIXEL_FORMAT_YUV_420_P_HP,
DMA_PIXEL_FORMAT_YUV_422_SP_HP,
DMA_PIXEL_FORMAT_YUV_422_P_HP,
DMA_PIXEL_FORMAT_AYUV_4444,
};
enum dpe_fb_format {
DPE_RGB_565 = 0,
DPE_RGBX_4444,
DPE_RGBA_4444,
DPE_RGBX_5551,
DPE_RGBA_5551,
DPE_RGBX_8888,
DPE_RGBA_8888,
DPE_BGR_565,
DPE_BGRX_4444,
DPE_BGRA_4444,
DPE_BGRX_5551,
DPE_BGRA_5551,
DPE_BGRX_8888,
DPE_BGRA_8888,
DPE_YUV_422_I,
/* YUV Semi-planar */
DPE_YCbCr_422_SP,
DPE_YCrCb_422_SP,
DPE_YCbCr_420_SP,
DPE_YCrCb_420_SP,
/* YUV Planar */
DPE_YCbCr_422_P,
DPE_YCrCb_422_P,
DPE_YCbCr_420_P,
DPE_YCrCb_420_P,
/* YUV Package */
DPE_YUYV_422_Pkg,
DPE_UYVY_422_Pkg,
DPE_YVYU_422_Pkg,
DPE_VYUY_422_Pkg,
};
#endif

View File

@ -293,9 +293,11 @@ static int kirin_drm_platform_remove(struct platform_device *pdev)
}
static const struct of_device_id kirin_drm_dt_ids[] = {
#ifdef CONFIG_DRM_HISI_KIRIN620
{ .compatible = "hisilicon,hi6220-ade",
.data = &ade_driver_data,
},
#endif
{ /* end node */ },
};
MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids);

View File

@ -52,6 +52,8 @@ struct kirin_drm_data {
void (*cleanup_hw_ctx)(void *hw_ctx);
};
#ifdef CONFIG_DRM_HISI_KIRIN620
extern struct kirin_drm_data ade_driver_data;
#endif
#endif /* __KIRIN_DRM_DRV_H__ */

View File

@ -0,0 +1,424 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* DesignWare MIPI DSI Host Controller v1.02 driver
*
* Copyright (c) 2016 Linaro Limited.
* Copyright (c) 2014-2016 Hisilicon Limited.
*
* Author:
* <shizongxuan@huawei.com>
* <zhangxiubin@huawei.com>
* <lvda3@hisilicon.com>
*/
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_encoder_slave.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_sysfs.h>
#include "kirin_drm_dsi.h"
#include "dw_dsi_reg.h"
static struct kirin_dsi_ops *hisi_dsi_ops;
void dsi_set_output_client(struct drm_device *dev)
{
enum dsi_output_client client;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_connector_list_iter conn_iter;
struct dw_dsi *dsi;
mutex_lock(&dev->mode_config.mutex);
/* find dsi encoder */
drm_for_each_encoder(encoder, dev)
if (encoder->encoder_type == DRM_MODE_ENCODER_DSI)
break;
dsi = encoder_to_dsi(encoder);
/* find HDMI connector */
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter)
if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
break;
drm_connector_list_iter_end(&conn_iter);
/*
* set the proper dsi output client
*/
client = connector->status == connector_status_connected ? OUT_HDMI :
OUT_PANEL;
if (client != dsi->cur_client) {
/*
* set the switch ic to select the HDMI or MIPI_DSI
*/
if (hisi_dsi_ops->version == KIRIN960_DSI)
gpiod_set_value_cansleep(dsi->gpio_mux, client);
dsi->cur_client = client;
/* let the userspace know panel connector status has changed */
drm_sysfs_hotplug_event(dev);
DRM_INFO("client change to %s\n",
client == OUT_HDMI ? "HDMI" : "panel");
}
mutex_unlock(&dev->mode_config.mutex);
}
EXPORT_SYMBOL_GPL(dsi_set_output_client);
/************************for the panel attach to dsi*****************************/
static int dsi_connector_get_modes(struct drm_connector *connector)
{
struct dw_dsi *dsi = connector_to_dsi(connector);
return drm_panel_get_modes(dsi->panel, connector);
}
static enum drm_mode_status
dsi_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
enum drm_mode_status mode_status = MODE_OK;
return mode_status;
}
static struct drm_encoder *
dsi_connector_best_encoder(struct drm_connector *connector)
{
struct dw_dsi *dsi = connector_to_dsi(connector);
return &dsi->encoder;
}
static struct drm_connector_helper_funcs dsi_connector_helper_funcs = {
.get_modes = dsi_connector_get_modes,
.mode_valid = dsi_connector_mode_valid,
.best_encoder = dsi_connector_best_encoder,
};
static enum drm_connector_status
dsi_connector_detect(struct drm_connector *connector, bool force)
{
struct dw_dsi *dsi = connector_to_dsi(connector);
enum drm_connector_status status;
status = dsi->cur_client == OUT_PANEL ? connector_status_connected :
connector_status_disconnected;
return status;
}
static void dsi_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
static struct drm_connector_funcs dsi_atomic_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = dsi_connector_detect,
.destroy = dsi_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static int dsi_connector_init(struct drm_device *dev, struct dw_dsi *dsi)
{
struct drm_encoder *encoder = &dsi->encoder;
struct drm_connector *connector = &dsi->connector;
int ret;
connector->polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_helper_add(connector, &dsi_connector_helper_funcs);
ret = drm_connector_init(dev, &dsi->connector,
&dsi_atomic_connector_funcs,
DRM_MODE_CONNECTOR_DSI);
if (ret)
return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
DRM_INFO("connector init\n");
return 0;
}
/****************************************************************************/
/***************************for the encoder_helper_funcs****************************************/
static const struct drm_encoder_funcs dw_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
static int dsi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
/* do nothing */
return 0;
}
static enum drm_mode_status
dsi_encoder_mode_valid(struct drm_encoder *encoder,
const struct drm_display_mode *mode)
{
return hisi_dsi_ops->encoder_valid(encoder, mode);
}
static void dsi_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
{
struct dw_dsi *dsi = encoder_to_dsi(encoder);
drm_mode_copy(&dsi->cur_mode, adj_mode);
}
static void dsi_encoder_enable(struct drm_encoder *encoder)
{
struct dw_dsi *dsi = encoder_to_dsi(encoder);
if (dsi->enable)
return;
hisi_dsi_ops->encoder_enable(encoder);
if (hisi_dsi_ops->version == KIRIN960_DSI) {
/* turn on panel */
if (dsi->panel && drm_panel_prepare(dsi->panel))
DRM_ERROR("failed to prepare panel\n");
/*dw_dsi_set_mode(dsi, DSI_VIDEO_MODE);*/
/* turn on panel's back light */
if (dsi->panel && drm_panel_enable(dsi->panel))
DRM_ERROR("failed to enable panel\n");
}
dsi->enable = true;
}
static void dw_dsi_set_mode(struct dw_dsi *dsi, enum dsi_work_mode mode)
{
struct dsi_hw_ctx *ctx = dsi->ctx;
void __iomem *base = ctx->base;
writel(RESET, base + PWR_UP);
writel(mode, base + MODE_CFG);
writel(POWERUP, base + PWR_UP);
}
static void dsi_encoder_disable(struct drm_encoder *encoder)
{
struct dw_dsi *dsi = encoder_to_dsi(encoder);
struct dsi_hw_ctx *ctx = dsi->ctx;
if (!dsi->enable)
return;
dw_dsi_set_mode(dsi, DSI_COMMAND_MODE);
if (hisi_dsi_ops->version == KIRIN960_DSI) {
/* turn off panel's backlight */
if (dsi->panel && drm_panel_disable(dsi->panel))
DRM_ERROR("failed to disable panel\n");
/* turn off panel */
if (dsi->panel && drm_panel_unprepare(dsi->panel))
DRM_ERROR("failed to unprepare panel\n");
clk_disable_unprepare(ctx->dss_dphy0_ref_clk);
clk_disable_unprepare(ctx->dss_dphy0_cfg_clk);
clk_disable_unprepare(ctx->dss_pclk_dsi0_clk);
}
dsi->enable = false;
}
static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = {
.atomic_check = dsi_encoder_atomic_check,
.mode_valid = dsi_encoder_mode_valid,
.mode_set = dsi_encoder_mode_set,
.enable = dsi_encoder_enable,
.disable = dsi_encoder_disable
};
/****************************************************************************/
static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
{
struct drm_encoder *encoder = &dsi->encoder;
struct drm_bridge *bridge = dsi->bridge;
int ret;
/* associate the bridge to dsi encoder */
ret = drm_bridge_attach(encoder, bridge, NULL, 0);
if (ret) {
DRM_ERROR("failed to attach external bridge\n");
return ret;
}
return 0;
}
static int dw_drm_encoder_init(struct device *dev, struct drm_device *drm_dev,
struct drm_encoder *encoder)
{
int ret;
u32 crtc_mask = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
if (!crtc_mask) {
DRM_ERROR("failed to find crtc mask\n");
return -EINVAL;
}
encoder->possible_crtcs = crtc_mask;
ret = drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs,
DRM_MODE_ENCODER_DSI, NULL);
if (ret) {
DRM_ERROR("failed to init dsi encoder\n");
return ret;
}
drm_encoder_helper_add(encoder, &dw_encoder_helper_funcs);
return 0;
}
static int dsi_bind(struct device *dev, struct device *master, void *data)
{
struct dsi_data *ddata = dev_get_drvdata(dev);
struct dw_dsi *dsi = &ddata->dsi;
struct drm_device *drm_dev = data;
int ret;
DRM_INFO("+.\n");
ret = dw_drm_encoder_init(dev, drm_dev, &dsi->encoder);
if (ret)
return ret;
if (dsi->bridge) {
ret = dsi_bridge_init(drm_dev, dsi);
if (ret)
return ret;
}
if (hisi_dsi_ops->version == KIRIN960_DSI) {
if (dsi->panel) {
ret = dsi_connector_init(drm_dev, dsi);
if (ret)
return ret;
}
} else if (hisi_dsi_ops->version == KIRIN620_DSI) {
/*the panel for the kirin620 drm have not support*/
}
DRM_INFO("-.\n");
return 0;
}
static void dsi_unbind(struct device *dev, struct device *master, void *data)
{
/* do nothing */
}
static const struct component_ops dsi_ops = {
.bind = dsi_bind,
.unbind = dsi_unbind,
};
static int dsi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dsi_data *data;
struct dw_dsi *dsi;
struct dsi_hw_ctx *ctx;
int ret;
hisi_dsi_ops = (struct kirin_dsi_ops *)of_device_get_match_data(dev);
DRM_INFO("+.\n");
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) {
DRM_ERROR("failed to allocate dsi data.\n");
return -ENOMEM;
}
dsi = &data->dsi;
ctx = &data->ctx;
dsi->ctx = ctx;
if (hisi_dsi_ops == NULL)
DRM_ERROR("hisi_dsi_ops is not bind\n");
ret = hisi_dsi_ops->host_init(dev, dsi);
if (ret)
return ret;
ret = hisi_dsi_ops->parse_dt(pdev, dsi);
if (ret)
goto err_host_unregister;
platform_set_drvdata(pdev, data);
ret = component_add(dev, &dsi_ops);
if (ret)
goto err_host_unregister;
DRM_INFO("-.\n");
return 0;
err_host_unregister:
mipi_dsi_host_unregister(&dsi->host);
return ret;
}
static int dsi_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &dsi_ops);
return 0;
}
static const struct of_device_id dsi_of_match[] = {
#ifdef CONFIG_DRM_HISI_KIRIN960
{
.compatible = "hisilicon,hi3660-dsi",
.data = &kirin_dsi_960,
},
#endif
#ifdef CONFIG_DRM_HISI_KIRIN620
{
.compatible = "hisilicon,hi6220-dsi",
.data = &kirin_dsi_620,
},
#endif
{ /* end node */ }
};
MODULE_DEVICE_TABLE(of, dsi_of_match);
static struct platform_driver dsi_driver = {
.probe = dsi_probe,
.remove = dsi_remove,
.driver = {
.name = "dw-dsi",
.of_match_table = dsi_of_match,
},
};
module_platform_driver(dsi_driver);
MODULE_DESCRIPTION("DesignWare MIPI DSI Host Controller v1.02 driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,253 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __KIRIN_DRM_DSI_H__
#define __KIRIN_DRM_DSI_H__
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/of_graph.h>
#include <linux/iopoll.h>
#include <video/mipi_display.h>
#include <linux/gpio/consumer.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <drm/drm_of.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_encoder_slave.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_panel.h>
#define ROUND(x, y) ((x) / (y) + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
#define PHY_REF_CLK_RATE 19200000
#define PHY_REF_CLK_PERIOD_PS (1000000000 / (PHY_REF_CLK_RATE / 1000))
#define encoder_to_dsi(encoder) container_of(encoder, struct dw_dsi, encoder)
#define host_to_dsi(host) container_of(host, struct dw_dsi, host)
#define connector_to_dsi(connector) \
container_of(connector, struct dw_dsi, connector)
enum dsi_output_client { OUT_HDMI = 0, OUT_PANEL, OUT_MAX };
struct dsi_phy_range {
u32 min_range_kHz;
u32 max_range_kHz;
u32 pll_vco_750M;
u32 hstx_ckg_sel;
};
static const struct dsi_phy_range dphy_range_info[] = {
{ 46875, 62500, 1, 7 },
{ 62500, 93750, 0, 7 },
{ 93750, 125000, 1, 6 },
{ 125000, 187500, 0, 6 },
{ 187500, 250000, 1, 5 },
{ 250000, 375000, 0, 5 },
{ 375000, 500000, 1, 4 },
{ 500000, 750000, 0, 4 },
{ 750000, 1000000, 1, 0 },
{ 1000000, 1500000, 0, 0 }
};
struct dsi_hw_ctx {
void __iomem *base;
char __iomem *peri_crg_base;
struct clk *pclk;
struct clk *dss_dphy0_ref_clk;
struct clk *dss_dphy1_ref_clk;
struct clk *dss_dphy0_cfg_clk;
struct clk *dss_dphy1_cfg_clk;
struct clk *dss_pclk_dsi0_clk;
struct clk *dss_pclk_dsi1_clk;
};
struct mipi_panel_info {
u8 dsi_version;
u8 vc;
u8 lane_nums;
u8 lane_nums_select_support;
u8 color_mode;
u32 dsi_bit_clk; /* clock lane(p/n) */
u32 burst_mode;
u32 max_tx_esc_clk;
u8 non_continue_en;
u32 dsi_bit_clk_val1;
u32 dsi_bit_clk_val2;
u32 dsi_bit_clk_val3;
u32 dsi_bit_clk_val4;
u32 dsi_bit_clk_val5;
u32 dsi_bit_clk_upt;
/*uint32_t dsi_pclk_rate;*/
u32 hs_wr_to_time;
/* dphy config parameter adjust*/
u32 clk_post_adjust;
u32 clk_pre_adjust;
u32 clk_pre_delay_adjust;
u32 clk_t_hs_exit_adjust;
u32 clk_t_hs_trial_adjust;
u32 clk_t_hs_prepare_adjust;
int clk_t_lpx_adjust;
u32 clk_t_hs_zero_adjust;
u32 data_post_delay_adjust;
int data_t_lpx_adjust;
u32 data_t_hs_prepare_adjust;
u32 data_t_hs_zero_adjust;
u32 data_t_hs_trial_adjust;
u32 rg_vrefsel_vcm_adjust;
/*only for Chicago<3660> use*/
u32 rg_vrefsel_vcm_clk_adjust;
u32 rg_vrefsel_vcm_data_adjust;
};
struct mipi_phy_params {
u32 clk_t_lpx;
u32 clk_t_hs_prepare;
u32 clk_t_hs_zero;
u32 clk_t_hs_trial;
u32 clk_t_wakeup;
u32 data_t_lpx;
u32 data_t_hs_prepare;
u32 data_t_hs_zero;
u32 data_t_hs_trial;
u32 data_t_ta_go;
u32 data_t_ta_get;
u32 data_t_wakeup;
u32 hstx_ckg_sel;
u32 pll_fbd_div5f;
u32 pll_fbd_div1f;
u32 pll_fbd_2p;
u32 pll_enbwt;
u32 pll_fbd_p;
u32 pll_fbd_s;
u32 pll_pre_div1p;
u32 pll_pre_p;
u32 pll_vco_750M;
u32 pll_lpf_rs;
u32 pll_lpf_cs;
u32 clk_division;
/********for hikey620************/
u32 clklp2hs_time;
u32 clkhs2lp_time;
u32 lp2hs_time;
u32 hs2lp_time;
u32 clk_to_data_delay;
u32 data_to_clk_delay;
u32 lane_byte_clk_kHz;
/*****************/
/****for hikey960*****/
u64 lane_byte_clk;
u32 clk_lane_lp2hs_time;
u32 clk_lane_hs2lp_time;
u32 data_lane_lp2hs_time;
u32 data_lane_hs2lp_time;
u32 clk2data_delay;
u32 data2clk_delay;
u32 clk_pre_delay;
u32 clk_post_delay;
u32 data_pre_delay;
u32 data_post_delay;
u32 phy_stop_wait_time;
u32 rg_vrefsel_vcm;
u32 rg_pll_enswc;
u32 rg_pll_chp;
u32 pll_register_override; /*0x1E[0]*/
u32 pll_power_down; /*0x1E[1]*/
u32 rg_band_sel; /*0x1E[2]*/
u32 rg_phase_gen_en; /*0x1E[3]*/
u32 reload_sel; /*0x1E[4]*/
u32 rg_pll_cp_p; /*0x1E[7:5]*/
u32 rg_pll_refsel; /*0x16[1:0]*/
u32 rg_pll_cp; /*0x16[7:5]*/
u32 load_command;
/*********/
};
struct ldi_panel_info {
u32 h_back_porch;
u32 h_front_porch;
u32 h_pulse_width;
/*
* note: vbp > 8 if used overlay compose,
* also lcd vbp > 8 in lcd power on sequence
*/
u32 v_back_porch;
u32 v_front_porch;
u32 v_pulse_width;
u8 hsync_plr;
u8 vsync_plr;
u8 pixelclk_plr;
u8 data_en_plr;
/* for cabc */
u8 dpi0_overlap_size;
u8 dpi1_overlap_size;
};
struct dw_dsi_client {
u32 lanes;
u32 phy_clock; /* in kHz */
enum mipi_dsi_pixel_format format;
unsigned long mode_flags;
};
struct dw_dsi {
struct drm_encoder encoder;
struct drm_bridge *bridge;
struct drm_panel *panel;
struct mipi_dsi_host host;
struct drm_connector connector; /* connector for panel */
struct drm_display_mode cur_mode;
struct dsi_hw_ctx *ctx;
struct mipi_phy_params phy;
struct mipi_panel_info mipi;
struct ldi_panel_info ldi;
u32 lanes;
enum mipi_dsi_pixel_format format;
unsigned long mode_flags;
struct gpio_desc *gpio_mux;
struct dw_dsi_client client[OUT_MAX];
enum dsi_output_client cur_client;
bool enable;
};
struct dsi_data {
struct dw_dsi dsi;
struct dsi_hw_ctx ctx;
};
enum kirin_dsi_version {
KIRIN620_DSI = 0,
KIRIN960_DSI
};
/* display controller init/cleanup ops */
struct kirin_dsi_ops {
enum kirin_dsi_version version;
int (*parse_dt)(struct platform_device *pdev, struct dw_dsi *dsi);
int (*host_init)(struct device *dev, struct dw_dsi *dsi);
void (*encoder_enable)(struct drm_encoder *encoder);
enum drm_mode_status (*encoder_valid)(
struct drm_encoder *encoder,
const struct drm_display_mode *mode);
};
#ifdef CONFIG_DRM_HISI_KIRIN960
extern const struct kirin_dsi_ops kirin_dsi_960;
#endif
#ifdef CONFIG_DRM_HISI_KIRIN620
extern const struct kirin_dsi_ops kirin_dsi_620;
#endif
#endif /* __KIRIN_DRM_DSI_H__ */