Changes since v5:
- fine tune the dt-bindings commit message.
Changes since v4:
- move pin mode control and dual edge control to deveice tree.
- update dt-bindings document for pin mode swap and dual edge control.
Changes since v3:
- add dpi pin mode control when dpi on or off.
- update dpi dual edge comment.
Changes since v2:
- update dt-bindings document for mt8183 dpi.
- separate dual edge modfication as independent patch.
Jitao Shi (4):
dt-bindings: display: mediatek: update dpi supported chips
drm/mediatek: dpi dual edge support
drm/mediatek: add mt8183 dpi clock factor
drm/mediatek: set dpi pin mode to gpio low to avoid leakage current
.../display/mediatek/mediatek,dpi.txt | 11 +++
drivers/gpu/drm/mediatek/mtk_dpi.c | 69 ++++++++++++++++++-
2 files changed, 79 insertions(+), 1 deletion(-)
--
2.21.0
DPI sample the data both rising and falling edge.
It can reduce half data io pins.
Signed-off-by: Jitao Shi <[email protected]>
---
drivers/gpu/drm/mediatek/mtk_dpi.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 01fa8b8d763d..36e4dbd27d1b 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -75,6 +75,7 @@ struct mtk_dpi {
enum mtk_dpi_out_bit_num bit_num;
enum mtk_dpi_out_channel_swap channel_swap;
int refcount;
+ bool dual_edge;
};
static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e)
@@ -348,6 +349,13 @@ static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
}
+static void mtk_dpi_enable_dual_edge(struct mtk_dpi *dpi)
+{
+ mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE,
+ DDR_EN | DDR_4PHASE);
+ mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, EDGE_SEL, EDGE_SEL);
+}
+
static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
enum mtk_dpi_out_color_format format)
{
@@ -439,7 +447,8 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
pll_rate = clk_get_rate(dpi->tvd_clk);
vm.pixelclock = pll_rate / factor;
- clk_set_rate(dpi->pixel_clk, vm.pixelclock);
+ clk_set_rate(dpi->pixel_clk,
+ vm.pixelclock * (dpi->dual_edge ? 2 : 1));
vm.pixelclock = clk_get_rate(dpi->pixel_clk);
dev_dbg(dpi->dev, "Got PLL %lu Hz, pixel clock %lu Hz\n",
@@ -504,6 +513,8 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
mtk_dpi_config_color_format(dpi, dpi->color_format);
mtk_dpi_config_2n_h_fre(dpi);
mtk_dpi_config_disable_edge(dpi);
+ if (dpi->dual_edge)
+ mtk_dpi_enable_dual_edge(dpi);
mtk_dpi_sw_reset(dpi, false);
return 0;
@@ -689,6 +700,7 @@ static int mtk_dpi_probe(struct platform_device *pdev)
dpi->dev = dev;
dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
+ dpi->dual_edge = of_property_read_bool(dev->of_node, "dpi_dual_edge");
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dpi->regs = devm_ioremap_resource(dev, mem);
--
2.21.0
Pull dpi pins low when dpi has nothing to display. Aovid leakage
current from some dpi pins (Hsync Vsync DE ... ).
Some chips have dpi pins, but there are some chip don't have pins.
So this function is controlled by device tree.
Signed-off-by: Jitao Shi <[email protected]>
---
drivers/gpu/drm/mediatek/mtk_dpi.c | 37 ++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index e1a33254dfbe..41712e5a721a 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -10,7 +10,9 @@
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/types.h>
@@ -74,8 +76,12 @@ struct mtk_dpi {
enum mtk_dpi_out_yc_map yc_map;
enum mtk_dpi_out_bit_num bit_num;
enum mtk_dpi_out_channel_swap channel_swap;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_gpio;
+ struct pinctrl_state *pins_dpi;
int refcount;
bool dual_edge;
+ bool dpi_pin_ctrl;
};
static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e)
@@ -387,6 +393,9 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
if (--dpi->refcount != 0)
return;
+ if (dpi->dpi_pin_ctrl)
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
+
mtk_dpi_disable(dpi);
clk_disable_unprepare(dpi->pixel_clk);
clk_disable_unprepare(dpi->engine_clk);
@@ -411,6 +420,9 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
goto err_pixel;
}
+ if (dpi->dpi_pin_ctrl)
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
+
mtk_dpi_enable(dpi);
return 0;
@@ -716,6 +728,31 @@ static int mtk_dpi_probe(struct platform_device *pdev)
dpi->dev = dev;
dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
dpi->dual_edge = of_property_read_bool(dev->of_node, "dpi_dual_edge");
+ dpi->dpi_pin_ctrl = of_property_read_bool(dev->of_node,
+ "dpi_pin_mode_swap");
+
+ if (dpi->dpi_pin_ctrl) {
+ dpi->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(dpi->pinctrl)) {
+ dev_err(&pdev->dev, "Cannot find pinctrl!\n");
+ return PTR_ERR(dpi->pinctrl);
+ }
+
+ dpi->pins_gpio = pinctrl_lookup_state(dpi->pinctrl,
+ "gpiomode");
+ if (IS_ERR(dpi->pins_gpio)) {
+ dev_err(&pdev->dev, "Cannot find pinctrl gpiomode!\n");
+ return PTR_ERR(dpi->pins_gpio);
+ }
+
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
+
+ dpi->pins_dpi = pinctrl_lookup_state(dpi->pinctrl, "dpimode");
+ if (IS_ERR(dpi->pins_dpi)) {
+ dev_err(&pdev->dev, "Cannot find pinctrl dpimode!\n");
+ return PTR_ERR(dpi->pins_dpi);
+ }
+ }
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dpi->regs = devm_ioremap_resource(dev, mem);
--
2.21.0