[PATCH v5 12/17] drm/meson: add support for MIPI-DSI transceiver

Nicolas Belin nbelin at baylibre.com
Wed May 31 02:22:42 PDT 2023


Le mar. 30 mai 2023 à 09:38, Neil Armstrong
<neil.armstrong at linaro.org> a écrit :
>
> The Amlogic G12A/G12B/SM1 SoCs embeds a Synopsys DW-MIPI-DSI transceiver
> (ver 1.21a), with a custom glue managing the IP resets, clock and data
> inputs similar to the DW-HDMI Glue on other Amlogic SoCs.
>
> This adds support for the Glue managing the transceiver, mimicing the init
> flow provided by Amlogic to setup the ENCL encoder, the glue, the transceiver,
> the digital D-PHY and the Analog PHY in the proper way.
>
> An optional "MEAS" clock can be enabled to measure the delay between each
> vsync feeding the DW-MIPI-DSI transceiver.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> Reviewed-by: Jagan Teki <jagan at amarulasolutions.com>
> Signed-off-by: Neil Armstrong <neil.armstrong at linaro.org>
> ---
>  drivers/gpu/drm/meson/Kconfig             |   7 +
>  drivers/gpu/drm/meson/Makefile            |   1 +
>  drivers/gpu/drm/meson/meson_dw_mipi_dsi.c | 352 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/meson/meson_dw_mipi_dsi.h | 160 ++++++++++++++
>  4 files changed, 520 insertions(+)
>
> diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
> index 823909da87db..615fdd0ce41b 100644
> --- a/drivers/gpu/drm/meson/Kconfig
> +++ b/drivers/gpu/drm/meson/Kconfig
> @@ -17,3 +17,10 @@ config DRM_MESON_DW_HDMI
>         default y if DRM_MESON
>         select DRM_DW_HDMI
>         imply DRM_DW_HDMI_I2S_AUDIO
> +
> +config DRM_MESON_DW_MIPI_DSI
> +       tristate "MIPI DSI Synopsys Controller support for Amlogic Meson Display"
> +       depends on DRM_MESON
> +       default y if DRM_MESON
> +       select DRM_DW_MIPI_DSI
> +       select GENERIC_PHY_MIPI_DPHY
> diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
> index 833e18c20603..43071bdbd4b9 100644
> --- a/drivers/gpu/drm/meson/Makefile
> +++ b/drivers/gpu/drm/meson/Makefile
> @@ -6,3 +6,4 @@ meson-drm-y += meson_encoder_hdmi.o meson_encoder_dsi.o
>
>  obj-$(CONFIG_DRM_MESON) += meson-drm.o
>  obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o
> +obj-$(CONFIG_DRM_MESON_DW_MIPI_DSI) += meson_dw_mipi_dsi.o
> diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
> new file mode 100644
> index 000000000000..dd505ac37976
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
> @@ -0,0 +1,352 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2021 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of_graph.h>
> +#include <linux/reset.h>
> +#include <linux/phy/phy.h>
> +#include <linux/bitfield.h>
> +
> +#include <video/mipi_display.h>
> +
> +#include <drm/bridge/dw_mipi_dsi.h>
> +#include <drm/drm_mipi_dsi.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_device.h>
> +#include <drm/drm_probe_helper.h>
> +#include <drm/drm_print.h>
> +
> +#include "meson_drv.h"
> +#include "meson_dw_mipi_dsi.h"
> +#include "meson_registers.h"
> +#include "meson_venc.h"
> +
> +#define DRIVER_NAME "meson-dw-mipi-dsi"
> +#define DRIVER_DESC "Amlogic Meson MIPI-DSI DRM driver"
> +
> +struct meson_dw_mipi_dsi {
> +       struct meson_drm *priv;
> +       struct device *dev;
> +       void __iomem *base;
> +       struct phy *phy;
> +       union phy_configure_opts phy_opts;
> +       struct dw_mipi_dsi *dmd;
> +       struct dw_mipi_dsi_plat_data pdata;
> +       struct mipi_dsi_device *dsi_device;
> +       const struct drm_display_mode *mode;
> +       struct clk *bit_clk;
> +       struct clk *px_clk;
> +       struct reset_control *top_rst;
> +};
> +
> +#define encoder_to_meson_dw_mipi_dsi(x) \
> +       container_of(x, struct meson_dw_mipi_dsi, encoder)
> +
> +static void meson_dw_mipi_dsi_hw_init(struct meson_dw_mipi_dsi *mipi_dsi)
> +{
> +       /* Software reset */
> +       writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
> +                           MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
> +                           MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
> +                           MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
> +                           mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
> +       writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
> +                           MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
> +                           0, mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
> +
> +       /* Enable clocks */
> +       writel_bits_relaxed(MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
> +                           MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
> +                           mipi_dsi->base + MIPI_DSI_TOP_CLK_CNTL);
> +
> +       /* Take memory out of power down */
> +       writel_relaxed(0, mipi_dsi->base + MIPI_DSI_TOP_MEM_PD);
> +}
> +
> +static int dw_mipi_dsi_phy_init(void *priv_data)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
> +       unsigned int dpi_data_format, venc_data_width;
> +       int ret;
> +
> +       /* Set the bit clock rate to hs_clk_rate */
> +       ret = clk_set_rate(mipi_dsi->bit_clk,
> +                          mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
> +       if (ret) {
> +               dev_err(mipi_dsi->dev, "Failed to set DSI Bit clock rate %lu (ret %d)\n",
> +                       mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate, ret);
> +               return ret;
> +       }
> +
> +       /* Make sure the rate of the bit clock is not modified by someone else */
> +       ret = clk_rate_exclusive_get(mipi_dsi->bit_clk);
> +       if (ret) {
> +               dev_err(mipi_dsi->dev,
> +                       "Failed to set the exclusivity on the bit clock rate (ret %d)\n", ret);
> +               return ret;
> +       }
> +
> +       ret = clk_set_rate(mipi_dsi->px_clk, mipi_dsi->mode->clock * 1000);
> +
> +       if (ret) {
> +               dev_err(mipi_dsi->dev, "Failed to set DSI Pixel clock rate %u (%d)\n",
> +                       mipi_dsi->mode->clock * 1000, ret);
> +               return ret;
> +       }
> +
> +       switch (mipi_dsi->dsi_device->format) {
> +       case MIPI_DSI_FMT_RGB888:
> +               dpi_data_format = DPI_COLOR_24BIT;
> +               venc_data_width = VENC_IN_COLOR_24B;
> +               break;
> +       case MIPI_DSI_FMT_RGB666:
> +               dpi_data_format = DPI_COLOR_18BIT_CFG_2;
> +               venc_data_width = VENC_IN_COLOR_18B;
> +               break;
> +       case MIPI_DSI_FMT_RGB666_PACKED:
> +       case MIPI_DSI_FMT_RGB565:
> +               return -EINVAL;
> +       };
> +
> +       /* Configure color format for DPI register */
> +       writel_relaxed(FIELD_PREP(MIPI_DSI_TOP_DPI_COLOR_MODE, dpi_data_format) |
> +                      FIELD_PREP(MIPI_DSI_TOP_IN_COLOR_MODE, venc_data_width) |
> +                      FIELD_PREP(MIPI_DSI_TOP_COMP2_SEL, 2) |
> +                      FIELD_PREP(MIPI_DSI_TOP_COMP1_SEL, 1) |
> +                      FIELD_PREP(MIPI_DSI_TOP_COMP0_SEL, 0),
> +                       mipi_dsi->base + MIPI_DSI_TOP_CNTL);
> +
> +       return phy_configure(mipi_dsi->phy, &mipi_dsi->phy_opts);
> +}
> +
> +static void dw_mipi_dsi_phy_power_on(void *priv_data)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
> +
> +       if (phy_power_on(mipi_dsi->phy))
> +               dev_warn(mipi_dsi->dev, "Failed to power on PHY\n");
> +}
> +
> +static void dw_mipi_dsi_phy_power_off(void *priv_data)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
> +
> +       if (phy_power_off(mipi_dsi->phy))
> +               dev_warn(mipi_dsi->dev, "Failed to power off PHY\n");
> +
> +       /* Remove the exclusivity on the bit clock rate */
> +       clk_rate_exclusive_put(mipi_dsi->bit_clk);
> +}
> +
> +static int
> +dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
> +                         unsigned long mode_flags, u32 lanes, u32 format,
> +                         unsigned int *lane_mbps)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
> +       int bpp;
> +
> +       mipi_dsi->mode = mode;
> +
> +       bpp = mipi_dsi_pixel_format_to_bpp(mipi_dsi->dsi_device->format);
> +
> +       phy_mipi_dphy_get_default_config(mode->clock * 1000,
> +                                        bpp, mipi_dsi->dsi_device->lanes,
> +                                        &mipi_dsi->phy_opts.mipi_dphy);
> +
> +       *lane_mbps = DIV_ROUND_UP(mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate, USEC_PER_SEC);
> +
> +       return 0;
> +}
> +
> +static int
> +dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
> +                          struct dw_mipi_dsi_dphy_timing *timing)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
> +
> +       switch (mipi_dsi->mode->hdisplay) {
> +       case 240:
> +       case 768:
> +       case 1920:
> +       case 2560:
> +               timing->clk_lp2hs = 23;
> +               timing->clk_hs2lp = 38;
> +               timing->data_lp2hs = 15;
> +               timing->data_hs2lp = 9;
> +               break;
> +
> +       default:
> +               timing->clk_lp2hs = 37;
> +               timing->clk_hs2lp = 135;
> +               timing->data_lp2hs = 50;
> +               timing->data_hs2lp = 3;
> +       }
> +
> +       return 0;
> +}
> +
> +static int
> +dw_mipi_dsi_get_esc_clk_rate(void *priv_data, unsigned int *esc_clk_rate)
> +{
> +       *esc_clk_rate = 4; /* Mhz */
> +
> +       return 0;
> +}
> +
> +static const struct dw_mipi_dsi_phy_ops meson_dw_mipi_dsi_phy_ops = {
> +       .init = dw_mipi_dsi_phy_init,
> +       .power_on = dw_mipi_dsi_phy_power_on,
> +       .power_off = dw_mipi_dsi_phy_power_off,
> +       .get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
> +       .get_timing = dw_mipi_dsi_phy_get_timing,
> +       .get_esc_clk_rate = dw_mipi_dsi_get_esc_clk_rate,
> +};
> +
> +static int meson_dw_mipi_dsi_host_attach(void *priv_data,
> +                                        struct mipi_dsi_device *device)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
> +       int ret;
> +
> +       mipi_dsi->dsi_device = device;
> +
> +       switch (device->format) {
> +       case MIPI_DSI_FMT_RGB888:
> +               break;
> +       case MIPI_DSI_FMT_RGB666:
> +               break;
> +       case MIPI_DSI_FMT_RGB666_PACKED:
> +       case MIPI_DSI_FMT_RGB565:
> +               dev_err(mipi_dsi->dev, "invalid pixel format %d\n", device->format);
> +               return -EINVAL;
> +       };
> +
> +       ret = phy_init(mipi_dsi->phy);
> +       if (ret)
> +               return ret;
> +
> +       meson_dw_mipi_dsi_hw_init(mipi_dsi);
> +
> +       return 0;
> +}
> +
> +static int meson_dw_mipi_dsi_host_detach(void *priv_data,
> +                                        struct mipi_dsi_device *device)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
> +
> +       if (device == mipi_dsi->dsi_device)
> +               mipi_dsi->dsi_device = NULL;
> +       else
> +               return -EINVAL;
> +
> +       return phy_exit(mipi_dsi->phy);
> +}
> +
> +static const struct dw_mipi_dsi_host_ops meson_dw_mipi_dsi_host_ops = {
> +       .attach = meson_dw_mipi_dsi_host_attach,
> +       .detach = meson_dw_mipi_dsi_host_detach,
> +};
> +
> +static int meson_dw_mipi_dsi_probe(struct platform_device *pdev)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi;
> +       struct device *dev = &pdev->dev;
> +
> +       mipi_dsi = devm_kzalloc(dev, sizeof(*mipi_dsi), GFP_KERNEL);
> +       if (!mipi_dsi)
> +               return -ENOMEM;
> +
> +       mipi_dsi->base = devm_platform_ioremap_resource(pdev, 0);
> +       if (IS_ERR(mipi_dsi->base))
> +               return PTR_ERR(mipi_dsi->base);
> +
> +       mipi_dsi->phy = devm_phy_get(dev, "dphy");
> +       if (IS_ERR(mipi_dsi->phy))
> +               return dev_err_probe(dev, PTR_ERR(mipi_dsi->phy),
> +                                    "failed to get mipi dphy\n");
> +
> +       mipi_dsi->bit_clk = devm_clk_get_enabled(dev, "bit");
> +       if (IS_ERR(mipi_dsi->bit_clk)) {
> +               int ret = PTR_ERR(mipi_dsi->bit_clk);
> +
> +               /* TOFIX GP0 on some platforms fails to lock in early boot, defer probe */
> +               if (ret == -EIO)
> +                       ret = -EPROBE_DEFER;
> +
> +               return dev_err_probe(dev, ret, "Unable to get enabled bit_clk\n");
> +       }
> +
> +       mipi_dsi->px_clk = devm_clk_get_enabled(dev, "px");
> +       if (IS_ERR(mipi_dsi->px_clk))
> +               return dev_err_probe(dev, PTR_ERR(mipi_dsi->px_clk),
> +                                    "Unable to get enabled px_clk\n");
> +
> +       /*
> +        * We use a TOP reset signal because the APB reset signal
> +        * is handled by the TOP control registers.
> +        */
> +       mipi_dsi->top_rst = devm_reset_control_get_exclusive(dev, "top");
> +       if (IS_ERR(mipi_dsi->top_rst))
> +               return dev_err_probe(dev, PTR_ERR(mipi_dsi->top_rst),
> +                                    "Unable to get reset control\n");
> +
> +       reset_control_assert(mipi_dsi->top_rst);
> +       usleep_range(10, 20);
> +       reset_control_deassert(mipi_dsi->top_rst);
> +
> +       /* MIPI DSI Controller */
> +
> +       mipi_dsi->dev = dev;
> +       mipi_dsi->pdata.base = mipi_dsi->base;
> +       mipi_dsi->pdata.max_data_lanes = 4;
> +       mipi_dsi->pdata.phy_ops = &meson_dw_mipi_dsi_phy_ops;
> +       mipi_dsi->pdata.host_ops = &meson_dw_mipi_dsi_host_ops;
> +       mipi_dsi->pdata.priv_data = mipi_dsi;
> +       platform_set_drvdata(pdev, mipi_dsi);
> +
> +       mipi_dsi->dmd = dw_mipi_dsi_probe(pdev, &mipi_dsi->pdata);
> +       if (IS_ERR(mipi_dsi->dmd))
> +               return dev_err_probe(dev, PTR_ERR(mipi_dsi->dmd),
> +                                    "Failed to probe dw_mipi_dsi\n");
> +
> +       return 0;
> +}
> +
> +static int meson_dw_mipi_dsi_remove(struct platform_device *pdev)
> +{
> +       struct meson_dw_mipi_dsi *mipi_dsi = platform_get_drvdata(pdev);
> +
> +       dw_mipi_dsi_remove(mipi_dsi->dmd);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id meson_dw_mipi_dsi_of_table[] = {
> +       { .compatible = "amlogic,meson-g12a-dw-mipi-dsi", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, meson_dw_mipi_dsi_of_table);
> +
> +static struct platform_driver meson_dw_mipi_dsi_platform_driver = {
> +       .probe          = meson_dw_mipi_dsi_probe,
> +       .remove         = meson_dw_mipi_dsi_remove,
> +       .driver         = {
> +               .name           = DRIVER_NAME,
> +               .of_match_table = meson_dw_mipi_dsi_of_table,
> +       },
> +};
> +module_platform_driver(meson_dw_mipi_dsi_platform_driver);
> +
> +MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h
> new file mode 100644
> index 000000000000..e1bd6b85d6a3
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h
> @@ -0,0 +1,160 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2020 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
> + */
> +
> +#ifndef __MESON_DW_MIPI_DSI_H
> +#define __MESON_DW_MIPI_DSI_H
> +
> +/* Top-level registers */
> +/* [31: 4]    Reserved.     Default 0.
> + *     [3] RW timing_rst_n: Default 1.
> + *             1=Assert SW reset of timing feature.   0=Release reset.
> + *     [2] RW dpi_rst_n: Default 1.
> + *             1=Assert SW reset on mipi_dsi_host_dpi block.   0=Release reset.
> + *     [1] RW intr_rst_n: Default 1.
> + *             1=Assert SW reset on mipi_dsi_host_intr block.  0=Release reset.
> + *     [0] RW dwc_rst_n:  Default 1.
> + *             1=Assert SW reset on IP core.   0=Release reset.
> + */
> +#define MIPI_DSI_TOP_SW_RESET                      0x3c0
> +
> +#define MIPI_DSI_TOP_SW_RESET_DWC      BIT(0)
> +#define MIPI_DSI_TOP_SW_RESET_INTR     BIT(1)
> +#define MIPI_DSI_TOP_SW_RESET_DPI      BIT(2)
> +#define MIPI_DSI_TOP_SW_RESET_TIMING   BIT(3)
> +
> +/* [31: 5] Reserved.   Default 0.
> + *     [4] RW manual_edpihalt: Default 0.
> + *             1=Manual suspend VencL; 0=do not suspend VencL.
> + *     [3] RW auto_edpihalt_en: Default 0.
> + *             1=Enable IP's edpihalt signal to suspend VencL;
> + *             0=IP's edpihalt signal does not affect VencL.
> + *     [2] RW clock_freerun: Apply to auto-clock gate only. Default 0.
> + *             0=Default, use auto-clock gating to save power;
> + *             1=use free-run clock, disable auto-clock gating, for debug mode.
> + *     [1] RW enable_pixclk: A manual clock gate option, due to DWC IP does not
> + *             have auto-clock gating. 1=Enable pixclk.      Default 0.
> + *     [0] RW enable_sysclk: A manual clock gate option, due to DWC IP does not
> + *             have auto-clock gating. 1=Enable sysclk.      Default 0.
> + */
> +#define MIPI_DSI_TOP_CLK_CNTL                      0x3c4
> +
> +#define MIPI_DSI_TOP_CLK_SYSCLK_EN     BIT(0)
> +#define MIPI_DSI_TOP_CLK_PIXCLK_EN     BIT(1)
> +
> +/* [31:24]    Reserved. Default 0.
> + * [23:20] RW dpi_color_mode: Define DPI pixel format. Default 0.
> + *             0=16-bit RGB565 config 1;
> + *             1=16-bit RGB565 config 2;
> + *             2=16-bit RGB565 config 3;
> + *             3=18-bit RGB666 config 1;
> + *             4=18-bit RGB666 config 2;
> + *             5=24-bit RGB888;
> + *             6=20-bit YCbCr 4:2:2;
> + *             7=24-bit YCbCr 4:2:2;
> + *             8=16-bit YCbCr 4:2:2;
> + *             9=30-bit RGB;
> + *             10=36-bit RGB;
> + *             11=12-bit YCbCr 4:2:0.
> + *    [19] Reserved. Default 0.
> + * [18:16] RW in_color_mode:  Define VENC data width. Default 0.
> + *             0=30-bit pixel;
> + *             1=24-bit pixel;
> + *             2=18-bit pixel, RGB666;
> + *             3=16-bit pixel, RGB565.
> + * [15:14] RW chroma_subsample: Define method of chroma subsampling. Default 0.
> + *             Applicable to YUV422 or YUV420 only.
> + *             0=Use even pixel's chroma;
> + *             1=Use odd pixel's chroma;
> + *             2=Use averaged value between even and odd pair.
> + * [13:12] RW comp2_sel:  Select which component to be Cr or B: Default 2.
> + *             0=comp0; 1=comp1; 2=comp2.
> + * [11:10] RW comp1_sel:  Select which component to be Cb or G: Default 1.
> + *             0=comp0; 1=comp1; 2=comp2.
> + *  [9: 8] RW comp0_sel:  Select which component to be Y  or R: Default 0.
> + *             0=comp0; 1=comp1; 2=comp2.
> + *     [7]    Reserved. Default 0.
> + *     [6] RW de_pol:  Default 0.
> + *             If DE input is active low, set to 1 to invert to active high.
> + *     [5] RW hsync_pol: Default 0.
> + *             If HS input is active low, set to 1 to invert to active high.
> + *     [4] RW vsync_pol: Default 0.
> + *             If VS input is active low, set to 1 to invert to active high.
> + *     [3] RW dpicolorm: Signal to IP.   Default 0.
> + *     [2] RW dpishutdn: Signal to IP.   Default 0.
> + *     [1]    Reserved.  Default 0.
> + *     [0]    Reserved.  Default 0.
> + */
> +#define MIPI_DSI_TOP_CNTL                          0x3c8
> +
> +/* VENC data width */
> +#define VENC_IN_COLOR_30B   0x0
> +#define VENC_IN_COLOR_24B   0x1
> +#define VENC_IN_COLOR_18B   0x2
> +#define VENC_IN_COLOR_16B   0x3
> +
> +/* DPI pixel format */
> +#define DPI_COLOR_16BIT_CFG_1          0
> +#define DPI_COLOR_16BIT_CFG_2          1
> +#define DPI_COLOR_16BIT_CFG_3          2
> +#define DPI_COLOR_18BIT_CFG_1          3
> +#define DPI_COLOR_18BIT_CFG_2          4
> +#define DPI_COLOR_24BIT                        5
> +#define DPI_COLOR_20BIT_YCBCR_422      6
> +#define DPI_COLOR_24BIT_YCBCR_422      7
> +#define DPI_COLOR_16BIT_YCBCR_422      8
> +#define DPI_COLOR_30BIT                        9
> +#define DPI_COLOR_36BIT                        10
> +#define DPI_COLOR_12BIT_YCBCR_420      11
> +
> +#define MIPI_DSI_TOP_DPI_COLOR_MODE    GENMASK(23, 20)
> +#define MIPI_DSI_TOP_IN_COLOR_MODE     GENMASK(18, 16)
> +#define MIPI_DSI_TOP_CHROMA_SUBSAMPLE  GENMASK(15, 14)
> +#define MIPI_DSI_TOP_COMP2_SEL         GENMASK(13, 12)
> +#define MIPI_DSI_TOP_COMP1_SEL         GENMASK(11, 10)
> +#define MIPI_DSI_TOP_COMP0_SEL         GENMASK(9, 8)
> +#define MIPI_DSI_TOP_DE_INVERT         BIT(6)
> +#define MIPI_DSI_TOP_HSYNC_INVERT      BIT(5)
> +#define MIPI_DSI_TOP_VSYNC_INVERT      BIT(4)
> +#define MIPI_DSI_TOP_DPICOLORM         BIT(3)
> +#define MIPI_DSI_TOP_DPISHUTDN         BIT(2)
> +
> +#define MIPI_DSI_TOP_SUSPEND_CNTL                  0x3cc
> +#define MIPI_DSI_TOP_SUSPEND_LINE                  0x3d0
> +#define MIPI_DSI_TOP_SUSPEND_PIX                   0x3d4
> +#define MIPI_DSI_TOP_MEAS_CNTL                     0x3d8
> +/* [0] R  stat_edpihalt:  edpihalt signal from IP.    Default 0. */
> +#define MIPI_DSI_TOP_STAT                          0x3dc
> +#define MIPI_DSI_TOP_MEAS_STAT_TE0                 0x3e0
> +#define MIPI_DSI_TOP_MEAS_STAT_TE1                 0x3e4
> +#define MIPI_DSI_TOP_MEAS_STAT_VS0                 0x3e8
> +#define MIPI_DSI_TOP_MEAS_STAT_VS1                 0x3ec
> +/* [31:16] RW intr_stat/clr. Default 0.
> + *             For each bit, read as this interrupt level status,
> + *             write 1 to clear.
> + * [31:22] Reserved
> + * [   21] stat/clr of eof interrupt
> + * [   21] vde_fall interrupt
> + * [   19] stat/clr of de_rise interrupt
> + * [   18] stat/clr of vs_fall interrupt
> + * [   17] stat/clr of vs_rise interrupt
> + * [   16] stat/clr of dwc_edpite interrupt
> + * [15: 0] RW intr_enable. Default 0.
> + *             For each bit, 1=enable this interrupt, 0=disable.
> + *     [15: 6] Reserved
> + *     [    5] eof interrupt
> + *     [    4] de_fall interrupt
> + *     [    3] de_rise interrupt
> + *     [    2] vs_fall interrupt
> + *     [    1] vs_rise interrupt
> + *     [    0] dwc_edpite interrupt
> + */
> +#define MIPI_DSI_TOP_INTR_CNTL_STAT                0x3f0
> +// 31: 2    Reserved.   Default 0.
> +//  1: 0 RW mem_pd.     Default 3.
> +#define MIPI_DSI_TOP_MEM_PD                        0x3f4
> +
> +#endif /* __MESON_DW_MIPI_DSI_H */
>
> --
> 2.34.1
>
Reviewed-by: Nicolas Belin <nbelin at baylibre.com>
Tested-by: Nicolas Belin <nbelin at baylibre.com> # on Khadas VIM3 + TS050 Panel

Thanks,
Nicolas



More information about the linux-arm-kernel mailing list