如何通过cmdline获取panel型号的dtsi文件节点(qcom,lcd,id)

来源:互联网 发布:java api中文文档 编辑:程序博客网 时间:2024/05/22 01:49

FROM:http://www.bkjia.com/HTML5/1206391.html

如何通过cmdline获取panel型号的dtsi文件节点(qcom,lcd,id)


platform:msm8976 android 7.11
1. 在lk层,常用的方法是通过读取panel的id来确定当前使用的panel的型号,然后将panel的型号放在cmdline里面,如下:
project:/ # cat /proc/cmdline
... ... ... androidconfig.secureboot=enabled mdss_mdp.panel=1:dsi:0:qcom,mdss_dsi_ili9885_lide_hcg_auo_fhd_video:1:none:cfg:single_dsi ... ... ...
2. 在kernel层,通过cmdline寻找panel的dtsi文件节点并得到属性,这个过程是在mdss_dsi_config_panel函数进行的,如下:
(x:\work\project\kernel\drivers\video\msm\mdss\Mdss_dsi.c)mdss_dsi_ctrl_probe-->mdss_dsi_config_panel
  1. static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev)
  2. {
  3. struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev);
  4. char panel_cfg[MDSS_MAX_PANEL_LEN];
  5. struct device_node *dsi_pan_node = NULL;
  6. int rc = 0;
  7. if (!ctrl_pdata) {
  8. pr_err("%s: Unable to get the ctrl_pdata\n", __func__);
  9. return NULL;
  10. }
  11. /* DSI panels can be different between controllers */
  12. rc = mdss_dsi_get_panel_cfg(panel_cfg, ctrl_pdata);
  13. if (!rc)
  14. /* dsi panel cfg not present */
  15. pr_warn("%s:%d:dsi specific cfg not present\n",
  16. __func__, __LINE__);
  17. /* find panel device node */
  18. dsi_pan_node = mdss_dsi_find_panel_of_node(pdev, panel_cfg);
  19. if (!dsi_pan_node) {
  20. pr_err("%s: can't find panel node %s\n", __func__, panel_cfg);
  21. of_node_put(dsi_pan_node);
  22. return NULL;
  23. }
  24. rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata);
  25. if (rc) {
  26. pr_err("%s: dsi panel init failed\n", __func__);
  27. of_node_put(dsi_pan_node);
  28. return NULL;
  29. }
  30. return dsi_pan_node;
  31. }
3. mdss_dsi_config_panel函数主要是由三个部分组成:
3.1. 解析lk层传给kernel层cmdline的mdss_mdp.panel属性,在mdss_dsi_get_panel_cfg函数进行,
3.2. 根据cmdline的mdss_mdp.panel属性寻找panel的dtsi文件节点,在mdss_dsi_find_panel_of_node函数进行
3.3. 解析panel dtsi文件节点中的属性并配置panel的操作集,在mdss_dsi_panel_init函数进行
4. 下面我们依次来说明这三个部分,首先是mdss_dsi_get_panel_cfg函数
vim x:\work\project\kernel\drivers\video\msm\mdss\Mdss_dsi.c
  1. static int mdss_dsi_get_panel_cfg(char *panel_cfg,
  2. struct mdss_dsi_ctrl_pdata *ctrl)
  3. {
  4. int rc;
  5. struct mdss_panel_cfg *pan_cfg = NULL;
  6. if (!panel_cfg)
  7. return MDSS_PANEL_INTF_INVALID;
  8. pan_cfg = ctrl->mdss_util->panel_intf_type(MDSS_PANEL_INTF_DSI);
  9. if (IS_ERR(pan_cfg)) {
  10. return PTR_ERR(pan_cfg);
  11. } else if (!pan_cfg) {
  12. panel_cfg[0] = 0;
  13. return 0;
  14. }
  15. pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
  16. pan_cfg->arg_cfg);
  17. rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
  18. sizeof(pan_cfg->arg_cfg));
  19. return rc;
  20. }
