RK3588 Linux调整显示MIPI信号驱动强度

1,内核添加如下补丁后可通过节点查看phy的各项参数:

--- a/kernel/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c

+++ b/kernel/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c

@@ -148,6 +148,25 @@

#define T_TA_GET(x) UPDATE(x, 7, 4)

#define T_TA_GO(x) UPDATE(x, 3, 0)

+#define REG_400M_MASK GENMASK(6, 4)

+#define REG_400M(x) UPDATE(x, 6, 4)

+#define BIAS_CON4 0x0010

+#define I_MUX_SEL_MASK GENMASK(6, 5)

+#define I_MUX_SEL(x) UPDATE(x, 6, 5)

+#define CAP_PEAKING_MASK GENMASK(14, 12)

+#define CAP_PEAKING(x) UPDATE(x, 14, 12)

+#define RES_UP_MASK GENMASK(7, 4)

+#define RES_UP(x) UPDATE(x, 7, 4)

+#define RES_DN_MASK GENMASK(3, 0)

+#define RES_DN(x) UPDATE(x, 3, 0)

+#define T_HS_ZERO_MASK GENMASK(15, 8)

+#define T_HS_PREPARE_MASK GENMASK(7, 0)

+#define T_HS_EXIT_MASK GENMASK(15, 8)

+#define T_HS_TRAIL_MASK GENMASK(7, 0)

+#define T_TA_GET_MASK GENMASK(7, 4)

+#define T_TA_GO_MASK GENMASK(3, 0)

/* MIPI_CDPHY_GRF registers */

#define MIPI_DCPHY_GRF_CON0 0x0000

#define S_CPHY_MODE HIWORD_UPDATE(1, 3, 3)

@@ -1236,6 +1255,456 @@ struct samsung_mipi_cphy_timing samsung_mipi_cphy_timing_table\[\] = {

{ 80, 1, 50, 25, 2, 0, 2 },

};

+static ssize_t

+reg_400m_show(struct device *device, struct device_attribute *attr, char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int level;

  • regmap_read(samsung->regmap, BIAS_CON2, &val);

  • level = (val & REG_400M_MASK) >> 4;

  • return sprintf(buf, "%d\n", level);

+}

+static ssize_t

+reg_400m_store(struct device *device, struct device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • if (val > 7)

  • val = 7;

  • regmap_update_bits(samsung->regmap, BIAS_CON2, REG_400M_MASK, REG_400M(val));

  • return count;

+}

+static DEVICE_ATTR_RW(reg_400m);

+static ssize_t

+cap_peaking_show(struct device *device, struct device_attribute *attr, char

  • *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int level;

  • regmap_read(samsung->regmap, COMBO_MD0_ANA_CON0, &val);

  • level = (val & CAP_PEAKING_MASK) >> 12;

  • return sprintf(buf, "%d\n", level);

+}

+static ssize_t

