一、前提:
1. rk3399核心板
2.linux4.4.19 源码
3. 多个MIPI显示屏的启动序列以及显示时序(重要)
4.rk3399MIPI通道0
5.接上一个uboot中的修改配置
二、内核驱动的修改
0. dts就不再给出了,请参考uboot的修改
1. 主要涉及的源码drivers/gpu/drm/panel/panel-simple.c
1.1 struct panel_simple 结构体中增加一项lcd_type的定义,用于多个函数中使用
lcd_type数据的获取:
//接收uboot的参数 2022-12-02 zz
static char *m_uboot_lcd_type_argument = "-1"; //用于xx屏幕显示
static int __init ubootadd_lcd_type_setup(char *s)
{
m_uboot_lcd_type_argument = s;
return 1;
}
__setup("lcd_type=", ubootadd_lcd_type_setup);
/********************************************************/
解析出屏的类型
1.2 mipi屏初始化序列部分的修改
我觉得(个人猜测)初始化序列在内核部分可以省略,因为uboot已经初始化了,好像没有再次初始化的必要了。但是代码我还是留着了。
static int panel_simple_get_cmds(struct panel_simple *panel)
{
const void *data = NULL;
int len;
int err;
int lcd_type = panel->lcd_type;printk("2022-12-07 debug: lcd_type = %d\n",lcd_type); //1 表示7inch,0表示5inch
if(lcd_type >= 0) //jc_7inch
{
if(lcd_type == 2) //2022-12-09 第二块5寸屏
data = of_get_property(panel->dev->of_node, "panel-init-sequence-5inch-2",
&len);
else
data = of_get_property(panel->dev->of_node, lcd_type?"panel-init-sequence-7inch":"panel-init-sequence-5inch",
&len);
// printk("2022-12-05debug: panel-init-sequence-7\n");
}
// else //jc_5inch
// {
// data = of_get_property(panel->dev->of_node, "panel-init-sequence-5inch",
// &len);
// printk("2022-12-05debug: panel-init-sequence-5\n");
// }else //其他选择, 112板其实不用读
{
data = of_get_property(panel->dev->of_node, "panel-init-sequence",
&len);
printk("2022-12-05debug: panel-init-sequence\n");
}
if (data) {
// printk("2022-12-05debug: data not NULL\n");
panel->on_cmds = devm_kzalloc(panel->dev,
sizeof(*panel->on_cmds),
GFP_KERNEL);
if (!panel->on_cmds)
return -ENOMEM;err = panel_simple_parse_cmds(panel->dev, data, len,
panel->on_cmds);
if (err) {
dev_err(panel->dev, "failed to parse panel init sequence\n");
return err;
}
}data = of_get_property(panel->dev->of_node, "panel-exit-sequence",
&len);
if (data) {
panel->off_cmds = devm_kzalloc(panel->dev,
sizeof(*panel->off_cmds),
GFP_KERNEL);
if (!panel->off_cmds)
return -ENOMEM;err = panel_simple_parse_cmds(panel->dev, data, len,
panel->off_cmds);
if (err) {
dev_err(panel->dev, "failed to parse panel exit sequence\n");
return err;
}
}
return 0;
}
1.3 时序配置部分
static int panel_simple_of_get_native_mode(struct panel_simple *panel)
{
struct drm_connector *connector = panel->base.connector;
struct drm_device *drm = panel->base.drm;
struct drm_display_mode *mode;
struct device_node *timings_np;
int ret;
timings_np = of_get_child_by_name(panel->dev->of_node,
"display-timings");
if (!timings_np) {
dev_dbg(panel->dev, "failed to find display-timings node\n");
return 0;
}
of_node_put(timings_np);
mode = drm_mode_create(drm);
if (!mode)
return 0;
//timing - 2022-12-08 by dazhi
//panel->lcd_type 0-->old5inch,1-->7inch,2-->new5inch,-1 表示xx板,选择时序3
ret = of_get_drm_display_mode(panel->dev->of_node, mode,
panel->lcd_type>=0?panel->lcd_type:3);//OF_USE_NATIVE_MODE);
if (ret) {
dev_dbg(panel->dev, "failed to find dts display timings\n");
drm_mode_destroy(drm, mode);
return 0;
}
drm_mode_set_name(mode);
mode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
return 1;
}
修改完毕,正常可用了。