通过日志,我们看到panel_cfg的字符串内容(0:qcom,mdss_dsi_ili9885_lide_hcg_auo_fhd_video:1:none:cfg:single_dsi),如下:
[ 1.045387] mdss_dsi_get_panel_cfg:629: cfg:[0:qcom,mdss_dsi_ili9885_lide_hcg_auo_fhd_video:1:none:cfg:single_dsi]
//0表示dsi0,说明panel_cfg的字符串内容包含panel的型号名称和panel所属的dsi number
5. 接下来我们来看看mdss_dsi_find_panel_of_node函数
vim x:\work\project\kernel\drivers\video\msm\mdss\Mdss_dsi.c
  1. static struct device_node *mdss_dsi_find_panel_of_node(
  2. struct platform_device *pdev, char *panel_cfg)
  3. {
  4. int len, i;
  5. int ctrl_id = pdev->id - 1;
  6. char panel_name[MDSS_MAX_PANEL_LEN];
  7. char ctrl_id_stream[3] = "0:";
  8. char *stream = NULL, *pan = NULL;
  9. struct device_node *dsi_pan_node = NULL, *mdss_node = NULL;
  10. len = strlen(panel_cfg);
  11. if (!len) {
  12. /* no panel cfg chg, parse dt */
  13. pr_debug("%s:%d: no cmd line cfg present\n",
  14. __func__, __LINE__);
  15. goto end;
  16. } else {
  17. if (ctrl_id == 1)
  18. strlcpy(ctrl_id_stream, "1:", 3);
  19. stream = strnstr(panel_cfg, ctrl_id_stream, len);
  20. if (!stream) {
  21. pr_err("controller config is not present\n");
  22. goto end;
  23. }
  24. stream += 2;
  25. pan = strnchr(stream, strlen(stream), ':');
  26. if (!pan) {
  27. strlcpy(panel_name, stream, MDSS_MAX_PANEL_LEN); //根据panel_cfg的字符串的内容,得到panel的型号名称是qcom,mdss_dsi_ili9885_lide_hcg_auo_fhd_video
  28. } else {
  29. for (i = 0; (stream + i) < pan; i++)
  30. panel_name[i] = *(stream + i);
  31. panel_name[i] = 0;
  32. }
  33. pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
  34. panel_cfg, panel_name);
  35. //日志如下:[ 1.045392] mdss_dsi_find_panel_of_node:2355:0:qcom,mdss_dsi_ili9885_lide_hcg_auo_fhd_video:1:none:cfg:single_dsi:qcom,mdss_dsi_ili9885_lide_hcg_auo_fhd_video
  36. mdss_node = of_parse_phandle(pdev->dev.of_node, //得到mdss_mdp节点,因为所有的panel型号都是挂在mdss_mdp节点下面,mdss_mdp节点的compatible = "qcom,mdss_mdp";
  37. "qcom,mdss-mdp", 0);
  38. if (!mdss_node) {
  39. pr_err("%s: %d: mdss_node null\n",
  40. __func__, __LINE__);
  41. return NULL;
  42. }
  43. dsi_pan_node = of_find_node_by_name(mdss_node, //根据panel的型号名称找到panel型号的dtsi文件节点
  44. panel_name);
  45. if (!dsi_pan_node) {
  46. pr_err("%s: invalid pan node, selecting prim panel\n",
  47. __func__);
  48. goto end;
  49. }
  50. return dsi_pan_node; //返回panel型号的dtsi文件节点
  51. }
  52. end:
  53. if (strcmp(panel_name, NONE_PANEL))
  54. dsi_pan_node = mdss_dsi_pref_prim_panel(pdev);
  55. return dsi_pan_node;
  56. }
6. 接下来我们来看看mdss_dsi_panel_init函数
vim x:\work\xxx\kernel\drivers\video\msm\mdss\Mdss_dsi_panel.c
  1. int mdss_dsi_panel_init(struct device_node *node,
  2. struct mdss_dsi_ctrl_pdata *ctrl_pdata)
  3. {
  4. int rc = 0;
  5. static const char *panel_name;
  6. struct mdss_panel_info *pinfo;
  7. if (!node || !ctrl_pdata) {
  8. pr_err("%s: Invalid arguments\n", __func__);
  9. return -ENODEV;
  10. }
  11. pinfo = &ctrl_pdata->panel_data.panel_info;
  12. pr_debug("%s:%d\n", __func__, __LINE__);
  13. pinfo->panel_name[0] = '\0';
  14. panel_name = of_get_property(node, "qcom,mdss-dsi-panel-name", NULL); //得到panel节点的qcom,mdss-dsi-panel-name属性
  15. if (!panel_name) {
  16. pr_info("%s:%d, Panel name not specified\n",
  17. __func__, __LINE__);
  18. } else {
  19. pr_info("%s: Panel Name = %s\n", __func__, panel_name);
  20. strlcpy(&pinfo->panel_name[0], panel_name, MDSS_MAX_PANEL_LEN);
  21. }
  22. rc = mdss_panel_parse_dt(node, ctrl_pdata); //解析panel节点下面其他的属性
  23. if (rc) {
  24. pr_err("%s:%d panel dt parse failed\n", __func__, __LINE__);
  25. return rc;
  26. }
  27. mdss_dsi_set_prim_panel(ctrl_pdata);
  28. pinfo->dynamic_switch_pending = false;
  29. pinfo->is_lpm_mode = false;
  30. pinfo->esd_rdy = false;
  31. ctrl_pdata->on = mdss_dsi_panel_on; //以下都是panel的操作集,唤醒屏幕的操作
  32. ctrl_pdata->post_panel_on = mdss_dsi_post_panel_on; //唤醒屏幕的延迟操作
  33. ctrl_pdata->off = mdss_dsi_panel_off; //休眠屏幕的操作
  34. ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config; //针对屏的低功耗配置
  35. ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl; //设置panel的背光操作函数
  36. ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode; //panel mode的切换,如:video2command,command2video
  37. return 0;
  38. }

原创粉丝点击