Commit 48865413 authored by Liu Ying's avatar Liu Ying Committed by Neil Armstrong

drm/bridge: fsl-ldb: Add i.MX93 LDB support

Same to i.MX8mp LDB, i.MX93 LDB is controlled by mediamix blk-ctrl
through LDB_CTRL and LVDS_CTRL registers.  i.MX93 LDB supports only
one LVDS channel(channel 0) and it's LVDS_CTRL register bit1 is used
as LVDS_EN instead of CH1_EN.  Add i.MX93 LDB support in the existing
i.MX8mp LDB bridge driver by adding i.MX93 LDB compatible string and
device data(to reflect different register offsets and LVDS_CTRL register
bit1 definition).
Reviewed-by: default avatarMarek Vasut <marex@denx.de>
Signed-off-by: default avatarLiu Ying <victor.liu@nxp.com>
Signed-off-by: default avatarNeil Armstrong <neil.armstrong@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230123021449.969243-3-victor.liu@nxp.com
parent 5e68a0ca
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <drm/drm_of.h> #include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#define LDB_CTRL 0x5c
#define LDB_CTRL_CH0_ENABLE BIT(0) #define LDB_CTRL_CH0_ENABLE BIT(0)
#define LDB_CTRL_CH0_DI_SELECT BIT(1) #define LDB_CTRL_CH0_DI_SELECT BIT(1)
#define LDB_CTRL_CH1_ENABLE BIT(2) #define LDB_CTRL_CH1_ENABLE BIT(2)
...@@ -35,9 +34,13 @@ ...@@ -35,9 +34,13 @@
#define LDB_CTRL_ASYNC_FIFO_ENABLE BIT(24) #define LDB_CTRL_ASYNC_FIFO_ENABLE BIT(24)
#define LDB_CTRL_ASYNC_FIFO_THRESHOLD_MASK GENMASK(27, 25) #define LDB_CTRL_ASYNC_FIFO_THRESHOLD_MASK GENMASK(27, 25)
#define LVDS_CTRL 0x128
#define LVDS_CTRL_CH0_EN BIT(0) #define LVDS_CTRL_CH0_EN BIT(0)
#define LVDS_CTRL_CH1_EN BIT(1) #define LVDS_CTRL_CH1_EN BIT(1)
/*
* LVDS_CTRL_LVDS_EN bit is poorly named in i.MX93 reference manual.
* Clear it to enable LVDS and set it to disable LVDS.
*/
#define LVDS_CTRL_LVDS_EN BIT(1)
#define LVDS_CTRL_VBG_EN BIT(2) #define LVDS_CTRL_VBG_EN BIT(2)
#define LVDS_CTRL_HS_EN BIT(3) #define LVDS_CTRL_HS_EN BIT(3)
#define LVDS_CTRL_PRE_EMPH_EN BIT(4) #define LVDS_CTRL_PRE_EMPH_EN BIT(4)
...@@ -52,6 +55,29 @@ ...@@ -52,6 +55,29 @@
#define LVDS_CTRL_VBG_ADJ(n) (((n) & 0x7) << 17) #define LVDS_CTRL_VBG_ADJ(n) (((n) & 0x7) << 17)
#define LVDS_CTRL_VBG_ADJ_MASK GENMASK(19, 17) #define LVDS_CTRL_VBG_ADJ_MASK GENMASK(19, 17)
enum fsl_ldb_devtype {
IMX8MP_LDB,
IMX93_LDB,
};
struct fsl_ldb_devdata {
u32 ldb_ctrl;
u32 lvds_ctrl;
bool lvds_en_bit;
};
static const struct fsl_ldb_devdata fsl_ldb_devdata[] = {
[IMX8MP_LDB] = {
.ldb_ctrl = 0x5c,
.lvds_ctrl = 0x128,
},
[IMX93_LDB] = {
.ldb_ctrl = 0x20,
.lvds_ctrl = 0x24,
.lvds_en_bit = true,
},
};
struct fsl_ldb { struct fsl_ldb {
struct device *dev; struct device *dev;
struct drm_bridge bridge; struct drm_bridge bridge;
...@@ -59,6 +85,7 @@ struct fsl_ldb { ...@@ -59,6 +85,7 @@ struct fsl_ldb {
struct clk *clk; struct clk *clk;
struct regmap *regmap; struct regmap *regmap;
bool lvds_dual_link; bool lvds_dual_link;
const struct fsl_ldb_devdata *devdata;
}; };
static inline struct fsl_ldb *to_fsl_ldb(struct drm_bridge *bridge) static inline struct fsl_ldb *to_fsl_ldb(struct drm_bridge *bridge)
...@@ -173,12 +200,12 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, ...@@ -173,12 +200,12 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
reg |= LDB_CTRL_DI1_VSYNC_POLARITY; reg |= LDB_CTRL_DI1_VSYNC_POLARITY;
} }
regmap_write(fsl_ldb->regmap, LDB_CTRL, reg); regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, reg);
/* Program LVDS_CTRL */ /* Program LVDS_CTRL */
reg = LVDS_CTRL_CC_ADJ(2) | LVDS_CTRL_PRE_EMPH_EN | reg = LVDS_CTRL_CC_ADJ(2) | LVDS_CTRL_PRE_EMPH_EN |
LVDS_CTRL_PRE_EMPH_ADJ(3) | LVDS_CTRL_VBG_EN; LVDS_CTRL_PRE_EMPH_ADJ(3) | LVDS_CTRL_VBG_EN;
regmap_write(fsl_ldb->regmap, LVDS_CTRL, reg); regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, reg);
/* Wait for VBG to stabilize. */ /* Wait for VBG to stabilize. */
usleep_range(15, 20); usleep_range(15, 20);
...@@ -187,7 +214,7 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, ...@@ -187,7 +214,7 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
if (fsl_ldb->lvds_dual_link) if (fsl_ldb->lvds_dual_link)
reg |= LVDS_CTRL_CH1_EN; reg |= LVDS_CTRL_CH1_EN;
regmap_write(fsl_ldb->regmap, LVDS_CTRL, reg); regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, reg);
} }
static void fsl_ldb_atomic_disable(struct drm_bridge *bridge, static void fsl_ldb_atomic_disable(struct drm_bridge *bridge,
...@@ -195,9 +222,14 @@ static void fsl_ldb_atomic_disable(struct drm_bridge *bridge, ...@@ -195,9 +222,14 @@ static void fsl_ldb_atomic_disable(struct drm_bridge *bridge,
{ {
struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge); struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge);
/* Stop both channels. */ /* Stop channel(s). */
regmap_write(fsl_ldb->regmap, LVDS_CTRL, 0); if (fsl_ldb->devdata->lvds_en_bit)
regmap_write(fsl_ldb->regmap, LDB_CTRL, 0); /* Set LVDS_CTRL_LVDS_EN bit to disable. */
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl,
LVDS_CTRL_LVDS_EN);
else
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, 0);
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, 0);
clk_disable_unprepare(fsl_ldb->clk); clk_disable_unprepare(fsl_ldb->clk);
} }
...@@ -263,6 +295,10 @@ static int fsl_ldb_probe(struct platform_device *pdev) ...@@ -263,6 +295,10 @@ static int fsl_ldb_probe(struct platform_device *pdev)
if (!fsl_ldb) if (!fsl_ldb)
return -ENOMEM; return -ENOMEM;
fsl_ldb->devdata = of_device_get_match_data(dev);
if (!fsl_ldb->devdata)
return -EINVAL;
fsl_ldb->dev = &pdev->dev; fsl_ldb->dev = &pdev->dev;
fsl_ldb->bridge.funcs = &funcs; fsl_ldb->bridge.funcs = &funcs;
fsl_ldb->bridge.of_node = dev->of_node; fsl_ldb->bridge.of_node = dev->of_node;
...@@ -321,7 +357,10 @@ static int fsl_ldb_remove(struct platform_device *pdev) ...@@ -321,7 +357,10 @@ static int fsl_ldb_remove(struct platform_device *pdev)
} }
static const struct of_device_id fsl_ldb_match[] = { static const struct of_device_id fsl_ldb_match[] = {
{ .compatible = "fsl,imx8mp-ldb", }, { .compatible = "fsl,imx8mp-ldb",
.data = &fsl_ldb_devdata[IMX8MP_LDB], },
{ .compatible = "fsl,imx93-ldb",
.data = &fsl_ldb_devdata[IMX93_LDB], },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, fsl_ldb_match); MODULE_DEVICE_TABLE(of, fsl_ldb_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment