RK3399 Android 7.1 新mipi副屏旋转

一、整体思路

手上的项目兼容了一款新mipi副屏,如果想了解,可以去看看

RK3399 Android 7.1 MIPI副屏兼容

兼容副屏后,已经能正常点亮,休眠唤醒也正常了,还剩一个问题:显示为竖屏,要改为横屏。

我参考了同事的做法,就是先在dev下创建一个设备文件/dev/dsi-panel-id,上层open该设备文件后通过ioctl方式访问kernel层,将kernel层的储存屏id的变量传递给上层。最后在上层判断屏id区别是新旧屏,如果是新屏,就旋转。

二、代码分析

1、kernel层

drivers/gpu/drm/panel/panel-simple.c

diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index db392b8..01dba51 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c

@@ -40,6 +40,9 @@
 #include <linux/of_graph.h>
 #include <video/videomode.h>
 
+static char panel_id;         //储存读取dts的panel id
+
+
 struct cmd_ctrl_hdr {
 	u8 dtype;	/* data type */
 	u8 wait;	/* ms */
@@ -2351,6 +2354,106 @@ static const struct of_device_id dsi_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, dsi_of_match);
 
+/*---------------------------liyj ---------------------------------------------------------------------------*/
+
+static struct class *dsi_panel_class = NULL;
+static struct device *dsi_panel_device = NULL;
+static struct miscdevice dsi_pane_id_device;
+#define NO_PANEL_ID 		0XFF
+#define DSI_PANEL_ID_MAGIC      0xFA
+#define DSI_PANEL_ID_GET        _IOR(DSI_PANEL_ID_MAGIC, 0x01, char)    //自定义一个ioctl命令,用于上层与kernel层的交互
+
//下面会有一个函数在sys文件系统下创建/sys/class/panel/dsi-panel节点,在控制台下使用cat id会回调id_show函数
+static ssize_t id_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+        return sprintf(buf, "%d",panel_id);
+}
+
+static DEVICE_ATTR_RO(id);

//在sys文件系统下创建/sys/class/panel/dsi-panel节点
+static int telpo_create_panel_sysfs_dir(void)
+{
+	printk("---liyj--- FILE : %s enter func : %s  LINE : %d\n",__FILE__,__func__,__LINE__);
+        dsi_panel_class = class_create(THIS_MODULE, "panel");
+        if (IS_ERR(dsi_panel_class))
+                return PTR_ERR(dsi_panel_class);
+
+        dsi_panel_device = device_create(dsi_panel_class, NULL, MKDEV(0, 0), NULL, "dsi-panel");
+        if (IS_ERR(dsi_panel_device)) {
+                class_destroy(dsi_panel_class);
+                return PTR_ERR(dsi_panel_device);
+        }
+
+        return device_create_file(dsi_panel_device, &dev_attr_id);
+}

+static int dsi_panel_id_dev_open(struct inode *inode, struct file *filp)
+{
+        return 0;
+}
+
+
//上层与kernel层交互的通道
+static long dsi_panel_id_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+        switch (cmd) {
+        case DSI_PANEL_ID_GET:
+		printk("***liyj***copy_to_user start\n");
+		if(copy_to_user((void * __user)arg,&panel_id,sizeof(panel_id)))
+		{
+			printk("***liyj***copy_to_user failed\n");
+		}
+	break;	
+        default:
+                printk("get dsi panel id err\n");
+                return -EINVAL;
+        }
+        return 0;
+}
+
+static const struct file_operations dsi_panel_id_dev_fops =
+{
+        .owner  = THIS_MODULE,
+        .llseek = no_llseek,
+        .open   = dsi_panel_id_dev_open,
+        .unlocked_ioctl = dsi_panel_id_dev_ioctl,
+        .compat_ioctl   = dsi_panel_id_dev_ioctl,
+};

//在dev下创建一个设备节点,用于上层跟kernel层的交互
+static int telpo_create_panel_misc_dev(void)
+{
+        int ret;
+
+	printk("---liyj--- FILE : %s enter func : %s  LINE : %d\n",__FILE__,__func__,__LINE__);
+        dsi_pane_id_device.minor = MISC_DYNAMIC_MINOR;
+        dsi_pane_id_device.name = "dsi-panel-id";
+        dsi_pane_id_device.fops = &dsi_panel_id_dev_fops;
+
+        ret = misc_register(&dsi_pane_id_device);
+        if (ret) {
+                pr_err("%s :dsi panel is misc register failed\n", __FILE__);
+                return -ENODEV;
+        }
+        return 0;
+}
+
+
+static char get_panel_id(struct device *dev)
+{
+	char g_panel_id ;
+	int len;
+	int ret;
+	struct device_node *np = dev->of_node;	
+	//g_panel_id = of_get_property(np,"id",&len);
+	of_property_read_u8(np,"id",&g_panel_id);       //读取dts中panel节点的id
+	printk("---liyj--- g_panel_id = %x\n",g_panel_id);
+	return g_panel_id;
+}

