Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d004edef authored by Shiju Mathew's avatar Shiju Mathew
Browse files

msm: ba: Add DT support for BA driver



Move BA platform specific data into DT and minor cleanups.

CRs-Fixed: 998927
Change-Id: Ib68a7b16986b92a46a98beab0c35591274c334ba
Signed-off-by: default avatarShiju Mathew <shijum@codeaurora.org>
parent bc936131
Loading
Loading
Loading
Loading
+32 −8
Original line number Diff line number Diff line
* Qualcomm Technologies Inc MSM BA

[Root level node]
=====
==================
Required properties:
- compatible: Must be "qcom,msm-ba".
- status :				A string that has to be set to "okay/ok" to enable
						the driver. By default this property will be set to
						"disable". Will be set to "ok/okay" status for
						specific platforms.

[Subnode]
==========
- qcom,ba-input-profile-#: Defines child nodes for the profiles supported
              by BA driver. Each profile should have properties "qcom,type",
              "qcom,name", "qcom,ba-input", "qcom,ba-output", "qcom,sd-name",
              "qcom,ba-node" and "qcom,user-type".
Required properties:
- qcom,type: Input type such as CVBS(0), HDMI(4) etc as defined in BA driver.
             This property is of type u32.
- qcom,name: Name of the input type. This property is of type string.
- qcom,ba-input: BA input id supported by a bridge chip for this profile.
             This property is of type u32.
- qcom,ba-output: BA output id for the profile. This property is of type u32.
- qcom,sd-name: Name of the sub-device driver associated with this profile.
              This property is of type string.
- qcom,ba-node: Defines the ba node id. This is the avdevice node used by camera
                for this profile. This property is of type u32.
- qcom,user-type: This property defines how the profile is being used. If this
             profile is used by kernel it is set to 0 and if used by userspace
             it is set to 1. This property is of type u32.
