mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 23:51:37 +00:00
Mediatek DRM next for Linux 5.5
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJdo9UAAAoJEOHKc6PJWU4kpBAP/3YaQv7HwNtHs8lIQ6yTiRJy fnO6JlrDa4GsSOL4dPTCkvVWVT5hh6jR7as1H2NoGcmz8+5/wePdZlT0FgSR8o+t VP+JIjpmmTwGLtuLjR1pbnGfX040NJqwRUK7Sj7lSkqWA1MUDJ3IwbKSixqzKvHV Th/T1rdPXaji8nhkv/Ff6KIJ66Fu5pwtJTBCOxSN4AItfGbDifaGL/pbEbh9LjOT 59UweYex23qSCBip1McW11hMfNk2zwOe+hUERgW1aWfXXx1q/WSAoyvvrYR88MF8 hIQ8Rr0W8/24usXbsch9Of5e5uIV4degqW6ty7cLngNOqI/Nm3kPaOT42TxzwAg+ rqAviDpG+CMFG5yl9EmJc2wbxEjy/IwzUoeY1guGnieZNrywqKH4OjC6BmMx99f8 lbjg6jjE9fMS6ONUqXb7ITtbshFjVpe0C7gQ0FqgRpD9Q4UE5Y4H+QKCQJBHlu/D +4s6n5BqPmwQBnCueqvXyJgPw0s/kI5us24+kf29cy0QzIoFwwBrayita+VRxKfs V94G1PuyUCMhVlWIDAPBFHxEtFsZW7A+0CP03bnyxb2MlmAjAHpl9A1saxqR9GKe 6Hc41GmBpC0xDDY2SQPPx2h89T3VVJNhQQB3GaJiphjpXt0ayAwm/4LM05W+hmju 5X0aoVQmp+ddSiQ+5DGR =zkCu -----END PGP SIGNATURE----- Merge tag 'mediatek-drm-next-5.5' of https://github.com/ckhu-mediatek/linux.git-tags into drm-next Mediatek DRM next for Linux 5.5 This include mipi_tx, dsi, and partial crtc for MT8183 SoC. Signed-off-by: Dave Airlie <airlied@redhat.com> From: CK Hu <ck.hu@mediatek.com> Link: https://patchwork.freedesktop.org/patch/msgid/1571103548.4416.6.camel@mtksdaap41
This commit is contained in:
commit
400e91347e
@ -27,19 +27,22 @@ Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt.
|
||||
|
||||
Required properties (all function blocks):
|
||||
- compatible: "mediatek,<chip>-disp-<function>", one of
|
||||
"mediatek,<chip>-disp-ovl" - overlay (4 layers, blending, csc)
|
||||
"mediatek,<chip>-disp-rdma" - read DMA / line buffer
|
||||
"mediatek,<chip>-disp-wdma" - write DMA
|
||||
"mediatek,<chip>-disp-color" - color processor
|
||||
"mediatek,<chip>-disp-aal" - adaptive ambient light controller
|
||||
"mediatek,<chip>-disp-gamma" - gamma correction
|
||||
"mediatek,<chip>-disp-merge" - merge streams from two RDMA sources
|
||||
"mediatek,<chip>-disp-split" - split stream to two encoders
|
||||
"mediatek,<chip>-disp-ufoe" - data compression engine
|
||||
"mediatek,<chip>-dsi" - DSI controller, see mediatek,dsi.txt
|
||||
"mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt
|
||||
"mediatek,<chip>-disp-mutex" - display mutex
|
||||
"mediatek,<chip>-disp-od" - overdrive
|
||||
"mediatek,<chip>-disp-ovl" - overlay (4 layers, blending, csc)
|
||||
"mediatek,<chip>-disp-ovl-2l" - overlay (2 layers, blending, csc)
|
||||
"mediatek,<chip>-disp-rdma" - read DMA / line buffer
|
||||
"mediatek,<chip>-disp-wdma" - write DMA
|
||||
"mediatek,<chip>-disp-ccorr" - color correction
|
||||
"mediatek,<chip>-disp-color" - color processor
|
||||
"mediatek,<chip>-disp-dither" - dither
|
||||
"mediatek,<chip>-disp-aal" - adaptive ambient light controller
|
||||
"mediatek,<chip>-disp-gamma" - gamma correction
|
||||
"mediatek,<chip>-disp-merge" - merge streams from two RDMA sources
|
||||
"mediatek,<chip>-disp-split" - split stream to two encoders
|
||||
"mediatek,<chip>-disp-ufoe" - data compression engine
|
||||
"mediatek,<chip>-dsi" - DSI controller, see mediatek,dsi.txt
|
||||
"mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt
|
||||
"mediatek,<chip>-disp-mutex" - display mutex
|
||||
"mediatek,<chip>-disp-od" - overdrive
|
||||
the supported chips are mt2701, mt2712 and mt8173.
|
||||
- reg: Physical base address and length of the function block register space
|
||||
- interrupts: The interrupt signal from the function block (required, except for
|
||||
@ -49,6 +52,7 @@ Required properties (all function blocks):
|
||||
For most function blocks this is just a single clock input. Only the DSI and
|
||||
DPI controller nodes have multiple clock inputs. These are documented in
|
||||
mediatek,dsi.txt and mediatek,dpi.txt, respectively.
|
||||
An exception is that the mt8183 mutex is always free running with no clocks property.
|
||||
|
||||
Required properties (DMA function blocks):
|
||||
- compatible: Should be one of
|
||||
|
@ -7,7 +7,7 @@ channel output.
|
||||
|
||||
Required properties:
|
||||
- compatible: "mediatek,<chip>-dsi"
|
||||
the supported chips are mt2701 and mt8173.
|
||||
the supported chips are mt2701, mt8173 and mt8183.
|
||||
- reg: Physical base address and length of the controller's registers
|
||||
- interrupts: The interrupt signal from the function block.
|
||||
- clocks: device clocks
|
||||
@ -26,7 +26,7 @@ The MIPI TX configuration module controls the MIPI D-PHY.
|
||||
|
||||
Required properties:
|
||||
- compatible: "mediatek,<chip>-mipi-tx"
|
||||
the supported chips are mt2701 and mt8173.
|
||||
the supported chips are mt2701, mt8173 and mt8183.
|
||||
- reg: Physical base address and length of the controller's registers
|
||||
- clocks: PLL reference clock
|
||||
- clock-output-names: name of the output clock line to the DSI encoder
|
||||
|
@ -12,6 +12,8 @@ mediatek-drm-y := mtk_disp_color.o \
|
||||
mtk_drm_plane.o \
|
||||
mtk_dsi.o \
|
||||
mtk_mipi_tx.o \
|
||||
mtk_mt8173_mipi_tx.o \
|
||||
mtk_mt8183_mipi_tx.o \
|
||||
mtk_dpi.o
|
||||
|
||||
obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
|
||||
|
@ -19,6 +19,8 @@
|
||||
#define DISP_REG_OVL_EN 0x000c
|
||||
#define DISP_REG_OVL_RST 0x0014
|
||||
#define DISP_REG_OVL_ROI_SIZE 0x0020
|
||||
#define DISP_REG_OVL_DATAPATH_CON 0x0024
|
||||
#define OVL_BGCLR_SEL_IN BIT(2)
|
||||
#define DISP_REG_OVL_ROI_BGCLR 0x0028
|
||||
#define DISP_REG_OVL_SRC_CON 0x002c
|
||||
#define DISP_REG_OVL_CON(n) (0x0030 + 0x20 * (n))
|
||||
@ -31,7 +33,9 @@
|
||||
#define DISP_REG_OVL_ADDR_MT8173 0x0f40
|
||||
#define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n))
|
||||
|
||||
#define OVL_RDMA_MEM_GMC 0x40402020
|
||||
#define GMC_THRESHOLD_BITS 16
|
||||
#define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
|
||||
#define GMC_THRESHOLD_LOW ((1 << GMC_THRESHOLD_BITS) / 8)
|
||||
|
||||
#define OVL_CON_BYTE_SWAP BIT(24)
|
||||
#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
|
||||
@ -49,6 +53,8 @@
|
||||
|
||||
struct mtk_disp_ovl_data {
|
||||
unsigned int addr;
|
||||
unsigned int gmc_bits;
|
||||
unsigned int layer_nr;
|
||||
bool fmt_rgb565_is_0;
|
||||
};
|
||||
|
||||
@ -126,15 +132,31 @@ static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
|
||||
static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
return 4;
|
||||
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
|
||||
|
||||
return ovl->data->layer_nr;
|
||||
}
|
||||
|
||||
static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx)
|
||||
{
|
||||
unsigned int reg;
|
||||
unsigned int gmc_thrshd_l;
|
||||
unsigned int gmc_thrshd_h;
|
||||
unsigned int gmc_value;
|
||||
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
|
||||
|
||||
writel(0x1, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
|
||||
writel(OVL_RDMA_MEM_GMC, comp->regs + DISP_REG_OVL_RDMA_GMC(idx));
|
||||
|
||||
gmc_thrshd_l = GMC_THRESHOLD_LOW >>
|
||||
(GMC_THRESHOLD_BITS - ovl->data->gmc_bits);
|
||||
gmc_thrshd_h = GMC_THRESHOLD_HIGH >>
|
||||
(GMC_THRESHOLD_BITS - ovl->data->gmc_bits);
|
||||
if (ovl->data->gmc_bits == 10)
|
||||
gmc_value = gmc_thrshd_h | gmc_thrshd_h << 16;
|
||||
else
|
||||
gmc_value = gmc_thrshd_l | gmc_thrshd_l << 8 |
|
||||
gmc_thrshd_h << 16 | gmc_thrshd_h << 24;
|
||||
writel(gmc_value, comp->regs + DISP_REG_OVL_RDMA_GMC(idx));
|
||||
|
||||
reg = readl(comp->regs + DISP_REG_OVL_SRC_CON);
|
||||
reg = reg | BIT(idx);
|
||||
@ -217,6 +239,24 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
mtk_ovl_layer_on(comp, idx);
|
||||
}
|
||||
|
||||
static void mtk_ovl_bgclr_in_on(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = reg | OVL_BGCLR_SEL_IN;
|
||||
writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
}
|
||||
|
||||
static void mtk_ovl_bgclr_in_off(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = reg & ~OVL_BGCLR_SEL_IN;
|
||||
writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
}
|
||||
|
||||
static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
|
||||
.config = mtk_ovl_config,
|
||||
.start = mtk_ovl_start,
|
||||
@ -227,6 +267,8 @@ static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
|
||||
.layer_on = mtk_ovl_layer_on,
|
||||
.layer_off = mtk_ovl_layer_off,
|
||||
.layer_config = mtk_ovl_layer_config,
|
||||
.bgclr_in_on = mtk_ovl_bgclr_in_on,
|
||||
.bgclr_in_off = mtk_ovl_bgclr_in_off,
|
||||
};
|
||||
|
||||
static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
|
||||
@ -276,7 +318,12 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_OVL);
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node,
|
||||
priv->data->layer_nr == 4 ?
|
||||
MTK_DISP_OVL :
|
||||
MTK_DISP_OVL_2L);
|
||||
if (comp_id < 0) {
|
||||
dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
|
||||
return comp_id;
|
||||
@ -289,8 +336,6 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
|
||||
@ -316,11 +361,15 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
|
||||
.addr = DISP_REG_OVL_ADDR_MT2701,
|
||||
.gmc_bits = 8,
|
||||
.layer_nr = 4,
|
||||
.fmt_rgb565_is_0 = false,
|
||||
};
|
||||
|
||||
static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
|
||||
.addr = DISP_REG_OVL_ADDR_MT8173,
|
||||
.gmc_bits = 8,
|
||||
.layer_nr = 4,
|
||||
.fmt_rgb565_is_0 = true,
|
||||
};
|
||||
|
||||
|
@ -272,6 +272,9 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
|
||||
|
||||
if (i == 1)
|
||||
mtk_ddp_comp_bgclr_in_on(comp);
|
||||
|
||||
mtk_ddp_comp_config(comp, width, height, vrefresh, bpc);
|
||||
mtk_ddp_comp_start(comp);
|
||||
}
|
||||
@ -280,9 +283,18 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
|
||||
for (i = 0; i < mtk_crtc->layer_nr; i++) {
|
||||
struct drm_plane *plane = &mtk_crtc->planes[i];
|
||||
struct mtk_plane_state *plane_state;
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
unsigned int comp_layer_nr = mtk_ddp_comp_layer_nr(comp);
|
||||
unsigned int local_layer;
|
||||
|
||||
plane_state = to_mtk_plane_state(plane->state);
|
||||
mtk_ddp_comp_layer_config(mtk_crtc->ddp_comp[0], i,
|
||||
|
||||
if (i >= comp_layer_nr) {
|
||||
comp = mtk_crtc->ddp_comp[1];
|
||||
local_layer = i - comp_layer_nr;
|
||||
} else
|
||||
local_layer = i;
|
||||
mtk_ddp_comp_layer_config(comp, local_layer,
|
||||
plane_state);
|
||||
}
|
||||
|
||||
@ -301,8 +313,12 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __func__);
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
|
||||
mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
|
||||
if (i == 1)
|
||||
mtk_ddp_comp_bgclr_in_off(mtk_crtc->ddp_comp[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
|
||||
mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
|
||||
mtk_crtc->ddp_comp[i]->id);
|
||||
@ -327,6 +343,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
|
||||
struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
unsigned int i;
|
||||
unsigned int comp_layer_nr = mtk_ddp_comp_layer_nr(comp);
|
||||
unsigned int local_layer;
|
||||
|
||||
/*
|
||||
* TODO: instead of updating the registers here, we should prepare
|
||||
@ -349,7 +367,14 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
|
||||
plane_state = to_mtk_plane_state(plane->state);
|
||||
|
||||
if (plane_state->pending.config) {
|
||||
mtk_ddp_comp_layer_config(comp, i, plane_state);
|
||||
if (i >= comp_layer_nr) {
|
||||
comp = mtk_crtc->ddp_comp[1];
|
||||
local_layer = i - comp_layer_nr;
|
||||
} else
|
||||
local_layer = i;
|
||||
|
||||
mtk_ddp_comp_layer_config(comp, local_layer,
|
||||
plane_state);
|
||||
plane_state->pending.config = false;
|
||||
}
|
||||
}
|
||||
@ -582,6 +607,12 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
}
|
||||
|
||||
mtk_crtc->layer_nr = mtk_ddp_comp_layer_nr(mtk_crtc->ddp_comp[0]);
|
||||
if (mtk_crtc->ddp_comp_nr > 1) {
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[1];
|
||||
|
||||
if (comp->funcs->bgclr_in_on)
|
||||
mtk_crtc->layer_nr += mtk_ddp_comp_layer_nr(comp);
|
||||
}
|
||||
mtk_crtc->planes = devm_kcalloc(dev, mtk_crtc->layer_nr,
|
||||
sizeof(struct drm_plane),
|
||||
GFP_KERNEL);
|
||||
|
@ -33,12 +33,15 @@
|
||||
#define DISP_REG_CONFIG_DSI_SEL 0x050
|
||||
#define DISP_REG_CONFIG_DPI_SEL 0x064
|
||||
|
||||
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
|
||||
#define MT2701_DISP_MUTEX0_MOD0 0x2c
|
||||
#define MT2701_DISP_MUTEX0_SOF0 0x30
|
||||
|
||||
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_MOD(mutex_mod_reg, n) (mutex_mod_reg + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_SOF(mutex_sof_reg, n) (mutex_sof_reg + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
|
||||
|
||||
#define INT_MUTEX BIT(1)
|
||||
|
||||
@ -139,12 +142,30 @@ struct mtk_disp_mutex {
|
||||
bool claimed;
|
||||
};
|
||||
|
||||
enum mtk_ddp_mutex_sof_id {
|
||||
DDP_MUTEX_SOF_SINGLE_MODE,
|
||||
DDP_MUTEX_SOF_DSI0,
|
||||
DDP_MUTEX_SOF_DSI1,
|
||||
DDP_MUTEX_SOF_DPI0,
|
||||
DDP_MUTEX_SOF_DPI1,
|
||||
DDP_MUTEX_SOF_DSI2,
|
||||
DDP_MUTEX_SOF_DSI3,
|
||||
};
|
||||
|
||||
struct mtk_ddp_data {
|
||||
const unsigned int *mutex_mod;
|
||||
const unsigned int *mutex_sof;
|
||||
const unsigned int mutex_mod_reg;
|
||||
const unsigned int mutex_sof_reg;
|
||||
const bool no_clk;
|
||||
};
|
||||
|
||||
struct mtk_ddp {
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct mtk_disp_mutex mutex[10];
|
||||
const unsigned int *mutex_mod;
|
||||
const struct mtk_ddp_data *data;
|
||||
};
|
||||
|
||||
static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
|
||||
@ -194,6 +215,37 @@ static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
|
||||
[DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
|
||||
};
|
||||
|
||||
static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_DSI3 + 1] = {
|
||||
[DDP_MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
||||
[DDP_MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
||||
[DDP_MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
|
||||
[DDP_MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0,
|
||||
[DDP_MUTEX_SOF_DPI1] = MUTEX_SOF_DPI1,
|
||||
[DDP_MUTEX_SOF_DSI2] = MUTEX_SOF_DSI2,
|
||||
[DDP_MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_data mt2701_ddp_driver_data = {
|
||||
.mutex_mod = mt2701_mutex_mod,
|
||||
.mutex_sof = mt2712_mutex_sof,
|
||||
.mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_data mt2712_ddp_driver_data = {
|
||||
.mutex_mod = mt2712_mutex_mod,
|
||||
.mutex_sof = mt2712_mutex_sof,
|
||||
.mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_data mt8173_ddp_driver_data = {
|
||||
.mutex_mod = mt8173_mutex_mod,
|
||||
.mutex_sof = mt2712_mutex_sof,
|
||||
.mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0,
|
||||
};
|
||||
|
||||
static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
|
||||
enum mtk_ddp_comp_id next,
|
||||
unsigned int *addr)
|
||||
@ -432,45 +484,49 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
unsigned int reg;
|
||||
unsigned int sof_id;
|
||||
unsigned int offset;
|
||||
|
||||
WARN_ON(&ddp->mutex[mutex->id] != mutex);
|
||||
|
||||
switch (id) {
|
||||
case DDP_COMPONENT_DSI0:
|
||||
reg = MUTEX_SOF_DSI0;
|
||||
sof_id = DDP_MUTEX_SOF_DSI0;
|
||||
break;
|
||||
case DDP_COMPONENT_DSI1:
|
||||
reg = MUTEX_SOF_DSI0;
|
||||
sof_id = DDP_MUTEX_SOF_DSI0;
|
||||
break;
|
||||
case DDP_COMPONENT_DSI2:
|
||||
reg = MUTEX_SOF_DSI2;
|
||||
sof_id = DDP_MUTEX_SOF_DSI2;
|
||||
break;
|
||||
case DDP_COMPONENT_DSI3:
|
||||
reg = MUTEX_SOF_DSI3;
|
||||
sof_id = DDP_MUTEX_SOF_DSI3;
|
||||
break;
|
||||
case DDP_COMPONENT_DPI0:
|
||||
reg = MUTEX_SOF_DPI0;
|
||||
sof_id = DDP_MUTEX_SOF_DPI0;
|
||||
break;
|
||||
case DDP_COMPONENT_DPI1:
|
||||
reg = MUTEX_SOF_DPI1;
|
||||
sof_id = DDP_MUTEX_SOF_DPI1;
|
||||
break;
|
||||
default:
|
||||
if (ddp->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(mutex->id);
|
||||
if (ddp->data->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(ddp->data->mutex_mod_reg,
|
||||
mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg |= 1 << ddp->mutex_mod[id];
|
||||
reg |= 1 << ddp->data->mutex_mod[id];
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
} else {
|
||||
offset = DISP_REG_MUTEX_MOD2(mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg |= 1 << (ddp->mutex_mod[id] - 32);
|
||||
reg |= 1 << (ddp->data->mutex_mod[id] - 32);
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
|
||||
writel_relaxed(ddp->data->mutex_sof[sof_id],
|
||||
ddp->regs +
|
||||
DISP_REG_MUTEX_SOF(ddp->data->mutex_sof_reg, mutex->id));
|
||||
}
|
||||
|
||||
void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
|
||||
@ -491,18 +547,21 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
|
||||
case DDP_COMPONENT_DPI0:
|
||||
case DDP_COMPONENT_DPI1:
|
||||
writel_relaxed(MUTEX_SOF_SINGLE_MODE,
|
||||
ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
|
||||
ddp->regs +
|
||||
DISP_REG_MUTEX_SOF(ddp->data->mutex_sof_reg,
|
||||
mutex->id));
|
||||
break;
|
||||
default:
|
||||
if (ddp->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(mutex->id);
|
||||
if (ddp->data->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(ddp->data->mutex_mod_reg,
|
||||
mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg &= ~(1 << ddp->mutex_mod[id]);
|
||||
reg &= ~(1 << ddp->data->mutex_mod[id]);
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
} else {
|
||||
offset = DISP_REG_MUTEX_MOD2(mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg &= ~(1 << (ddp->mutex_mod[id] - 32));
|
||||
reg &= ~(1 << (ddp->data->mutex_mod[id] - 32));
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
}
|
||||
break;
|
||||
@ -564,10 +623,14 @@ static int mtk_ddp_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < 10; i++)
|
||||
ddp->mutex[i].id = i;
|
||||
|
||||
ddp->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(ddp->clk)) {
|
||||
dev_err(dev, "Failed to get clock\n");
|
||||
return PTR_ERR(ddp->clk);
|
||||
ddp->data = of_device_get_match_data(dev);
|
||||
|
||||
if (!ddp->data->no_clk) {
|
||||
ddp->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(ddp->clk)) {
|
||||
dev_err(dev, "Failed to get clock\n");
|
||||
return PTR_ERR(ddp->clk);
|
||||
}
|
||||
}
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@ -577,8 +640,6 @@ static int mtk_ddp_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(ddp->regs);
|
||||
}
|
||||
|
||||
ddp->mutex_mod = of_device_get_match_data(dev);
|
||||
|
||||
platform_set_drvdata(pdev, ddp);
|
||||
|
||||
return 0;
|
||||
@ -590,9 +651,12 @@ static int mtk_ddp_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id ddp_driver_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod},
|
||||
{ .compatible = "mediatek,mt2712-disp-mutex", .data = mt2712_mutex_mod},
|
||||
{ .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
|
||||
{ .compatible = "mediatek,mt2701-disp-mutex",
|
||||
.data = &mt2701_ddp_driver_data},
|
||||
{ .compatible = "mediatek,mt2712-disp-mutex",
|
||||
.data = &mt2712_ddp_driver_data},
|
||||
{ .compatible = "mediatek,mt8173-disp-mutex",
|
||||
.data = &mt8173_ddp_driver_data},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
|
||||
|
@ -33,6 +33,18 @@
|
||||
#define DISP_AAL_EN 0x0000
|
||||
#define DISP_AAL_SIZE 0x0030
|
||||
|
||||
#define DISP_CCORR_EN 0x0000
|
||||
#define CCORR_EN BIT(0)
|
||||
#define DISP_CCORR_CFG 0x0020
|
||||
#define CCORR_RELAY_MODE BIT(0)
|
||||
#define DISP_CCORR_SIZE 0x0030
|
||||
|
||||
#define DISP_DITHER_EN 0x0000
|
||||
#define DITHER_EN BIT(0)
|
||||
#define DISP_DITHER_CFG 0x0020
|
||||
#define DITHER_RELAY_MODE BIT(0)
|
||||
#define DISP_DITHER_SIZE 0x0030
|
||||
|
||||
#define DISP_GAMMA_EN 0x0000
|
||||
#define DISP_GAMMA_CFG 0x0020
|
||||
#define DISP_GAMMA_SIZE 0x0030
|
||||
@ -123,6 +135,42 @@ static void mtk_aal_stop(struct mtk_ddp_comp *comp)
|
||||
writel_relaxed(0x0, comp->regs + DISP_AAL_EN);
|
||||
}
|
||||
|
||||
static void mtk_ccorr_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc)
|
||||
{
|
||||
writel(h << 16 | w, comp->regs + DISP_CCORR_SIZE);
|
||||
writel(CCORR_RELAY_MODE, comp->regs + DISP_CCORR_CFG);
|
||||
}
|
||||
|
||||
static void mtk_ccorr_start(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel(CCORR_EN, comp->regs + DISP_CCORR_EN);
|
||||
}
|
||||
|
||||
static void mtk_ccorr_stop(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel_relaxed(0x0, comp->regs + DISP_CCORR_EN);
|
||||
}
|
||||
|
||||
static void mtk_dither_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc)
|
||||
{
|
||||
writel(h << 16 | w, comp->regs + DISP_DITHER_SIZE);
|
||||
writel(DITHER_RELAY_MODE, comp->regs + DISP_DITHER_CFG);
|
||||
}
|
||||
|
||||
static void mtk_dither_start(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel(DITHER_EN, comp->regs + DISP_DITHER_EN);
|
||||
}
|
||||
|
||||
static void mtk_dither_stop(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel_relaxed(0x0, comp->regs + DISP_DITHER_EN);
|
||||
}
|
||||
|
||||
static void mtk_gamma_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc)
|
||||
@ -171,6 +219,18 @@ static const struct mtk_ddp_comp_funcs ddp_aal = {
|
||||
.stop = mtk_aal_stop,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_ccorr = {
|
||||
.config = mtk_ccorr_config,
|
||||
.start = mtk_ccorr_start,
|
||||
.stop = mtk_ccorr_stop,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_dither = {
|
||||
.config = mtk_dither_config,
|
||||
.start = mtk_dither_start,
|
||||
.stop = mtk_dither_stop,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_gamma = {
|
||||
.gamma_set = mtk_gamma_set,
|
||||
.config = mtk_gamma_config,
|
||||
@ -189,11 +249,14 @@ static const struct mtk_ddp_comp_funcs ddp_ufoe = {
|
||||
|
||||
static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
|
||||
[MTK_DISP_OVL] = "ovl",
|
||||
[MTK_DISP_OVL_2L] = "ovl_2l",
|
||||
[MTK_DISP_RDMA] = "rdma",
|
||||
[MTK_DISP_WDMA] = "wdma",
|
||||
[MTK_DISP_COLOR] = "color",
|
||||
[MTK_DISP_CCORR] = "ccorr",
|
||||
[MTK_DISP_AAL] = "aal",
|
||||
[MTK_DISP_GAMMA] = "gamma",
|
||||
[MTK_DISP_DITHER] = "dither",
|
||||
[MTK_DISP_UFOE] = "ufoe",
|
||||
[MTK_DSI] = "dsi",
|
||||
[MTK_DPI] = "dpi",
|
||||
@ -213,8 +276,10 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
|
||||
[DDP_COMPONENT_AAL0] = { MTK_DISP_AAL, 0, &ddp_aal },
|
||||
[DDP_COMPONENT_AAL1] = { MTK_DISP_AAL, 1, &ddp_aal },
|
||||
[DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL },
|
||||
[DDP_COMPONENT_CCORR] = { MTK_DISP_CCORR, 0, &ddp_ccorr },
|
||||
[DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, NULL },
|
||||
[DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, NULL },
|
||||
[DDP_COMPONENT_DITHER] = { MTK_DISP_DITHER, 0, &ddp_dither },
|
||||
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL },
|
||||
[DDP_COMPONENT_DPI1] = { MTK_DPI, 1, NULL },
|
||||
[DDP_COMPONENT_DSI0] = { MTK_DSI, 0, NULL },
|
||||
@ -226,6 +291,8 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
|
||||
[DDP_COMPONENT_OD1] = { MTK_DISP_OD, 1, &ddp_od },
|
||||
[DDP_COMPONENT_OVL0] = { MTK_DISP_OVL, 0, NULL },
|
||||
[DDP_COMPONENT_OVL1] = { MTK_DISP_OVL, 1, NULL },
|
||||
[DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L, 0, NULL },
|
||||
[DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L, 1, NULL },
|
||||
[DDP_COMPONENT_PWM0] = { MTK_DISP_PWM, 0, NULL },
|
||||
[DDP_COMPONENT_PWM1] = { MTK_DISP_PWM, 1, NULL },
|
||||
[DDP_COMPONENT_PWM2] = { MTK_DISP_PWM, 2, NULL },
|
||||
|
@ -17,9 +17,12 @@ struct drm_crtc_state;
|
||||
|
||||
enum mtk_ddp_comp_type {
|
||||
MTK_DISP_OVL,
|
||||
MTK_DISP_OVL_2L,
|
||||
MTK_DISP_RDMA,
|
||||
MTK_DISP_WDMA,
|
||||
MTK_DISP_COLOR,
|
||||
MTK_DISP_CCORR,
|
||||
MTK_DISP_DITHER,
|
||||
MTK_DISP_AAL,
|
||||
MTK_DISP_GAMMA,
|
||||
MTK_DISP_UFOE,
|
||||
@ -36,8 +39,10 @@ enum mtk_ddp_comp_id {
|
||||
DDP_COMPONENT_AAL0,
|
||||
DDP_COMPONENT_AAL1,
|
||||
DDP_COMPONENT_BLS,
|
||||
DDP_COMPONENT_CCORR,
|
||||
DDP_COMPONENT_COLOR0,
|
||||
DDP_COMPONENT_COLOR1,
|
||||
DDP_COMPONENT_DITHER,
|
||||
DDP_COMPONENT_DPI0,
|
||||
DDP_COMPONENT_DPI1,
|
||||
DDP_COMPONENT_DSI0,
|
||||
@ -48,6 +53,8 @@ enum mtk_ddp_comp_id {
|
||||
DDP_COMPONENT_OD0,
|
||||
DDP_COMPONENT_OD1,
|
||||
DDP_COMPONENT_OVL0,
|
||||
DDP_COMPONENT_OVL_2L0,
|
||||
DDP_COMPONENT_OVL_2L1,
|
||||
DDP_COMPONENT_OVL1,
|
||||
DDP_COMPONENT_PWM0,
|
||||
DDP_COMPONENT_PWM1,
|
||||
@ -77,6 +84,8 @@ struct mtk_ddp_comp_funcs {
|
||||
struct mtk_plane_state *state);
|
||||
void (*gamma_set)(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc_state *state);
|
||||
void (*bgclr_in_on)(struct mtk_ddp_comp *comp);
|
||||
void (*bgclr_in_off)(struct mtk_ddp_comp *comp);
|
||||
};
|
||||
|
||||
struct mtk_ddp_comp {
|
||||
@ -158,6 +167,18 @@ static inline void mtk_ddp_gamma_set(struct mtk_ddp_comp *comp,
|
||||
comp->funcs->gamma_set(comp, state);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_bgclr_in_on(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->bgclr_in_on)
|
||||
comp->funcs->bgclr_in_on(comp);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_bgclr_in_off(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->bgclr_in_off)
|
||||
comp->funcs->bgclr_in_off(comp);
|
||||
}
|
||||
|
||||
int mtk_ddp_comp_get_id(struct device_node *node,
|
||||
enum mtk_ddp_comp_type comp_type);
|
||||
int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node,
|
||||
|
@ -547,6 +547,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
|
||||
*/
|
||||
if (comp_type == MTK_DISP_COLOR ||
|
||||
comp_type == MTK_DISP_OVL ||
|
||||
comp_type == MTK_DISP_OVL_2L ||
|
||||
comp_type == MTK_DISP_RDMA ||
|
||||
comp_type == MTK_DSI ||
|
||||
comp_type == MTK_DPI) {
|
||||
@ -669,8 +670,8 @@ static struct platform_driver * const mtk_drm_drivers[] = {
|
||||
&mtk_disp_rdma_driver,
|
||||
&mtk_dpi_driver,
|
||||
&mtk_drm_platform_driver,
|
||||
&mtk_dsi_driver,
|
||||
&mtk_mipi_tx_driver,
|
||||
&mtk_dsi_driver,
|
||||
};
|
||||
|
||||
static int __init mtk_drm_init(void)
|
||||
|
@ -40,6 +40,7 @@
|
||||
#define DSI_CON_CTRL 0x10
|
||||
#define DSI_RESET BIT(0)
|
||||
#define DSI_EN BIT(1)
|
||||
#define DPHY_RESET BIT(2)
|
||||
|
||||
#define DSI_MODE_CTRL 0x14
|
||||
#define MODE (3)
|
||||
@ -73,6 +74,7 @@
|
||||
#define DSI_VBP_NL 0x24
|
||||
#define DSI_VFP_NL 0x28
|
||||
#define DSI_VACT_NL 0x2C
|
||||
#define DSI_SIZE_CON 0x38
|
||||
#define DSI_HSA_WC 0x50
|
||||
#define DSI_HBP_WC 0x54
|
||||
#define DSI_HFP_WC 0x58
|
||||
@ -126,7 +128,10 @@
|
||||
#define VM_CMD_EN BIT(0)
|
||||
#define TS_VFP_EN BIT(5)
|
||||
|
||||
#define DSI_CMDQ0 0x180
|
||||
#define DSI_SHADOW_DEBUG 0x190U
|
||||
#define FORCE_COMMIT BIT(0)
|
||||
#define BYPASS_SHADOW BIT(1)
|
||||
|
||||
#define CONFIG (0xff << 0)
|
||||
#define SHORT_PACKET 0
|
||||
#define LONG_PACKET 2
|
||||
@ -135,12 +140,6 @@
|
||||
#define DATA_0 (0xff << 16)
|
||||
#define DATA_1 (0xff << 24)
|
||||
|
||||
#define T_LPX 5
|
||||
#define T_HS_PREP 6
|
||||
#define T_HS_TRAIL 8
|
||||
#define T_HS_EXIT 7
|
||||
#define T_HS_ZERO 10
|
||||
|
||||
#define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
|
||||
|
||||
#define MTK_DSI_HOST_IS_READ(type) \
|
||||
@ -149,8 +148,33 @@
|
||||
(type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
|
||||
(type == MIPI_DSI_DCS_READ))
|
||||
|
||||
struct mtk_phy_timing {
|
||||
u32 lpx;
|
||||
u32 da_hs_prepare;
|
||||
u32 da_hs_zero;
|
||||
u32 da_hs_trail;
|
||||
|
||||
u32 ta_go;
|
||||
u32 ta_sure;
|
||||
u32 ta_get;
|
||||
u32 da_hs_exit;
|
||||
|
||||
u32 clk_hs_zero;
|
||||
u32 clk_hs_trail;
|
||||
|
||||
u32 clk_hs_prepare;
|
||||
u32 clk_hs_post;
|
||||
u32 clk_hs_exit;
|
||||
};
|
||||
|
||||
struct phy;
|
||||
|
||||
struct mtk_dsi_driver_data {
|
||||
const u32 reg_cmdq_off;
|
||||
bool has_shadow_ctl;
|
||||
bool has_size_ctl;
|
||||
};
|
||||
|
||||
struct mtk_dsi {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct device *dev;
|
||||
@ -173,10 +197,12 @@ struct mtk_dsi {
|
||||
enum mipi_dsi_pixel_format format;
|
||||
unsigned int lanes;
|
||||
struct videomode vm;
|
||||
struct mtk_phy_timing phy_timing;
|
||||
int refcount;
|
||||
bool enabled;
|
||||
u32 irq_data;
|
||||
wait_queue_head_t irq_wait_queue;
|
||||
const struct mtk_dsi_driver_data *driver_data;
|
||||
};
|
||||
|
||||
static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e)
|
||||
@ -205,17 +231,36 @@ static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
|
||||
{
|
||||
u32 timcon0, timcon1, timcon2, timcon3;
|
||||
u32 ui, cycle_time;
|
||||
struct mtk_phy_timing *timing = &dsi->phy_timing;
|
||||
|
||||
ui = 1000 / dsi->data_rate + 0x01;
|
||||
cycle_time = 8000 / dsi->data_rate + 0x01;
|
||||
ui = DIV_ROUND_UP(1000000000, dsi->data_rate);
|
||||
cycle_time = div_u64(8000000000ULL, dsi->data_rate);
|
||||
|
||||
timcon0 = T_LPX | T_HS_PREP << 8 | T_HS_ZERO << 16 | T_HS_TRAIL << 24;
|
||||
timcon1 = 4 * T_LPX | (3 * T_LPX / 2) << 8 | 5 * T_LPX << 16 |
|
||||
T_HS_EXIT << 24;
|
||||
timcon2 = ((NS_TO_CYCLE(0x64, cycle_time) + 0xa) << 24) |
|
||||
(NS_TO_CYCLE(0x150, cycle_time) << 16);
|
||||
timcon3 = NS_TO_CYCLE(0x40, cycle_time) | (2 * T_LPX) << 16 |
|
||||
NS_TO_CYCLE(80 + 52 * ui, cycle_time) << 8;
|
||||
timing->lpx = NS_TO_CYCLE(60, cycle_time);
|
||||
timing->da_hs_prepare = NS_TO_CYCLE(50 + 5 * ui, cycle_time);
|
||||
timing->da_hs_zero = NS_TO_CYCLE(110 + 6 * ui, cycle_time);
|
||||
timing->da_hs_trail = NS_TO_CYCLE(77 + 4 * ui, cycle_time);
|
||||
|
||||
timing->ta_go = 4 * timing->lpx;
|
||||
timing->ta_sure = 3 * timing->lpx / 2;
|
||||
timing->ta_get = 5 * timing->lpx;
|
||||
timing->da_hs_exit = 2 * timing->lpx;
|
||||
|
||||
timing->clk_hs_zero = NS_TO_CYCLE(336, cycle_time);
|
||||
timing->clk_hs_trail = NS_TO_CYCLE(100, cycle_time) + 10;
|
||||
|
||||
timing->clk_hs_prepare = NS_TO_CYCLE(64, cycle_time);
|
||||
timing->clk_hs_post = NS_TO_CYCLE(80 + 52 * ui, cycle_time);
|
||||
timing->clk_hs_exit = 2 * timing->lpx;
|
||||
|
||||
timcon0 = timing->lpx | timing->da_hs_prepare << 8 |
|
||||
timing->da_hs_zero << 16 | timing->da_hs_trail << 24;
|
||||
timcon1 = timing->ta_go | timing->ta_sure << 8 |
|
||||
timing->ta_get << 16 | timing->da_hs_exit << 24;
|
||||
timcon2 = 1 << 8 | timing->clk_hs_zero << 16 |
|
||||
timing->clk_hs_trail << 24;
|
||||
timcon3 = timing->clk_hs_prepare | timing->clk_hs_post << 8 |
|
||||
timing->clk_hs_exit << 16;
|
||||
|
||||
writel(timcon0, dsi->regs + DSI_PHY_TIMECON0);
|
||||
writel(timcon1, dsi->regs + DSI_PHY_TIMECON1);
|
||||
@ -239,6 +284,12 @@ static void mtk_dsi_reset_engine(struct mtk_dsi *dsi)
|
||||
mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0);
|
||||
}
|
||||
|
||||
static void mtk_dsi_reset_dphy(struct mtk_dsi *dsi)
|
||||
{
|
||||
mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, DPHY_RESET);
|
||||
mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, 0);
|
||||
}
|
||||
|
||||
static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
|
||||
{
|
||||
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
|
||||
@ -402,7 +453,8 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
|
||||
u32 horizontal_sync_active_byte;
|
||||
u32 horizontal_backporch_byte;
|
||||
u32 horizontal_frontporch_byte;
|
||||
u32 dsi_tmp_buf_bpp;
|
||||
u32 dsi_tmp_buf_bpp, data_phy_cycles;
|
||||
struct mtk_phy_timing *timing = &dsi->phy_timing;
|
||||
|
||||
struct videomode *vm = &dsi->vm;
|
||||
|
||||
@ -416,6 +468,10 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
|
||||
writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL);
|
||||
writel(vm->vactive, dsi->regs + DSI_VACT_NL);
|
||||
|
||||
if (dsi->driver_data->has_size_ctl)
|
||||
writel(vm->vactive << 16 | vm->hactive,
|
||||
dsi->regs + DSI_SIZE_CON);
|
||||
|
||||
horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10);
|
||||
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
|
||||
@ -425,7 +481,34 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
|
||||
horizontal_backporch_byte = ((vm->hback_porch + vm->hsync_len) *
|
||||
dsi_tmp_buf_bpp - 10);
|
||||
|
||||
horizontal_frontporch_byte = (vm->hfront_porch * dsi_tmp_buf_bpp - 12);
|
||||
data_phy_cycles = timing->lpx + timing->da_hs_prepare +
|
||||
timing->da_hs_zero + timing->da_hs_exit + 2;
|
||||
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
|
||||
if (vm->hfront_porch * dsi_tmp_buf_bpp >
|
||||
data_phy_cycles * dsi->lanes + 18) {
|
||||
horizontal_frontporch_byte = vm->hfront_porch *
|
||||
dsi_tmp_buf_bpp -
|
||||
data_phy_cycles *
|
||||
dsi->lanes - 18;
|
||||
} else {
|
||||
DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n");
|
||||
horizontal_frontporch_byte = vm->hfront_porch *
|
||||
dsi_tmp_buf_bpp;
|
||||
}
|
||||
} else {
|
||||
if (vm->hfront_porch * dsi_tmp_buf_bpp >
|
||||
data_phy_cycles * dsi->lanes + 12) {
|
||||
horizontal_frontporch_byte = vm->hfront_porch *
|
||||
dsi_tmp_buf_bpp -
|
||||
data_phy_cycles *
|
||||
dsi->lanes - 12;
|
||||
} else {
|
||||
DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n");
|
||||
horizontal_frontporch_byte = vm->hfront_porch *
|
||||
dsi_tmp_buf_bpp;
|
||||
}
|
||||
}
|
||||
|
||||
writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
|
||||
writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
|
||||
@ -523,10 +606,9 @@ static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t)
|
||||
|
||||
static int mtk_dsi_poweron(struct mtk_dsi *dsi)
|
||||
{
|
||||
struct device *dev = dsi->dev;
|
||||
struct device *dev = dsi->host.dev;
|
||||
int ret;
|
||||
u64 pixel_clock, total_bits;
|
||||
u32 htotal, htotal_bits, bit_per_pixel, overhead_cycles, overhead_bits;
|
||||
u32 bit_per_pixel;
|
||||
|
||||
if (++dsi->refcount != 1)
|
||||
return 0;
|
||||
@ -545,24 +627,8 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* htotal_time = htotal * byte_per_pixel / num_lanes
|
||||
* overhead_time = lpx + hs_prepare + hs_zero + hs_trail + hs_exit
|
||||
* mipi_ratio = (htotal_time + overhead_time) / htotal_time
|
||||
* data_rate = pixel_clock * bit_per_pixel * mipi_ratio / num_lanes;
|
||||
*/
|
||||
pixel_clock = dsi->vm.pixelclock;
|
||||
htotal = dsi->vm.hactive + dsi->vm.hback_porch + dsi->vm.hfront_porch +
|
||||
dsi->vm.hsync_len;
|
||||
htotal_bits = htotal * bit_per_pixel;
|
||||
|
||||
overhead_cycles = T_LPX + T_HS_PREP + T_HS_ZERO + T_HS_TRAIL +
|
||||
T_HS_EXIT;
|
||||
overhead_bits = overhead_cycles * dsi->lanes * 8;
|
||||
total_bits = htotal_bits + overhead_bits;
|
||||
|
||||
dsi->data_rate = DIV_ROUND_UP_ULL(pixel_clock * total_bits,
|
||||
htotal * dsi->lanes);
|
||||
dsi->data_rate = DIV_ROUND_UP_ULL(dsi->vm.pixelclock * bit_per_pixel,
|
||||
dsi->lanes);
|
||||
|
||||
ret = clk_set_rate(dsi->hs_clk, dsi->data_rate);
|
||||
if (ret < 0) {
|
||||
@ -585,10 +651,17 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
|
||||
}
|
||||
|
||||
mtk_dsi_enable(dsi);
|
||||
|
||||
if (dsi->driver_data->has_shadow_ctl)
|
||||
writel(FORCE_COMMIT | BYPASS_SHADOW,
|
||||
dsi->regs + DSI_SHADOW_DEBUG);
|
||||
|
||||
mtk_dsi_reset_engine(dsi);
|
||||
mtk_dsi_phy_timconfig(dsi);
|
||||
|
||||
mtk_dsi_rxtx_control(dsi);
|
||||
usleep_range(30, 100);
|
||||
mtk_dsi_reset_dphy(dsi);
|
||||
mtk_dsi_ps_control_vact(dsi);
|
||||
mtk_dsi_set_vm_cmd(dsi);
|
||||
mtk_dsi_config_vdo_timing(dsi);
|
||||
@ -939,6 +1012,7 @@ static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
|
||||
const char *tx_buf = msg->tx_buf;
|
||||
u8 config, cmdq_size, cmdq_off, type = msg->type;
|
||||
u32 reg_val, cmdq_mask, i;
|
||||
u32 reg_cmdq_off = dsi->driver_data->reg_cmdq_off;
|
||||
|
||||
if (MTK_DSI_HOST_IS_READ(type))
|
||||
config = BTA;
|
||||
@ -958,9 +1032,11 @@ static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
|
||||
}
|
||||
|
||||
for (i = 0; i < msg->tx_len; i++)
|
||||
writeb(tx_buf[i], dsi->regs + DSI_CMDQ0 + cmdq_off + i);
|
||||
mtk_dsi_mask(dsi, (reg_cmdq_off + cmdq_off + i) & (~0x3U),
|
||||
(0xffUL << (((i + cmdq_off) & 3U) * 8U)),
|
||||
tx_buf[i] << (((i + cmdq_off) & 3U) * 8U));
|
||||
|
||||
mtk_dsi_mask(dsi, DSI_CMDQ0, cmdq_mask, reg_val);
|
||||
mtk_dsi_mask(dsi, reg_cmdq_off, cmdq_mask, reg_val);
|
||||
mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size);
|
||||
}
|
||||
|
||||
@ -1050,12 +1126,6 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_host_register(&dsi->host);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to register DSI host: %d\n", ret);
|
||||
goto err_ddp_comp_unregister;
|
||||
}
|
||||
|
||||
ret = mtk_dsi_create_conn_enc(drm, dsi);
|
||||
if (ret) {
|
||||
DRM_ERROR("Encoder create failed with %d\n", ret);
|
||||
@ -1065,8 +1135,6 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
return 0;
|
||||
|
||||
err_unregister:
|
||||
mipi_dsi_host_unregister(&dsi->host);
|
||||
err_ddp_comp_unregister:
|
||||
mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
|
||||
return ret;
|
||||
}
|
||||
@ -1078,7 +1146,6 @@ static void mtk_dsi_unbind(struct device *dev, struct device *master,
|
||||
struct mtk_dsi *dsi = dev_get_drvdata(dev);
|
||||
|
||||
mtk_dsi_destroy_conn_enc(dsi);
|
||||
mipi_dsi_host_unregister(&dsi->host);
|
||||
mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
|
||||
}
|
||||
|
||||
@ -1102,31 +1169,38 @@ static int mtk_dsi_probe(struct platform_device *pdev)
|
||||
|
||||
dsi->host.ops = &mtk_dsi_ops;
|
||||
dsi->host.dev = dev;
|
||||
ret = mipi_dsi_host_register(&dsi->host);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to register DSI host: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
|
||||
&dsi->panel, &dsi->bridge);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_unregister_host;
|
||||
|
||||
dsi->driver_data = of_device_get_match_data(dev);
|
||||
|
||||
dsi->engine_clk = devm_clk_get(dev, "engine");
|
||||
if (IS_ERR(dsi->engine_clk)) {
|
||||
ret = PTR_ERR(dsi->engine_clk);
|
||||
dev_err(dev, "Failed to get engine clock: %d\n", ret);
|
||||
return ret;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
dsi->digital_clk = devm_clk_get(dev, "digital");
|
||||
if (IS_ERR(dsi->digital_clk)) {
|
||||
ret = PTR_ERR(dsi->digital_clk);
|
||||
dev_err(dev, "Failed to get digital clock: %d\n", ret);
|
||||
return ret;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
dsi->hs_clk = devm_clk_get(dev, "hs");
|
||||
if (IS_ERR(dsi->hs_clk)) {
|
||||
ret = PTR_ERR(dsi->hs_clk);
|
||||
dev_err(dev, "Failed to get hs clock: %d\n", ret);
|
||||
return ret;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@ -1134,33 +1208,35 @@ static int mtk_dsi_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(dsi->regs)) {
|
||||
ret = PTR_ERR(dsi->regs);
|
||||
dev_err(dev, "Failed to ioremap memory: %d\n", ret);
|
||||
return ret;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
dsi->phy = devm_phy_get(dev, "dphy");
|
||||
if (IS_ERR(dsi->phy)) {
|
||||
ret = PTR_ERR(dsi->phy);
|
||||
dev_err(dev, "Failed to get MIPI-DPHY: %d\n", ret);
|
||||
return ret;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DSI);
|
||||
if (comp_id < 0) {
|
||||
dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
|
||||
return comp_id;
|
||||
ret = comp_id;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_init(dev, dev->of_node, &dsi->ddp_comp, comp_id,
|
||||
&mtk_dsi_funcs);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize component: %d\n", ret);
|
||||
return ret;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
irq_num = platform_get_irq(pdev, 0);
|
||||
if (irq_num < 0) {
|
||||
dev_err(&pdev->dev, "failed to request dsi irq resource\n");
|
||||
return -EPROBE_DEFER;
|
||||
dev_err(&pdev->dev, "failed to get dsi irq_num: %d\n", irq_num);
|
||||
ret = irq_num;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW);
|
||||
@ -1168,14 +1244,24 @@ static int mtk_dsi_probe(struct platform_device *pdev)
|
||||
IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request mediatek dsi irq\n");
|
||||
return -EPROBE_DEFER;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&dsi->irq_wait_queue);
|
||||
|
||||
platform_set_drvdata(pdev, dsi);
|
||||
|
||||
return component_add(&pdev->dev, &mtk_dsi_component_ops);
|
||||
ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add component: %d\n", ret);
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_host:
|
||||
mipi_dsi_host_unregister(&dsi->host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mtk_dsi_remove(struct platform_device *pdev)
|
||||
@ -1184,13 +1270,32 @@ static int mtk_dsi_remove(struct platform_device *pdev)
|
||||
|
||||
mtk_output_dsi_disable(dsi);
|
||||
component_del(&pdev->dev, &mtk_dsi_component_ops);
|
||||
mipi_dsi_host_unregister(&dsi->host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = {
|
||||
.reg_cmdq_off = 0x200,
|
||||
};
|
||||
|
||||
static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = {
|
||||
.reg_cmdq_off = 0x180,
|
||||
};
|
||||
|
||||
static const struct mtk_dsi_driver_data mt8183_dsi_driver_data = {
|
||||
.reg_cmdq_off = 0x200,
|
||||
.has_shadow_ctl = true,
|
||||
.has_size_ctl = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_dsi_of_match[] = {
|
||||
{ .compatible = "mediatek,mt2701-dsi" },
|
||||
{ .compatible = "mediatek,mt8173-dsi" },
|
||||
{ .compatible = "mediatek,mt2701-dsi",
|
||||
.data = &mt2701_dsi_driver_data },
|
||||
{ .compatible = "mediatek,mt8173-dsi",
|
||||
.data = &mt8173_dsi_driver_data },
|
||||
{ .compatible = "mediatek,mt8183-dsi",
|
||||
.data = &mt8183_dsi_driver_data },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -3,292 +3,39 @@
|
||||
* Copyright (c) 2015 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include "mtk_mipi_tx.h"
|
||||
|
||||
#define MIPITX_DSI_CON 0x00
|
||||
#define RG_DSI_LDOCORE_EN BIT(0)
|
||||
#define RG_DSI_CKG_LDOOUT_EN BIT(1)
|
||||
#define RG_DSI_BCLK_SEL (3 << 2)
|
||||
#define RG_DSI_LD_IDX_SEL (7 << 4)
|
||||
#define RG_DSI_PHYCLK_SEL (2 << 8)
|
||||
#define RG_DSI_DSICLK_FREQ_SEL BIT(10)
|
||||
#define RG_DSI_LPTX_CLMP_EN BIT(11)
|
||||
|
||||
#define MIPITX_DSI_CLOCK_LANE 0x04
|
||||
#define MIPITX_DSI_DATA_LANE0 0x08
|
||||
#define MIPITX_DSI_DATA_LANE1 0x0c
|
||||
#define MIPITX_DSI_DATA_LANE2 0x10
|
||||
#define MIPITX_DSI_DATA_LANE3 0x14
|
||||
#define RG_DSI_LNTx_LDOOUT_EN BIT(0)
|
||||
#define RG_DSI_LNTx_CKLANE_EN BIT(1)
|
||||
#define RG_DSI_LNTx_LPTX_IPLUS1 BIT(2)
|
||||
#define RG_DSI_LNTx_LPTX_IPLUS2 BIT(3)
|
||||
#define RG_DSI_LNTx_LPTX_IMINUS BIT(4)
|
||||
#define RG_DSI_LNTx_LPCD_IPLUS BIT(5)
|
||||
#define RG_DSI_LNTx_LPCD_IMINUS BIT(6)
|
||||
#define RG_DSI_LNTx_RT_CODE (0xf << 8)
|
||||
|
||||
#define MIPITX_DSI_TOP_CON 0x40
|
||||
#define RG_DSI_LNT_INTR_EN BIT(0)
|
||||
#define RG_DSI_LNT_HS_BIAS_EN BIT(1)
|
||||
#define RG_DSI_LNT_IMP_CAL_EN BIT(2)
|
||||
#define RG_DSI_LNT_TESTMODE_EN BIT(3)
|
||||
#define RG_DSI_LNT_IMP_CAL_CODE (0xf << 4)
|
||||
#define RG_DSI_LNT_AIO_SEL (7 << 8)
|
||||
#define RG_DSI_PAD_TIE_LOW_EN BIT(11)
|
||||
#define RG_DSI_DEBUG_INPUT_EN BIT(12)
|
||||
#define RG_DSI_PRESERVE (7 << 13)
|
||||
|
||||
#define MIPITX_DSI_BG_CON 0x44
|
||||
#define RG_DSI_BG_CORE_EN BIT(0)
|
||||
#define RG_DSI_BG_CKEN BIT(1)
|
||||
#define RG_DSI_BG_DIV (0x3 << 2)
|
||||
#define RG_DSI_BG_FAST_CHARGE BIT(4)
|
||||
#define RG_DSI_VOUT_MSK (0x3ffff << 5)
|
||||
#define RG_DSI_V12_SEL (7 << 5)
|
||||
#define RG_DSI_V10_SEL (7 << 8)
|
||||
#define RG_DSI_V072_SEL (7 << 11)
|
||||
#define RG_DSI_V04_SEL (7 << 14)
|
||||
#define RG_DSI_V032_SEL (7 << 17)
|
||||
#define RG_DSI_V02_SEL (7 << 20)
|
||||
#define RG_DSI_BG_R1_TRIM (0xf << 24)
|
||||
#define RG_DSI_BG_R2_TRIM (0xf << 28)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON0 0x50
|
||||
#define RG_DSI_MPPLL_PLL_EN BIT(0)
|
||||
#define RG_DSI_MPPLL_DIV_MSK (0x1ff << 1)
|
||||
#define RG_DSI_MPPLL_PREDIV (3 << 1)
|
||||
#define RG_DSI_MPPLL_TXDIV0 (3 << 3)
|
||||
#define RG_DSI_MPPLL_TXDIV1 (3 << 5)
|
||||
#define RG_DSI_MPPLL_POSDIV (7 << 7)
|
||||
#define RG_DSI_MPPLL_MONVC_EN BIT(10)
|
||||
#define RG_DSI_MPPLL_MONREF_EN BIT(11)
|
||||
#define RG_DSI_MPPLL_VOD_EN BIT(12)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON1 0x54
|
||||
#define RG_DSI_MPPLL_SDM_FRA_EN BIT(0)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_PH_INIT BIT(1)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_EN BIT(2)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_PRD (0xffff << 16)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON2 0x58
|
||||
|
||||
#define MIPITX_DSI_PLL_TOP 0x64
|
||||
#define RG_DSI_MPPLL_PRESERVE (0xff << 8)
|
||||
|
||||
#define MIPITX_DSI_PLL_PWR 0x68
|
||||
#define RG_DSI_MPPLL_SDM_PWR_ON BIT(0)
|
||||
#define RG_DSI_MPPLL_SDM_ISO_EN BIT(1)
|
||||
#define RG_DSI_MPPLL_SDM_PWR_ACK BIT(8)
|
||||
|
||||
#define MIPITX_DSI_SW_CTRL 0x80
|
||||
#define SW_CTRL_EN BIT(0)
|
||||
|
||||
#define MIPITX_DSI_SW_CTRL_CON0 0x84
|
||||
#define SW_LNTC_LPTX_PRE_OE BIT(0)
|
||||
#define SW_LNTC_LPTX_OE BIT(1)
|
||||
#define SW_LNTC_LPTX_P BIT(2)
|
||||
#define SW_LNTC_LPTX_N BIT(3)
|
||||
#define SW_LNTC_HSTX_PRE_OE BIT(4)
|
||||
#define SW_LNTC_HSTX_OE BIT(5)
|
||||
#define SW_LNTC_HSTX_ZEROCLK BIT(6)
|
||||
#define SW_LNT0_LPTX_PRE_OE BIT(7)
|
||||
#define SW_LNT0_LPTX_OE BIT(8)
|
||||
#define SW_LNT0_LPTX_P BIT(9)
|
||||
#define SW_LNT0_LPTX_N BIT(10)
|
||||
#define SW_LNT0_HSTX_PRE_OE BIT(11)
|
||||
#define SW_LNT0_HSTX_OE BIT(12)
|
||||
#define SW_LNT0_LPRX_EN BIT(13)
|
||||
#define SW_LNT1_LPTX_PRE_OE BIT(14)
|
||||
#define SW_LNT1_LPTX_OE BIT(15)
|
||||
#define SW_LNT1_LPTX_P BIT(16)
|
||||
#define SW_LNT1_LPTX_N BIT(17)
|
||||
#define SW_LNT1_HSTX_PRE_OE BIT(18)
|
||||
#define SW_LNT1_HSTX_OE BIT(19)
|
||||
#define SW_LNT2_LPTX_PRE_OE BIT(20)
|
||||
#define SW_LNT2_LPTX_OE BIT(21)
|
||||
#define SW_LNT2_LPTX_P BIT(22)
|
||||
#define SW_LNT2_LPTX_N BIT(23)
|
||||
#define SW_LNT2_HSTX_PRE_OE BIT(24)
|
||||
#define SW_LNT2_HSTX_OE BIT(25)
|
||||
|
||||
struct mtk_mipitx_data {
|
||||
const u32 mppll_preserve;
|
||||
};
|
||||
|
||||
struct mtk_mipi_tx {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
u32 data_rate;
|
||||
const struct mtk_mipitx_data *driver_data;
|
||||
struct clk_hw pll_hw;
|
||||
struct clk *pll;
|
||||
};
|
||||
|
||||
static inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw)
|
||||
inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct mtk_mipi_tx, pll_hw);
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 bits)
|
||||
void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 bits)
|
||||
{
|
||||
u32 temp = readl(mipi_tx->regs + offset);
|
||||
|
||||
writel(temp & ~bits, mipi_tx->regs + offset);
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 bits)
|
||||
void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 bits)
|
||||
{
|
||||
u32 temp = readl(mipi_tx->regs + offset);
|
||||
|
||||
writel(temp | bits, mipi_tx->regs + offset);
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 mask, u32 data)
|
||||
void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 mask, u32 data)
|
||||
{
|
||||
u32 temp = readl(mipi_tx->regs + offset);
|
||||
|
||||
writel((temp & ~mask) | (data & mask), mipi_tx->regs + offset);
|
||||
}
|
||||
|
||||
static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
u8 txdiv, txdiv0, txdiv1;
|
||||
u64 pcw;
|
||||
|
||||
dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate);
|
||||
|
||||
if (mipi_tx->data_rate >= 500000000) {
|
||||
txdiv = 1;
|
||||
txdiv0 = 0;
|
||||
txdiv1 = 0;
|
||||
} else if (mipi_tx->data_rate >= 250000000) {
|
||||
txdiv = 2;
|
||||
txdiv0 = 1;
|
||||
txdiv1 = 0;
|
||||
} else if (mipi_tx->data_rate >= 125000000) {
|
||||
txdiv = 4;
|
||||
txdiv0 = 2;
|
||||
txdiv1 = 0;
|
||||
} else if (mipi_tx->data_rate > 62000000) {
|
||||
txdiv = 8;
|
||||
txdiv0 = 2;
|
||||
txdiv1 = 1;
|
||||
} else if (mipi_tx->data_rate >= 50000000) {
|
||||
txdiv = 16;
|
||||
txdiv0 = 2;
|
||||
txdiv1 = 2;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_BG_CON,
|
||||
RG_DSI_VOUT_MSK |
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN,
|
||||
(4 << 20) | (4 << 17) | (4 << 14) |
|
||||
(4 << 11) | (4 << 8) | (4 << 5) |
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
|
||||
usleep_range(30, 100);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
|
||||
(8 << 4) | RG_DSI_LNT_HS_BIAS_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON |
|
||||
RG_DSI_MPPLL_SDM_ISO_EN,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 |
|
||||
RG_DSI_MPPLL_PREDIV,
|
||||
(txdiv0 << 3) | (txdiv1 << 5));
|
||||
|
||||
/*
|
||||
* PLL PCW config
|
||||
* PCW bit 24~30 = integer part of pcw
|
||||
* PCW bit 0~23 = fractional part of pcw
|
||||
* pcw = data_Rate*4*txdiv/(Ref_clk*2);
|
||||
* Post DIV =4, so need data_Rate*4
|
||||
* Ref_clk is 26MHz
|
||||
*/
|
||||
pcw = div_u64(((u64)mipi_tx->data_rate * 2 * txdiv) << 24,
|
||||
26000000);
|
||||
writel(pcw, mipi_tx->regs + MIPITX_DSI_PLL_CON2);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
|
||||
RG_DSI_MPPLL_SDM_FRA_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
usleep_range(20, 100);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
|
||||
RG_DSI_MPPLL_SDM_SSC_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
|
||||
RG_DSI_MPPLL_PRESERVE,
|
||||
mipi_tx->driver_data->mppll_preserve);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
|
||||
dev_dbg(mipi_tx->dev, "unprepare\n");
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
|
||||
RG_DSI_MPPLL_PRESERVE, 0);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN |
|
||||
RG_DSI_MPPLL_SDM_PWR_ON,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_LNT_HS_BIAS_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_BG_CON,
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_DIV_MSK);
|
||||
}
|
||||
|
||||
static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
return clamp_val(rate, 50000000, 1250000000);
|
||||
}
|
||||
|
||||
static int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
|
||||
@ -299,37 +46,14 @@ static int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
|
||||
return mipi_tx->data_rate;
|
||||
}
|
||||
|
||||
static const struct clk_ops mtk_mipi_tx_pll_ops = {
|
||||
.prepare = mtk_mipi_tx_pll_prepare,
|
||||
.unprepare = mtk_mipi_tx_pll_unprepare,
|
||||
.round_rate = mtk_mipi_tx_pll_round_rate,
|
||||
.set_rate = mtk_mipi_tx_pll_set_rate,
|
||||
.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
|
||||
};
|
||||
|
||||
static int mtk_mipi_tx_power_on_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
u32 reg;
|
||||
|
||||
for (reg = MIPITX_DSI_CLOCK_LANE;
|
||||
reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
|
||||
mtk_mipi_tx_set_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_mipi_tx_power_on(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
@ -341,30 +65,16 @@ static int mtk_mipi_tx_power_on(struct phy *phy)
|
||||
return ret;
|
||||
|
||||
/* Enable DSI Lane LDO outputs, disable pad tie low */
|
||||
mtk_mipi_tx_power_on_signal(phy);
|
||||
|
||||
mipi_tx->driver_data->mipi_tx_enable_signal(phy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_power_off_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
u32 reg;
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
|
||||
for (reg = MIPITX_DSI_CLOCK_LANE;
|
||||
reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
}
|
||||
|
||||
static int mtk_mipi_tx_power_off(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
|
||||
/* Enable pad tie low, disable DSI Lane LDO outputs */
|
||||
mtk_mipi_tx_power_off_signal(phy);
|
||||
mipi_tx->driver_data->mipi_tx_disable_signal(phy);
|
||||
|
||||
/* Disable PLL and power down core */
|
||||
clk_disable_unprepare(mipi_tx->pll);
|
||||
@ -383,10 +93,9 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_mipi_tx *mipi_tx;
|
||||
struct resource *mem;
|
||||
struct clk *ref_clk;
|
||||
const char *ref_clk_name;
|
||||
struct clk *ref_clk;
|
||||
struct clk_init_data clk_init = {
|
||||
.ops = &mtk_mipi_tx_pll_ops,
|
||||
.num_parents = 1,
|
||||
.parent_names = (const char * const *)&ref_clk_name,
|
||||
.flags = CLK_SET_RATE_GATE,
|
||||
@ -400,6 +109,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi_tx->driver_data = of_device_get_match_data(dev);
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mipi_tx->regs = devm_ioremap_resource(dev, mem);
|
||||
if (IS_ERR(mipi_tx->regs)) {
|
||||
@ -414,6 +124,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "Failed to get reference clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ref_clk_name = __clk_get_name(ref_clk);
|
||||
|
||||
ret = of_property_read_string(dev->of_node, "clock-output-names",
|
||||
@ -423,6 +134,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
clk_init.ops = mipi_tx->driver_data->mipi_tx_clk_ops;
|
||||
|
||||
mipi_tx->pll_hw.init = &clk_init;
|
||||
mipi_tx->pll = devm_clk_register(dev, &mipi_tx->pll_hw);
|
||||
if (IS_ERR(mipi_tx->pll)) {
|
||||
@ -457,20 +170,14 @@ static int mtk_mipi_tx_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtk_mipitx_data mt2701_mipitx_data = {
|
||||
.mppll_preserve = (3 << 8)
|
||||
};
|
||||
|
||||
static const struct mtk_mipitx_data mt8173_mipitx_data = {
|
||||
.mppll_preserve = (0 << 8)
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_mipi_tx_match[] = {
|
||||
{ .compatible = "mediatek,mt2701-mipi-tx",
|
||||
.data = &mt2701_mipitx_data },
|
||||
{ .compatible = "mediatek,mt8173-mipi-tx",
|
||||
.data = &mt8173_mipitx_data },
|
||||
{},
|
||||
{ .compatible = "mediatek,mt8183-mipi-tx",
|
||||
.data = &mt8183_mipitx_data },
|
||||
{ },
|
||||
};
|
||||
|
||||
struct platform_driver mtk_mipi_tx_driver = {
|
||||
@ -481,3 +188,4 @@ struct platform_driver mtk_mipi_tx_driver = {
|
||||
.of_match_table = mtk_mipi_tx_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
49
drivers/gpu/drm/mediatek/mtk_mipi_tx.h
Normal file
49
drivers/gpu/drm/mediatek/mtk_mipi_tx.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2019 MediaTek Inc.
|
||||
* Author: Jitao Shi <jitao.shi@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _MTK_MIPI_TX_H
|
||||
#define _MTK_MIPI_TX_H
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
|
||||
struct mtk_mipitx_data {
|
||||
const u32 mppll_preserve;
|
||||
const struct clk_ops *mipi_tx_clk_ops;
|
||||
void (*mipi_tx_enable_signal)(struct phy *phy);
|
||||
void (*mipi_tx_disable_signal)(struct phy *phy);
|
||||
};
|
||||
|
||||
struct mtk_mipi_tx {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
u32 data_rate;
|
||||
const struct mtk_mipitx_data *driver_data;
|
||||
struct clk_hw pll_hw;
|
||||
struct clk *pll;
|
||||
};
|
||||
|
||||
struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw);
|
||||
void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 bits);
|
||||
void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 bits);
|
||||
void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 mask,
|
||||
u32 data);
|
||||
int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
|
||||
extern const struct mtk_mipitx_data mt2701_mipitx_data;
|
||||
extern const struct mtk_mipitx_data mt8173_mipitx_data;
|
||||
extern const struct mtk_mipitx_data mt8183_mipitx_data;
|
||||
|
||||
#endif
|
288
drivers/gpu/drm/mediatek/mtk_mt8173_mipi_tx.c
Normal file
288
drivers/gpu/drm/mediatek/mtk_mt8173_mipi_tx.c
Normal file
@ -0,0 +1,288 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 MediaTek Inc.
|
||||
* Author: jitao.shi <jitao.shi@mediatek.com>
|
||||
*/
|
||||
|
||||
#include "mtk_mipi_tx.h"
|
||||
|
||||
#define MIPITX_DSI_CON 0x00
|
||||
#define RG_DSI_LDOCORE_EN BIT(0)
|
||||
#define RG_DSI_CKG_LDOOUT_EN BIT(1)
|
||||
#define RG_DSI_BCLK_SEL (3 << 2)
|
||||
#define RG_DSI_LD_IDX_SEL (7 << 4)
|
||||
#define RG_DSI_PHYCLK_SEL (2 << 8)
|
||||
#define RG_DSI_DSICLK_FREQ_SEL BIT(10)
|
||||
#define RG_DSI_LPTX_CLMP_EN BIT(11)
|
||||
|
||||
#define MIPITX_DSI_CLOCK_LANE 0x04
|
||||
#define MIPITX_DSI_DATA_LANE0 0x08
|
||||
#define MIPITX_DSI_DATA_LANE1 0x0c
|
||||
#define MIPITX_DSI_DATA_LANE2 0x10
|
||||
#define MIPITX_DSI_DATA_LANE3 0x14
|
||||
#define RG_DSI_LNTx_LDOOUT_EN BIT(0)
|
||||
#define RG_DSI_LNTx_CKLANE_EN BIT(1)
|
||||
#define RG_DSI_LNTx_LPTX_IPLUS1 BIT(2)
|
||||
#define RG_DSI_LNTx_LPTX_IPLUS2 BIT(3)
|
||||
#define RG_DSI_LNTx_LPTX_IMINUS BIT(4)
|
||||
#define RG_DSI_LNTx_LPCD_IPLUS BIT(5)
|
||||
#define RG_DSI_LNTx_LPCD_IMINUS BIT(6)
|
||||
#define RG_DSI_LNTx_RT_CODE (0xf << 8)
|
||||
|
||||
#define MIPITX_DSI_TOP_CON 0x40
|
||||
#define RG_DSI_LNT_INTR_EN BIT(0)
|
||||
#define RG_DSI_LNT_HS_BIAS_EN BIT(1)
|
||||
#define RG_DSI_LNT_IMP_CAL_EN BIT(2)
|
||||
#define RG_DSI_LNT_TESTMODE_EN BIT(3)
|
||||
#define RG_DSI_LNT_IMP_CAL_CODE (0xf << 4)
|
||||
#define RG_DSI_LNT_AIO_SEL (7 << 8)
|
||||
#define RG_DSI_PAD_TIE_LOW_EN BIT(11)
|
||||
#define RG_DSI_DEBUG_INPUT_EN BIT(12)
|
||||
#define RG_DSI_PRESERVE (7 << 13)
|
||||
|
||||
#define MIPITX_DSI_BG_CON 0x44
|
||||
#define RG_DSI_BG_CORE_EN BIT(0)
|
||||
#define RG_DSI_BG_CKEN BIT(1)
|
||||
#define RG_DSI_BG_DIV (0x3 << 2)
|
||||
#define RG_DSI_BG_FAST_CHARGE BIT(4)
|
||||
#define RG_DSI_VOUT_MSK (0x3ffff << 5)
|
||||
#define RG_DSI_V12_SEL (7 << 5)
|
||||
#define RG_DSI_V10_SEL (7 << 8)
|
||||
#define RG_DSI_V072_SEL (7 << 11)
|
||||
#define RG_DSI_V04_SEL (7 << 14)
|
||||
#define RG_DSI_V032_SEL (7 << 17)
|
||||
#define RG_DSI_V02_SEL (7 << 20)
|
||||
#define RG_DSI_BG_R1_TRIM (0xf << 24)
|
||||
#define RG_DSI_BG_R2_TRIM (0xf << 28)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON0 0x50
|
||||
#define RG_DSI_MPPLL_PLL_EN BIT(0)
|
||||
#define RG_DSI_MPPLL_DIV_MSK (0x1ff << 1)
|
||||
#define RG_DSI_MPPLL_PREDIV (3 << 1)
|
||||
#define RG_DSI_MPPLL_TXDIV0 (3 << 3)
|
||||
#define RG_DSI_MPPLL_TXDIV1 (3 << 5)
|
||||
#define RG_DSI_MPPLL_POSDIV (7 << 7)
|
||||
#define RG_DSI_MPPLL_MONVC_EN BIT(10)
|
||||
#define RG_DSI_MPPLL_MONREF_EN BIT(11)
|
||||
#define RG_DSI_MPPLL_VOD_EN BIT(12)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON1 0x54
|
||||
#define RG_DSI_MPPLL_SDM_FRA_EN BIT(0)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_PH_INIT BIT(1)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_EN BIT(2)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_PRD (0xffff << 16)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON2 0x58
|
||||
|
||||
#define MIPITX_DSI_PLL_TOP 0x64
|
||||
#define RG_DSI_MPPLL_PRESERVE (0xff << 8)
|
||||
|
||||
#define MIPITX_DSI_PLL_PWR 0x68
|
||||
#define RG_DSI_MPPLL_SDM_PWR_ON BIT(0)
|
||||
#define RG_DSI_MPPLL_SDM_ISO_EN BIT(1)
|
||||
#define RG_DSI_MPPLL_SDM_PWR_ACK BIT(8)
|
||||
|
||||
#define MIPITX_DSI_SW_CTRL 0x80
|
||||
#define SW_CTRL_EN BIT(0)
|
||||
|
||||
#define MIPITX_DSI_SW_CTRL_CON0 0x84
|
||||
#define SW_LNTC_LPTX_PRE_OE BIT(0)
|
||||
#define SW_LNTC_LPTX_OE BIT(1)
|
||||
#define SW_LNTC_LPTX_P BIT(2)
|
||||
#define SW_LNTC_LPTX_N BIT(3)
|
||||
#define SW_LNTC_HSTX_PRE_OE BIT(4)
|
||||
#define SW_LNTC_HSTX_OE BIT(5)
|
||||
#define SW_LNTC_HSTX_ZEROCLK BIT(6)
|
||||
#define SW_LNT0_LPTX_PRE_OE BIT(7)
|
||||
#define SW_LNT0_LPTX_OE BIT(8)
|
||||
#define SW_LNT0_LPTX_P BIT(9)
|
||||
#define SW_LNT0_LPTX_N BIT(10)
|
||||
#define SW_LNT0_HSTX_PRE_OE BIT(11)
|
||||
#define SW_LNT0_HSTX_OE BIT(12)
|
||||
#define SW_LNT0_LPRX_EN BIT(13)
|
||||
#define SW_LNT1_LPTX_PRE_OE BIT(14)
|
||||
#define SW_LNT1_LPTX_OE BIT(15)
|
||||
#define SW_LNT1_LPTX_P BIT(16)
|
||||
#define SW_LNT1_LPTX_N BIT(17)
|
||||
#define SW_LNT1_HSTX_PRE_OE BIT(18)
|
||||
#define SW_LNT1_HSTX_OE BIT(19)
|
||||
#define SW_LNT2_LPTX_PRE_OE BIT(20)
|
||||
#define SW_LNT2_LPTX_OE BIT(21)
|
||||
#define SW_LNT2_LPTX_P BIT(22)
|
||||
#define SW_LNT2_LPTX_N BIT(23)
|
||||
#define SW_LNT2_HSTX_PRE_OE BIT(24)
|
||||
#define SW_LNT2_HSTX_OE BIT(25)
|
||||
|
||||
static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
u8 txdiv, txdiv0, txdiv1;
|
||||
u64 pcw;
|
||||
|
||||
dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate);
|
||||
|
||||
if (mipi_tx->data_rate >= 500000000) {
|
||||
txdiv = 1;
|
||||
txdiv0 = 0;
|
||||
txdiv1 = 0;
|
||||
} else if (mipi_tx->data_rate >= 250000000) {
|
||||
txdiv = 2;
|
||||
txdiv0 = 1;
|
||||
txdiv1 = 0;
|
||||
} else if (mipi_tx->data_rate >= 125000000) {
|
||||
txdiv = 4;
|
||||
txdiv0 = 2;
|
||||
txdiv1 = 0;
|
||||
} else if (mipi_tx->data_rate > 62000000) {
|
||||
txdiv = 8;
|
||||
txdiv0 = 2;
|
||||
txdiv1 = 1;
|
||||
} else if (mipi_tx->data_rate >= 50000000) {
|
||||
txdiv = 16;
|
||||
txdiv0 = 2;
|
||||
txdiv1 = 2;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_BG_CON,
|
||||
RG_DSI_VOUT_MSK |
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN,
|
||||
(4 << 20) | (4 << 17) | (4 << 14) |
|
||||
(4 << 11) | (4 << 8) | (4 << 5) |
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
|
||||
usleep_range(30, 100);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
|
||||
(8 << 4) | RG_DSI_LNT_HS_BIAS_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON |
|
||||
RG_DSI_MPPLL_SDM_ISO_EN,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 |
|
||||
RG_DSI_MPPLL_PREDIV,
|
||||
(txdiv0 << 3) | (txdiv1 << 5));
|
||||
|
||||
/*
|
||||
* PLL PCW config
|
||||
* PCW bit 24~30 = integer part of pcw
|
||||
* PCW bit 0~23 = fractional part of pcw
|
||||
* pcw = data_Rate*4*txdiv/(Ref_clk*2);
|
||||
* Post DIV =4, so need data_Rate*4
|
||||
* Ref_clk is 26MHz
|
||||
*/
|
||||
pcw = div_u64(((u64)mipi_tx->data_rate * 2 * txdiv) << 24,
|
||||
26000000);
|
||||
writel(pcw, mipi_tx->regs + MIPITX_DSI_PLL_CON2);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
|
||||
RG_DSI_MPPLL_SDM_FRA_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
usleep_range(20, 100);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
|
||||
RG_DSI_MPPLL_SDM_SSC_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
|
||||
RG_DSI_MPPLL_PRESERVE,
|
||||
mipi_tx->driver_data->mppll_preserve);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
|
||||
dev_dbg(mipi_tx->dev, "unprepare\n");
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
|
||||
RG_DSI_MPPLL_PRESERVE, 0);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN |
|
||||
RG_DSI_MPPLL_SDM_PWR_ON,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_LNT_HS_BIAS_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_BG_CON,
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_DIV_MSK);
|
||||
}
|
||||
|
||||
static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
return clamp_val(rate, 50000000, 1250000000);
|
||||
}
|
||||
|
||||
static const struct clk_ops mtk_mipi_tx_pll_ops = {
|
||||
.prepare = mtk_mipi_tx_pll_prepare,
|
||||
.unprepare = mtk_mipi_tx_pll_unprepare,
|
||||
.round_rate = mtk_mipi_tx_pll_round_rate,
|
||||
.set_rate = mtk_mipi_tx_pll_set_rate,
|
||||
.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
|
||||
};
|
||||
|
||||
static void mtk_mipi_tx_power_on_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
u32 reg;
|
||||
|
||||
for (reg = MIPITX_DSI_CLOCK_LANE;
|
||||
reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
|
||||
mtk_mipi_tx_set_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_power_off_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
u32 reg;
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
|
||||
for (reg = MIPITX_DSI_CLOCK_LANE;
|
||||
reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
}
|
||||
|
||||
const struct mtk_mipitx_data mt2701_mipitx_data = {
|
||||
.mppll_preserve = (3 << 8),
|
||||
.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
|
||||
.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
|
||||
.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
|
||||
};
|
||||
|
||||
const struct mtk_mipitx_data mt8173_mipitx_data = {
|
||||
.mppll_preserve = (0 << 8),
|
||||
.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
|
||||
.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
|
||||
.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
|
||||
};
|
149
drivers/gpu/drm/mediatek/mtk_mt8183_mipi_tx.c
Normal file
149
drivers/gpu/drm/mediatek/mtk_mt8183_mipi_tx.c
Normal file
@ -0,0 +1,149 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 MediaTek Inc.
|
||||
* Author: jitao.shi <jitao.shi@mediatek.com>
|
||||
*/
|
||||
|
||||
#include "mtk_mipi_tx.h"
|
||||
|
||||
#define MIPITX_LANE_CON 0x000c
|
||||
#define RG_DSI_CPHY_T1DRV_EN BIT(0)
|
||||
#define RG_DSI_ANA_CK_SEL BIT(1)
|
||||
#define RG_DSI_PHY_CK_SEL BIT(2)
|
||||
#define RG_DSI_CPHY_EN BIT(3)
|
||||
#define RG_DSI_PHYCK_INV_EN BIT(4)
|
||||
#define RG_DSI_PWR04_EN BIT(5)
|
||||
#define RG_DSI_BG_LPF_EN BIT(6)
|
||||
#define RG_DSI_BG_CORE_EN BIT(7)
|
||||
#define RG_DSI_PAD_TIEL_SEL BIT(8)
|
||||
|
||||
#define MIPITX_PLL_PWR 0x0028
|
||||
#define MIPITX_PLL_CON0 0x002c
|
||||
#define MIPITX_PLL_CON1 0x0030
|
||||
#define MIPITX_PLL_CON2 0x0034
|
||||
#define MIPITX_PLL_CON3 0x0038
|
||||
#define MIPITX_PLL_CON4 0x003c
|
||||
#define RG_DSI_PLL_IBIAS (3 << 10)
|
||||
|
||||
#define MIPITX_D2_SW_CTL_EN 0x0144
|
||||
#define MIPITX_D0_SW_CTL_EN 0x0244
|
||||
#define MIPITX_CK_CKMODE_EN 0x0328
|
||||
#define DSI_CK_CKMODE_EN BIT(0)
|
||||
#define MIPITX_CK_SW_CTL_EN 0x0344
|
||||
#define MIPITX_D1_SW_CTL_EN 0x0444
|
||||
#define MIPITX_D3_SW_CTL_EN 0x0544
|
||||
#define DSI_SW_CTL_EN BIT(0)
|
||||
#define AD_DSI_PLL_SDM_PWR_ON BIT(0)
|
||||
#define AD_DSI_PLL_SDM_ISO_EN BIT(1)
|
||||
|
||||
#define RG_DSI_PLL_EN BIT(4)
|
||||
#define RG_DSI_PLL_POSDIV (0x7 << 8)
|
||||
|
||||
static int mtk_mipi_tx_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
unsigned int txdiv, txdiv0;
|
||||
u64 pcw;
|
||||
|
||||
dev_dbg(mipi_tx->dev, "enable: %u bps\n", mipi_tx->data_rate);
|
||||
|
||||
if (mipi_tx->data_rate >= 2000000000) {
|
||||
txdiv = 1;
|
||||
txdiv0 = 0;
|
||||
} else if (mipi_tx->data_rate >= 1000000000) {
|
||||
txdiv = 2;
|
||||
txdiv0 = 1;
|
||||
} else if (mipi_tx->data_rate >= 500000000) {
|
||||
txdiv = 4;
|
||||
txdiv0 = 2;
|
||||
} else if (mipi_tx->data_rate > 250000000) {
|
||||
txdiv = 8;
|
||||
txdiv0 = 3;
|
||||
} else if (mipi_tx->data_rate >= 125000000) {
|
||||
txdiv = 16;
|
||||
txdiv0 = 4;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON4, RG_DSI_PLL_IBIAS);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
udelay(1);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
|
||||
pcw = div_u64(((u64)mipi_tx->data_rate * txdiv) << 24, 26000000);
|
||||
writel(pcw, mipi_tx->regs + MIPITX_PLL_CON0);
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_POSDIV,
|
||||
txdiv0 << 8);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_pll_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
|
||||
}
|
||||
|
||||
static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
return clamp_val(rate, 50000000, 1600000000);
|
||||
}
|
||||
|
||||
static const struct clk_ops mtk_mipi_tx_pll_ops = {
|
||||
.enable = mtk_mipi_tx_pll_enable,
|
||||
.disable = mtk_mipi_tx_pll_disable,
|
||||
.round_rate = mtk_mipi_tx_pll_round_rate,
|
||||
.set_rate = mtk_mipi_tx_pll_set_rate,
|
||||
.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
|
||||
};
|
||||
|
||||
static void mtk_mipi_tx_power_on_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
|
||||
/* BG_LPF_EN / BG_CORE_EN */
|
||||
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN,
|
||||
mipi_tx->regs + MIPITX_LANE_CON);
|
||||
usleep_range(30, 100);
|
||||
writel(RG_DSI_BG_CORE_EN | RG_DSI_BG_LPF_EN,
|
||||
mipi_tx->regs + MIPITX_LANE_CON);
|
||||
|
||||
/* Switch OFF each Lane */
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN);
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_power_off_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
|
||||
/* Switch ON each Lane */
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
|
||||
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN,
|
||||
mipi_tx->regs + MIPITX_LANE_CON);
|
||||
writel(RG_DSI_PAD_TIEL_SEL, mipi_tx->regs + MIPITX_LANE_CON);
|
||||
}
|
||||
|
||||
const struct mtk_mipitx_data mt8183_mipitx_data = {
|
||||
.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
|
||||
.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
|
||||
.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
|
||||
};
|
Loading…
Reference in New Issue
Block a user