+/*---------------------------liyj ---------------------------------------------------------------------------*/
+
 static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
 {
 	struct panel_simple *panel;
@@ -2360,6 +2463,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
 	int err;
 	u32 val;
 
+
 	id = of_match_node(dsi_of_match, dsi->dev.of_node);
 	if (!id)
 		return -ENODEV;
@@ -2390,6 +2494,14 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
 
 	if (!of_property_read_u32(dsi->dev.of_node, "dsi,lanes", &val))
 		dsi->lanes = val;
+//liyj add start
+	panel_id = get_panel_id(&dsi->dev);
+	if (panel_id != NO_PANEL_ID) {
+		telpo_create_panel_sysfs_dir();
+		telpo_create_panel_misc_dev();
+        }
+
+//liyj add end
 
 	return mipi_dsi_attach(dsi);
 }

dts中新屏节点的配置

&dsi {
        status = "okay";
        rockchip,lane-rate = <528>;
        enable-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
        panel@0 {
                compatible = "simple-panel-dsi";
                reg = <0>;
        ............
        ............

         num = <0>;
                id = [93];     //新屏的id
                id-reg = <0xda>;   //要读取的id寄存器

        ............
        ............
        }


............
}

2、上层

system/core/drmservice/drmservice.c

diff --git a/system/core/drmservice/drmservice.c b/system/core/drmservice/drmservice.c
index 4640716..61cd86d 100755
--- a/system/core/drmservice/drmservice.c
+++ b/system/core/drmservice/drmservice.c
@@ -1074,6 +1074,59 @@ void copy_dir(const char *old_path,const char *new_path)
 }
 
 
+#define DSI_PANEL_ID_MAGIC 0xFA
+#define DSI_PANEL_ID_GET   _IOR(DSI_PANEL_ID_MAGIC, 0x01,char)
+#define DSI_PANEL_ID_DEV_PATH "/dev/dsi-panel-id"
+#define NO_PANEL_ID 0xff
+#define PANEL_OLD   0    //old panel   
+#define PANEL_NEW   147	//new panel  新屏id,我的新屏id是0x93,十进制就是147  
+static void get_dsi_panel_id(void)
+{
+    int fd = -1;
+    char id = NO_PANEL_ID;
+    int ret;	
+    char model_value[PROPERTY_VALUE_MAX] = {0};
+    property_get("ro.internal.model", model_value, "");
+
+    fd = open(DSI_PANEL_ID_DEV_PATH, O_RDONLY);     //1、打开设备文件
+    if (fd > 0) {
+	SLOGE("---liyj--- fd > 0");
+        ret = ioctl(fd, DSI_PANEL_ID_GET, &id);    //2、通过自定义的cmd跟kernel交互,获取panel id
+	if(ret <0)
+	{
+		SLOGE("---liyj--- ioctl failed\n");
+	}	
+	SLOGE("---liyj--- id = %d\n",id);
+        close(fd);
+    }
+    if (id == NO_PANEL_ID)
+        return;
+
+    if (!(strcmp(model_value, "TPS680C"))) {
+        ALOGE("set TPS680C panel");
+        switch (id) {
+            case PANEL_OLD:
+                ALOGE("set panel as PANEL_OLD");
+                property_set("persist.sys.rotation.efull-1", "true");
+                property_set("persist.sys.rotation.einit", "0");
+                break;
+            case PANEL_NEW:      //新屏
+                ALOGE("set panel as PANEL_NEW");
+                property_set("persist.sys.rotation.efull-1", "false");
+                property_set("persist.sys.rotation.einit", "3");   //旋转270度
+                break;
+            default:
+                SLOGD("not support panel id, set PANEL_NEW as default");
+                property_set("persist.sys.rotation.efull-1", "false");
+                property_set("persist.sys.rotation.einit", "3");
+                break;
+        }
+    } else {
+        ALOGE("no model panel set");
+    }
+}
+

/** * Program entry pointer */
@@ -1091,6 +1144,8 @@ int main( int argc, char *argv[] )
 	SLOGE("get prop_board_platform,prop_board_platform = %s , diff=%d",prop_board_platform,
 		strcmp(prop_board_platform,"rk3399"));
 
+	get_dsi_panel_id();     //函数调用,获取panel id
+
     //get hid data
     rknand_sys_storage_test_hid();
     SLOGE("Get HID data:%s", hid_buf_idb);

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值