Commit 5f0ed4f8 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'mediatek-drm-next-5.8' of...

Merge tag 'mediatek-drm-next-5.8' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-next

Mediatek DRM Next for Linux 5.8

This include dpi pin mode swap, config mipi_tx current and impedance,
and some fixup.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20200521014612.17175-1-chunkuang.hu@kernel.org
parents c41219fd 3852489c
...@@ -17,6 +17,9 @@ Required properties: ...@@ -17,6 +17,9 @@ Required properties:
Documentation/devicetree/bindings/graph.txt. This port should be connected Documentation/devicetree/bindings/graph.txt. This port should be connected
to the input port of an attached HDMI or LVDS encoder chip. to the input port of an attached HDMI or LVDS encoder chip.
Optional properties:
- pinctrl-names: Contain "default" and "sleep".
Example: Example:
dpi0: dpi@1401d000 { dpi0: dpi@1401d000 {
...@@ -27,6 +30,9 @@ dpi0: dpi@1401d000 { ...@@ -27,6 +30,9 @@ dpi0: dpi@1401d000 {
<&mmsys CLK_MM_DPI_ENGINE>, <&mmsys CLK_MM_DPI_ENGINE>,
<&apmixedsys CLK_APMIXED_TVDPLL>; <&apmixedsys CLK_APMIXED_TVDPLL>;
clock-names = "pixel", "engine", "pll"; clock-names = "pixel", "engine", "pll";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&dpi_pin_func>;
pinctrl-1 = <&dpi_pin_idle>;
port { port {
dpi0_out: endpoint { dpi0_out: endpoint {
......
...@@ -33,6 +33,13 @@ Required properties: ...@@ -33,6 +33,13 @@ Required properties:
- #clock-cells: must be <0>; - #clock-cells: must be <0>;
- #phy-cells: must be <0>. - #phy-cells: must be <0>.
Optional properties:
- drive-strength-microamp: adjust driving current, should be 3000 ~ 6000. And
the step is 200.
- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If
unspecified default values shall be used.
- nvmem-cell-names: Should be "calibration-data"
Example: Example:
mipi_tx0: mipi-dphy@10215000 { mipi_tx0: mipi-dphy@10215000 {
...@@ -42,6 +49,9 @@ mipi_tx0: mipi-dphy@10215000 { ...@@ -42,6 +49,9 @@ mipi_tx0: mipi-dphy@10215000 {
clock-output-names = "mipi_tx0_pll"; clock-output-names = "mipi_tx0_pll";
#clock-cells = <0>; #clock-cells = <0>;
#phy-cells = <0>; #phy-cells = <0>;
drive-strength-microamp = <4600>;
nvmem-cells= <&mipi_tx_calibration>;
nvmem-cell-names = "calibration-data";
}; };
dsi0: dsi@1401b000 { dsi0: dsi@1401b000 {
......
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -75,6 +77,9 @@ struct mtk_dpi { ...@@ -75,6 +77,9 @@ struct mtk_dpi {
enum mtk_dpi_out_yc_map yc_map; enum mtk_dpi_out_yc_map yc_map;
enum mtk_dpi_out_bit_num bit_num; enum mtk_dpi_out_bit_num bit_num;
enum mtk_dpi_out_channel_swap channel_swap; enum mtk_dpi_out_channel_swap channel_swap;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_gpio;
struct pinctrl_state *pins_dpi;
int refcount; int refcount;
}; };
...@@ -380,6 +385,9 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) ...@@ -380,6 +385,9 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
if (--dpi->refcount != 0) if (--dpi->refcount != 0)
return; return;
if (dpi->pinctrl && dpi->pins_gpio)
pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
mtk_dpi_disable(dpi); mtk_dpi_disable(dpi);
clk_disable_unprepare(dpi->pixel_clk); clk_disable_unprepare(dpi->pixel_clk);
clk_disable_unprepare(dpi->engine_clk); clk_disable_unprepare(dpi->engine_clk);
...@@ -404,6 +412,9 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) ...@@ -404,6 +412,9 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
goto err_pixel; goto err_pixel;
} }
if (dpi->pinctrl && dpi->pins_dpi)
pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
mtk_dpi_enable(dpi); mtk_dpi_enable(dpi);
return 0; return 0;
...@@ -697,6 +708,26 @@ static int mtk_dpi_probe(struct platform_device *pdev) ...@@ -697,6 +708,26 @@ static int mtk_dpi_probe(struct platform_device *pdev)
dpi->dev = dev; dpi->dev = dev;
dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev); dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
dpi->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(dpi->pinctrl)) {
dpi->pinctrl = NULL;
dev_dbg(&pdev->dev, "Cannot find pinctrl!\n");
}
if (dpi->pinctrl) {
dpi->pins_gpio = pinctrl_lookup_state(dpi->pinctrl, "sleep");
if (IS_ERR(dpi->pins_gpio)) {
dpi->pins_gpio = NULL;
dev_dbg(&pdev->dev, "Cannot find pinctrl idle!\n");
}
if (dpi->pins_gpio)
pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
dpi->pins_dpi = pinctrl_lookup_state(dpi->pinctrl, "default");
if (IS_ERR(dpi->pins_dpi)) {
dpi->pins_dpi = NULL;
dev_dbg(&pdev->dev, "Cannot find pinctrl active!\n");
}
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dpi->regs = devm_ioremap_resource(dev, mem); dpi->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(dpi->regs)) { if (IS_ERR(dpi->regs)) {
......
...@@ -224,6 +224,9 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, ...@@ -224,6 +224,9 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
expected = sg_dma_address(sg->sgl); expected = sg_dma_address(sg->sgl);
for_each_sg(sg->sgl, s, sg->nents, i) { for_each_sg(sg->sgl, s, sg->nents, i) {
if (!sg_dma_len(s))
break;
if (sg_dma_address(s) != expected) { if (sg_dma_address(s) != expected) {
DRM_ERROR("sg_table is not contiguous"); DRM_ERROR("sg_table is not contiguous");
ret = -EINVAL; ret = -EINVAL;
......
...@@ -311,14 +311,10 @@ static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer, ...@@ -311,14 +311,10 @@ static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer,
u8 checksum; u8 checksum;
int ctrl_frame_en = 0; int ctrl_frame_en = 0;
frame_type = *buffer; frame_type = *buffer++;
buffer += 1; frame_ver = *buffer++;
frame_ver = *buffer; frame_len = *buffer++;
buffer += 1; checksum = *buffer++;
frame_len = *buffer;
buffer += 1;
checksum = *buffer;
buffer += 1;
frame_data = buffer; frame_data = buffer;
dev_dbg(hdmi->dev, dev_dbg(hdmi->dev,
...@@ -982,7 +978,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi, ...@@ -982,7 +978,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct hdmi_avi_infoframe frame; struct hdmi_avi_infoframe frame;
u8 buffer[17]; u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
ssize_t err; ssize_t err;
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
...@@ -1008,7 +1004,7 @@ static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi, ...@@ -1008,7 +1004,7 @@ static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi,
const char *product) const char *product)
{ {
struct hdmi_spd_infoframe frame; struct hdmi_spd_infoframe frame;
u8 buffer[29]; u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE];
ssize_t err; ssize_t err;
err = hdmi_spd_infoframe_init(&frame, vendor, product); err = hdmi_spd_infoframe_init(&frame, vendor, product);
...@@ -1031,7 +1027,7 @@ static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi, ...@@ -1031,7 +1027,7 @@ static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi,
static int mtk_hdmi_setup_audio_infoframe(struct mtk_hdmi *hdmi) static int mtk_hdmi_setup_audio_infoframe(struct mtk_hdmi *hdmi)
{ {
struct hdmi_audio_infoframe frame; struct hdmi_audio_infoframe frame;
u8 buffer[14]; u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
ssize_t err; ssize_t err;
err = hdmi_audio_infoframe_init(&frame); err = hdmi_audio_infoframe_init(&frame);
......
...@@ -88,6 +88,44 @@ static const struct phy_ops mtk_mipi_tx_ops = { ...@@ -88,6 +88,44 @@ static const struct phy_ops mtk_mipi_tx_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static void mtk_mipi_tx_get_calibration_datal(struct mtk_mipi_tx *mipi_tx)
{
struct nvmem_cell *cell;
size_t len;
u32 *buf;
cell = nvmem_cell_get(mipi_tx->dev, "calibration-data");
if (IS_ERR(cell)) {
dev_info(mipi_tx->dev, "can't get nvmem_cell_get, ignore it\n");
return;
}
buf = (u32 *)nvmem_cell_read(cell, &len);
nvmem_cell_put(cell);
if (IS_ERR(buf)) {
dev_info(mipi_tx->dev, "can't get data, ignore it\n");
return;
}
if (len < 3 * sizeof(u32)) {
dev_info(mipi_tx->dev, "invalid calibration data\n");
kfree(buf);
return;
}
mipi_tx->rt_code[0] = ((buf[0] >> 6 & 0x1f) << 5) |
(buf[0] >> 11 & 0x1f);
mipi_tx->rt_code[1] = ((buf[1] >> 27 & 0x1f) << 5) |
(buf[0] >> 1 & 0x1f);
mipi_tx->rt_code[2] = ((buf[1] >> 17 & 0x1f) << 5) |
(buf[1] >> 22 & 0x1f);
mipi_tx->rt_code[3] = ((buf[1] >> 7 & 0x1f) << 5) |
(buf[1] >> 12 & 0x1f);
mipi_tx->rt_code[4] = ((buf[2] >> 27 & 0x1f) << 5) |
(buf[1] >> 2 & 0x1f);
kfree(buf);
}
static int mtk_mipi_tx_probe(struct platform_device *pdev) static int mtk_mipi_tx_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -125,6 +163,20 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) ...@@ -125,6 +163,20 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = of_property_read_u32(dev->of_node, "drive-strength-microamp",
&mipi_tx->mipitx_drive);
/* If can't get the "mipi_tx->mipitx_drive", set it default 0x8 */
if (ret < 0)
mipi_tx->mipitx_drive = 4600;
/* check the mipitx_drive valid */
if (mipi_tx->mipitx_drive > 6000 || mipi_tx->mipitx_drive < 3000) {
dev_warn(dev, "drive-strength-microamp is invalid %d, not in 3000 ~ 6000\n",
mipi_tx->mipitx_drive);
mipi_tx->mipitx_drive = clamp_val(mipi_tx->mipitx_drive, 3000,
6000);
}
ref_clk_name = __clk_get_name(ref_clk); ref_clk_name = __clk_get_name(ref_clk);
ret = of_property_read_string(dev->of_node, "clock-output-names", ret = of_property_read_string(dev->of_node, "clock-output-names",
...@@ -160,6 +212,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) ...@@ -160,6 +212,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
mipi_tx->dev = dev; mipi_tx->dev = dev;
mtk_mipi_tx_get_calibration_datal(mipi_tx);
return of_clk_add_provider(dev->of_node, of_clk_src_simple_get, return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
mipi_tx->pll); mipi_tx->pll);
} }
......
...@@ -12,9 +12,11 @@ ...@@ -12,9 +12,11 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/slab.h>
struct mtk_mipitx_data { struct mtk_mipitx_data {
const u32 mppll_preserve; const u32 mppll_preserve;
...@@ -27,6 +29,8 @@ struct mtk_mipi_tx { ...@@ -27,6 +29,8 @@ struct mtk_mipi_tx {
struct device *dev; struct device *dev;
void __iomem *regs; void __iomem *regs;
u32 data_rate; u32 data_rate;
u32 mipitx_drive;
u32 rt_code[5];
const struct mtk_mipitx_data *driver_data; const struct mtk_mipitx_data *driver_data;
struct clk_hw pll_hw; struct clk_hw pll_hw;
struct clk *pll; struct clk *pll;
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#define RG_DSI_BG_CORE_EN BIT(7) #define RG_DSI_BG_CORE_EN BIT(7)
#define RG_DSI_PAD_TIEL_SEL BIT(8) #define RG_DSI_PAD_TIEL_SEL BIT(8)
#define MIPITX_VOLTAGE_SEL 0x0010
#define RG_DSI_HSTX_LDO_REF_SEL (0xf << 6)
#define MIPITX_PLL_PWR 0x0028 #define MIPITX_PLL_PWR 0x0028
#define MIPITX_PLL_CON0 0x002c #define MIPITX_PLL_CON0 0x002c
#define MIPITX_PLL_CON1 0x0030 #define MIPITX_PLL_CON1 0x0030
...@@ -25,6 +28,7 @@ ...@@ -25,6 +28,7 @@
#define MIPITX_PLL_CON4 0x003c #define MIPITX_PLL_CON4 0x003c
#define RG_DSI_PLL_IBIAS (3 << 10) #define RG_DSI_PLL_IBIAS (3 << 10)
#define MIPITX_D2P_RTCODE 0x0100
#define MIPITX_D2_SW_CTL_EN 0x0144 #define MIPITX_D2_SW_CTL_EN 0x0144
#define MIPITX_D0_SW_CTL_EN 0x0244 #define MIPITX_D0_SW_CTL_EN 0x0244
#define MIPITX_CK_CKMODE_EN 0x0328 #define MIPITX_CK_CKMODE_EN 0x0328
...@@ -105,6 +109,24 @@ static const struct clk_ops mtk_mipi_tx_pll_ops = { ...@@ -105,6 +109,24 @@ static const struct clk_ops mtk_mipi_tx_pll_ops = {
.recalc_rate = mtk_mipi_tx_pll_recalc_rate, .recalc_rate = mtk_mipi_tx_pll_recalc_rate,
}; };
static void mtk_mipi_tx_config_calibration_data(struct mtk_mipi_tx *mipi_tx)
{
int i, j;
for (i = 0; i < 5; i++) {
if ((mipi_tx->rt_code[i] & 0x1f) == 0)
mipi_tx->rt_code[i] |= 0x10;
if ((mipi_tx->rt_code[i] >> 5 & 0x1f) == 0)
mipi_tx->rt_code[i] |= 0x10 << 5;
for (j = 0; j < 10; j++)
mtk_mipi_tx_update_bits(mipi_tx,
MIPITX_D2P_RTCODE * (i + 1) + j * 4,
1, mipi_tx->rt_code[i] >> j & 1);
}
}
static void mtk_mipi_tx_power_on_signal(struct phy *phy) static void mtk_mipi_tx_power_on_signal(struct phy *phy)
{ {
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
...@@ -123,6 +145,12 @@ static void mtk_mipi_tx_power_on_signal(struct phy *phy) ...@@ -123,6 +145,12 @@ static void mtk_mipi_tx_power_on_signal(struct phy *phy)
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN); mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL,
RG_DSI_HSTX_LDO_REF_SEL,
(mipi_tx->mipitx_drive - 3000) / 200 << 6);
mtk_mipi_tx_config_calibration_data(mipi_tx);
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN); mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN);
} }
......
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