+cap_peaking_store(struct device *device, struct device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • if (val > 7)

  • val = 7;

  • regmap_update_bits(samsung->regmap, DPHY_MC_ANA_CON0, CAP_PEAKING_MASK,

  • CAP_PEAKING(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD0_ANA_CON0, CAP_PEAKING_MASK,

  • CAP_PEAKING(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD1_ANA_CON0, CAP_PEAKING_MASK,

  • CAP_PEAKING(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD2_ANA_CON0, CAP_PEAKING_MASK,

  • CAP_PEAKING(val));

  • regmap_update_bits(samsung->regmap, DPHY_MD3_ANA_CON0, CAP_PEAKING_MASK,

  • CAP_PEAKING(val));

  • return count;

+}

+static DEVICE_ATTR_RW(cap_peaking);

+static ssize_t

+res_up_show(struct device *device, struct device_attribute *attr, char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int level;

  • regmap_read(samsung->regmap, COMBO_MD0_ANA_CON0, &val);

  • level = (val & RES_UP_MASK) >> 4;

  • return sprintf(buf, "%d\n", level);

+}

+static ssize_t

+res_up_store(struct device *device, struct device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • if (val > 15)

  • val = 15;

  • regmap_update_bits(samsung->regmap, DPHY_MC_ANA_CON0, RES_UP_MASK,

  • RES_UP(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD0_ANA_CON0, RES_UP_MASK,

  • RES_UP(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD1_ANA_CON0, RES_UP_MASK,

  • RES_UP(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD2_ANA_CON0, RES_UP_MASK,

  • RES_UP(val));

  • regmap_update_bits(samsung->regmap, DPHY_MD3_ANA_CON0, RES_UP_MASK,

  • RES_UP(val));

  • return count;

+}

+static DEVICE_ATTR_RW(res_up);

+static ssize_t

+res_dn_show(struct device *device, struct device_attribute *attr, char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int level;

  • regmap_read(samsung->regmap, COMBO_MD0_ANA_CON0, &val);

  • level = (val & RES_DN_MASK);

  • return sprintf(buf, "%d\n", level);

+}

+static ssize_t

+res_dn_store(struct device *device, struct device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • if (val > 15)

  • val = 15;

  • regmap_update_bits(samsung->regmap, DPHY_MC_ANA_CON0, RES_DN_MASK,

  • RES_DN(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD0_ANA_CON0, RES_DN_MASK,

  • RES_DN(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD1_ANA_CON0, RES_DN_MASK,

  • RES_DN(val));

  • regmap_update_bits(samsung->regmap, COMBO_MD2_ANA_CON0, RES_DN_MASK,

  • RES_DN(val));

  • regmap_update_bits(samsung->regmap, DPHY_MD3_ANA_CON0, RES_DN_MASK,

  • RES_DN(val));

  • return count;

+}

+static DEVICE_ATTR_RW(res_dn);

+static ssize_t

+output_voltage_show(struct device *device, struct device_attribute *attr, char

  • *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int level;

  • regmap_read(samsung->regmap, BIAS_CON4, &val);

  • level = (val & I_MUX_SEL_MASK) >> 5;

  • return sprintf(buf, "%d\n", level);

+}

+static ssize_t

+output_voltage_store(struct device *device, struct device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • if (val > 3)

  • val = 3;

  • regmap_update_bits(samsung->regmap, BIAS_CON4,

  • I_MUX_SEL_MASK, I_MUX_SEL(val));

  • return count;

+}

+static DEVICE_ATTR_RW(output_voltage);

+static ssize_t

+hs_exit_show(struct device *device, struct device_attribute *attr, char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int hs_exit;

  • regmap_read(samsung->regmap, COMBO_MD0_TIME_CON2, &val);

  • hs_exit = (val & GENMASK(15, 8)) >> 8;

  • return sprintf(buf, "%d\n", hs_exit);

+}

+static ssize_t hs_exit_store(struct device *device, struct device_attribute

  • *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • unsigned long hs_exit;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • hs_exit = T_HS_EXIT(val);

  • regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON2, T_HS_EXIT_MASK,

  • hs_exit);

  • regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON2, T_HS_EXIT_MASK,

  • hs_exit);

  • regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON2, T_HS_EXIT_MASK,

  • hs_exit);

  • if (!samsung->c_option) {

  • regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON2, T_HS_EXIT_MASK,

  • hs_exit);

  • regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON2, T_HS_EXIT_MASK,

  • hs_exit);

  • }

  • return count;

+}

+static DEVICE_ATTR_RW(hs_exit);

+static ssize_t

+hs_trail_or_post_3_show(struct device *device, struct device_attribute *attr,

  • char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int hs_trail;

  • regmap_read(samsung->regmap, COMBO_MD0_TIME_CON2, &val);

  • hs_trail = val & GENMASK(7, 0);

  • return sprintf(buf, "%d\n", hs_trail);

+}

+static ssize_t hs_trail_or_post_3_store(struct device *device, struct

  • device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • unsigned long hs_trail;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • hs_trail = T_HS_TRAIL(val);

  • regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON2, T_HS_TRAIL_MASK,

  • hs_trail);

  • regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON2, T_HS_TRAIL_MASK,

  • hs_trail);

  • regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON2, T_HS_TRAIL_MASK,

  • hs_trail);

  • if (!samsung->c_option) {

  • regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON2, T_HS_TRAIL_MASK,

  • hs_trail);

  • regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON2, T_HS_TRAIL_MASK,

  • hs_trail);

  • }

  • return count;

