高通平台msm8953 display子系统学习

硬件上,高通平台有一个mipi-dsi接口连接LCM,由MDP(mobile display processor)进行管理,就是一般说的LCD控制器

软件上,高通平台提供MDSS(Multimedia Display Sub-system)进行管理

软件驱动目录:kernel/msm-4.9/drivers/video/fbdev/msm
主要分为三部分:
MDP驱动:对使用的硬件资源进行初始化,同时在fb设备中注册mdp的使用接口,文件mdss_mdp3.c

DSI驱动:解析模组厂商提供的panel的dtsi文件,从哪个文件中能够获取到panel的mode,分辨率,还有Driver IC的初始化command;文件mdss_dsi_panel.c

FB驱动:实现Linux Framebuffer的注册和为上层用户提供访问控制接口;文件mdss_fb.c

一般的执行顺序是: MDP probe → DSI probe → FB probe

下面分析每部分的代码
LCD控制器、I2C控制器等一般都是平台设备,设备用platform_device表示,驱动用platform_driver表示。

MDP设备在dts文件中定义:

msm8953-mdss.dtsi
&soc {
   
   
	mdss_mdp: qcom,mdss_mdp@1a00000 {
   
   
		compatible = "qcom,mdss_mdp";
		reg = <0x01a00000 0x90000>,
		      <0x01ab0000 0x1040>;
		reg-names = "mdp_phys", "vbif_phys";
		interrupts = <0 72 0>;
		vdd-supply = <&gdsc_mdss>;

		/* Bus Scale Settings */
		qcom,msm-bus,name = "mdss_mdp";
		qcom,msm-bus,num-cases = <3>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
			<22 512 0 0>,
			<22 512 0 6400000>,
			<22 512 0 6400000>;

		/* Fudge factors */
		qcom,mdss-ab-factor = <1 1>;		/* 1 time  */
		qcom,mdss-ib-factor = <1 1>;		/* 1 time  */
		qcom,mdss-clk-factor = <105 100>;	/* 1.05 times */

		qcom,max-mixer-width = <2048>;
		qcom,max-pipe-width = <2048>;

MDP驱动的注册:

static const struct of_device_id mdss_mdp_dt_match[] = {
   
   
	{
   
    .compatible = "qcom,mdss_mdp",},
	{
   
   }
};
MODULE_DEVICE_TABLE(of, mdss_mdp_dt_match);

static struct platform_driver mdss_mdp_driver = {
   
   
	.probe = mdss_mdp_probe,
	.remove = mdss_mdp_remove,
	.suspend = mdss_mdp_suspend,
	.resume = mdss_mdp_resume,
	.shutdown = NULL,
	.driver = {
   
   
		/*
		 * Driver name must match the device name added in
		 * platform.c.
		 */
		.name = "mdp",
		.of_match_table = mdss_mdp_dt_match,
		.pm = &mdss_mdp_pm_ops,
	},
};

static int mdss_mdp_register_driver(void)
{
   
   
	return platform_driver_register(&mdss_mdp_driver);
}

static int __init mdss_mdp_driver_init(void)
{
   
   
	int ret;

	ret = mdss_mdp_register_driver();
	if (ret) {
   
   
		pr_err("mdp_register_driver() failed!\n");
		return ret;
	}

	return 0;

}

老套路,设备和驱动匹配之后,调用mdss_mdp_probe函数,这个函数首先分配mdss_data_type结构体内存,然后对成员进行初始化:

static int mdss_mdp_probe(struct platform_device *pdev)
{
   
   
	struct resource *res;
	int rc;
	struct mdss_data_type *mdata;
	uint32_t intf_sel = 0;
	uint32_t split_display = 0;
	int num_of_display_on = 0;
	int i = 0;

	if (!pdev->dev.of_node) {
   
   
		pr_err("MDP driver only supports device tree probe\n");
		return -ENOTSUPP;
	}

	if (mdss_res) {
   
   
		pr_err("MDP already initialized\n");
		return -EINVAL;
	}

	mdata = devm_kzalloc(&pdev->dev, sizeof(*mdata), GFP_KERNEL);
	if (mdata == NULL)
		return -ENOMEM;

	pdev->id = 0;
	mdata->pdev = pdev;
	platform_set_drvdata(pdev, mdata);
	mdss_res = mdata;
	mutex_init(&mdata->reg_lock);
	mutex_init(&mdata->reg_bus_lock);
	mutex_init(&mdata->bus_lock);
	INIT_LIST_HEAD(&mdata->reg_bus_clist);
	atomic_set(&mdata->sd_client_count, 0);
	atomic_set(&mdata->active_intf_cnt, 0);

	mdss_res->mdss_util = mdss_get_util_intf();
	if (mdss_res->mdss_util == NULL) {
   
   
		pr_err("Failed to get mdss utility functions\n");
		return -ENODEV;
	}

	mdss_res->mdss_util->get_iommu_domain = mdss_smmu_get_domain_id;
	mdss_res->mdss_util->iommu_attached = is_mdss_iommu_attached;
	mdss_res->mdss_util->iommu_ctrl = mdss_iommu_ctrl;
	mdss_res->mdss_util->bus_scale_set_quota = mdss_bus_scale_set_quota;
	mdss_res->mdss_util->bus_bandwidth_ctrl = mdss_bus_bandwidth_ctrl;
	mdss_res->mdss_util->panel_intf_type = mdss_panel_intf_type;
	mdss_res->mdss_util->panel_intf_status = mdss_panel_get_intf_status;

	rc = msm_mdss_ioremap_byname(pdev, &mdata->mdss_io, "mdp_phys");
	if (rc) {
   
   
		pr_err("unable to map MDP base\n");
		goto probe_done;
	}
	pr_debug("MDSS HW Base addr=0x%x len=0x%x\n",
		(int) (unsigned long) mdata->mdss_io.base,
		mdata->mdss_io.len);

	rc = msm_mdss_ioremap_byname(pdev, &mdata->vbif_io, "vbif_phys");
	if (rc) {
   
   
		pr_err("unable to map MDSS VBIF base\n");
		goto probe_done;
	}
	pr_debug("MDSS VBIF HW Base addr=0x%x len=0x%x\n",
		(int) (unsigned long) mdata->vbif_io.base,
		mdata->vbif_io.len);

	rc = msm_mdss_ioremap_byname(pdev, &mdata->vbif_nrt_io,
				     "vbif_nrt_phys");
	if (rc)
		pr_debug("unable to map MDSS VBIF non-realtime base\n");
	else
		pr_debug("MDSS VBIF NRT HW Base addr=%pK len=0x%x\n",
			mdata->vbif_nrt_io.base, mdata->vbif_nrt_io.len);

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
   
   
		pr_err("unable to get MDSS irq\n");
		rc = -ENOMEM;
		goto probe_done;
	}

	mdss_mdp_hw.irq_info = kcalloc(1, sizeof(struct irq_info), GFP_KERNEL);
	if (!mdss_mdp_hw.irq_info)
		return -ENOMEM;

	mdss_mdp_hw.irq_info->irq = res->start;
	mdss_mdp_hw.ptr = mdata;

	/* export misc. interrupts to external driver */
	mdata->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 32,
			&mdss_irq_domain_ops, mdata);
	if (!mdata->irq_domain) {
   
   
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值