forked from Minki/linux
Mediatek DRM Next for Linux 5.8
-----BEGIN PGP SIGNATURE----- iQJMBAABCgA2FiEEACwLKSDmq+9RDv5P4cpzo8lZTiQFAl7FwFkYHGNodW5rdWFu Zy5odUBrZXJuZWwub3JnAAoJEOHKc6PJWU4khCkP/1ZKyyJd83FLQZ142j5KD64j XeiJ7xxVNIjMcgJMLImOevF3XbNuON58D0xwcU+06yrUntt7qbWztug0OrmZvRiI H4qxMXf5Yp/5EFGCVXrKw+UP9LPcYas2z2aD7WWI9p1NI6SQIBsazWu01daMd87U GbxTg5xpOT0rFt6fpTpRyWEeQD2AALDRWTovxG1VfmYB5ZnioBk29vReSPQA93Un HZhBQPTvj3NBgFtqhZQlS+4nr8CnAcJs++fcAKHnSJyQ3klmLcYIux8fKSRCd81W F7dzshL1S1tPgFnU/CegiysfdEZX1FEaYSuzk6ALKAV6s/Xz+qz9FdUVZYxcE/2s eG1fCXu6OVg1JYoFRO4ZcyfuMDHNwZzhyRb58atCN5s2gJwY+nID5nRiyFrPTA47 J+1cJubk/n3mWyezZp2oqo6u2a74C80RPMgjpAAG3VPoQGvEvUuNZXn4u5idpixT LDYyMfdgJNL+cP78+y2WXFfAqUtg8A7IfnisT5teSr5t+HQ74H57mBb5muYehKhu 6gzyBkj5Nen1NIpwF+v0EX73PtzpUWmzk6AT6/8lrfq6Sjf3WTBzGeiI4e0vrUs9 aqIYRImMKGPZ5rTAvKx9fh2oZzH9B6x/zTUOMCZPkkXuHKg3PncXZywDVdq1Nwgz vrsKuCrpNsyHPDQ6G+D6 =qbjB -----END PGP SIGNATURE----- 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: Dave 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
This commit is contained in:
commit
5f0ed4f8f6
@ -17,6 +17,9 @@ Required properties:
|
||||
Documentation/devicetree/bindings/graph.txt. This port should be connected
|
||||
to the input port of an attached HDMI or LVDS encoder chip.
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names: Contain "default" and "sleep".
|
||||
|
||||
Example:
|
||||
|
||||
dpi0: dpi@1401d000 {
|
||||
@ -27,6 +30,9 @@ dpi0: dpi@1401d000 {
|
||||
<&mmsys CLK_MM_DPI_ENGINE>,
|
||||
<&apmixedsys CLK_APMIXED_TVDPLL>;
|
||||
clock-names = "pixel", "engine", "pll";
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&dpi_pin_func>;
|
||||
pinctrl-1 = <&dpi_pin_idle>;
|
||||
|
||||
port {
|
||||
dpi0_out: endpoint {
|
||||
|
@ -33,6 +33,13 @@ Required properties:
|
||||
- #clock-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:
|
||||
|
||||
mipi_tx0: mipi-dphy@10215000 {
|
||||
@ -42,6 +49,9 @@ mipi_tx0: mipi-dphy@10215000 {
|
||||
clock-output-names = "mipi_tx0_pll";
|
||||
#clock-cells = <0>;
|
||||
#phy-cells = <0>;
|
||||
drive-strength-microamp = <4600>;
|
||||
nvmem-cells= <&mipi_tx_calibration>;
|
||||
nvmem-cell-names = "calibration-data";
|
||||
};
|
||||
|
||||
dsi0: dsi@1401b000 {
|
||||
|
@ -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>
|
||||
|
||||
@ -75,6 +77,9 @@ 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;
|
||||
};
|
||||
|
||||
@ -380,6 +385,9 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
|
||||
if (--dpi->refcount != 0)
|
||||
return;
|
||||
|
||||
if (dpi->pinctrl && dpi->pins_gpio)
|
||||
pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
|
||||
|
||||
mtk_dpi_disable(dpi);
|
||||
clk_disable_unprepare(dpi->pixel_clk);
|
||||
clk_disable_unprepare(dpi->engine_clk);
|
||||
@ -404,6 +412,9 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
|
||||
goto err_pixel;
|
||||
}
|
||||
|
||||
if (dpi->pinctrl && dpi->pins_dpi)
|
||||
pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
|
||||
|
||||
mtk_dpi_enable(dpi);
|
||||
return 0;
|
||||
|
||||
@ -697,6 +708,26 @@ 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->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);
|
||||
dpi->regs = devm_ioremap_resource(dev, mem);
|
||||
if (IS_ERR(dpi->regs)) {
|
||||
|
@ -224,6 +224,9 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
|
||||
expected = sg_dma_address(sg->sgl);
|
||||
for_each_sg(sg->sgl, s, sg->nents, i) {
|
||||
if (!sg_dma_len(s))
|
||||
break;
|
||||
|
||||
if (sg_dma_address(s) != expected) {
|
||||
DRM_ERROR("sg_table is not contiguous");
|
||||
ret = -EINVAL;
|
||||
|
@ -311,14 +311,10 @@ static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer,
|
||||
u8 checksum;
|
||||
int ctrl_frame_en = 0;
|
||||
|
||||
frame_type = *buffer;
|
||||
buffer += 1;
|
||||
frame_ver = *buffer;
|
||||
buffer += 1;
|
||||
frame_len = *buffer;
|
||||
buffer += 1;
|
||||
checksum = *buffer;
|
||||
buffer += 1;
|
||||
frame_type = *buffer++;
|
||||
frame_ver = *buffer++;
|
||||
frame_len = *buffer++;
|
||||
checksum = *buffer++;
|
||||
frame_data = buffer;
|
||||
|
||||
dev_dbg(hdmi->dev,
|
||||
@ -982,7 +978,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct hdmi_avi_infoframe frame;
|
||||
u8 buffer[17];
|
||||
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
|
||||
ssize_t err;
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
|
||||
@ -1008,7 +1004,7 @@ static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi,
|
||||
const char *product)
|
||||
{
|
||||
struct hdmi_spd_infoframe frame;
|
||||
u8 buffer[29];
|
||||
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE];
|
||||
ssize_t err;
|
||||
|
||||
err = hdmi_spd_infoframe_init(&frame, vendor, product);
|
||||
@ -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)
|
||||
{
|
||||
struct hdmi_audio_infoframe frame;
|
||||
u8 buffer[14];
|
||||
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
|
||||
ssize_t err;
|
||||
|
||||
err = hdmi_audio_infoframe_init(&frame);
|
||||
|
@ -88,6 +88,44 @@ static const struct phy_ops mtk_mipi_tx_ops = {
|
||||
.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)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -125,6 +163,20 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
||||
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);
|
||||
|
||||
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)
|
||||
|
||||
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,
|
||||
mipi_tx->pll);
|
||||
}
|
||||
|
@ -12,9 +12,11 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct mtk_mipitx_data {
|
||||
const u32 mppll_preserve;
|
||||
@ -27,6 +29,8 @@ struct mtk_mipi_tx {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
u32 data_rate;
|
||||
u32 mipitx_drive;
|
||||
u32 rt_code[5];
|
||||
const struct mtk_mipitx_data *driver_data;
|
||||
struct clk_hw pll_hw;
|
||||
struct clk *pll;
|
||||
|
@ -17,6 +17,9 @@
|
||||
#define RG_DSI_BG_CORE_EN BIT(7)
|
||||
#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_CON0 0x002c
|
||||
#define MIPITX_PLL_CON1 0x0030
|
||||
@ -25,6 +28,7 @@
|
||||
#define MIPITX_PLL_CON4 0x003c
|
||||
#define RG_DSI_PLL_IBIAS (3 << 10)
|
||||
|
||||
#define MIPITX_D2P_RTCODE 0x0100
|
||||
#define MIPITX_D2_SW_CTL_EN 0x0144
|
||||
#define MIPITX_D0_SW_CTL_EN 0x0244
|
||||
#define MIPITX_CK_CKMODE_EN 0x0328
|
||||
@ -105,6 +109,24 @@ static const struct clk_ops mtk_mipi_tx_pll_ops = {
|
||||
.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)
|
||||
{
|
||||
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)
|
||||
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_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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user