+}

+static DEVICE_ATTR_RW(hs_trail_or_post_3);

+static ssize_t

+hs_zero_or_prebegin_3_show(struct device *device, struct device_attribute *attr,

  • char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int hs_zero;

  • regmap_read(samsung->regmap, COMBO_MD0_TIME_CON1, &val);

  • hs_zero = (val & GENMASK(15, 8)) >> 8;

  • return sprintf(buf, "%d\n", hs_zero);

+}

+static ssize_t hs_zero_or_prebegin_3_store(struct device *device, struct

  • device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • unsigned long hs_zero;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • hs_zero = T_HS_ZERO(val);

  • regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON1,

  • T_HS_ZERO_MASK, hs_zero);

  • regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON1,

  • T_HS_ZERO_MASK, hs_zero);

  • regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON1,

  • T_HS_ZERO_MASK, hs_zero);

  • if (!samsung->c_option) {

  • regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON1,

  • T_HS_ZERO_MASK, hs_zero);

  • regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON1,

  • T_HS_ZERO_MASK, hs_zero);

  • }

  • return count;

+}

+static DEVICE_ATTR_RW(hs_zero_or_prebegin_3);

+static ssize_t

+hs_prepare_or_prepare_3_show(struct device *device, struct device_attribute

  • *attr, char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int hs_prepare;

  • regmap_read(samsung->regmap, COMBO_MD0_TIME_CON1, &val);

  • hs_prepare = val & GENMASK(7, 0);

  • return sprintf(buf, "%d\n", hs_prepare);

+}

+static ssize_t hs_prepare_or_prepare_3_store(struct device *device, struct

+device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • unsigned long hs_prepare;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • hs_prepare = T_HS_PREPARE(val);

  • regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON1,

  • T_HS_PREPARE_MASK, hs_prepare);

  • regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON1,

  • T_HS_PREPARE_MASK, hs_prepare);

  • regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON1,

  • T_HS_PREPARE_MASK, hs_prepare);

  • if (!samsung->c_option) {

  • regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON1,

  • T_HS_PREPARE_MASK, hs_prepare);

  • regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON1,

  • T_HS_PREPARE_MASK, hs_prepare);

  • }

  • return count;

+}

+static DEVICE_ATTR_RW(hs_prepare_or_prepare_3);

+static ssize_t

+lpx_show(struct device *device, struct device_attribute *attr, char *buf)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned int val;

  • unsigned int lpx;

  • regmap_read(samsung->regmap, COMBO_MD0_TIME_CON0, &val);

  • lpx = (val & GENMASK(11, 4)) >> 4;

  • return sprintf(buf, "%d\n", lpx);

+}

+static ssize_t lpx_store(struct device *device, struct device_attribute *attr,

  • const char *buf, size_t count)

+{

  • struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);

  • unsigned long val;

  • unsigned long lpx = 0;

  • if (kstrtoul(buf, 10, &val))

  • return -EINVAL;

  • lpx |= T_LPX(val);

  • /* T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */

  • regmap_write(samsung->regmap, COMBO_MD0_TIME_CON0, lpx);

  • regmap_write(samsung->regmap, COMBO_MD1_TIME_CON0, lpx);

  • regmap_write(samsung->regmap, COMBO_MD2_TIME_CON0, lpx);

  • if (!samsung->c_option) {

  • regmap_write(samsung->regmap, DPHY_MC_TIME_CON0, lpx);

  • regmap_write(samsung->regmap, DPHY_MD3_TIME_CON0, lpx);

  • }

  • return count;

+}

+static DEVICE_ATTR_RW(lpx);

+static struct attribute *samsung_mipi_dcphy_cts_attrs\[\] = {

  • &dev_attr_lpx.attr,

  • &dev_attr_hs_prepare_or_prepare_3.attr,

  • &dev_attr_hs_zero_or_prebegin_3.attr,

  • &dev_attr_hs_trail_or_post_3.attr,

  • &dev_attr_hs_exit.attr,

  • &dev_attr_output_voltage.attr,

  • &dev_attr_res_up.attr,

  • &dev_attr_res_dn.attr,

  • &dev_attr_cap_peaking.attr,

  • &dev_attr_reg_400m.attr,

  • NULL

+};

