This is MT2701 DRM support PATCH v13, based on 4.11-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 v12: - Fix DSI enable flow we changed at v12
Changes since v11: - Update mtk_dsi_poweron() and mtk_output_dsi_enable() to symmetric flow
Changes since v10: - Add binding descriptions for newly added bindings - Remove color data pointer from generic mtk_ddp_comp - Remove "drm/mediatek: add mipi_tx data rate check" from the patch series - Remove "drm/mediatek: add dsi ulp mode control" from the patch series - Update descriptions for "drm/mediatek: add non-continuous clock mode and EOT packet control" - Fix DSI disable flow
Changes since v9: - Split DSI patches into smaller parts - Use a real linux errno for return value - Add error handling in mtk_output_dsi_enable() - Remove unused changes and redundant delays - Add helpers and macros for configuration - Combine "drm/mediatek: rename macros, add chip prefix" and "drm/mediatek: add *driver_data for different hardware setting"
Changes since v8: - enable 3 DSI interrupts only - move mtk_dsi_wait_for_irq_done() to the patch of irq control - use the name BLS in DRM driver part - move BLS declaration to a separate patch - update mtk_dsi_switch_to_cmd_mode() - update mtk_output_dsi_enable() and mtk_output_dsi_disable()
Changes since v7: - Remove redundant codes - Move the definition of DDP_COMPONENT_BLS to patch of "drm/mediatek: update display module connections" - Move _dsi_irq_wait_queue into platform driver data - Move mtk_dsi_irq_data_clear() to patch of "drm/mediatek: add dsi interrupt control" - Add more descriptions in the commit messages
Changes since v6: - Change data type of irq_data to u32 - Rewrite mtk_dsi_host_transfer() for simplify - Move some MIPI_TX config to patch of "drm/mediatek: add *driver_data for different hardware settings". - Remove device tree from this patch series
Changes since v5: - Remove DPI device tree and compatible string - Use one wait queue to handle interrupt status - Update the interrupt check flow and DSI_INT_ALL_BITS - Use same function for host read/write command - various fixes
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
Thanks, yt.shen
YT Shen (10): dt-bindings: display: mediatek: update supported chips drm/mediatek: add helpers for coverting from the generic components drm/mediatek: add *driver_data for different hardware settings drm/mediatek: add shadow register support drm/mediatek: add BLS component drm/mediatek: update display module connections drm/mediatek: cleaning up and refine drm/mediatek: add non-continuous clock mode and EOT packet control drm/mediatek: update DSI sub driver flow for sending commands to panel drm/mediatek: add support for Mediatek SoC MT2701
shaoming chen (2): drm/mediatek: add dsi interrupt control drm/mediatek: add dsi transfer function
.../bindings/display/mediatek/mediatek,disp.txt | 2 + .../bindings/display/mediatek/mediatek,dsi.txt | 2 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 64 ++- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 39 +- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 75 +-- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 138 +++-- drivers/gpu/drm/mediatek/mtk_drm_ddp.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 69 ++- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 54 +- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 9 + drivers/gpu/drm/mediatek/mtk_dsi.c | 572 ++++++++++++++++----- drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 38 +- 13 files changed, 828 insertions(+), 238 deletions(-)
Add decriptions about supported chips, including MT2701 & MT8173
Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: Rob Herring robh@kernel.org --- Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt | 2 ++ Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt index 708f566..383183a 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt @@ -40,6 +40,7 @@ Required properties (all function blocks): "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 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 merge and split function blocks). @@ -54,6 +55,7 @@ Required properties (DMA function blocks): "mediatek,<chip>-disp-ovl" "mediatek,<chip>-disp-rdma" "mediatek,<chip>-disp-wdma" + the supported chips are mt2701 and mt8173. - larb: Should contain a phandle pointing to the local arbiter device as defined in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt - iommus: Should point to the respective IOMMU block with master port as diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt index 2b1585a..fadf327 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt @@ -7,6 +7,7 @@ channel output.
Required properties: - compatible: "mediatek,<chip>-dsi" + the supported chips are mt2701 and mt8173. - reg: Physical base address and length of the controller's registers - interrupts: The interrupt signal from the function block. - clocks: device clocks @@ -25,6 +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. - 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
define helpers for converting from 'mtk_ddp_comp' to 'mtk_disp_ovl' define helpers for converting from 'mtk_ddp_comp' to 'mtk_disp_rdma'
Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 15 +++++++++------ drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index c703102..ce2759f 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -57,6 +57,11 @@ struct mtk_disp_ovl { struct drm_crtc *crtc; };
+static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp) +{ + return container_of(comp, struct mtk_disp_ovl, ddp_comp); +} + static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) { struct mtk_disp_ovl *priv = dev_id; @@ -76,20 +81,18 @@ static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp, struct drm_crtc *crtc) { - struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl, - ddp_comp); + struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
- priv->crtc = crtc; + ovl->crtc = crtc; writel(0x0, comp->regs + DISP_REG_OVL_INTSTA); writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN); }
static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp) { - struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl, - ddp_comp); + struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
- priv->crtc = NULL; + ovl->crtc = NULL; writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN); }
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 0df05f9..21eff6f 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -49,6 +49,11 @@ struct mtk_disp_rdma { struct drm_crtc *crtc; };
+static inline struct mtk_disp_rdma *comp_to_rdma(struct mtk_ddp_comp *comp) +{ + return container_of(comp, struct mtk_disp_rdma, ddp_comp); +} + static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id) { struct mtk_disp_rdma *priv = dev_id; @@ -77,20 +82,18 @@ static void rdma_update_bits(struct mtk_ddp_comp *comp, unsigned int reg, static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp, struct drm_crtc *crtc) { - struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma, - ddp_comp); + struct mtk_disp_rdma *rdma = comp_to_rdma(comp);
- priv->crtc = crtc; + rdma->crtc = crtc; rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, RDMA_FRAME_END_INT); }
static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp) { - struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma, - ddp_comp); + struct mtk_disp_rdma *rdma = comp_to_rdma(comp);
- priv->crtc = NULL; + rdma->crtc = NULL; rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0); }
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. MIPI_TX pll setting changed. And add prefix for mtk_ddp_main & mtk_ddp_ext & mutex_mod.
Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 41 ++++++++++++----- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 18 +++++++- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 71 +++++++++++++++-------------- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 57 +++++++++++++++++++---- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 25 +++++++--- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 8 ++++ drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 24 +++++++++- 7 files changed, 181 insertions(+), 63 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index ce2759f..4552178 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -35,18 +35,27 @@ #define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n)) #define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n)) #define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n)) -#define DISP_REG_OVL_ADDR(n) (0x0f40 + 0x20 * (n)) +#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 OVL_CON_BYTE_SWAP BIT(24) -#define OVL_CON_CLRFMT_RGB565 (0 << 12) -#define OVL_CON_CLRFMT_RGB888 (1 << 12) +#define OVL_CON_CLRFMT_RGB (1 << 12) #define OVL_CON_CLRFMT_RGBA8888 (2 << 12) #define OVL_CON_CLRFMT_ARGB8888 (3 << 12) +#define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ + 0 : OVL_CON_CLRFMT_RGB) +#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ + OVL_CON_CLRFMT_RGB : 0) #define OVL_CON_AEN BIT(8) #define OVL_CON_ALPHA 0xff
+struct mtk_disp_ovl_data { + unsigned int addr; + bool fmt_rgb565_is_0; +}; + /** * struct mtk_disp_ovl - DISP_OVL driver structure * @ddp_comp - structure containing type enum and hardware resources @@ -55,6 +64,7 @@ struct mtk_disp_ovl { struct mtk_ddp_comp ddp_comp; struct drm_crtc *crtc; + const struct mtk_disp_ovl_data *data; };
static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp) @@ -141,18 +151,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_disp_ovl *ovl, unsigned int fmt) { switch (fmt) { default: case DRM_FORMAT_RGB565: - return OVL_CON_CLRFMT_RGB565; + return OVL_CON_CLRFMT_RGB565(ovl); case DRM_FORMAT_BGR565: - return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP; + return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP; case DRM_FORMAT_RGB888: - return OVL_CON_CLRFMT_RGB888; + return OVL_CON_CLRFMT_RGB888(ovl); case DRM_FORMAT_BGR888: - return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP; + return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP; case DRM_FORMAT_RGBX8888: case DRM_FORMAT_RGBA8888: return OVL_CON_CLRFMT_ARGB8888; @@ -171,6 +181,7 @@ static unsigned int ovl_fmt_convert(unsigned int fmt) static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, struct mtk_plane_state *state) { + struct mtk_disp_ovl *ovl = comp_to_ovl(comp); struct mtk_plane_pending_state *pending = &state->pending; unsigned int addr = pending->addr; unsigned int pitch = pending->pitch & 0xffff; @@ -182,7 +193,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(ovl, fmt); if (idx != 0) con |= OVL_CON_AEN | OVL_CON_ALPHA;
@@ -190,7 +201,7 @@ 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 + DISP_REG_OVL_ADDR(ovl, idx));
if (pending->enable) mtk_ovl_layer_on(comp, idx); @@ -267,6 +278,8 @@ 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, @@ -290,8 +303,14 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev) return 0; }
+static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { + .addr = DISP_REG_OVL_ADDR_MT8173, + .fmt_rgb565_is_0 = true, +}; + 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 21eff6f..e5e5318 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -38,6 +38,11 @@ #define RDMA_FIFO_UNDERFLOW_EN BIT(31) #define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16) #define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16) +#define RDMA_FIFO_SIZE(rdma) ((rdma)->data->fifo_size) + +struct mtk_disp_rdma_data { + unsigned int fifo_size; +};
/** * struct mtk_disp_rdma - DISP_RDMA driver structure @@ -47,6 +52,7 @@ struct mtk_disp_rdma { struct mtk_ddp_comp ddp_comp; struct drm_crtc *crtc; + const struct mtk_disp_rdma_data *data; };
static inline struct mtk_disp_rdma *comp_to_rdma(struct mtk_ddp_comp *comp) @@ -114,6 +120,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, { unsigned int threshold; unsigned int reg; + struct mtk_disp_rdma *rdma = comp_to_rdma(comp);
rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width); rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height); @@ -126,7 +133,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(RDMA_FIFO_SIZE(rdma)) | RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold); writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON); } @@ -211,6 +218,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev) return ret; }
+ priv->data = of_device_get_match_data(dev); + platform_set_drvdata(pdev, priv);
ret = component_add(dev, &mtk_disp_rdma_component_ops); @@ -227,8 +236,13 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev) return 0; }
+static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = { + .fifo_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 17ba935..8030769 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -36,21 +36,21 @@ #define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n)) #define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n))
-#define MUTEX_MOD_DISP_OVL0 BIT(11) -#define MUTEX_MOD_DISP_OVL1 BIT(12) -#define MUTEX_MOD_DISP_RDMA0 BIT(13) -#define MUTEX_MOD_DISP_RDMA1 BIT(14) -#define MUTEX_MOD_DISP_RDMA2 BIT(15) -#define MUTEX_MOD_DISP_WDMA0 BIT(16) -#define MUTEX_MOD_DISP_WDMA1 BIT(17) -#define MUTEX_MOD_DISP_COLOR0 BIT(18) -#define MUTEX_MOD_DISP_COLOR1 BIT(19) -#define MUTEX_MOD_DISP_AAL BIT(20) -#define MUTEX_MOD_DISP_GAMMA BIT(21) -#define MUTEX_MOD_DISP_UFOE BIT(22) -#define MUTEX_MOD_DISP_PWM0 BIT(23) -#define MUTEX_MOD_DISP_PWM1 BIT(24) -#define MUTEX_MOD_DISP_OD BIT(25) +#define MT8173_MUTEX_MOD_DISP_OVL0 BIT(11) +#define MT8173_MUTEX_MOD_DISP_OVL1 BIT(12) +#define MT8173_MUTEX_MOD_DISP_RDMA0 BIT(13) +#define MT8173_MUTEX_MOD_DISP_RDMA1 BIT(14) +#define MT8173_MUTEX_MOD_DISP_RDMA2 BIT(15) +#define MT8173_MUTEX_MOD_DISP_WDMA0 BIT(16) +#define MT8173_MUTEX_MOD_DISP_WDMA1 BIT(17) +#define MT8173_MUTEX_MOD_DISP_COLOR0 BIT(18) +#define MT8173_MUTEX_MOD_DISP_COLOR1 BIT(19) +#define MT8173_MUTEX_MOD_DISP_AAL BIT(20) +#define MT8173_MUTEX_MOD_DISP_GAMMA BIT(21) +#define MT8173_MUTEX_MOD_DISP_UFOE BIT(22) +#define MT8173_MUTEX_MOD_DISP_PWM0 BIT(23) +#define MT8173_MUTEX_MOD_DISP_PWM1 BIT(24) +#define MT8173_MUTEX_MOD_DISP_OD BIT(25)
#define MUTEX_SOF_SINGLE_MODE 0 #define MUTEX_SOF_DSI0 1 @@ -77,24 +77,25 @@ 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] = { - [DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL, - [DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0, - [DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1, - [DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA, - [DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD, - [DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0, - [DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1, - [DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0, - [DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1, - [DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0, - [DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1, - [DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2, - [DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE, - [DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0, - [DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1, +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, + [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA, + [DDP_COMPONENT_OD] = MT8173_MUTEX_MOD_DISP_OD, + [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0, + [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1, + [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0, + [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1, + [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0, + [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1, + [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2, + [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE, + [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0, + [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1, };
static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, @@ -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 48cc01f..3ff788c 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -39,9 +39,10 @@ #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_START_MT8173 0x0c00 +#define DISP_COLOR_START(comp) ((comp)->data->color_offset) +#define DISP_COLOR_WIDTH(comp) (DISP_COLOR_START(comp) + 0x50) +#define DISP_COLOR_HEIGHT(comp) (DISP_COLOR_START(comp) + 0x54)
#define DISP_AAL_EN 0x0000 #define DISP_AAL_SIZE 0x0030 @@ -80,6 +81,20 @@ #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) #define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0)
+struct mtk_disp_color_data { + unsigned int color_offset; +}; + +struct mtk_disp_color { + struct mtk_ddp_comp ddp_comp; + const struct mtk_disp_color_data *data; +}; + +static inline struct mtk_disp_color *comp_to_color(struct mtk_ddp_comp *comp) +{ + return container_of(comp, struct mtk_disp_color, ddp_comp); +} + void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc, unsigned int CFG) { @@ -107,15 +122,19 @@ static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, unsigned int bpc) { - writel(w, comp->regs + DISP_COLOR_WIDTH); - writel(h, comp->regs + DISP_COLOR_HEIGHT); + struct mtk_disp_color *color = comp_to_color(comp); + + writel(w, comp->regs + DISP_COLOR_WIDTH(color)); + writel(h, comp->regs + DISP_COLOR_HEIGHT(color)); }
static void mtk_color_start(struct mtk_ddp_comp *comp) { + struct mtk_disp_color *color = comp_to_color(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 + DISP_COLOR_START(color)); }
static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, @@ -264,6 +283,16 @@ struct mtk_ddp_comp_match { [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL }, };
+static const struct mtk_disp_color_data mt8173_color_driver_data = { + .color_offset = DISP_COLOR_START_MT8173, +}; + +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) { @@ -286,10 +315,24 @@ 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; + struct mtk_disp_color *color;
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) return -EINVAL;
+ type = mtk_ddp_matches[comp_id].type; + if (type == MTK_DISP_COLOR) { + devm_kfree(dev, comp); + color = devm_kzalloc(dev, sizeof(*color), GFP_KERNEL); + if (!color) + return -ENOMEM; + + match = of_match_node(mtk_disp_color_driver_dt_match, node); + color->data = match->data; + comp = &color->ddp_comp; + } + comp->id = comp_id; comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs;
@@ -308,8 +351,6 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, if (IS_ERR(comp->clk)) comp->clk = NULL;
- type = mtk_ddp_matches[comp_id].type; - /* 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_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index b5f88e6..6ef19f2 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -128,7 +128,7 @@ static int mtk_atomic_commit(struct drm_device *drm, .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, @@ -139,7 +139,7 @@ static int mtk_atomic_commit(struct drm_device *drm, 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, @@ -147,6 +147,13 @@ static int mtk_atomic_commit(struct drm_device *drm, 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; @@ -189,17 +196,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; @@ -363,6 +372,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); @@ -514,7 +524,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 df322a7..21a4339 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_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; @@ -39,6 +46,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; diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c index 1c366f8..c4a0165 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) @@ -123,10 +127,15 @@ #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; unsigned int data_rate; + const struct mtk_mipitx_data *driver_data; struct clk_hw pll_hw; struct clk *pll; }; @@ -243,6 +252,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->mppll_preserve); + return 0; }
@@ -255,6 +268,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, @@ -391,6 +407,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)) { @@ -448,8 +465,13 @@ static int mtk_mipi_tx_remove(struct platform_device *pdev) return 0; }
+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,mt8173-mipi-tx", }, + { .compatible = "mediatek,mt8173-mipi-tx", + .data = &mt8173_mipitx_data }, {}, };
We need to acquire mutex before using the resources, and need to release it after finished. So we don't need to write registers in the blanking period.
Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 75 ++++++++++++++++++++------------- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 25 +++++++++++ drivers/gpu/drm/mediatek/mtk_drm_ddp.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 + 4 files changed, 74 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index a73de1e..4988e50 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -329,6 +329,42 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) pm_runtime_put(drm->dev); }
+static void mtk_crtc_ddp_config(struct drm_crtc *crtc) +{ + struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); + struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; + unsigned int i; + + /* + * TODO: instead of updating the registers here, we should prepare + * working registers in atomic_commit and let the hardware command + * queue update module registers on vblank. + */ + if (state->pending_config) { + mtk_ddp_comp_config(ovl, state->pending_width, + state->pending_height, + state->pending_vrefresh, 0); + + state->pending_config = false; + } + + if (mtk_crtc->pending_planes) { + for (i = 0; i < OVL_LAYER_NR; i++) { + struct drm_plane *plane = &mtk_crtc->planes[i]; + struct mtk_plane_state *plane_state; + + plane_state = to_mtk_plane_state(plane->state); + + if (plane_state->pending.config) { + mtk_ddp_comp_layer_config(ovl, i, plane_state); + plane_state->pending.config = false; + } + } + mtk_crtc->pending_planes = false; + } +} + static void mtk_drm_crtc_enable(struct drm_crtc *crtc) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); @@ -405,6 +441,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_drm_private *priv = crtc->dev->dev_private; unsigned int pending_planes = 0; int i;
@@ -426,6 +463,12 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, if (crtc->state->color_mgmt_changed) for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state); + + if (priv->data->shadow_register) { + mtk_disp_mutex_acquire(mtk_crtc->mutex); + mtk_crtc_ddp_config(crtc); + mtk_disp_mutex_release(mtk_crtc->mutex); + } }
static const struct drm_crtc_funcs mtk_crtc_funcs = { @@ -471,36 +514,10 @@ static int mtk_drm_crtc_init(struct drm_device *drm, void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); - struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); - unsigned int i; + struct mtk_drm_private *priv = crtc->dev->dev_private;
- /* - * TODO: instead of updating the registers here, we should prepare - * working registers in atomic_commit and let the hardware command - * queue update module registers on vblank. - */ - if (state->pending_config) { - mtk_ddp_comp_config(ovl, state->pending_width, - state->pending_height, - state->pending_vrefresh, 0); - - state->pending_config = false; - } - - if (mtk_crtc->pending_planes) { - for (i = 0; i < OVL_LAYER_NR; i++) { - struct drm_plane *plane = &mtk_crtc->planes[i]; - struct mtk_plane_state *plane_state; - - plane_state = to_mtk_plane_state(plane->state); - - if (plane_state->pending.config) { - mtk_ddp_comp_layer_config(ovl, i, plane_state); - plane_state->pending.config = false; - } - } - mtk_crtc->pending_planes = false; - } + if (!priv->data->shadow_register) + mtk_crtc_ddp_config(crtc);
mtk_drm_finish_page_flip(mtk_crtc); } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 8030769..b77d456 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -12,6 +12,7 @@ */
#include <linux/clk.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -32,10 +33,13 @@ #define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100
#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 INT_MUTEX BIT(1) + #define MT8173_MUTEX_MOD_DISP_OVL0 BIT(11) #define MT8173_MUTEX_MOD_DISP_OVL1 BIT(12) #define MT8173_MUTEX_MOD_DISP_RDMA0 BIT(13) @@ -300,6 +304,27 @@ void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex) writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); }
+void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex) +{ + struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, + mutex[mutex->id]); + u32 tmp; + + writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); + writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id)); + if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id), + tmp, tmp & INT_MUTEX, 1, 10000)) + pr_err("could not acquire mutex %d\n", mutex->id); +} + +void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex) +{ + struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, + mutex[mutex->id]); + + writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id)); +} + static int mtk_ddp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h index 92c1175..f9a7991 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h @@ -37,5 +37,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex, enum mtk_ddp_comp_id id); void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex); void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex); +void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex); +void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex);
#endif /* MTK_DRM_DDP_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 21a4339..aef8747 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -33,6 +33,7 @@ struct mtk_mmsys_driver_data { unsigned int main_len; const enum mtk_ddp_comp_id *ext_path; unsigned int ext_len; + bool shadow_register; };
struct mtk_drm_private {
Add BLS component for PWM + GAMMA function
Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 5 ++++- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 3ff788c..f6e853a 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -255,6 +255,7 @@ static void mtk_gamma_set(struct mtk_ddp_comp *comp, [MTK_DISP_PWM] = "pwm", [MTK_DISP_MUTEX] = "mutex", [MTK_DISP_OD] = "od", + [MTK_DISP_BLS] = "bls", };
struct mtk_ddp_comp_match { @@ -265,6 +266,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, &ddp_aal }, + [DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 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 }, @@ -336,7 +338,8 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, comp->id = comp_id; comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs;
- if (comp_id == DDP_COMPONENT_DPI0 || + if (comp_id == DDP_COMPONENT_BLS || + comp_id == DDP_COMPONENT_DPI0 || comp_id == DDP_COMPONENT_DSI0 || comp_id == DDP_COMPONENT_PWM0) { comp->regs = NULL; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index 22a33ee..0828cf8 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -36,11 +36,13 @@ enum mtk_ddp_comp_type { MTK_DISP_PWM, MTK_DISP_MUTEX, MTK_DISP_OD, + MTK_DISP_BLS, MTK_DDP_COMP_TYPE_MAX, };
enum mtk_ddp_comp_id { DDP_COMPONENT_AAL, + DDP_COMPONENT_BLS, DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR1, DDP_COMPONENT_DPI0,
update connections for OVL, RDMA, BLS, DSI
Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index b77d456..a9b209c 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -32,6 +32,10 @@ #define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN 0x0c8 #define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100
+#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030 +#define DISP_REG_CONFIG_OUT_SEL 0x04c +#define DISP_REG_CONFIG_DSI_SEL 0x050 + #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)) @@ -71,6 +75,10 @@ #define DPI0_SEL_IN_RDMA1 0x1 #define COLOR1_SEL_IN_OVL1 0x1
+#define OVL_MOUT_EN_RDMA 0x1 +#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 +#define DSI_SEL_IN_BLS 0x0 + struct mtk_disp_mutex { int id; bool claimed; @@ -111,6 +119,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; value = OVL0_MOUT_EN_COLOR0; + } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) { + *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN; + value = OVL_MOUT_EN_RDMA; } else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) { *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN; value = OD_MOUT_EN_RDMA0; @@ -148,6 +159,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN; value = COLOR1_SEL_IN_OVL1; + } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) { + *addr = DISP_REG_CONFIG_DSI_SEL; + value = DSI_SEL_IN_BLS; } else { value = 0; } @@ -155,6 +169,15 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, return value; }
+static void mtk_ddp_sout_sel(void __iomem *config_regs, + enum mtk_ddp_comp_id cur, + enum mtk_ddp_comp_id next) +{ + if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) + writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1, + config_regs + DISP_REG_CONFIG_OUT_SEL); +} + void mtk_ddp_add_comp_to_path(void __iomem *config_regs, enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next) @@ -167,6 +190,8 @@ void mtk_ddp_add_comp_to_path(void __iomem *config_regs, writel_relaxed(reg, config_regs + addr); }
+ mtk_ddp_sout_sel(config_regs, cur, next); + value = mtk_ddp_sel_in(cur, next, &addr); if (value) { reg = readl_relaxed(config_regs + addr) | value;
cleaning up unused define and refine function name and variable
Signed-off-by: shaoming chen shaoming.chen@mediatek.com Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dsi.c | 73 ++++++++++++++++------------------ drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 8 ++-- 2 files changed, 39 insertions(+), 42 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index dd71cbb..5d66b98 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -27,9 +27,6 @@
#include "mtk_drm_ddp_comp.h"
-#define DSI_VIDEO_FIFO_DEPTH (1920 / 4) -#define DSI_HOST_FIFO_DEPTH 64 - #define DSI_START 0x00
#define DSI_CON_CTRL 0x10 @@ -46,7 +43,7 @@ #define MIX_MODE BIT(17)
#define DSI_TXRX_CTRL 0x18 -#define VC_NUM (2 << 0) +#define VC_NUM BIT(1) #define LANE_NUM (0xf << 2) #define DIS_EOT BIT(6) #define NULL_EN BIT(7) @@ -164,7 +161,7 @@ static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data) writel((temp & ~mask) | (data & mask), dsi->regs + offset); }
-static void dsi_phy_timconfig(struct mtk_dsi *dsi) +static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) { u32 timcon0, timcon1, timcon2, timcon3; u32 ui, cycle_time; @@ -196,7 +193,7 @@ static void mtk_dsi_disable(struct mtk_dsi *dsi) mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0); }
-static void mtk_dsi_reset(struct mtk_dsi *dsi) +static void mtk_dsi_reset_engine(struct mtk_dsi *dsi) { mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET); mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0); @@ -267,8 +264,8 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) }
mtk_dsi_enable(dsi); - mtk_dsi_reset(dsi); - dsi_phy_timconfig(dsi); + mtk_dsi_reset_engine(dsi); + mtk_dsi_phy_timconfig(dsi);
return 0;
@@ -281,33 +278,33 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) return ret; }
-static void dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi) +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); }
-static void dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi) +static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi) { mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN); mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0); }
-static void dsi_lane0_ulp_mode_enter(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); }
-static void dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi) +static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi) { mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN); mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0); }
-static bool dsi_clk_hs_state(struct mtk_dsi *dsi) +static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi) { u32 tmp_reg1;
@@ -315,15 +312,15 @@ static bool dsi_clk_hs_state(struct mtk_dsi *dsi) return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false; }
-static void dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter) +static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter) { - if (enter && !dsi_clk_hs_state(dsi)) + if (enter && !mtk_dsi_clk_hs_state(dsi)) mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN); - else if (!enter && dsi_clk_hs_state(dsi)) + else if (!enter && mtk_dsi_clk_hs_state(dsi)) mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); }
-static void dsi_set_mode(struct mtk_dsi *dsi) +static void mtk_dsi_set_mode(struct mtk_dsi *dsi) { u32 vid_mode = CMD_MODE;
@@ -338,7 +335,7 @@ static void dsi_set_mode(struct mtk_dsi *dsi) writel(vid_mode, dsi->regs + DSI_MODE_CTRL); }
-static void dsi_ps_control_vact(struct mtk_dsi *dsi) +static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi) { struct videomode *vm = &dsi->vm; u32 dsi_buf_bpp, ps_wc; @@ -372,7 +369,7 @@ static void dsi_ps_control_vact(struct mtk_dsi *dsi) writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); }
-static void dsi_rxtx_control(struct mtk_dsi *dsi) +static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) { u32 tmp_reg;
@@ -397,9 +394,9 @@ static void dsi_rxtx_control(struct mtk_dsi *dsi) writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); }
-static void dsi_ps_control(struct mtk_dsi *dsi) +static void mtk_dsi_ps_control(struct mtk_dsi *dsi) { - unsigned int dsi_tmp_buf_bpp; + u32 dsi_tmp_buf_bpp; u32 tmp_reg;
switch (dsi->format) { @@ -429,12 +426,12 @@ static void dsi_ps_control(struct mtk_dsi *dsi) writel(tmp_reg, dsi->regs + DSI_PSCTRL); }
-static void dsi_config_vdo_timing(struct mtk_dsi *dsi) +static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) { - unsigned int horizontal_sync_active_byte; - unsigned int horizontal_backporch_byte; - unsigned int horizontal_frontporch_byte; - unsigned int dsi_tmp_buf_bpp; + u32 horizontal_sync_active_byte; + u32 horizontal_backporch_byte; + u32 horizontal_frontporch_byte; + u32 dsi_tmp_buf_bpp;
struct videomode *vm = &dsi->vm;
@@ -463,7 +460,7 @@ static void dsi_config_vdo_timing(struct mtk_dsi *dsi) writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
- dsi_ps_control(dsi); + mtk_dsi_ps_control(dsi); }
static void mtk_dsi_start(struct mtk_dsi *dsi) @@ -480,8 +477,8 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi) if (--dsi->refcount != 0) return;
- dsi_lane0_ulp_mode_enter(dsi); - dsi_clk_ulp_mode_enter(dsi); + mtk_dsi_lane0_ulp_mode_enter(dsi); + mtk_dsi_clk_ulp_mode_enter(dsi);
mtk_dsi_disable(dsi);
@@ -511,18 +508,18 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi) return; }
- dsi_rxtx_control(dsi); + mtk_dsi_rxtx_control(dsi);
- dsi_clk_ulp_mode_leave(dsi); - dsi_lane0_ulp_mode_leave(dsi); - dsi_clk_hs_mode(dsi, 0); - dsi_set_mode(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);
- dsi_ps_control_vact(dsi); - dsi_config_vdo_timing(dsi); + mtk_dsi_ps_control_vact(dsi); + mtk_dsi_config_vdo_timing(dsi);
- dsi_set_mode(dsi); - dsi_clk_hs_mode(dsi, 1); + mtk_dsi_set_mode(dsi); + mtk_dsi_clk_hs_mode(dsi, 1);
mtk_dsi_start(dsi);
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c index c4a0165..fd84914 100644 --- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c +++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c @@ -134,7 +134,7 @@ struct mtk_mipitx_data { struct mtk_mipi_tx { struct device *dev; void __iomem *regs; - unsigned int data_rate; + u32 data_rate; const struct mtk_mipitx_data *driver_data; struct clk_hw pll_hw; struct clk *pll; @@ -172,7 +172,7 @@ static void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 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); - unsigned int txdiv, txdiv0, txdiv1; + u8 txdiv, txdiv0, txdiv1; u64 pcw;
dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate); @@ -326,7 +326,7 @@ static unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw, static int mtk_mipi_tx_power_on_signal(struct phy *phy) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); - unsigned int reg; + u32 reg;
for (reg = MIPITX_DSI_CLOCK_LANE; reg <= MIPITX_DSI_DATA_LANE3; reg += 4) @@ -357,7 +357,7 @@ static int mtk_mipi_tx_power_on(struct phy *phy) static void mtk_mipi_tx_power_off_signal(struct phy *phy) { struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); - unsigned int reg; + u32 reg;
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON, RG_DSI_PAD_TIE_LOW_EN);
From: shaoming chen shaoming.chen@mediatek.com
add dsi interrupt control
Signed-off-by: shaoming chen shaoming.chen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dsi.c | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 5d66b98..57955636 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -18,6 +18,7 @@ #include <drm/drm_panel.h> #include <linux/clk.h> #include <linux/component.h> +#include <linux/irq.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/of_graph.h> @@ -29,6 +30,16 @@
#define DSI_START 0x00
+#define DSI_INTEN 0x08 + +#define DSI_INTSTA 0x0c +#define LPRX_RD_RDY_INT_FLAG BIT(0) +#define CMD_DONE_INT_FLAG BIT(1) +#define TE_RDY_INT_FLAG BIT(2) +#define VM_DONE_INT_FLAG BIT(3) +#define EXT_TE_RDY_INT_FLAG BIT(4) +#define DSI_BUSY BIT(31) + #define DSI_CON_CTRL 0x10 #define DSI_RESET BIT(0) #define DSI_EN BIT(1) @@ -71,6 +82,9 @@
#define DSI_HSTX_CKL_WC 0x64
+#define DSI_RACK 0x84 +#define RACK BIT(0) + #define DSI_PHY_LCCON 0x104 #define LC_HS_TX_EN BIT(0) #define LC_ULPM_EN BIT(1) @@ -137,6 +151,8 @@ struct mtk_dsi { struct videomode vm; int refcount; bool enabled; + u32 irq_data; + wait_queue_head_t irq_wait_queue; };
static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e) @@ -469,6 +485,64 @@ static void mtk_dsi_start(struct mtk_dsi *dsi) writel(1, dsi->regs + DSI_START); }
+static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi) +{ + u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; + + writel(inten, dsi->regs + DSI_INTEN); +} + +static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit) +{ + dsi->irq_data |= irq_bit; +} + +static __maybe_unused void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit) +{ + dsi->irq_data &= ~irq_bit; +} + +static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag, + unsigned int timeout) +{ + s32 ret = 0; + unsigned long jiffies = msecs_to_jiffies(timeout); + + ret = wait_event_interruptible_timeout(dsi->irq_wait_queue, + dsi->irq_data & irq_flag, + jiffies); + if (ret == 0) { + DRM_WARN("Wait DSI IRQ(0x%08x) Timeout\n", irq_flag); + + mtk_dsi_enable(dsi); + mtk_dsi_reset_engine(dsi); + } + + return ret; +} + +static irqreturn_t mtk_dsi_irq(int irq, void *dev_id) +{ + struct mtk_dsi *dsi = dev_id; + u32 status, tmp; + u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; + + status = readl(dsi->regs + DSI_INTSTA) & flag; + + if (status) { + do { + mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK); + tmp = readl(dsi->regs + DSI_INTSTA); + } while (tmp & DSI_BUSY); + + mtk_dsi_mask(dsi, DSI_INTSTA, status, 0); + mtk_dsi_irq_data_set(dsi, status); + wake_up_interruptible(&dsi->irq_wait_queue); + } + + return IRQ_HANDLED; +} + static void mtk_dsi_poweroff(struct mtk_dsi *dsi) { if (WARN_ON(dsi->refcount == 0)) @@ -517,6 +591,7 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
mtk_dsi_ps_control_vact(dsi); mtk_dsi_config_vdo_timing(dsi); + mtk_dsi_set_interrupt_enable(dsi);
mtk_dsi_set_mode(dsi); mtk_dsi_clk_hs_mode(dsi, 1); @@ -800,6 +875,7 @@ static int mtk_dsi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *remote_node, *endpoint; struct resource *regs; + int irq_num; int comp_id; int ret;
@@ -876,6 +952,22 @@ static int mtk_dsi_probe(struct platform_device *pdev) return ret; }
+ 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; + } + + irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW); + ret = devm_request_irq(&pdev->dev, irq_num, mtk_dsi_irq, + IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi); + if (ret) { + dev_err(&pdev->dev, "failed to request mediatek dsi irq\n"); + return -EPROBE_DEFER; + } + + init_waitqueue_head(&dsi->irq_wait_queue); + platform_set_drvdata(pdev, dsi);
return component_add(&pdev->dev, &mtk_dsi_component_ops);
From: shaoming chen shaoming.chen@mediatek.com
add dsi read/write commands for transfer function
Signed-off-by: shaoming chen shaoming.chen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dsi.c | 168 ++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 57955636..2e2cc3a 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" @@ -80,8 +81,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)
@@ -117,6 +126,15 @@ #define CLK_HS_POST (0xff << 8) #define CLK_HS_EXIT (0xff << 16)
+#define DSI_CMDQ0 0x180 +#define CONFIG (0xff << 0) +#define SHORT_PACKET 0 +#define LONG_PACKET 2 +#define BTA BIT(2) +#define DATA_ID (0xff << 8) +#define DATA_0 (0xff << 16) +#define DATA_1 (0xff << 24) + #define T_LPX 5 #define T_HS_PREP 6 #define T_HS_TRAIL 8 @@ -125,6 +143,12 @@
#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)) + struct phy;
struct mtk_dsi { @@ -497,12 +521,12 @@ static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit) dsi->irq_data |= irq_bit; }
-static __maybe_unused void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit) +static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit) { dsi->irq_data &= ~irq_bit; }
-static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag, +static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag, unsigned int timeout) { s32 ret = 0; @@ -814,9 +838,149 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host, return 0; }
+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) { + DRM_WARN("polling dsi wait not busy timeout!\n"); + + mtk_dsi_enable(dsi); + mtk_dsi_reset_engine(dsi); + } +} + +static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data) +{ + switch (type) { + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: + return 1; + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: + return 2; + case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: + case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: + return read_data[1] + read_data[2] * 16; + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: + DRM_INFO("type is 0x02, try again\n"); + break; + default: + DRM_INFO("type(0x%x) cannot be non-recognite\n", type); + break; + } + + return 0; +} + +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; + + if (MTK_DSI_HOST_IS_READ(type)) + config = BTA; + else + config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET; + + if (msg->tx_len > 2) { + cmdq_size = 1 + (msg->tx_len + 3) / 4; + cmdq_off = 4; + cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1; + reg_val = (msg->tx_len << 16) | (type << 8) | config; + } else { + cmdq_size = 1; + cmdq_off = 2; + cmdq_mask = CONFIG | DATA_ID; + reg_val = (type << 8) | config; + } + + for (i = 0; i < msg->tx_len; i++) + writeb(tx_buf[i], dsi->regs + DSI_CMDQ0 + cmdq_off + i); + + mtk_dsi_mask(dsi, DSI_CMDQ0, cmdq_mask, reg_val); + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size); +} + +static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi, + const struct mipi_dsi_msg *msg, u8 flag) +{ + mtk_dsi_wait_for_idle(dsi); + mtk_dsi_irq_data_clear(dsi, flag); + mtk_dsi_cmdq(dsi, msg); + mtk_dsi_start(dsi); + + if (!mtk_dsi_wait_for_irq_done(dsi, flag, 2000)) + return -ETIME; + else + 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); + u32 recv_cnt, i; + u8 read_data[16]; + void *src_addr; + u8 irq_flag = CMD_DONE_INT_FLAG; + + if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) { + DRM_ERROR("dsi engine is not command mode\n"); + return -EINVAL; + } + + if (MTK_DSI_HOST_IS_READ(msg->type)) + irq_flag |= LPRX_RD_RDY_INT_FLAG; + + if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0) + return -ETIME; + + if (!MTK_DSI_HOST_IS_READ(msg->type)) + return 0; + + if (!msg->rx_buf) { + DRM_ERROR("dsi receive buffer size may be NULL\n"); + return -EINVAL; + } + + for (i = 0; i < 16; i++) + *(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i); + + recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data); + + if (recv_cnt > 2) + src_addr = &read_data[4]; + else + src_addr = &read_data[1]; + + if (recv_cnt > 10) + recv_cnt = 10; + + if (recv_cnt > msg->rx_len) + recv_cnt = msg->rx_len; + + if (recv_cnt) + memcpy(msg->rx_buf, src_addr, recv_cnt); + + DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n", + recv_cnt, *((u8 *)(msg->tx_buf))); + + return recv_cnt; +} + 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)
This patch will update dsi clock control method. 1. dsi non-continue clock mode will enhance antistatic effect for panel 2. EOT packet control will judge whether dsi send end of packet or not by customize
Signed-off-by: shaoming chen shaoming.chen@mediatek.com Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dsi.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 2e2cc3a..09528e2 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -431,6 +431,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); }
This patch update enable/disable flow of DSI module. Original flow works on there is a bridge chip: DSI -> bridge -> panel. In this case: DSI -> panel, the DSI sub driver flow should be updated. We need to initialize DSI first so that we can send commands to panel.
Signed-off-by: shaoming chen shaoming.chen@mediatek.com Signed-off-by: YT Shen yt.shen@mediatek.com Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dsi.c | 259 ++++++++++++++++++++++--------------- 1 file changed, 158 insertions(+), 101 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 09528e2..b6eac92 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -126,6 +126,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 CONFIG (0xff << 0) #define SHORT_PACKET 0 @@ -239,85 +243,6 @@ static void mtk_dsi_reset_engine(struct mtk_dsi *dsi) mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0); }
-static int mtk_dsi_poweron(struct mtk_dsi *dsi) -{ - struct device *dev = dsi->dev; - int ret; - u64 pixel_clock, total_bits; - u32 htotal, htotal_bits, bit_per_pixel, overhead_cycles, overhead_bits; - - if (++dsi->refcount != 1) - return 0; - - switch (dsi->format) { - case MIPI_DSI_FMT_RGB565: - bit_per_pixel = 16; - break; - case MIPI_DSI_FMT_RGB666_PACKED: - bit_per_pixel = 18; - break; - case MIPI_DSI_FMT_RGB666: - case MIPI_DSI_FMT_RGB888: - default: - bit_per_pixel = 24; - break; - } - - /** - * vm.pixelclock is in kHz, pixel_clock unit is Hz, so multiply by 1000 - * 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 * 1000; - 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); - - ret = clk_set_rate(dsi->hs_clk, dsi->data_rate); - if (ret < 0) { - dev_err(dev, "Failed to set data rate: %d\n", ret); - goto err_refcount; - } - - phy_power_on(dsi->phy); - - ret = clk_prepare_enable(dsi->engine_clk); - if (ret < 0) { - dev_err(dev, "Failed to enable engine clock: %d\n", ret); - goto err_phy_power_off; - } - - ret = clk_prepare_enable(dsi->digital_clk); - if (ret < 0) { - dev_err(dev, "Failed to enable digital clock: %d\n", ret); - 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: - clk_disable_unprepare(dsi->engine_clk); -err_phy_power_off: - phy_power_off(dsi->phy); -err_refcount: - dsi->refcount--; - return ret; -} - static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi) { mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); @@ -365,16 +290,23 @@ static void mtk_dsi_set_mode(struct mtk_dsi *dsi) u32 vid_mode = CMD_MODE;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { - vid_mode = SYNC_PULSE_MODE; - - if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) && - !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) vid_mode = BURST_MODE; + else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) + vid_mode = SYNC_PULSE_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) +{ + 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; @@ -512,6 +444,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 = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; @@ -570,6 +512,116 @@ static irqreturn_t mtk_dsi_irq(int irq, void *dev_id) return IRQ_HANDLED; }
+static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t) +{ + mtk_dsi_irq_data_clear(dsi, irq_flag); + mtk_dsi_set_cmd_mode(dsi); + + if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag, t)) { + DRM_ERROR("failed to switch cmd mode\n"); + return -ETIME; + } else { + return 0; + } +} + +static int mtk_dsi_poweron(struct mtk_dsi *dsi) +{ + struct device *dev = dsi->dev; + int ret; + u64 pixel_clock, total_bits; + u32 htotal, htotal_bits, bit_per_pixel, overhead_cycles, overhead_bits; + + if (++dsi->refcount != 1) + return 0; + + switch (dsi->format) { + case MIPI_DSI_FMT_RGB565: + bit_per_pixel = 16; + break; + case MIPI_DSI_FMT_RGB666_PACKED: + bit_per_pixel = 18; + break; + case MIPI_DSI_FMT_RGB666: + case MIPI_DSI_FMT_RGB888: + default: + bit_per_pixel = 24; + break; + } + + /** + * vm.pixelclock is in kHz, pixel_clock unit is Hz, so multiply by 1000 + * 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 * 1000; + 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); + + ret = clk_set_rate(dsi->hs_clk, dsi->data_rate); + if (ret < 0) { + dev_err(dev, "Failed to set data rate: %d\n", ret); + goto err_refcount; + } + + phy_power_on(dsi->phy); + + ret = clk_prepare_enable(dsi->engine_clk); + if (ret < 0) { + dev_err(dev, "Failed to enable engine clock: %d\n", ret); + goto err_phy_power_off; + } + + ret = clk_prepare_enable(dsi->digital_clk); + if (ret < 0) { + dev_err(dev, "Failed to enable digital clock: %d\n", ret); + goto err_disable_engine_clk; + } + + mtk_dsi_enable(dsi); + mtk_dsi_reset_engine(dsi); + mtk_dsi_phy_timconfig(dsi); + + mtk_dsi_rxtx_control(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_clk_ulp_mode_leave(dsi); + mtk_dsi_lane0_ulp_mode_leave(dsi); + mtk_dsi_clk_hs_mode(dsi, 0); + + if (dsi->panel) { + if (drm_panel_prepare(dsi->panel)) { + DRM_ERROR("failed to prepare the panel\n"); + goto err_disable_digital_clk; + } + } + + return 0; +err_disable_digital_clk: + clk_disable_unprepare(dsi->digital_clk); +err_disable_engine_clk: + clk_disable_unprepare(dsi->engine_clk); +err_phy_power_off: + phy_power_off(dsi->phy); +err_refcount: + dsi->refcount--; + return ret; +} + static void mtk_dsi_poweroff(struct mtk_dsi *dsi) { if (WARN_ON(dsi->refcount == 0)) @@ -578,6 +630,16 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi) if (--dsi->refcount != 0) return;
+ if (!mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500)) { + 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);
@@ -596,36 +658,30 @@ 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; }
- mtk_dsi_rxtx_control(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); - mtk_dsi_set_mode(dsi); mtk_dsi_clk_hs_mode(dsi, 1);
mtk_dsi_start(dsi);
+ if (dsi->panel) { + if (drm_panel_enable(dsi->panel)) { + DRM_ERROR("failed to enable the panel\n"); + goto err_dsi_power_off; + } + } + dsi->enabled = true; + + return; +err_dsi_power_off: + mtk_dsi_stop(dsi); + mtk_dsi_poweroff(dsi); }
static void mtk_output_dsi_disable(struct mtk_dsi *dsi) @@ -640,6 +696,7 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi) } }
+ mtk_dsi_stop(dsi); mtk_dsi_poweroff(dsi);
dsi->enabled = false;
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 Acked-by: CK Hu ck.hu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 8 ++++++++ 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_drv.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_dsi.c | 1 + drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 6 ++++++ 7 files changed, 74 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 4552178..a14d7d6 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -35,6 +35,7 @@ #define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n)) #define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n)) #define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n)) +#define DISP_REG_OVL_ADDR_MT2701 0x0040 #define DISP_REG_OVL_ADDR_MT8173 0x0f40 #define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n))
@@ -303,12 +304,19 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev) return 0; }
+static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { + .addr = DISP_REG_OVL_ADDR_MT2701, + .fmt_rgb565_is_0 = false, +}; + static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { .addr = DISP_REG_OVL_ADDR_MT8173, .fmt_rgb565_is_0 = true, };
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 e5e5318..b68a513 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -236,11 +236,17 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev) return 0; }
+static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = { + .fifo_size = SZ_4K, +}; + static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = { .fifo_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 a9b209c..8130f3d 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, @@ -390,6 +406,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 f6e853a..8b52416 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -39,6 +39,7 @@ #define DISP_REG_UFO_START 0x0000
#define DISP_COLOR_CFG_MAIN 0x0400 +#define DISP_COLOR_START_MT2701 0x0f00 #define DISP_COLOR_START_MT8173 0x0c00 #define DISP_COLOR_START(comp) ((comp)->data->color_offset) #define DISP_COLOR_WIDTH(comp) (DISP_COLOR_START(comp) + 0x50) @@ -285,11 +286,17 @@ struct mtk_ddp_comp_match { [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL }, };
+static const struct mtk_disp_color_data mt2701_color_driver_data = { + .color_offset = DISP_COLOR_START_MT2701, +}; + static const struct mtk_disp_color_data mt8173_color_driver_data = { .color_offset = DISP_COLOR_START_MT8173, };
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_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 6ef19f2..ae1be46 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -128,6 +128,19 @@ static int mtk_atomic_commit(struct drm_device *drm, .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, @@ -147,6 +160,14 @@ static int mtk_atomic_commit(struct drm_device *drm, 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), @@ -341,16 +362,22 @@ static void mtk_drm_unbind(struct device *dev) };
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,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_BLS }, { .compatible = "mediatek,mt8173-disp-pwm", .data = (void *)MTK_DISP_PWM }, { .compatible = "mediatek,mt8173-disp-od", .data = (void *)MTK_DISP_OD }, { } @@ -524,6 +551,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 b6eac92..1a5b0f7 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -1208,6 +1208,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 fd84914..90e9131 100644 --- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c +++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c @@ -465,11 +465,17 @@ 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 }, {},
dri-devel@lists.freedesktop.org