Example:

	qcom,ba {
	qcom,msm-ba {
		compatible = "qcom,msm-ba";
		status = "disable";
		qcom,ba-input-profile-0 {
			qcom,type = <4>;          /* input type   */
			qcom,name = "HDMI-1";     /* input name   */
			qcom,ba-input = <13>;     /* ba input id  */
			qcom,ba-output = <0>;     /* ba output id */
			qcom,sd-name = "adv7481"; /* sd name      */
			qcom,ba-node = <0>;       /* ba node      */
			qcom,user-type = <1>;     /* user type    */
		};
	};
+3 −3
Original line number Diff line number Diff line
@@ -146,8 +146,8 @@ int msm_ba_enum_input(void *instance, struct v4l2_input *input)
		input->type = V4L2_INPUT_TYPE_CAMERA;
		input->std = V4L2_STD_ALL;
		strlcpy(input->name, ba_input->name, sizeof(input->name));
		if (BA_INPUT_HDMI == ba_input->inputType ||
			BA_INPUT_MHL == ba_input->inputType)
		if (BA_INPUT_HDMI == ba_input->input_type ||
			BA_INPUT_MHL == ba_input->input_type)
			input->capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS;
		else
			input->capabilities = V4L2_IN_CAP_STD;
@@ -382,7 +382,7 @@ int msm_ba_g_fmt(void *instance, struct v4l2_format *f)
				inst->sd_input.index);
		return -EINVAL;
	}
	if (BA_INPUT_HDMI != ba_input->inputType) {
	if (BA_INPUT_HDMI != ba_input->input_type) {
		rc = v4l2_subdev_call(sd, video, querystd, &new_std);
		if (rc) {
			dprintk(BA_ERR, "querystd failed %d for sd: %s",
+4 −22
Original line number Diff line number Diff line
@@ -19,25 +19,6 @@
#include "msm_ba_debug.h"
#include "msm_ba_common.h"

struct msm_ba_input_config msm_ba_inp_cfg[] = {
	/* type, index, name, adv inp, dev id, sd name, dev node,
	   input user type
	*/
	{BA_INPUT_CVBS, 0, "CVBS-0", BA_IP_CVBS_0, 0, "adv7180", -1,
		BA_INPUT_USERTYPE_KERNEL},
#ifdef CONFIG_MSM_S_PLATFORM
	{BA_INPUT_CVBS, 1, "CVBS-1", BA_IP_CVBS_0, 0, "adv7180", 0,
		BA_INPUT_USERTYPE_USER},
#else
	{BA_INPUT_CVBS, 1, "CVBS-1", BA_IP_CVBS_0, 1, "adv7180", 0,
		BA_INPUT_USERTYPE_USER},
	{BA_INPUT_CVBS, 2, "CVBS-2", BA_IP_CVBS_1, 1, "adv7180", 0,
		BA_INPUT_USERTYPE_USER},
#endif
	{BA_INPUT_HDMI, 1, "HDMI-1", BA_IP_HDMI_1, 2, "adv7481", 2,
		BA_INPUT_USERTYPE_USER},
};

static struct msm_ba_ctrl msm_ba_ctrls[] = {
	{
		.id = MSM_BA_PRIV_SD_NODE_ADDR,
@@ -201,6 +182,7 @@ void msm_ba_add_inputs(struct v4l2_subdev *sd)
{
	struct msm_ba_input *input = NULL;
	struct msm_ba_dev *dev_ctxt = NULL;
	struct msm_ba_input_config *msm_ba_inp_cfg = NULL;
	int i;
	int str_length = 0;
	int rc;
@@ -213,8 +195,9 @@ void msm_ba_add_inputs(struct v4l2_subdev *sd)
	if (!list_empty(&dev_ctxt->inputs))
		start_index = dev_ctxt->num_inputs;

	msm_ba_inp_cfg = dev_ctxt->msm_ba_inp_cfg;
	dev_id = msm_ba_inp_cfg[start_index].ba_out;
	end_index = sizeof(msm_ba_inp_cfg)/sizeof(msm_ba_inp_cfg[0]);
	end_index = dev_ctxt->num_config_inputs;
	for (i = start_index; i < end_index; i++) {
		str_length = strlen(msm_ba_inp_cfg[i].sd_name);
		rc = memcmp(sd->name, msm_ba_inp_cfg[i].sd_name, str_length);
@@ -225,8 +208,7 @@ void msm_ba_add_inputs(struct v4l2_subdev *sd)
				dprintk(BA_ERR, "Failed to allocate memory");
				break;
			}
			input->inputType = msm_ba_inp_cfg[i].inputType;
			input->name_index = msm_ba_inp_cfg[i].index;
			input->input_type = msm_ba_inp_cfg[i].input_type;
			strlcpy(input->name, msm_ba_inp_cfg[i].name,
				sizeof(input->name));
			input->bridge_chip_ip = msm_ba_inp_cfg[i].ba_ip;
+6 −7
Original line number Diff line number Diff line
@@ -67,11 +67,8 @@ enum instance_state {
};

struct ba_ctxt {

	struct mutex ba_cs;

	struct msm_ba_dev *dev_ctxt;

	struct dentry *debugfs_root;
};

@@ -119,8 +116,7 @@ enum msm_ba_input_usr_type {
};

struct msm_ba_input_config {
	enum msm_ba_ip_type inputType;
	unsigned int index;
	enum msm_ba_ip_type input_type;
	const char *name;
	int ba_ip;
	int ba_out;
@@ -136,7 +132,7 @@ struct msm_ba_sd_event {

struct msm_ba_input {
	struct list_head list;
	enum msm_ba_ip_type inputType;
	enum msm_ba_ip_type input_type;
	unsigned int name_index;
	char name[32];
	int bridge_chip_ip;
@@ -154,7 +150,6 @@ struct msm_ba_input {
struct msm_ba_dev {
	struct mutex dev_cs;

	struct platform_device *pdev;
	enum ba_dev_state state;

	struct list_head inputs;
@@ -172,6 +167,10 @@ struct msm_ba_dev {
	struct list_head sd_events;
	struct delayed_work sd_events_work;

	/* BA input config list */
	struct msm_ba_input_config *msm_ba_inp_cfg;
	uint32_t num_config_inputs;

	struct dentry *debugfs_root;
};

+115 −50
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/io.h>
@@ -290,10 +290,89 @@ static const struct v4l2_file_operations msm_ba_v4l2_ba_fops = {
	.poll = msm_ba_v4l2_poll,
};

static const struct of_device_id msm_ba_dt_match[] = {
	{.compatible = "qcom,msm-ba"},
	{}
};
static int parse_ba_dt(struct platform_device *pdev)
{
	uint32_t profile_count = 0;
	struct device_node *np = pdev->dev.of_node;
	struct device_node *child_np = NULL;
	struct msm_ba_dev *dev_ctxt = NULL;
	struct ba_ctxt *ba_ctxt = msm_ba_get_ba_context();
	char *key = NULL;
	uint32_t err = 0;

	dev_ctxt = ba_ctxt->dev_ctxt;

	profile_count = of_get_child_count(np);
	if (profile_count == 0) {
		dprintk(BA_ERR, "%s: Error reading DT. node=%s",
			__func__, np->full_name);
		return -ENODEV;
	}

	dev_ctxt->msm_ba_inp_cfg = devm_kzalloc(&pdev->dev,
			sizeof(struct msm_ba_input_config) * profile_count,
			GFP_KERNEL);
	if (!dev_ctxt->msm_ba_inp_cfg)
		return -ENOMEM;

	for_each_child_of_node(np, child_np) {
		key = "qcom,type";
		err = of_property_read_u32(child_np, key,
			&dev_ctxt->msm_ba_inp_cfg->input_type);
		if (err)
			goto read_fail;

		key = "qcom,name";
		err = of_property_read_string(child_np, key,
			&dev_ctxt->msm_ba_inp_cfg->name);
		if (err)
			goto read_fail;

		key = "qcom,ba-input";
		err = of_property_read_u32(child_np, key,
			&dev_ctxt->msm_ba_inp_cfg->ba_ip);
		if (err)
			goto read_fail;

		key = "qcom,ba-output";
		err = of_property_read_u32(child_np, key,
			&dev_ctxt->msm_ba_inp_cfg->ba_out);
		if (err)
			goto read_fail;

		key = "qcom,sd-name";
		err = of_property_read_string(child_np, key,
			&dev_ctxt->msm_ba_inp_cfg->sd_name);
		if (err)
			goto read_fail;

		key = "qcom,ba-node";
		err = of_property_read_u32(child_np, key,
			&dev_ctxt->msm_ba_inp_cfg->ba_node);
		if (err)
			goto read_fail;


		key = "qcom,user-type";
		err = of_property_read_u32(child_np, key,
			&dev_ctxt->msm_ba_inp_cfg->input_user_type);
		if (err)
			goto read_fail;

		dev_ctxt->num_config_inputs++;
	}

read_fail:
	if (err) {
		dprintk(BA_INFO, "%s: Error reading DT. node=%s key=%s",
			__func__, np->full_name, key);
		devm_kfree(&pdev->dev, dev_ctxt->msm_ba_inp_cfg);

		dev_ctxt->num_config_inputs = 0;
	}

	return err;
}

static int msm_ba_device_init(struct platform_device *pdev,
					struct msm_ba_dev **ret_dev_ctxt)
@@ -312,18 +391,12 @@ static int msm_ba_device_init(struct platform_device *pdev,
		return -EINVAL;
	}

	dev_ctxt = kzalloc(sizeof(struct msm_ba_dev), GFP_KERNEL);
	dev_ctxt = devm_kzalloc(&pdev->dev, sizeof(struct msm_ba_dev),
			GFP_KERNEL);
	if (NULL == dev_ctxt)
		return -ENOMEM;

	dev_set_drvdata(&pdev->dev, dev_ctxt);
	dev_ctxt->pdev = pdev;
	if (!pdev->dev.of_node) {
		dprintk(BA_ERR, "%s(%d) pdev node is NULL",
			__func__, __LINE__);
		rc = -EINVAL;
		goto err_dev_init;
	}
	platform_set_drvdata(pdev, dev_ctxt);

	INIT_LIST_HEAD(&dev_ctxt->inputs);
	INIT_LIST_HEAD(&dev_ctxt->instances);
@@ -382,9 +455,8 @@ static int msm_ba_device_init(struct platform_device *pdev,
		dprintk(BA_ERR, "Failed to register v4l2 device");
	}

err_dev_init:
	if (rc) {
		kfree(dev_ctxt);
		devm_kfree(&pdev->dev, dev_ctxt);
		dev_ctxt = NULL;
	}
	dprintk(BA_INFO, "Exit %s with error %d", __func__, rc);
@@ -392,7 +464,7 @@ err_dev_init:
	return rc;
}

static int msm_ba_probe_ba_device(struct platform_device *pdev)
static int msm_ba_probe(struct platform_device *pdev)
{
	struct ba_ctxt *ba_ctxt;
	int rc = 0;
@@ -406,41 +478,29 @@ static int msm_ba_probe_ba_device(struct platform_device *pdev)
		return -EINVAL;
	}
	rc = msm_ba_device_init(pdev, &ba_ctxt->dev_ctxt);
	if (rc) {
	if (rc)
		dprintk(BA_ERR, "Failed to init device");
	} else {
	else
		ba_ctxt->dev_ctxt->debugfs_root = msm_ba_debugfs_init_dev(
			ba_ctxt->dev_ctxt, ba_ctxt->debugfs_root);
		pdev->dev.platform_data = ba_ctxt->dev_ctxt;
	}
	dprintk(BA_INFO, "Exit %s with error %d", __func__, rc);

	rc = parse_ba_dt(pdev);
	if (rc < 0) {
		dprintk(BA_ERR, "%s: devicetree error. Exit init", __func__);
		return rc;
	}
	dprintk(BA_INFO, "Exit %s with error %d", __func__, rc);

static int msm_ba_probe(struct platform_device *pdev)
{
	if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-ba"))
		return msm_ba_probe_ba_device(pdev);
	/* How did we end up here? */
	BUG();
	return -EINVAL;
	return rc;
}

static int msm_ba_remove(struct platform_device *pdev)
{
	struct msm_ba_dev *dev_ctxt;
	struct msm_ba_dev *dev_ctxt = platform_get_drvdata(pdev);
	struct msm_ba_sd_event *ba_sd_event = NULL;
	struct msm_ba_sd_event *ba_sd_event_tmp = NULL;
	int rc = 0;

	dprintk(BA_INFO, "Enter %s", __func__);
	if (!pdev) {
		dprintk(BA_ERR, "%s invalid input 0x%p", __func__, pdev);
		rc = -EINVAL;
	} else {
		dev_ctxt = pdev->dev.platform_data;

	if (NULL == dev_ctxt) {
		dprintk(BA_ERR, "%s invalid device", __func__);
		rc = -EINVAL;
@@ -454,10 +514,10 @@ static int msm_ba_remove(struct platform_device *pdev)
			kfree(ba_sd_event);
		}

			kfree(dev_ctxt);
		devm_kfree(&pdev->dev, dev_ctxt->msm_ba_inp_cfg);
		devm_kfree(&pdev->dev, dev_ctxt);
		dev_ctxt = NULL;
	}
	}
	dprintk(BA_INFO, "Exit %s with error %d", __func__, rc);

	return rc;
@@ -520,6 +580,11 @@ int msm_ba_destroy(void)
	return rc;
}

static const struct of_device_id msm_ba_dt_match[] = {
	{.compatible = "qcom,msm-ba"},
	{}
};

MODULE_DEVICE_TABLE(of, msm_ba_dt_match);

static struct platform_driver msm_ba_driver = {