Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1451823 > unrolled thread
| Started by | YT Shen <yt.shen@mediatek.com> |
|---|---|
| First post | 2016-07-28 11:30 +0200 |
| Last post | 2016-07-28 11:40 +0200 |
| Articles | 8 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v5 00/10] MT2701 DRM support YT Shen <yt.shen@mediatek.com> - 2016-07-28 11:30 +0200
[PATCH v5 02/10] drm/mediatek: add *driver_data for different hardware settings YT Shen <yt.shen@mediatek.com> - 2016-07-28 11:30 +0200
[PATCH v5 10/10] arm: dts: mt2701: Add display subsystem related nodes for MT2701 YT Shen <yt.shen@mediatek.com> - 2016-07-28 11:40 +0200
[PATCH v5 09/10] drm/mediatek: add support for Mediatek SoC MT2701 YT Shen <yt.shen@mediatek.com> - 2016-07-28 11:40 +0200
[PATCH v5 07/10] drm/mediatek: add dsi transfer function YT Shen <yt.shen@mediatek.com> - 2016-07-28 11:40 +0200
Re: [PATCH v5 07/10] drm/mediatek: add dsi transfer function CK Hu <ck.hu@mediatek.com> - 2016-08-02 09:30 +0200
Re: [PATCH v5 07/10] drm/mediatek: add dsi transfer function YT Shen <yt.shen@mediatek.com> - 2016-08-02 11:20 +0200
[PATCH v5 08/10] drm/mediatek: update DSI sub driver flow YT Shen <yt.shen@mediatek.com> - 2016-07-28 11:40 +0200
| From | YT Shen <yt.shen@mediatek.com> |
|---|---|
| Date | 2016-07-28 11:30 +0200 |
| Subject | [PATCH v5 00/10] MT2701 DRM support |
| Message-ID | <rZPND-4ie-7@gated-at.bofh.it> |
This is MT2701 DRM support PATCH v5, based on 4.7-rc1.
We add DSI interrupt control, transfer function for MIPI DSI panel support.
Most codes are the same, except some register changed.
For example:
- DISP_OVL address offset changed, color format definition changed.
- DISP_RDMA fifo size changed.
- DISP_COLOR offset changed.
- MIPI_TX setting changed.
We add a new component DDP_COMPONENT_BLS, and the connections are updated.
OVL -> RDMA -> COLOR -> BLS -> DSI
RDMA -> DPI
And we have shadow register support in MT2701.
Changes since v4:
- Add messages when timeout in mtk_disp_mutex_acquire()
- Add descriptions for DISP_REG_MUTEX registers
- Move connection settings for display modules to a separate patch
- Remove 'mt2701-disp-wdma' because it is unused
- Move cleaning up and renaming to a separate patch
- Use wait_event_interruptible_timeout() to replace polling
- Remove irq_num from mtk_dsi structure
- Remove redundant and debug codes
Changes since v3:
- Add DSI support for MIPI DSI panels
- Update BLS binding to PWM nodes
- Remove ufoe device nodes
- Remove redundant parentheses
- Remove global variable initialization
Changes since v2:
- Rename mtk_ddp_mux_sel to mtk_ddp_sout_sel
- Update mt2701_mtk_ddp_ext components
- Changed to prefix naming
- Reorder the patch series
- Use of_device_get_match_data() to get driver private data
- Use iopoll macros to implement mtk_disp_mutex_acquire()
- Removed empty device tree nodes
Changes since v1:
- Removed BLS bindings and codes, which belong to pwm driver
- Moved mtk_disp_mutex_acquire() just before mtk_crtc_ddp_config()
- Split patch into smaller parts
- Added const keyword to constant structure
- Removed codes for special memory align
The PATCH depends on the following patch:
https://patchwork.kernel.org/patch/8832441/ ("dt-bindings: ARM: Mediatek: Document bindings for MT2701")
https://patchwork.kernel.org/patch/9222997/ ("dt-bindings: pwm: Add MediaTek display PWM bindings")
https://patchwork.kernel.org/patch/9164029/ ("dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and smi")
https://patchwork.kernel.org/patch/9164017/ ("iommu/mediatek: move the common struct into header file")
https://patchwork.kernel.org/patch/9164025/ ("memory/mediatek: add support for mt2701")
https://patchwork.kernel.org/patch/9164041/ ("iommu/mediatek: add support for mtk iommu generation one HW")
https://patchwork.kernel.org/patch/9164013/ ("ARM: dts: mt2701: add iommu/smi dtsi node for mt2701")
Thanks,
yt.shen
YT Shen (8):
drm/mediatek: rename macros, add chip prefix
drm/mediatek: add *driver_data for different hardware settings
drm/mediatek: add shadow register support
drm/mediatek: update display module connections
drm/mediatek: cleaning up and refine
drm/mediatek: update DSI sub driver flow
drm/mediatek: add support for Mediatek SoC MT2701
arm: dts: mt2701: Add display subsystem related nodes for MT2701
shaoming chen (2):
drm/mediatek: add dsi interrupt control
drm/mediatek: add dsi transfer function
arch/arm/boot/dts/mt2701.dtsi | 100 +++++
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 32 +-
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 17 +-
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 75 ++--
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 137 +++++--
drivers/gpu/drm/mediatek/mtk_drm_ddp.h | 2 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 34 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 14 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 55 ++-
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 9 +
drivers/gpu/drm/mediatek/mtk_dsi.c | 548 ++++++++++++++++++++++++---
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 67 +++-
12 files changed, 930 insertions(+), 160 deletions(-)
--
1.7.9.5
[toc] | [next] | [standalone]
| From | YT Shen <yt.shen@mediatek.com> |
|---|---|
| Date | 2016-07-28 11:30 +0200 |
| Subject | [PATCH v5 02/10] drm/mediatek: add *driver_data for different hardware settings |
| Message-ID | <rZPND-4ie-19@gated-at.bofh.it> |
| In reply to | #1451823 |
There are some hardware settings changed, between MT8173 & MT2701:
DISP_OVL address offset changed, color format definition changed.
DISP_RDMA fifo size changed.
DISP_COLOR offset changed.
And add prefix for mtk_ddp_main & mtk_ddp_ext & mutex_mod.
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 26 ++++++++++++++++----------
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 11 +++++++++--
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 11 +++++++----
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 27 +++++++++++++++++++++------
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 13 +++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 25 ++++++++++++++++++-------
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 8 ++++++++
7 files changed, 92 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 8f62671f..eb5c05e 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -40,8 +40,6 @@
#define OVL_RDMA_MEM_GMC 0x40402020
#define OVL_CON_BYTE_SWAP BIT(24)
-#define OVL_CON_CLRFMT_RGB565 (0 << 12)
-#define OVL_CON_CLRFMT_RGB888 (1 << 12)
#define OVL_CON_CLRFMT_RGBA8888 (2 << 12)
#define OVL_CON_CLRFMT_ARGB8888 (3 << 12)
#define OVL_CON_AEN BIT(8)
@@ -136,18 +134,18 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
}
-static unsigned int ovl_fmt_convert(unsigned int fmt)
+static unsigned int ovl_fmt_convert(struct mtk_ddp_comp *comp, unsigned int fmt)
{
switch (fmt) {
default:
case DRM_FORMAT_RGB565:
- return OVL_CON_CLRFMT_RGB565;
+ return comp->data->ovl.fmt_rgb565;
case DRM_FORMAT_BGR565:
- return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP;
+ return comp->data->ovl.fmt_rgb565 | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_RGB888:
- return OVL_CON_CLRFMT_RGB888;
+ return comp->data->ovl.fmt_rgb888;
case DRM_FORMAT_BGR888:
- return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP;
+ return comp->data->ovl.fmt_rgb888 | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_RGBA8888:
return OVL_CON_CLRFMT_ARGB8888;
@@ -177,7 +175,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
if (!pending->enable)
mtk_ovl_layer_off(comp, idx);
- con = ovl_fmt_convert(fmt);
+ con = ovl_fmt_convert(comp, fmt);
if (idx != 0)
con |= OVL_CON_AEN | OVL_CON_ALPHA;
@@ -185,7 +183,8 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
- writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx));
+ writel_relaxed(addr, comp->regs + comp->data->ovl.addr_offset
+ + idx * 0x20);
if (pending->enable)
mtk_ovl_layer_on(comp, idx);
@@ -269,6 +268,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}
+ priv->ddp_comp.data = of_device_get_match_data(dev);
+
platform_set_drvdata(pdev, priv);
ret = component_add(dev, &mtk_disp_ovl_component_ops);
@@ -285,8 +286,13 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
+ .ovl = {0x0f40, 0, 1 << 12}
+};
+
static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
- { .compatible = "mediatek,mt8173-disp-ovl", },
+ { .compatible = "mediatek,mt8173-disp-ovl",
+ .data = &mt8173_ovl_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 5fb80cb..fb0db50 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -122,7 +122,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
*/
threshold = width * height * vrefresh * 4 * 7 / 1000000;
reg = RDMA_FIFO_UNDERFLOW_EN |
- RDMA_FIFO_PSEUDO_SIZE(SZ_8K) |
+ RDMA_FIFO_PSEUDO_SIZE(comp->data->rdma_fifo_pseudo_size) |
RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON);
}
@@ -207,6 +207,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
return ret;
}
+ priv->ddp_comp.data = of_device_get_match_data(dev);
+
platform_set_drvdata(pdev, priv);
ret = component_add(dev, &mtk_disp_rdma_component_ops);
@@ -223,8 +225,13 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
+ .rdma_fifo_pseudo_size = SZ_8K,
+};
+
static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
- { .compatible = "mediatek,mt8173-disp-rdma", },
+ { .compatible = "mediatek,mt8173-disp-rdma",
+ .data = &mt8173_rdma_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 2fc4321..8030769 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -77,9 +77,10 @@ struct mtk_ddp {
struct clk *clk;
void __iomem *regs;
struct mtk_disp_mutex mutex[10];
+ const unsigned int *mutex_mod;
};
-static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
[DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
@@ -247,7 +248,7 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
break;
default:
reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
- reg |= mutex_mod[id];
+ reg |= ddp->mutex_mod[id];
writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
return;
}
@@ -273,7 +274,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
break;
default:
reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
- reg &= ~mutex_mod[id];
+ reg &= ~(ddp->mutex_mod[id]);
writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
break;
}
@@ -326,6 +327,8 @@ 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;
@@ -337,7 +340,7 @@ static int mtk_ddp_remove(struct platform_device *pdev)
}
static const struct of_device_id ddp_driver_dt_match[] = {
- { .compatible = "mediatek,mt8173-disp-mutex" },
+ { .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
{},
};
MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 3970fcf..4b4e449 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -34,9 +34,8 @@
#define DISP_REG_UFO_START 0x0000
#define DISP_COLOR_CFG_MAIN 0x0400
-#define DISP_COLOR_START 0x0c00
-#define DISP_COLOR_WIDTH 0x0c50
-#define DISP_COLOR_HEIGHT 0x0c54
+#define DISP_COLOR_WIDTH 0x50
+#define DISP_COLOR_HEIGHT 0x54
#define OD_RELAY_MODE BIT(0)
@@ -48,15 +47,15 @@
static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
unsigned int h, unsigned int vrefresh)
{
- writel(w, comp->regs + DISP_COLOR_WIDTH);
- writel(h, comp->regs + DISP_COLOR_HEIGHT);
+ writel(w, comp->regs + comp->data->color_offset + DISP_COLOR_WIDTH);
+ writel(h, comp->regs + comp->data->color_offset + DISP_COLOR_HEIGHT);
}
static void mtk_color_start(struct mtk_ddp_comp *comp)
{
writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL,
comp->regs + DISP_COLOR_CFG_MAIN);
- writel(0x1, comp->regs + DISP_COLOR_START);
+ writel(0x1, comp->regs + comp->data->color_offset);
}
static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
@@ -131,6 +130,16 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL },
};
+static const struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
+ .color_offset = 0x0c00,
+};
+
+static const struct of_device_id mtk_disp_color_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8173-disp-color",
+ .data = &mt8173_color_driver_data},
+ {},
+};
+
int mtk_ddp_comp_get_id(struct device_node *node,
enum mtk_ddp_comp_type comp_type)
{
@@ -153,6 +162,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
enum mtk_ddp_comp_type type;
struct device_node *larb_node;
struct platform_device *larb_pdev;
+ const struct of_device_id *match;
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
return -EINVAL;
@@ -177,6 +187,11 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
type = mtk_ddp_matches[comp_id].type;
+ if (type == MTK_DISP_COLOR) {
+ match = of_match_node(mtk_disp_color_driver_dt_match, node);
+ comp->data = match->data;
+ }
+
/* Only DMA capable components need the LARB property */
comp->larb_dev = NULL;
if (type != MTK_DISP_OVL &&
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 6b13ba9..53065c7 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -75,6 +75,18 @@ struct mtk_ddp_comp_funcs {
struct mtk_plane_state *state);
};
+struct mtk_ddp_comp_driver_data {
+ union {
+ struct ovl {
+ unsigned int addr_offset;
+ unsigned int fmt_rgb565;
+ unsigned int fmt_rgb888;
+ } ovl;
+ unsigned int rdma_fifo_pseudo_size;
+ unsigned int color_offset;
+ };
+};
+
struct mtk_ddp_comp {
struct clk *clk;
void __iomem *regs;
@@ -82,6 +94,7 @@ struct mtk_ddp_comp {
struct device *larb_dev;
enum mtk_ddp_comp_id id;
const struct mtk_ddp_comp_funcs *funcs;
+ const struct mtk_ddp_comp_driver_data *data;
};
static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index b1223d5..80b4f54 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -109,7 +109,7 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
.atomic_commit = mtk_atomic_commit,
};
-static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
+static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_AAL,
@@ -120,7 +120,7 @@ static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
DDP_COMPONENT_PWM0,
};
-static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
+static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
DDP_COMPONENT_OVL1,
DDP_COMPONENT_COLOR1,
DDP_COMPONENT_GAMMA,
@@ -128,6 +128,13 @@ static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
DDP_COMPONENT_DPI0,
};
+static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
+ .main_path = mt8173_mtk_ddp_main,
+ .main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
+ .ext_path = mt8173_mtk_ddp_ext,
+ .ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext),
+};
+
static int mtk_drm_kms_init(struct drm_device *drm)
{
struct mtk_drm_private *private = drm->dev_private;
@@ -170,17 +177,19 @@ static int mtk_drm_kms_init(struct drm_device *drm)
* and each statically assigned to a crtc:
* OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
*/
- ret = mtk_drm_crtc_create(drm, mtk_ddp_main, ARRAY_SIZE(mtk_ddp_main));
+ ret = mtk_drm_crtc_create(drm, private->data->main_path,
+ private->data->main_len);
if (ret < 0)
goto err_component_unbind;
/* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
- ret = mtk_drm_crtc_create(drm, mtk_ddp_ext, ARRAY_SIZE(mtk_ddp_ext));
+ ret = mtk_drm_crtc_create(drm, private->data->ext_path,
+ private->data->ext_len);
if (ret < 0)
goto err_component_unbind;
/* Use OVL device for all DMA memory allocations */
- np = private->comp_node[mtk_ddp_main[0]] ?:
- private->comp_node[mtk_ddp_ext[0]];
+ np = private->comp_node[private->data->main_path[0]] ?:
+ private->comp_node[private->data->ext_path[0]];
pdev = of_find_device_by_node(np);
if (!pdev) {
ret = -ENODEV;
@@ -353,6 +362,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
mutex_init(&private->commit.lock);
INIT_WORK(&private->commit.work, mtk_atomic_work);
+ private->data = of_device_get_match_data(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
private->config_regs = devm_ioremap_resource(dev, mem);
@@ -504,7 +514,8 @@ static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
mtk_drm_sys_resume);
static const struct of_device_id mtk_drm_of_ids[] = {
- { .compatible = "mediatek,mt8173-mmsys", },
+ { .compatible = "mediatek,mt8173-mmsys",
+ .data = &mt8173_mmsys_driver_data},
{ }
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index aa93894..fa0b106 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -28,6 +28,13 @@ struct drm_fb_helper;
struct drm_property;
struct regmap;
+struct mtk_mmsys_driver_data {
+ const enum mtk_ddp_comp_id *main_path;
+ unsigned int main_len;
+ const enum mtk_ddp_comp_id *ext_path;
+ unsigned int ext_len;
+};
+
struct mtk_drm_private {
struct drm_device *drm;
struct device *dma_dev;
@@ -40,6 +47,7 @@ struct mtk_drm_private {
void __iomem *config_regs;
struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
+ const struct mtk_mmsys_driver_data *data;
struct {
struct drm_atomic_state *state;
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | YT Shen <yt.shen@mediatek.com> |
|---|---|
| Date | 2016-07-28 11:40 +0200 |
| Subject | [PATCH v5 10/10] arm: dts: mt2701: Add display subsystem related nodes for MT2701 |
| Message-ID | <rZPXj-4m8-3@gated-at.bofh.it> |
| In reply to | #1451823 |
This patch adds the device nodes for the DISP function blocks for MT2701
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
arch/arm/boot/dts/mt2701.dtsi | 100 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 363de0d..7da9310 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -24,6 +24,11 @@
compatible = "mediatek,mt2701";
interrupt-parent = <&sysirq>;
+ aliases {
+ rdma0 = &rdma0;
+ rdma1 = &rdma1;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -171,6 +176,16 @@
power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
};
+ mipi_tx0: mipi-dphy@10010000 {
+ compatible = "mediatek,mt2701-mipi-tx";
+ reg = <0 0x10010000 0 0x90>;
+ clocks = <&clk26m>;
+ clock-output-names = "mipi_tx0_pll";
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
sysirq: interrupt-controller@10200100 {
compatible = "mediatek,mt2701-sysirq",
"mediatek,mt6577-sysirq";
@@ -255,6 +270,68 @@
status = "disabled";
};
+ ovl@14007000 {
+ compatible = "mediatek,mt2701-disp-ovl";
+ reg = <0 0x14007000 0 0x1000>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DISP_OVL>;
+ iommus = <&iommu MT2701_M4U_PORT_DISP_OVL_0>;
+ mediatek,larb = <&larb0>;
+ };
+
+ rdma0: rdma@14008000 {
+ compatible = "mediatek,mt2701-disp-rdma";
+ reg = <0 0x14008000 0 0x1000>;
+ interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DISP_RDMA>;
+ iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA>;
+ mediatek,larb = <&larb0>;
+ };
+
+ wdma@14009000 {
+ compatible = "mediatek,mt2701-disp-wdma";
+ reg = <0 0x14009000 0 0x1000>;
+ interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DISP_WDMA>;
+ iommus = <&iommu MT2701_M4U_PORT_DISP_WDMA>;
+ mediatek,larb = <&larb0>;
+ };
+
+ bls@1400a000 {
+ compatible = "mediatek,mt2701-disp-pwm";
+ reg = <0 0x1400a000 0 0x1000>;
+ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DISP_BLS>;
+ };
+
+ color@1400b000 {
+ compatible = "mediatek,mt2701-disp-color";
+ reg = <0 0x1400b000 0 0x1000>;
+ interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DISP_COLOR>;
+ };
+
+ dsi0: dsi@1400c000 {
+ compatible = "mediatek,mt2701-dsi";
+ reg = <0 0x1400c000 0 0x1000>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DSI_ENGINE>, <&mmsys CLK_MM_DSI_DIG>,
+ <&mipi_tx0>;
+ clock-names = "engine", "digital", "hs";
+ mediatek,syscon-dsi = <&mmsys 0x138>;
+ mediatek,ssc-range = <5>;
+ phys = <&mipi_tx0>;
+ phy-names = "dphy";
+ status = "disabled";
+ };
+
+ mutex: mutex@1400e000 {
+ compatible = "mediatek,mt2701-disp-mutex";
+ reg = <0 0x1400e000 0 0x1000>;
+ interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_MUTEX_32K>;
+ };
+
larb0: larb@14010000 {
compatible = "mediatek,mt2701-smi-larb";
reg = <0 0x14010000 0 0x1000>;
@@ -265,6 +342,29 @@
power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
};
+ rdma1: rdma@14012000 {
+ compatible = "mediatek,mt2701-disp-rdma";
+ reg = <0 0x14012000 0 0x1000>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DISP_RDMA1>;
+ iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA1>;
+ mediatek,larb = <&larb0>;
+ };
+
+ dpi0: dpi@14014000 {
+ compatible = "mediatek,mt2701-dpi";
+ reg = <0 0x14014000 0 0x1000>;
+ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&mmsys CLK_MM_DPI1_DIGL>,
+ <&mmsys CLK_MM_DPI1_ENGINE>,
+ <&topckgen CLK_TOP_DPI1_SEL>,
+ <&topckgen CLK_TOP_TVDPLL>,
+ <&topckgen CLK_TOP_TVDPLL_D2>,
+ <&topckgen CLK_TOP_TVDPLL_D4>;
+ clock-names = "pixel", "engine", "sel","div1","div2","div4";
+ status = "disabled";
+ };
+
imgsys: syscon@15000000 {
compatible = "mediatek,mt2701-imgsys", "syscon";
reg = <0 0x15000000 0 0x1000>;
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | YT Shen <yt.shen@mediatek.com> |
|---|---|
| Date | 2016-07-28 11:40 +0200 |
| Subject | [PATCH v5 09/10] drm/mediatek: add support for Mediatek SoC MT2701 |
| Message-ID | <rZPXj-4m8-17@gated-at.bofh.it> |
| In reply to | #1451823 |
This patch add support for the Mediatek MT2701 DISP subsystem.
There is only one OVL engine in MT2701.
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 6 ++++++
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 6 ++++++
drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 17 +++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 7 +++++++
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 1 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 30 +++++++++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_dsi.c | 1 +
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 27 +++++++++++++++++++++++-
8 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index eb5c05e..1da0a71 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -286,11 +286,17 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt2701_ovl_driver_data = {
+ .ovl = {0x0040, 1 << 12, 0}
+};
+
static const struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
.ovl = {0x0f40, 0, 1 << 12}
};
static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
+ { .compatible = "mediatek,mt2701-disp-ovl",
+ .data = &mt2701_ovl_driver_data},
{ .compatible = "mediatek,mt8173-disp-ovl",
.data = &mt8173_ovl_driver_data},
{},
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index fb0db50..506a353 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -225,11 +225,17 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_ddp_comp_driver_data mt2701_rdma_driver_data = {
+ .rdma_fifo_pseudo_size = SZ_4K,
+};
+
static const struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
.rdma_fifo_pseudo_size = SZ_8K,
};
static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
+ { .compatible = "mediatek,mt2701-disp-rdma",
+ .data = &mt2701_rdma_driver_data},
{ .compatible = "mediatek,mt8173-disp-rdma",
.data = &mt8173_rdma_driver_data},
{},
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 329da541..7678ac0 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -60,6 +60,13 @@
#define MT8173_MUTEX_MOD_DISP_PWM1 BIT(24)
#define MT8173_MUTEX_MOD_DISP_OD BIT(25)
+#define MT2701_MUTEX_MOD_DISP_OVL BIT(3)
+#define MT2701_MUTEX_MOD_DISP_WDMA BIT(6)
+#define MT2701_MUTEX_MOD_DISP_COLOR BIT(7)
+#define MT2701_MUTEX_MOD_DISP_BLS BIT(9)
+#define MT2701_MUTEX_MOD_DISP_RDMA0 BIT(10)
+#define MT2701_MUTEX_MOD_DISP_RDMA1 BIT(12)
+
#define MUTEX_SOF_SINGLE_MODE 0
#define MUTEX_SOF_DSI0 1
#define MUTEX_SOF_DSI1 2
@@ -92,6 +99,15 @@ struct mtk_ddp {
const unsigned int *mutex_mod;
};
+static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+ [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
+ [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
+ [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
+ [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0,
+ [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1,
+ [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
+};
+
static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
@@ -389,6 +405,7 @@ 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,mt8173-disp-mutex", .data = mt8173_mutex_mod},
{},
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 4b4e449..465819b 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -112,6 +112,7 @@ struct mtk_ddp_comp_match {
static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL] = { MTK_DISP_AAL, 0, NULL },
+ [DDP_COMPONENT_BLS] = { MTK_DISP_PWM, 0, NULL },
[DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color },
[DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color },
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL },
@@ -130,11 +131,17 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL },
};
+static const struct mtk_ddp_comp_driver_data mt2701_color_driver_data = {
+ .color_offset = 0x0f00,
+};
+
static const struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
.color_offset = 0x0c00,
};
static const struct of_device_id mtk_disp_color_driver_dt_match[] = {
+ { .compatible = "mediatek,mt2701-disp-color",
+ .data = &mt2701_color_driver_data},
{ .compatible = "mediatek,mt8173-disp-color",
.data = &mt8173_color_driver_data},
{},
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 53065c7..0850aa4 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
enum mtk_ddp_comp_id {
DDP_COMPONENT_AAL,
+ DDP_COMPONENT_BLS,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_COLOR1,
DDP_COMPONENT_DPI0,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 80b4f54..ebaa08a 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -109,6 +109,19 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
.atomic_commit = mtk_atomic_commit,
};
+static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
+ DDP_COMPONENT_OVL0,
+ DDP_COMPONENT_RDMA0,
+ DDP_COMPONENT_COLOR0,
+ DDP_COMPONENT_BLS,
+ DDP_COMPONENT_DSI0,
+};
+
+static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
+ DDP_COMPONENT_RDMA1,
+ DDP_COMPONENT_DPI0,
+};
+
static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0,
@@ -128,6 +141,14 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
DDP_COMPONENT_DPI0,
};
+static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
+ .main_path = mt2701_mtk_ddp_main,
+ .main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
+ .ext_path = mt2701_mtk_ddp_ext,
+ .ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
+ .shadow_register = true,
+};
+
static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
.main_path = mt8173_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
@@ -331,16 +352,23 @@ static const struct component_master_ops mtk_drm_ops = {
};
static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
+ { .compatible = "mediatek,mt2701-disp-ovl", .data = (void *)MTK_DISP_OVL },
{ .compatible = "mediatek,mt8173-disp-ovl", .data = (void *)MTK_DISP_OVL },
+ { .compatible = "mediatek,mt2701-disp-rdma", .data = (void *)MTK_DISP_RDMA },
{ .compatible = "mediatek,mt8173-disp-rdma", .data = (void *)MTK_DISP_RDMA },
{ .compatible = "mediatek,mt8173-disp-wdma", .data = (void *)MTK_DISP_WDMA },
+ { .compatible = "mediatek,mt2701-disp-color", .data = (void *)MTK_DISP_COLOR },
{ .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR },
{ .compatible = "mediatek,mt8173-disp-aal", .data = (void *)MTK_DISP_AAL},
{ .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, },
{ .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE },
+ { .compatible = "mediatek,mt2701-dsi", .data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8173-dsi", .data = (void *)MTK_DSI },
+ { .compatible = "mediatek,mt2701-dpi", .data = (void *)MTK_DPI },
{ .compatible = "mediatek,mt8173-dpi", .data = (void *)MTK_DPI },
+ { .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
+ { .compatible = "mediatek,mt2701-disp-pwm", .data = (void *)MTK_DISP_PWM },
{ .compatible = "mediatek,mt8173-disp-pwm", .data = (void *)MTK_DISP_PWM },
{ .compatible = "mediatek,mt8173-disp-od", .data = (void *)MTK_DISP_OD },
{ }
@@ -514,6 +542,8 @@ static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
mtk_drm_sys_resume);
static const struct of_device_id mtk_drm_of_ids[] = {
+ { .compatible = "mediatek,mt2701-mmsys",
+ .data = &mt2701_mmsys_driver_data},
{ .compatible = "mediatek,mt8173-mmsys",
.data = &mt8173_mmsys_driver_data},
{ }
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 2646f83..0d7e6ba 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -1342,6 +1342,7 @@ static int mtk_dsi_remove(struct platform_device *pdev)
}
static const struct of_device_id mtk_dsi_of_match[] = {
+ { .compatible = "mediatek,mt2701-dsi" },
{ .compatible = "mediatek,mt8173-dsi" },
{ },
};
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
index 0666f15..083d3fd 100644
--- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
+++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
@@ -16,6 +16,7 @@
#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>
@@ -87,6 +88,9 @@
#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)
@@ -127,6 +131,8 @@ 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;
};
@@ -245,6 +251,10 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
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->data);
+
return 0;
}
@@ -257,6 +267,9 @@ static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw)
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,
@@ -393,6 +406,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
if (!mipi_tx)
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)) {
@@ -450,8 +464,19 @@ static int mtk_mipi_tx_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_mipitx_data mt2701_mipitx_data = {
+ .data = (3 << 8)
+};
+
+static const struct mtk_mipitx_data mt8173_mipitx_data = {
+ .data = (0 << 8)
+};
+
static const struct of_device_id mtk_mipi_tx_match[] = {
- { .compatible = "mediatek,mt8173-mipi-tx", },
+ { .compatible = "mediatek,mt2701-mipi-tx",
+ .data = &mt2701_mipitx_data },
+ { .compatible = "mediatek,mt8173-mipi-tx",
+ .data = &mt8173_mipitx_data },
{},
};
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | YT Shen <yt.shen@mediatek.com> |
|---|---|
| Date | 2016-07-28 11:40 +0200 |
| Subject | [PATCH v5 07/10] drm/mediatek: add dsi transfer function |
| Message-ID | <rZPXj-4m8-19@gated-at.bofh.it> |
| In reply to | #1451823 |
From: shaoming chen <shaoming.chen@mediatek.com>
add dsi read/write commands for transfer function
Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 286 ++++++++++++++++++++++++++++++++++++
1 file changed, 286 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 553443a..1d36524 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -24,6 +24,7 @@
#include <linux/of_graph.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <video/mipi_display.h>
#include <video/videomode.h>
#include "mtk_drm_ddp_comp.h"
@@ -81,8 +82,16 @@
#define DSI_HBP_WC 0x54
#define DSI_HFP_WC 0x58
+#define DSI_CMDQ_SIZE 0x60
+#define CMDQ_SIZE 0x3f
+
#define DSI_HSTX_CKL_WC 0x64
+#define DSI_RX_DATA0 0x74
+#define DSI_RX_DATA1 0x78
+#define DSI_RX_DATA2 0x7c
+#define DSI_RX_DATA3 0x80
+
#define DSI_RACK 0x84
#define RACK BIT(0)
@@ -118,8 +127,25 @@
#define CLK_HS_POST (0xff << 8)
#define CLK_HS_EXIT (0xff << 16)
+#define DSI_CMDQ0 0x180
+
#define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
+#define MTK_DSI_HOST_IS_READ(type) \
+ ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
+ (type == MIPI_DSI_DCS_READ))
+
+#define MTK_DSI_HOST_IS_WRITE(type) \
+ ((type == MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM) || \
+ (type == MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM) || \
+ (type == MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM) || \
+ (type == MIPI_DSI_DCS_SHORT_WRITE) || \
+ (type == MIPI_DSI_DCS_SHORT_WRITE_PARAM) || \
+ (type == MIPI_DSI_GENERIC_LONG_WRITE) || \
+ (type == MIPI_DSI_DCS_LONG_WRITE))
+
struct phy;
struct mtk_dsi {
@@ -149,6 +175,17 @@ struct mtk_dsi {
int irq_data;
};
+struct dsi_rxtx_data {
+ u8 byte0;
+ u8 byte1;
+ u8 byte2;
+ u8 byte3;
+};
+
+struct dsi_tx_cmdq_regs {
+ struct dsi_rxtx_data data[128];
+};
+
static wait_queue_head_t _dsi_cmd_done_wait_queue;
static wait_queue_head_t _dsi_dcs_read_wait_queue;
static wait_queue_head_t _dsi_wait_vm_done_queue;
@@ -813,9 +850,258 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
return 0;
}
+static void mtk_dsi_set_cmdq(void __iomem *reg, u32 mask, u32 data)
+{
+ u32 temp = readl(reg);
+
+ writel((temp & ~mask) | (data & mask), reg);
+}
+
+static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
+{
+ u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
+
+ while (timeout_ms--) {
+ if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
+ break;
+
+ usleep_range(2, 4);
+ }
+
+ if (timeout_ms == 0) {
+ dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
+
+ mtk_dsi_enable(dsi);
+ mtk_dsi_reset_engine(dsi);
+ }
+}
+
+static void mtk_dsi_wait_for_cmd_done(struct mtk_dsi *dsi)
+{
+ s32 ret = 0;
+ unsigned long timeout = msecs_to_jiffies(500);
+
+ ret = wait_event_interruptible_timeout(_dsi_cmd_done_wait_queue,
+ dsi->irq_data & CMD_DONE_INT_FLAG, timeout);
+ if (ret == 0) {
+ dev_info(dsi->dev, "dsi wait engine cmd done fail\n");
+ mtk_dsi_enable(dsi);
+ mtk_dsi_reset_engine(dsi);
+ return;
+ }
+
+ dsi->irq_data &= ~CMD_DONE_INT_FLAG;
+}
+
+static ssize_t mtk_dsi_host_read_cmd(struct mtk_dsi *dsi,
+ const struct mipi_dsi_msg *msg)
+{
+ u8 max_try_count = 5;
+ u32 recv_cnt, tmp_val;
+ struct dsi_rxtx_data read_data0, read_data1, read_data2, read_data3;
+ u8 config, type, data0, data1;
+ s32 ret;
+
+ u8 *buffer = msg->rx_buf;
+ u8 buffer_size = msg->rx_len;
+
+ if (readl(dsi->regs + DSI_MODE_CTRL) & 0x03) {
+ dev_info(dsi->dev, "dsi engine is not command mode\n");
+ return -1;
+ }
+
+ if (!buffer) {
+ dev_info(dsi->dev, "dsi receive buffer size may be NULL\n");
+ return -1;
+ }
+
+ do {
+ if (max_try_count == 0) {
+ dev_info(dsi->dev, "dsi engine read counter has been maxinum\n");
+ return -1;
+ }
+
+ max_try_count--;
+ recv_cnt = 0;
+
+ mtk_dsi_wait_for_idle(dsi);
+
+ config = 0x04;
+ data0 = *((u8 *)(msg->tx_buf));
+
+ if (buffer_size < 3)
+ type = MIPI_DSI_DCS_READ;
+ else
+ type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
+
+ data1 = 0;
+
+ tmp_val = (data1 << 24) | (data0 << 16) | (type << 8) | config;
+
+ writel(tmp_val, dsi->regs + DSI_CMDQ0);
+ mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, 1);
+
+ mtk_dsi_start(dsi);
+
+ /* 2s timeout*/
+ ret = wait_event_interruptible_timeout(_dsi_dcs_read_wait_queue,
+ dsi->irq_data & LPRX_RD_RDY_INT_FLAG, timeout);
+ if (ret == 0) {
+ dev_info(dsi->dev, "Wait DSI read ready timeout!!!\n");
+
+ mtk_dsi_enable(dsi);
+ mtk_dsi_reset_engine(dsi);
+
+ return ret;
+ }
+
+ dsi->irq_data &= ~LPRX_RD_RDY_INT_FLAG;
+
+ *(u32 *)(&read_data0) = readl(dsi->regs + DSI_RX_DATA0);
+ *(u32 *)(&read_data1) = readl(dsi->regs + DSI_RX_DATA1);
+ *(u32 *)(&read_data2) = readl(dsi->regs + DSI_RX_DATA2);
+ *(u32 *)(&read_data3) = readl(dsi->regs + DSI_RX_DATA3);
+
+ type = read_data0.byte0;
+
+ if (type == MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE ||
+ type == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
+
+ /*
+ * Data ID(1 byte) + Word Count(2 bytes) + ECC(1 byte) +
+ * data 0 + ...+ data WC-1 + CHECKSUM (2 bytes)
+ */
+ recv_cnt = read_data0.byte1 + read_data0.byte2 * 16;
+ dev_info(dsi->dev, "long packet size: %d\n", recv_cnt);
+
+ /*
+ * the buffer size is 16 bytes once, so the data payload
+ * is, 16 - bytes(data ID + WC + ECC + CHECKSUM), if
+ * over 10 bytes, it will be read again
+ */
+ if (recv_cnt > 10)
+ recv_cnt = 10;
+
+ if (recv_cnt > buffer_size)
+ recv_cnt = buffer_size;
+
+ if (recv_cnt <= 4) {
+ memcpy(buffer, &read_data1, recv_cnt);
+ } else if (recv_cnt <= 8) {
+ memcpy(buffer, &read_data1, 4);
+ memcpy(buffer + 4, &read_data2, recv_cnt - 4);
+ } else {
+ memcpy(buffer, &read_data1, 4);
+ memcpy(buffer + 4, &read_data2, 4);
+ memcpy(buffer + 8, &read_data3, recv_cnt - 8);
+ }
+ } else if (type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE ||
+ type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE ||
+ type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE ||
+ type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
+
+ if (type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE ||
+ type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)
+ recv_cnt = 1;
+ else
+ recv_cnt = 2;
+
+ if (recv_cnt > buffer_size)
+ recv_cnt = buffer_size;
+
+ memcpy(buffer, &read_data0.byte1, recv_cnt);
+ } else if (type == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
+ dev_info(dsi->dev, "packet type is 0x02, try again\n");
+ } else {
+ dev_info(dsi->dev, "packet type(0x%x) cannot be non-recognize\n",
+ type);
+
+ return 0;
+ }
+ } while (type == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT);
+
+ dev_info(dsi->dev, "dsi get %d byte data from the panel address(0x%x)\n",
+ recv_cnt, *((u8 *)(msg->tx_buf)));
+
+ return recv_cnt;
+}
+
+static ssize_t mtk_dsi_host_write_cmd(struct mtk_dsi *dsi,
+ const struct mipi_dsi_msg *msg)
+{
+ u32 i;
+ u32 goto_addr, mask_para, set_para, reg_val;
+ void __iomem *cmdq_reg;
+ u8 config, type, data0, data1;
+ u16 wc16;
+ const char *tx_buf = msg->tx_buf;
+ struct dsi_tx_cmdq_regs *dsi_cmd_reg;
+
+ dsi_cmd_reg = (struct dsi_tx_cmdq_regs *)(dsi->regs + DSI_CMDQ0);
+
+ mtk_dsi_wait_for_idle(dsi);
+
+ if (msg->tx_len > 2) {
+ config = 2;
+ type = msg->type;
+ wc16 = msg->tx_len;
+
+ reg_val = (wc16 << 16) | (type << 8) | config;
+
+ writel(reg_val, &dsi_cmd_reg->data[0]);
+
+ for (i = 0; i < msg->tx_len; i++) {
+ goto_addr = (u32)(&dsi_cmd_reg->data[1].byte0) + i;
+ mask_para = (0xff << ((goto_addr & 0x3) * 8));
+ set_para = (tx_buf[i] << ((goto_addr & 0x3) * 8));
+ cmdq_reg = (void __iomem *)(goto_addr & (~0x3));
+ mtk_dsi_set_cmdq(cmdq_reg, mask_para, set_para);
+ }
+
+ mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE,
+ 1 + (msg->tx_len + 3) / 4);
+ } else {
+ config = 0;
+ data0 = tx_buf[0];
+ if (msg->tx_len == 2) {
+ type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
+ data1 = tx_buf[1];
+ } else {
+ type = MIPI_DSI_DCS_SHORT_WRITE;
+ data1 = 0;
+ }
+
+ reg_val = (data1 << 24) | (data0 << 16) | (type << 8) | config;
+
+ writel(reg_val, &dsi_cmd_reg->data[0]);
+ mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, 1);
+ }
+
+ mtk_dsi_start(dsi);
+ mtk_dsi_wait_for_cmd_done(dsi);
+
+ return 0;
+}
+
+static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ const struct mipi_dsi_msg *msg)
+{
+ struct mtk_dsi *dsi = host_to_dsi(host);
+ u8 type = msg->type;
+ ssize_t ret = 0;
+
+ if (MTK_DSI_HOST_IS_READ(type))
+ ret = mtk_dsi_host_read_cmd(dsi, msg);
+ else if (MTK_DSI_HOST_IS_WRITE(type))
+ ret = mtk_dsi_host_write_cmd(dsi, msg);
+
+ return ret;
+}
+
static const struct mipi_dsi_host_ops mtk_dsi_ops = {
.attach = mtk_dsi_host_attach,
.detach = mtk_dsi_host_detach,
+ .transfer = mtk_dsi_host_transfer,
};
static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | CK Hu <ck.hu@mediatek.com> |
|---|---|
| Date | 2016-08-02 09:30 +0200 |
| Subject | Re: [PATCH v5 07/10] drm/mediatek: add dsi transfer function |
| Message-ID | <s1Cjg-1l9-19@gated-at.bofh.it> |
| In reply to | #1451831 |
Hi, YT:
On Thu, 2016-07-28 at 17:28 +0800, YT Shen wrote:
> From: shaoming chen <shaoming.chen@mediatek.com>
>
> add dsi read/write commands for transfer function
>
> Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> ---
> drivers/gpu/drm/mediatek/mtk_dsi.c | 286 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 286 insertions(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 553443a..1d36524 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -24,6 +24,7 @@
> #include <linux/of_graph.h>
> #include <linux/phy/phy.h>
> #include <linux/platform_device.h>
> +#include <video/mipi_display.h>
> #include <video/videomode.h>
>
> #include "mtk_drm_ddp_comp.h"
> @@ -81,8 +82,16 @@
> #define DSI_HBP_WC 0x54
> #define DSI_HFP_WC 0x58
>
> +#define DSI_CMDQ_SIZE 0x60
> +#define CMDQ_SIZE 0x3f
> +
> #define DSI_HSTX_CKL_WC 0x64
>
> +#define DSI_RX_DATA0 0x74
> +#define DSI_RX_DATA1 0x78
> +#define DSI_RX_DATA2 0x7c
> +#define DSI_RX_DATA3 0x80
> +
> #define DSI_RACK 0x84
> #define RACK BIT(0)
>
> @@ -118,8 +127,25 @@
> #define CLK_HS_POST (0xff << 8)
> #define CLK_HS_EXIT (0xff << 16)
>
> +#define DSI_CMDQ0 0x180
> +
> #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
>
> +#define MTK_DSI_HOST_IS_READ(type) \
> + ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
> + (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
> + (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
> + (type == MIPI_DSI_DCS_READ))
> +
> +#define MTK_DSI_HOST_IS_WRITE(type) \
> + ((type == MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM) || \
> + (type == MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM) || \
> + (type == MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM) || \
> + (type == MIPI_DSI_DCS_SHORT_WRITE) || \
> + (type == MIPI_DSI_DCS_SHORT_WRITE_PARAM) || \
> + (type == MIPI_DSI_GENERIC_LONG_WRITE) || \
> + (type == MIPI_DSI_DCS_LONG_WRITE))
> +
> struct phy;
>
> struct mtk_dsi {
> @@ -149,6 +175,17 @@ struct mtk_dsi {
> int irq_data;
> };
>
> +struct dsi_rxtx_data {
> + u8 byte0;
> + u8 byte1;
> + u8 byte2;
> + u8 byte3;
> +};
> +
> +struct dsi_tx_cmdq_regs {
> + struct dsi_rxtx_data data[128];
> +};
> +
> static wait_queue_head_t _dsi_cmd_done_wait_queue;
> static wait_queue_head_t _dsi_dcs_read_wait_queue;
> static wait_queue_head_t _dsi_wait_vm_done_queue;
> @@ -813,9 +850,258 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> return 0;
> }
>
> +static void mtk_dsi_set_cmdq(void __iomem *reg, u32 mask, u32 data)
> +{
> + u32 temp = readl(reg);
> +
> + writel((temp & ~mask) | (data & mask), reg);
> +}
> +
> +static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> +{
> + u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
> +
> + while (timeout_ms--) {
> + if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
> + break;
> +
> + usleep_range(2, 4);
> + }
> +
> + if (timeout_ms == 0) {
> + dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
> +
> + mtk_dsi_enable(dsi);
> + mtk_dsi_reset_engine(dsi);
> + }
> +}
> +
> +static void mtk_dsi_wait_for_cmd_done(struct mtk_dsi *dsi)
> +{
> + s32 ret = 0;
> + unsigned long timeout = msecs_to_jiffies(500);
> +
> + ret = wait_event_interruptible_timeout(_dsi_cmd_done_wait_queue,
> + dsi->irq_data & CMD_DONE_INT_FLAG, timeout);
> + if (ret == 0) {
> + dev_info(dsi->dev, "dsi wait engine cmd done fail\n");
> + mtk_dsi_enable(dsi);
> + mtk_dsi_reset_engine(dsi);
> + return;
> + }
> +
> + dsi->irq_data &= ~CMD_DONE_INT_FLAG;
I think you should move this before trigger HW. Sometimes this interrupt
is coming and this flag is set but you do not wait this event and do not
clear it. Then when you want to wait, the flag is already set by long
time ago interrupt.
> +}
> +
> +static ssize_t mtk_dsi_host_read_cmd(struct mtk_dsi *dsi,
> + const struct mipi_dsi_msg *msg)
> +{
> + u8 max_try_count = 5;
> + u32 recv_cnt, tmp_val;
> + struct dsi_rxtx_data read_data0, read_data1, read_data2, read_data3;
> + u8 config, type, data0, data1;
> + s32 ret;
> +
> + u8 *buffer = msg->rx_buf;
> + u8 buffer_size = msg->rx_len;
> +
> + if (readl(dsi->regs + DSI_MODE_CTRL) & 0x03) {
> + dev_info(dsi->dev, "dsi engine is not command mode\n");
> + return -1;
> + }
> +
> + if (!buffer) {
> + dev_info(dsi->dev, "dsi receive buffer size may be NULL\n");
> + return -1;
> + }
> +
> + do {
> + if (max_try_count == 0) {
> + dev_info(dsi->dev, "dsi engine read counter has been maxinum\n");
> + return -1;
> + }
> +
> + max_try_count--;
> + recv_cnt = 0;
> +
> + mtk_dsi_wait_for_idle(dsi);
> +
> + config = 0x04;
> + data0 = *((u8 *)(msg->tx_buf));
> +
> + if (buffer_size < 3)
> + type = MIPI_DSI_DCS_READ;
> + else
> + type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
> +
> + data1 = 0;
> +
> + tmp_val = (data1 << 24) | (data0 << 16) | (type << 8) | config;
> +
> + writel(tmp_val, dsi->regs + DSI_CMDQ0);
> + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, 1);
> +
> + mtk_dsi_start(dsi);
This part looks like the same as mtk_dsi_host_write_cmd() with
msg->tx_len = 1. Maybe you can try to merge these two part.
> +
> + /* 2s timeout*/
> + ret = wait_event_interruptible_timeout(_dsi_dcs_read_wait_queue,
> + dsi->irq_data & LPRX_RD_RDY_INT_FLAG, timeout);
> + if (ret == 0) {
> + dev_info(dsi->dev, "Wait DSI read ready timeout!!!\n");
> +
> + mtk_dsi_enable(dsi);
> + mtk_dsi_reset_engine(dsi);
> +
> + return ret;
> + }
> +
> + dsi->irq_data &= ~LPRX_RD_RDY_INT_FLAG;
I think you should move this before trigger HW. Sometimes this interrupt
is coming and this flag is set but you do not wait this event and do not
clear it. Then when you want to wait, the flag is already set by long
time ago interrupt.
> +
> + *(u32 *)(&read_data0) = readl(dsi->regs + DSI_RX_DATA0);
> + *(u32 *)(&read_data1) = readl(dsi->regs + DSI_RX_DATA1);
> + *(u32 *)(&read_data2) = readl(dsi->regs + DSI_RX_DATA2);
> + *(u32 *)(&read_data3) = readl(dsi->regs + DSI_RX_DATA3);
> +
> + type = read_data0.byte0;
> +
> + if (type == MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE ||
> + type == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
> +
> + /*
> + * Data ID(1 byte) + Word Count(2 bytes) + ECC(1 byte) +
> + * data 0 + ...+ data WC-1 + CHECKSUM (2 bytes)
Is CHECKSUM useless? Why not check it?
> + */
> + recv_cnt = read_data0.byte1 + read_data0.byte2 * 16;
> + dev_info(dsi->dev, "long packet size: %d\n", recv_cnt);
> +
> + /*
> + * the buffer size is 16 bytes once, so the data payload
> + * is, 16 - bytes(data ID + WC + ECC + CHECKSUM), if
> + * over 10 bytes, it will be read again
> + */
> + if (recv_cnt > 10)
> + recv_cnt = 10;
> +
> + if (recv_cnt > buffer_size)
> + recv_cnt = buffer_size;
> +
> + if (recv_cnt <= 4) {
> + memcpy(buffer, &read_data1, recv_cnt);
> + } else if (recv_cnt <= 8) {
> + memcpy(buffer, &read_data1, 4);
> + memcpy(buffer + 4, &read_data2, recv_cnt - 4);
> + } else {
> + memcpy(buffer, &read_data1, 4);
> + memcpy(buffer + 4, &read_data2, 4);
> + memcpy(buffer + 8, &read_data3, recv_cnt - 8);
> + }
I think you can ignore read_data1, read_data2, and read_data3. Using a
'for loop' and readb() here can directly read register data into buffer.
> + } else if (type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE ||
> + type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE ||
> + type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE ||
> + type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
> +
> + if (type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE ||
> + type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)
> + recv_cnt = 1;
> + else
> + recv_cnt = 2;
> +
> + if (recv_cnt > buffer_size)
> + recv_cnt = buffer_size;
> +
> + memcpy(buffer, &read_data0.byte1, recv_cnt);
> + } else if (type == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
> + dev_info(dsi->dev, "packet type is 0x02, try again\n");
> + } else {
> + dev_info(dsi->dev, "packet type(0x%x) cannot be non-recognize\n",
> + type);
> +
> + return 0;
> + }
> + } while (type == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT);
> +
> + dev_info(dsi->dev, "dsi get %d byte data from the panel address(0x%x)\n",
> + recv_cnt, *((u8 *)(msg->tx_buf)));
> +
> + return recv_cnt;
> +}
> +
> +static ssize_t mtk_dsi_host_write_cmd(struct mtk_dsi *dsi,
> + const struct mipi_dsi_msg *msg)
> +{
> + u32 i;
> + u32 goto_addr, mask_para, set_para, reg_val;
> + void __iomem *cmdq_reg;
> + u8 config, type, data0, data1;
> + u16 wc16;
> + const char *tx_buf = msg->tx_buf;
> + struct dsi_tx_cmdq_regs *dsi_cmd_reg;
> +
> + dsi_cmd_reg = (struct dsi_tx_cmdq_regs *)(dsi->regs + DSI_CMDQ0);
> +
> + mtk_dsi_wait_for_idle(dsi);
> +
> + if (msg->tx_len > 2) {
> + config = 2;
> + type = msg->type;
> + wc16 = msg->tx_len;
> +
> + reg_val = (wc16 << 16) | (type << 8) | config;
> +
> + writel(reg_val, &dsi_cmd_reg->data[0]);
> +
> + for (i = 0; i < msg->tx_len; i++) {
> + goto_addr = (u32)(&dsi_cmd_reg->data[1].byte0) + i;
> + mask_para = (0xff << ((goto_addr & 0x3) * 8));
> + set_para = (tx_buf[i] << ((goto_addr & 0x3) * 8));
> + cmdq_reg = (void __iomem *)(goto_addr & (~0x3));
> + mtk_dsi_set_cmdq(cmdq_reg, mask_para, set_para);
> + }
Because you use writel(), so this part look so complicated. If you use
writeb(), this would be much simpler.
> +
> + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE,
> + 1 + (msg->tx_len + 3) / 4);
> + } else {
> + config = 0;
> + data0 = tx_buf[0];
> + if (msg->tx_len == 2) {
> + type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
> + data1 = tx_buf[1];
> + } else {
> + type = MIPI_DSI_DCS_SHORT_WRITE;
> + data1 = 0;
> + }
> +
> + reg_val = (data1 << 24) | (data0 << 16) | (type << 8) | config;
> +
> + writel(reg_val, &dsi_cmd_reg->data[0]);
> + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, 1);
> + }
> +
> + mtk_dsi_start(dsi);
> + mtk_dsi_wait_for_cmd_done(dsi);
> +
> + return 0;
> +}
> +
> +static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
> + const struct mipi_dsi_msg *msg)
> +{
> + struct mtk_dsi *dsi = host_to_dsi(host);
> + u8 type = msg->type;
> + ssize_t ret = 0;
> +
> + if (MTK_DSI_HOST_IS_READ(type))
> + ret = mtk_dsi_host_read_cmd(dsi, msg);
> + else if (MTK_DSI_HOST_IS_WRITE(type))
> + ret = mtk_dsi_host_write_cmd(dsi, msg);
> +
> + return ret;
> +}
> +
> static const struct mipi_dsi_host_ops mtk_dsi_ops = {
> .attach = mtk_dsi_host_attach,
> .detach = mtk_dsi_host_detach,
> + .transfer = mtk_dsi_host_transfer,
> };
>
> static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
Regards,
CK
[toc] | [prev] | [next] | [standalone]
| From | YT Shen <yt.shen@mediatek.com> |
|---|---|
| Date | 2016-08-02 11:20 +0200 |
| Subject | Re: [PATCH v5 07/10] drm/mediatek: add dsi transfer function |
| Message-ID | <s1E1I-2tq-23@gated-at.bofh.it> |
| In reply to | #1453635 |
Hi CK,
On Tue, 2016-08-02 at 14:55 +0800, CK Hu wrote:
> Hi, YT:
>
> On Thu, 2016-07-28 at 17:28 +0800, YT Shen wrote:
> > From: shaoming chen <shaoming.chen@mediatek.com>
> >
> > add dsi read/write commands for transfer function
> >
> > Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> > ---
> > drivers/gpu/drm/mediatek/mtk_dsi.c | 286 ++++++++++++++++++++++++++++++++++++
> > 1 file changed, 286 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > index 553443a..1d36524 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > @@ -24,6 +24,7 @@
> > #include <linux/of_graph.h>
> > #include <linux/phy/phy.h>
> > #include <linux/platform_device.h>
> > +#include <video/mipi_display.h>
> > #include <video/videomode.h>
> >
> > #include "mtk_drm_ddp_comp.h"
> > @@ -81,8 +82,16 @@
> > #define DSI_HBP_WC 0x54
> > #define DSI_HFP_WC 0x58
> >
> > +#define DSI_CMDQ_SIZE 0x60
> > +#define CMDQ_SIZE 0x3f
> > +
> > #define DSI_HSTX_CKL_WC 0x64
> >
> > +#define DSI_RX_DATA0 0x74
> > +#define DSI_RX_DATA1 0x78
> > +#define DSI_RX_DATA2 0x7c
> > +#define DSI_RX_DATA3 0x80
> > +
> > #define DSI_RACK 0x84
> > #define RACK BIT(0)
> >
> > @@ -118,8 +127,25 @@
> > #define CLK_HS_POST (0xff << 8)
> > #define CLK_HS_EXIT (0xff << 16)
> >
> > +#define DSI_CMDQ0 0x180
> > +
> > #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
> >
> > +#define MTK_DSI_HOST_IS_READ(type) \
> > + ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
> > + (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
> > + (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
> > + (type == MIPI_DSI_DCS_READ))
> > +
> > +#define MTK_DSI_HOST_IS_WRITE(type) \
> > + ((type == MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM) || \
> > + (type == MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM) || \
> > + (type == MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM) || \
> > + (type == MIPI_DSI_DCS_SHORT_WRITE) || \
> > + (type == MIPI_DSI_DCS_SHORT_WRITE_PARAM) || \
> > + (type == MIPI_DSI_GENERIC_LONG_WRITE) || \
> > + (type == MIPI_DSI_DCS_LONG_WRITE))
> > +
> > struct phy;
> >
> > struct mtk_dsi {
> > @@ -149,6 +175,17 @@ struct mtk_dsi {
> > int irq_data;
> > };
> >
> > +struct dsi_rxtx_data {
> > + u8 byte0;
> > + u8 byte1;
> > + u8 byte2;
> > + u8 byte3;
> > +};
> > +
> > +struct dsi_tx_cmdq_regs {
> > + struct dsi_rxtx_data data[128];
> > +};
> > +
> > static wait_queue_head_t _dsi_cmd_done_wait_queue;
> > static wait_queue_head_t _dsi_dcs_read_wait_queue;
> > static wait_queue_head_t _dsi_wait_vm_done_queue;
> > @@ -813,9 +850,258 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> > return 0;
> > }
> >
> > +static void mtk_dsi_set_cmdq(void __iomem *reg, u32 mask, u32 data)
> > +{
> > + u32 temp = readl(reg);
> > +
> > + writel((temp & ~mask) | (data & mask), reg);
> > +}
> > +
> > +static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> > +{
> > + u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
> > +
> > + while (timeout_ms--) {
> > + if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
> > + break;
> > +
> > + usleep_range(2, 4);
> > + }
> > +
> > + if (timeout_ms == 0) {
> > + dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
> > +
> > + mtk_dsi_enable(dsi);
> > + mtk_dsi_reset_engine(dsi);
> > + }
> > +}
> > +
> > +static void mtk_dsi_wait_for_cmd_done(struct mtk_dsi *dsi)
> > +{
> > + s32 ret = 0;
> > + unsigned long timeout = msecs_to_jiffies(500);
> > +
> > + ret = wait_event_interruptible_timeout(_dsi_cmd_done_wait_queue,
> > + dsi->irq_data & CMD_DONE_INT_FLAG, timeout);
> > + if (ret == 0) {
> > + dev_info(dsi->dev, "dsi wait engine cmd done fail\n");
> > + mtk_dsi_enable(dsi);
> > + mtk_dsi_reset_engine(dsi);
> > + return;
> > + }
> > +
> > + dsi->irq_data &= ~CMD_DONE_INT_FLAG;
>
> I think you should move this before trigger HW. Sometimes this interrupt
> is coming and this flag is set but you do not wait this event and do not
> clear it. Then when you want to wait, the flag is already set by long
> time ago interrupt.
OK, we will fix it.
>
> > +}
> > +
> > +static ssize_t mtk_dsi_host_read_cmd(struct mtk_dsi *dsi,
> > + const struct mipi_dsi_msg *msg)
> > +{
> > + u8 max_try_count = 5;
> > + u32 recv_cnt, tmp_val;
> > + struct dsi_rxtx_data read_data0, read_data1, read_data2, read_data3;
> > + u8 config, type, data0, data1;
> > + s32 ret;
> > +
> > + u8 *buffer = msg->rx_buf;
> > + u8 buffer_size = msg->rx_len;
> > +
> > + if (readl(dsi->regs + DSI_MODE_CTRL) & 0x03) {
> > + dev_info(dsi->dev, "dsi engine is not command mode\n");
> > + return -1;
> > + }
> > +
> > + if (!buffer) {
> > + dev_info(dsi->dev, "dsi receive buffer size may be NULL\n");
> > + return -1;
> > + }
> > +
> > + do {
> > + if (max_try_count == 0) {
> > + dev_info(dsi->dev, "dsi engine read counter has been maxinum\n");
> > + return -1;
> > + }
> > +
> > + max_try_count--;
> > + recv_cnt = 0;
> > +
> > + mtk_dsi_wait_for_idle(dsi);
> > +
> > + config = 0x04;
> > + data0 = *((u8 *)(msg->tx_buf));
> > +
> > + if (buffer_size < 3)
> > + type = MIPI_DSI_DCS_READ;
> > + else
> > + type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
> > +
> > + data1 = 0;
> > +
> > + tmp_val = (data1 << 24) | (data0 << 16) | (type << 8) | config;
> > +
> > + writel(tmp_val, dsi->regs + DSI_CMDQ0);
> > + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, 1);
> > +
> > + mtk_dsi_start(dsi);
>
> This part looks like the same as mtk_dsi_host_write_cmd() with
> msg->tx_len = 1. Maybe you can try to merge these two part.
Will do.
>
> > +
> > + /* 2s timeout*/
> > + ret = wait_event_interruptible_timeout(_dsi_dcs_read_wait_queue,
> > + dsi->irq_data & LPRX_RD_RDY_INT_FLAG, timeout);
> > + if (ret == 0) {
> > + dev_info(dsi->dev, "Wait DSI read ready timeout!!!\n");
> > +
> > + mtk_dsi_enable(dsi);
> > + mtk_dsi_reset_engine(dsi);
> > +
> > + return ret;
> > + }
> > +
> > + dsi->irq_data &= ~LPRX_RD_RDY_INT_FLAG;
>
> I think you should move this before trigger HW. Sometimes this interrupt
> is coming and this flag is set but you do not wait this event and do not
> clear it. Then when you want to wait, the flag is already set by long
> time ago interrupt.
Will do.
>
> > +
> > + *(u32 *)(&read_data0) = readl(dsi->regs + DSI_RX_DATA0);
> > + *(u32 *)(&read_data1) = readl(dsi->regs + DSI_RX_DATA1);
> > + *(u32 *)(&read_data2) = readl(dsi->regs + DSI_RX_DATA2);
> > + *(u32 *)(&read_data3) = readl(dsi->regs + DSI_RX_DATA3);
> > +
> > + type = read_data0.byte0;
> > +
> > + if (type == MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE ||
> > + type == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
> > +
> > + /*
> > + * Data ID(1 byte) + Word Count(2 bytes) + ECC(1 byte) +
> > + * data 0 + ...+ data WC-1 + CHECKSUM (2 bytes)
>
> Is CHECKSUM useless? Why not check it?
We will check this.
>
> > + */
> > + recv_cnt = read_data0.byte1 + read_data0.byte2 * 16;
> > + dev_info(dsi->dev, "long packet size: %d\n", recv_cnt);
> > +
> > + /*
> > + * the buffer size is 16 bytes once, so the data payload
> > + * is, 16 - bytes(data ID + WC + ECC + CHECKSUM), if
> > + * over 10 bytes, it will be read again
> > + */
> > + if (recv_cnt > 10)
> > + recv_cnt = 10;
> > +
> > + if (recv_cnt > buffer_size)
> > + recv_cnt = buffer_size;
> > +
> > + if (recv_cnt <= 4) {
> > + memcpy(buffer, &read_data1, recv_cnt);
> > + } else if (recv_cnt <= 8) {
> > + memcpy(buffer, &read_data1, 4);
> > + memcpy(buffer + 4, &read_data2, recv_cnt - 4);
> > + } else {
> > + memcpy(buffer, &read_data1, 4);
> > + memcpy(buffer + 4, &read_data2, 4);
> > + memcpy(buffer + 8, &read_data3, recv_cnt - 8);
> > + }
>
> I think you can ignore read_data1, read_data2, and read_data3. Using a
> 'for loop' and readb() here can directly read register data into buffer.
We will rewrite this part.
>
>
> > + } else if (type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE ||
> > + type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE ||
> > + type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE ||
> > + type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
> > +
> > + if (type == MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE ||
> > + type == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)
> > + recv_cnt = 1;
> > + else
> > + recv_cnt = 2;
> > +
> > + if (recv_cnt > buffer_size)
> > + recv_cnt = buffer_size;
> > +
> > + memcpy(buffer, &read_data0.byte1, recv_cnt);
> > + } else if (type == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
> > + dev_info(dsi->dev, "packet type is 0x02, try again\n");
> > + } else {
> > + dev_info(dsi->dev, "packet type(0x%x) cannot be non-recognize\n",
> > + type);
> > +
> > + return 0;
> > + }
> > + } while (type == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT);
> > +
> > + dev_info(dsi->dev, "dsi get %d byte data from the panel address(0x%x)\n",
> > + recv_cnt, *((u8 *)(msg->tx_buf)));
> > +
> > + return recv_cnt;
> > +}
> > +
> > +static ssize_t mtk_dsi_host_write_cmd(struct mtk_dsi *dsi,
> > + const struct mipi_dsi_msg *msg)
> > +{
> > + u32 i;
> > + u32 goto_addr, mask_para, set_para, reg_val;
> > + void __iomem *cmdq_reg;
> > + u8 config, type, data0, data1;
> > + u16 wc16;
> > + const char *tx_buf = msg->tx_buf;
> > + struct dsi_tx_cmdq_regs *dsi_cmd_reg;
> > +
> > + dsi_cmd_reg = (struct dsi_tx_cmdq_regs *)(dsi->regs + DSI_CMDQ0);
> > +
> > + mtk_dsi_wait_for_idle(dsi);
> > +
> > + if (msg->tx_len > 2) {
> > + config = 2;
> > + type = msg->type;
> > + wc16 = msg->tx_len;
> > +
> > + reg_val = (wc16 << 16) | (type << 8) | config;
> > +
> > + writel(reg_val, &dsi_cmd_reg->data[0]);
> > +
> > + for (i = 0; i < msg->tx_len; i++) {
> > + goto_addr = (u32)(&dsi_cmd_reg->data[1].byte0) + i;
> > + mask_para = (0xff << ((goto_addr & 0x3) * 8));
> > + set_para = (tx_buf[i] << ((goto_addr & 0x3) * 8));
> > + cmdq_reg = (void __iomem *)(goto_addr & (~0x3));
> > + mtk_dsi_set_cmdq(cmdq_reg, mask_para, set_para);
> > + }
>
> Because you use writel(), so this part look so complicated. If you use
> writeb(), this would be much simpler.
OK, we will use writeb() in the next version.
Regards,
yt.shen
>
> > +
> > + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE,
> > + 1 + (msg->tx_len + 3) / 4);
> > + } else {
> > + config = 0;
> > + data0 = tx_buf[0];
> > + if (msg->tx_len == 2) {
> > + type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
> > + data1 = tx_buf[1];
> > + } else {
> > + type = MIPI_DSI_DCS_SHORT_WRITE;
> > + data1 = 0;
> > + }
> > +
> > + reg_val = (data1 << 24) | (data0 << 16) | (type << 8) | config;
> > +
> > + writel(reg_val, &dsi_cmd_reg->data[0]);
> > + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, 1);
> > + }
> > +
> > + mtk_dsi_start(dsi);
> > + mtk_dsi_wait_for_cmd_done(dsi);
> > +
> > + return 0;
> > +}
> > +
> > +static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
> > + const struct mipi_dsi_msg *msg)
> > +{
> > + struct mtk_dsi *dsi = host_to_dsi(host);
> > + u8 type = msg->type;
> > + ssize_t ret = 0;
> > +
> > + if (MTK_DSI_HOST_IS_READ(type))
> > + ret = mtk_dsi_host_read_cmd(dsi, msg);
> > + else if (MTK_DSI_HOST_IS_WRITE(type))
> > + ret = mtk_dsi_host_write_cmd(dsi, msg);
> > +
> > + return ret;
> > +}
> > +
> > static const struct mipi_dsi_host_ops mtk_dsi_ops = {
> > .attach = mtk_dsi_host_attach,
> > .detach = mtk_dsi_host_detach,
> > + .transfer = mtk_dsi_host_transfer,
> > };
> >
> > static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
>
> Regards,
> CK
>
[toc] | [prev] | [next] | [standalone]
| From | YT Shen <yt.shen@mediatek.com> |
|---|---|
| Date | 2016-07-28 11:40 +0200 |
| Subject | [PATCH v5 08/10] drm/mediatek: update DSI sub driver flow |
| Message-ID | <rZPXk-4m8-27@gated-at.bofh.it> |
| In reply to | #1451823 |
This patch update enable/disable flow of DSI module and MIPI TX module
Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
Signed-off-by: YT Shen <yt.shen@mediatek.com>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 104 ++++++++++++++++++++++++++------
drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 32 +++++-----
2 files changed, 103 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 1d36524..2646f83 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -95,6 +95,8 @@
#define DSI_RACK 0x84
#define RACK BIT(0)
+#define DSI_MEM_CONTI 0x90
+
#define DSI_PHY_LCCON 0x104
#define LC_HS_TX_EN BIT(0)
#define LC_ULPM_EN BIT(1)
@@ -127,6 +129,10 @@
#define CLK_HS_POST (0xff << 8)
#define CLK_HS_EXIT (0xff << 16)
+#define DSI_VM_CMD_CON 0x130
+#define VM_CMD_EN BIT(0)
+#define TS_VFP_EN BIT(5)
+
#define DSI_CMDQ0 0x180
#define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
@@ -266,7 +272,9 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
* mipi_ratio is mipi clk coefficient for balance the pixel clk in mipi.
* we set mipi_ratio is 1.05.
*/
- dsi->data_rate = dsi->vm.pixelclock * 3 * 21 / (1 * 1000 * 10);
+ dsi->data_rate = dsi->vm.pixelclock * 12 * 21;
+ dsi->data_rate /= (dsi->lanes * 1000 * 10);
+ dev_info(dev, "set mipitx's data rate: %dMHz\n", dsi->data_rate);
ret = clk_set_rate(dsi->hs_clk, dsi->data_rate * 1000000);
if (ret < 0) {
@@ -288,10 +296,6 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
goto err_disable_engine_clk;
}
- mtk_dsi_enable(dsi);
- mtk_dsi_reset_engine(dsi);
- mtk_dsi_phy_timconfig(dsi);
-
return 0;
err_disable_engine_clk:
@@ -306,7 +310,7 @@ err_refcount:
static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
- mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
+ mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, LC_ULPM_EN);
}
static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
@@ -319,7 +323,7 @@ static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi)
{
mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0);
- mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
+ mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, LD0_ULPM_EN);
}
static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
@@ -355,11 +359,21 @@ static void mtk_dsi_set_mode(struct mtk_dsi *dsi)
if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) &&
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
vid_mode = BURST_MODE;
+ else
+ vid_mode = SYNC_EVENT_MODE;
}
writel(vid_mode, dsi->regs + DSI_MODE_CTRL);
}
+static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi)
+{
+ writel(0x3c, dsi->regs + DSI_MEM_CONTI);
+
+ mtk_dsi_mask(dsi, DSI_VM_CMD_CON, VM_CMD_EN, VM_CMD_EN);
+ mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN);
+}
+
static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi)
{
struct videomode *vm = &dsi->vm;
@@ -416,6 +430,9 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
break;
}
+ tmp_reg |= (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6;
+ tmp_reg |= (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3;
+
writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
}
@@ -494,6 +511,16 @@ static void mtk_dsi_start(struct mtk_dsi *dsi)
writel(1, dsi->regs + DSI_START);
}
+static void mtk_dsi_stop(struct mtk_dsi *dsi)
+{
+ writel(0, dsi->regs + DSI_START);
+}
+
+static void mtk_dsi_set_cmd_mode(struct mtk_dsi *dsi)
+{
+ writel(CMD_MODE, dsi->regs + DSI_MODE_CTRL);
+}
+
static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi)
{
u32 inten = DSI_INT_ALL_BITS;
@@ -543,6 +570,27 @@ static irqreturn_t mtk_dsi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi)
+{
+ s32 ret = 0;
+ unsigned long timeout = msecs_to_jiffies(500);
+
+ mtk_dsi_set_cmd_mode(dsi);
+
+ ret = wait_event_interruptible_timeout(_dsi_wait_vm_done_queue,
+ dsi->irq_data & VM_DONE_INT_FLAG, timeout);
+ if (ret == 0) {
+ dev_info(dsi->dev, "dsi wait engine idle timeout\n");
+
+ mtk_dsi_enable(dsi);
+ mtk_dsi_reset_engine(dsi);
+
+ return;
+ }
+
+ dsi->irq_data &= ~VM_DONE_INT_FLAG;
+}
+
static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
{
if (WARN_ON(dsi->refcount == 0))
@@ -551,6 +599,17 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
if (--dsi->refcount != 0)
return;
+ mtk_dsi_switch_to_cmd_mode(dsi);
+
+ if (dsi->panel) {
+ if (drm_panel_unprepare(dsi->panel)) {
+ DRM_ERROR("failed to unprepare the panel\n");
+ return;
+ }
+ }
+
+ mtk_dsi_reset_engine(dsi);
+
mtk_dsi_lane0_ulp_mode_enter(dsi);
mtk_dsi_clk_ulp_mode_enter(dsi);
@@ -569,29 +628,37 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
if (dsi->enabled)
return;
- if (dsi->panel) {
- if (drm_panel_prepare(dsi->panel)) {
- DRM_ERROR("failed to setup the panel\n");
- return;
- }
- }
-
ret = mtk_dsi_poweron(dsi);
if (ret < 0) {
DRM_ERROR("failed to power on dsi\n");
return;
}
+ usleep_range(20000, 21000);
+
mtk_dsi_rxtx_control(dsi);
+ mtk_dsi_phy_timconfig(dsi);
+ mtk_dsi_ps_control_vact(dsi);
+ mtk_dsi_set_vm_cmd(dsi);
+ mtk_dsi_config_vdo_timing(dsi);
+ mtk_dsi_set_interrupt_enable(dsi);
+ mtk_dsi_enable(dsi);
mtk_dsi_clk_ulp_mode_leave(dsi);
mtk_dsi_lane0_ulp_mode_leave(dsi);
mtk_dsi_clk_hs_mode(dsi, 0);
- mtk_dsi_set_mode(dsi);
- mtk_dsi_ps_control_vact(dsi);
- mtk_dsi_config_vdo_timing(dsi);
- mtk_dsi_set_interrupt_enable(dsi);
+ if (dsi->panel) {
+ if (drm_panel_prepare(dsi->panel)) {
+ DRM_ERROR("failed to prepare the panel\n");
+ return;
+ }
+
+ if (drm_panel_enable(dsi->panel)) {
+ DRM_ERROR("failed to enable the panel\n");
+ return;
+ }
+ }
mtk_dsi_set_mode(dsi);
mtk_dsi_clk_hs_mode(dsi, 1);
@@ -613,6 +680,7 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi)
}
}
+ mtk_dsi_stop(dsi);
mtk_dsi_poweroff(dsi);
dsi->enabled = false;
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
index 19481c7..0666f15 100644
--- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
+++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
@@ -168,7 +168,9 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate);
- if (mipi_tx->data_rate >= 500000000) {
+ if (mipi_tx->data_rate > 1250000000) {
+ return -EINVAL;
+ } else if (mipi_tx->data_rate >= 500000000) {
txdiv = 1;
txdiv0 = 0;
txdiv1 = 0;
@@ -192,6 +194,10 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
return -EINVAL;
}
+ 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_update_bits(mipi_tx, MIPITX_DSI_BG_CON,
RG_DSI_VOUT_MSK |
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN,
@@ -201,24 +207,18 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
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_CON,
+ RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN,
+ 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,
+ RG_DSI_MPPLL_PREDIV | RG_DSI_MPPLL_TXDIV0 |
+ RG_DSI_MPPLL_TXDIV1 | RG_DSI_MPPLL_POSDIV,
(txdiv0 << 3) | (txdiv1 << 5));
/*
@@ -233,10 +233,12 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
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_update_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
+ RG_DSI_MPPLL_SDM_FRA_EN,
+ RG_DSI_MPPLL_SDM_FRA_EN);
- mtk_mipi_tx_set_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_PLL_EN, RG_DSI_MPPLL_PLL_EN);
usleep_range(20, 100);
--
1.7.9.5
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web