1.1 rk3576 bt1120硬件确认

1.1 rk3576 bt1120硬件确认 rk3576 bt1120硬件确认查阅硬件设计指南可以确认 rk3576是支持 16bit bt1120模式 最高支持1080p60Hz。image对应引脚可以查阅引脚设计指南或者设备树pinctrl bt1120只有这些引脚如下图所示image1.2、nvp6021硬件确认电源有供电引脚控制需要开启并测了一下是否正常。image复位这里是active low 因为使用硬件原理图上加了三极管需要取反处理imageI2C地址及电平使用i2c的电平必须为3v3或者转为3v3的。imageimage2、驱动及设备树配置2.1、nvp6021驱动实现nvp6021厂家是没有提供Linux版本驱动的只提供一个1080P_720P5060_74.25MHz_16bit_20191213.txt这种寄存器配置根据这个配置结合设备树简单实现对应分辨率及帧数选择。通过设备树nextchip,vmode 属性来选择对应寄存器写入。复制代码nvp6021: nvp602130 {pinctrl-names “default”;pinctrl-0 nvp6021_rst_pins;compatible “nextchip,nvp6021”;reg 0x30;reset-gpios gpio3 RK_PD4 GPIO_ACTIVE_HIGH;nextchip,vmode 0; // 0:1080p30, 1:1080p25, 2:720p60, 3:720p50};复制代码实现的驱动源码复位引脚电平会导致寄存器是否正常写入以实际硬件为准。复制代码// SPDX-License-Identifier: GPL-2.0/*NVP6021 AHD TX initialization driver (I2C only)Supports video modes:0 1080p301 1080p252 720p603 720p50*/#include linux/module.h#include linux/i2c.h#include linux/gpio/consumer.h#include linux/delay.h#include linux/of.h#include linux/property.h/* Video mode defines (matching original DecoderInitial) */#define NVP6021_VMODE_1080P30 0#define NVP6021_VMODE_1080P25 1#define NVP6021_VMODE_720P60 2#define NVP6021_VMODE_720P50 3struct nvp6021_priv {struct i2c_client *client;struct gpio_desc *reset_gpio;u8 vmode;};/* Write one byte to register address */static int nvp6021_write(struct i2c_client *client, u8 reg, u8 val){return i2c_smbus_write_byte_data(client, reg, val);}/* Hardware reset sequence (exactly as original) */static void nvp6021_hw_reset(struct nvp6021_priv *priv){if (!priv-reset_gpio) {dev_warn(priv-client-dev, “No reset GPIO, skip reset\n”);return;}gpiod_set_value_cansleep(priv-reset_gpio, 0); usleep_range(2000, 3000); gpiod_set_value_cansleep(priv-reset_gpio, 1); usleep_range(20000, 21000); gpiod_set_value_cansleep(priv-reset_gpio, 0); usleep_range(5000, 6000);}/* Full initialization sequence based on the given code */static int nvp6021_initialize(struct nvp6021_priv *priv){struct i2c_client *client priv-client;u8 vmode priv-vmode;int ret;dev_info(client-dev, Initializing NVP6021 (vmode%d)\n, vmode); /* Hardware reset */ nvp6021_hw_reset(priv); /* ---- BANK0 ---- */ ret nvp6021_write(client, 0xFF, 0x00); // select BANK0 if (ret) goto err; ret nvp6021_write(client, 0x00, 0x01); if (ret) goto err; switch (vmode) { case NVP6021_VMODE_1080P30: ret nvp6021_write(client, 0x01, 0xF0); if (ret) goto err; ret nvp6021_write(client, 0x04, 0x00); //ret nvp6021_write(client, 0x04, 0x85); break; case NVP6021_VMODE_1080P25: ret nvp6021_write(client, 0x01, 0xF1); if (ret) goto err; ret nvp6021_write(client, 0x04, 0x00); break; case NVP6021_VMODE_720P60: ret nvp6021_write(client, 0x01, 0xE2); if (ret) goto err; ret nvp6021_write(client, 0x04, 0x00); break; case NVP6021_VMODE_720P50: ret nvp6021_write(client, 0x01, 0xE3); if (ret) goto err; ret nvp6021_write(client, 0x04, 0x00); break; default: dev_err(client-dev, Invalid vmode %d\n, vmode); return -EINVAL; } if (ret) goto err; /* ---- BANK1 ---- */ ret nvp6021_write(client, 0xFF, 0x01); // select BANK1 if (ret) goto err; ret nvp6021_write(client, 0x0E, 0x00); if (ret) goto err; /* ---- BANK2 (main configuration) ---- */ ret nvp6021_write(client, 0xFF, 0x02); // select BANK2 if (ret) goto err; /* Write the sequence exactly as provided */ u8 init_vals[][2] { {0x00, 0xFE}, {0x02, 0x00}, {0x04, 0x80}, {0x05, 0x00}, {0x06, 0x10}, {0x0C, 0x04}, {0x0D, 0x3F}, {0x0E, 0x00}, {0x10, 0xEB}, {0x11, 0x10}, {0x12, 0xF0}, {0x13, 0x10}, {0x14, 0x01}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00}, {0x18, 0x00}, {0x19, 0x00}, {0x1C, 0x80}, {0x1D, 0x80}, {0x1E, 0x80}, {0x36, 0x01}, {0x37, 0x80}, {0x39, 0x00}, {0x3C, 0x00}, {0x3D, 0x00}, {0x3E, 0x00}, {0x40, 0x01}, {0x41, 0xFF}, {0x42, 0x80}, {0x60, 0x80}, {0x61, 0x80}, {0x63, 0xE0}, {0x64, 0x19}, {0x65, 0x04}, {0x66, 0xEB}, {0x67, 0x60}, {0x68, 0x00}, {0x69, 0x00}, {0x6A, 0x00}, {0x6B, 0x00}, }; for (int i 0; i ARRAY_SIZE(init_vals); i) { ret nvp6021_write(client, init_vals[i][0], init_vals[i][1]); if (ret) goto err; } /* Clear 0x20..0x34 */ for (u8 r 0x20; r 0x34; r) { ret nvp6021_write(client, r, 0x00); if (ret) goto err; } /* Clear 0x48..0x57 */ for (u8 r 0x48; r 0x57; r) { ret nvp6021_write(client, r, 0x00); if (ret) goto err; } /* Extra clears */ ret nvp6021_write(client, 0x59, 0x00); if (ret) goto err; ret nvp6021_write(client, 0x5A, 0x00); if (ret) goto err; for (u8 r 0x5C; r 0x5F; r) { ret nvp6021_write(client, r, 0x00); if (ret) goto err; } /* Mode-dependent BANK2 writes (0x3A, 0x01) */ switch (vmode) { case NVP6021_VMODE_1080P30: ret nvp6021_write(client, 0x3A, 0x11); if (ret) goto err; ret nvp6021_write(client, 0x01, 0xF0); break; case NVP6021_VMODE_1080P25: ret nvp6021_write(client, 0x3A, 0x11); if (ret) goto err; ret nvp6021_write(client, 0x01, 0xF1); break; case NVP6021_VMODE_720P60: ret nvp6021_write(client, 0x3A, 0x11); if (ret) goto err; ret nvp6021_write(client, 0x01, 0xE2); break; case NVP6021_VMODE_720P50: ret nvp6021_write(client, 0x3A, 0x11); if (ret) goto err; ret nvp6021_write(client, 0x01, 0xE3); break; } if (ret) goto err; /* Second BANK2 access – mode‑specific fine‑tuning */ ret nvp6021_write(client, 0xFF, 0x02); // ensure BANK2 if (ret) goto err; switch (vmode) { case NVP6021_VMODE_1080P30: ret nvp6021_write(client, 0x3D, 0x80); if (ret) goto err; ret nvp6021_write(client, 0x5C, 0x52); if (ret) goto err; ret nvp6021_write(client, 0x5D, 0xCA); if (ret) goto err; ret nvp6021_write(client, 0x5E, 0xF0); if (ret) goto err; ret nvp6021_write(client, 0x5F, 0x2C); if (ret) goto err; ret nvp6021_write(client, 0x1D, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x1E, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x37, 0xB0); break; case NVP6021_VMODE_1080P25: ret nvp6021_write(client, 0x3D, 0x80); if (ret) goto err; ret nvp6021_write(client, 0x5C, 0x52); if (ret) goto err; ret nvp6021_write(client, 0x5D, 0xC3); if (ret) goto err; ret nvp6021_write(client, 0x5E, 0x7D); if (ret) goto err; ret nvp6021_write(client, 0x5F, 0xC8); if (ret) goto err; ret nvp6021_write(client, 0x1D, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x1E, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x37, 0xB0); break; case NVP6021_VMODE_720P60: ret nvp6021_write(client, 0x3D, 0x80); if (ret) goto err; ret nvp6021_write(client, 0x5C, 0x52); if (ret) goto err; ret nvp6021_write(client, 0x5D, 0xC5); if (ret) goto err; ret nvp6021_write(client, 0x5E, 0xF9); if (ret) goto err; ret nvp6021_write(client, 0x5F, 0x2C); if (ret) goto err; ret nvp6021_write(client, 0x1D, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x1E, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x37, 0xB0); break; case NVP6021_VMODE_720P50: ret nvp6021_write(client, 0x3D, 0x80); if (ret) goto err; ret nvp6021_write(client, 0x5C, 0x52); if (ret) goto err; ret nvp6021_write(client, 0x5D, 0xCF); if (ret) goto err; ret nvp6021_write(client, 0x5E, 0xE7); if (ret) goto err; ret nvp6021_write(client, 0x5F, 0x2C); if (ret) goto err; ret nvp6021_write(client, 0x1D, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x1E, 0xB0); if (ret) goto err; ret nvp6021_write(client, 0x37, 0xB0); break; } if (ret) goto err; dev_info(client-dev, NVP6021 initialization completed successfully\n); //return 0; //ret nvp6021_write(client, 0xFF, 0x02); // 确保选择 BANK2 //if (ret) goto err; //ret nvp6021_write(client, 0x04, 0x81); // 0x04 的 bit7 置 1 使能彩条输出 //if (ret) goto err; dev_info(client-dev, NVP6021 initialization done (color bar test enabled)\n); return 0;err:dev_err(client-dev, “I2C write failed\n”);return ret;}/* Probe - called when device is found on I2C bus */static int nvp6021_probe(struct i2c_client *client,const struct i2c_device_id *id){struct device *dev client-dev;struct nvp6021_priv *priv;u32 vmode NVP6021_VMODE_1080P30;int ret;priv devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv-client client; i2c_set_clientdata(client, priv); /* Obtain reset GPIO (active high as in original) */ priv-reset_gpio devm_gpiod_get_optional(dev, reset, GPIOD_OUT_LOW); if (IS_ERR(priv-reset_gpio)) return dev_err_probe(dev, PTR_ERR(priv-reset_gpio), Failed to get reset GPIO\n); /* Read video mode from device tree property */ device_property_read_u32(dev, nextchip,vmode, vmode); if (vmode NVP6021_VMODE_720P50) { dev_warn(dev, Invalid vmode %u, fallback to 1080p30\n, vmode); vmode NVP6021_VMODE_1080P30; } priv-vmode (u8)vmode; /* Run initialization sequence */ ret nvp6021_initialize(priv); if (ret) return ret; dev_info(dev, NVP6021 driver probe successful\n); return 0;}static const struct of_device_id nvp6021_of_match[] {{ .compatible “nextchip,nvp6021” },{ }};MODULE_DEVICE_TABLE(of, nvp6021_of_match);static const struct i2c_device_id nvp6021_id[] {{ “nvp6021”, 0 },{ }};MODULE_DEVICE_TABLE(i2c, nvp6021_id);static struct i2c_driver nvp6021_driver {.driver {.name “nvp6021”,.of_match_table nvp6021_of_match,},.probe nvp6021_probe,.id_table nvp6021_id,};module_i2c_driver(nvp6021_driver);MODULE_DESCRIPTION(“Nextchip NVP6021 AHD TX initialization driver”);MODULE_AUTHOR(“lhx”);MODULE_LICENSE(“GPL”);复制代码使用i2c-tools功能查看寄存器是正常写入,驱动里面有三个bank的寄存器配置这里以切换到bank0为例子imageimage2.2 设备树配置复制代码#include dt-bindings/display/media-bus-format.h#include dt-bindings/display/rockchip_vop.h/{panel: panel {compatible “simple-panel”;clock-frequency 74250000;bus-format MEDIA_BUS_FMT_YUYV8_1X16;status “okay”;display-timings { native-mode timing_1080p30; timing_1080p30: timing { clock-frequency 74250000; // 74.25MHz时钟 hactive 1920; // 有效水平像素 vactive 1080; // 有效垂直行数 hfront-porch 88; // 水平前沿 hback-porch 148; // 水平后沿 hsync-len 44; // 水平同步脉冲 vfront-porch 4; // 垂直前沿 vback-porch 36; // 垂直后沿 vsync-len 5; // 垂直同步脉冲 hsync-active 1; // 高电平有效 vsync-active 1; // 高电平有效 de-active 0; // DE信号极性 pixelclk-active 0; // 像素时钟下降沿采样 }; timing_720p60: timing1 { clock-frequency 74250000; hactive 1280; vactive 720; hfront-porch 110; hback-porch 220; hsync-len 40; vfront-porch 5; vback-porch 20; vsync-len 5; hsync-active 1; vsync-active 1; de-active 0; pixelclk-active 0; }; }; port { panel_in_rgb: endpoint { remote-endpoint rgb_out_panel; }; }; };};display_subsystem {status “okay”;};i2c8 {clock-frequency 400000;pinctrl-0 i2c8m1_xfer;status “okay”;nvp6021: nvp602130 { pinctrl-names default; pinctrl-0 nvp6021_rst_pins; compatible nextchip,nvp6021; reg 0x30; reset-gpios gpio3 RK_PD4 GPIO_ACTIVE_HIGH; nextchip,vmode 2; // 0:1080p30, 1:1080p25, 2:720p60, 3:720p50 };};rgb {status “okay”;pinctrl-names “default”;pinctrl-0 bt1120_pins;ports { port1 { reg 1; rgb_out_panel: endpoint { remote-endpoint panel_in_rgb; }; }; };};rgb_in_vp2 {status “okay”;