+static const struct attribute_group samsung_mipi_dcphy_cts_attr_group = {

  • .attrs = samsung_mipi_dcphy_cts_attrs,

+};

+static int samsung_mipi_dcphy_cts_sysfs_add(struct samsung_mipi_dcphy *samsung)

+{

  • struct device *dev = samsung->dev;

  • int ret;

  • ret = sysfs_create_group(&dev->kobj, &samsung_mipi_dcphy_cts_attr_group);

  • if (ret) {

  • dev_err(dev, "failed to register sysfs. err: %d\n", ret);

  • return ret;

  • };

  • return 0;

+}

struct hsfreq_range {

u32 range_h;

u16 cfg_bit;

@@ -2385,6 +2854,14 @@ static int samsung_mipi_dcphy_probe(struct platform_device *pdev)

samsung->stream_on = samsung_dcphy_rx_stream_on;

samsung->stream_off = samsung_dcphy_rx_stream_off;

mutex_init(&samsung->mutex);

  • ret = samsung_mipi_dcphy_cts_sysfs_add(samsung);

  • if (ret)

  • return ret;

具体节点说明可参考《Rockchip_Developer_Guide_MIPI_DSI2_CN.pdf》中"调试节点"章节。

比如要提高驱动强度,可在samsung_mipi_dcphy_probe末尾添加如下代码:

/*D-PHY默认强度为0(400mV),修改默认设置MIPI驱动强度为最大。b00:400mV b01:200mV b10:530mV b11:530mV*/

regmap_update_bits(samsung->regmap, BIAS_CON4,

I_MUX_SEL_MASK, I_MUX_SEL(3));

查看驱动强度的节点:cat /sys/devices/platform/feda0000.phy/output_voltage

2,uboot中调整phy参数在/u-boot/drivers/video/drm/samsung_mipi_dcphy.c中

可在samsung_mipi_dcphy_bias_block_enable函数中配置,如下:

static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung)

{

phy_write(samsung, BIAS_CON0, 0x0010);

phy_write(samsung, BIAS_CON1, 0x0110);

phy_write(samsung, BIAS_CON2, 0x3223);

if (samsung->c_option){

phy_update_bits(samsung, BIAS_CON4, I_MUX_SEL_MASK, I_MUX_SEL(2));

}

}

比如我要修改D-PHY时mipi强度为最大530mV,可如下修改:

static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung)

{

phy_write(samsung, BIAS_CON0, 0x0010);

phy_write(samsung, BIAS_CON1, 0x0110);

phy_write(samsung, BIAS_CON2, 0x3223);

// if (samsung->c_option){

phy_update_bits(samsung, BIAS_CON4, I_MUX_SEL_MASK, I_MUX_SEL(2));

// }

}

相关推荐
龙迅代理6 天前
LT9102---MIPI Single-port to MIPI Dual-port
mipi·command mode
讯技光电-深圳7 天前
LITESTAR 4D照明设计系统软件,照明设计领域唯一拥有开放数据库的程序
照明·显示
洞察物理世界16 天前
【SI_Mipi M PHY】一文了解Mipi M PHY基本知识
ufs·mipi·mphy
橘色的喵22 天前
一根数据源,两条出图路:UVC(USB)与 CSI-2(MIPI)对比解读
usb·isp·mipi·uvc·csi-2
洞察物理世界2 个月前
【SI_Mipi C PHY 02】一文掌握Mipi C PHY测试方案
mipi·mipi c phy·一致性测试
REDcker2 个月前
显示分辨率标准对照详解
前端·网络·分辨率·显示·屏幕
洞察物理世界2 个月前
【SI_Mipi C PHY】快速了解Mipi C PHY协议
mipi·mipi c phy
9527华安2 个月前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi
Gary Studio3 个月前
MIPI D-PHY 协议:从传统 LP 状态机到全新 ALP 模式详解
协议·mipi