static int mhl_i2c_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	int rc = 0;

	pr_debug("%s:\n", __func__);

	mhl_info = NULL;
	isDiscoveryCalled = false;
	notify_usb_online = NULL;

	device_discovery_cb = NULL;
	context_cb = NULL;

	mhl_i2c_client = client;

	mhl_info = kzalloc(sizeof(*mhl_info), GFP_KERNEL);
	if (!mhl_info) {
		pr_err("%s: FAILED: cannot alloc platform_switch\n", __func__);
		rc = -ENOMEM;
		goto failed_probe;
	}

	if (client->dev.of_node) {
		rc = mhl_tx_get_dt_data(&client->dev);
		if (rc) {
			pr_err("%s:device tree error\n", __func__);
			goto failed_probe;
		}
		rc = mhl_pf_gpio_config_init();
		if (rc) {
			pr_err("%s:device tree error\n", __func__);
			goto failed_probe;
		}
	} else
		pr_err("%s: dev.of_node is null\n", __func__);

	mhl_info->notify = mhl_pf_switch_device_discovery;

	if (msm_register_usb_ext_notification(mhl_info) != 0) {
		pr_err("%s: register for usb notifcn failed\n", __func__);
		rc = -EPROBE_DEFER;
		goto failed_probe;
	}

	return 0;

failed_probe:
	mhl_pf_swtich_resource_free();

	return rc;
}
static int mhl_i2c_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	int rc = 0;
	struct mhl_tx_platform_data *pdata = NULL;
	struct mhl_tx_ctrl *mhl_ctrl;
	struct usb_ext_notification *mhl_info = NULL;
	struct msm_hdmi_mhl_ops *hdmi_mhl_ops = NULL;

	mhl_ctrl = devm_kzalloc(&client->dev, sizeof(*mhl_ctrl), GFP_KERNEL);
	if (!mhl_ctrl) {
		pr_err("%s: FAILED: cannot alloc hdmi tx ctrl\n", __func__);
		rc = -ENOMEM;
		goto failed_no_mem;
	}

	if (client->dev.of_node) {
		pdata = devm_kzalloc(&client->dev,
			     sizeof(struct mhl_tx_platform_data), GFP_KERNEL);
		if (!pdata) {
			dev_err(&client->dev, "Failed to allocate memory\n");
			rc = -ENOMEM;
			goto failed_no_mem;
		}

		rc = mhl_tx_get_dt_data(&client->dev, pdata);
		if (rc) {
			pr_err("%s: FAILED: parsing device tree data; rc=%d\n",
				__func__, rc);
			goto failed_dt_data;
		}
		mhl_ctrl->i2c_handle = client;
		mhl_ctrl->pdata = pdata;
		i2c_set_clientdata(client, mhl_ctrl);
	}

	/*
	 * Regulator init
	 */
	rc = mhl_vreg_config(mhl_ctrl, 1);
	if (rc) {
		pr_err("%s: vreg init failed [%d]\n",
			__func__, rc);
		goto failed_probe;
	}

	/*
	 * GPIO init
	 */
	rc = mhl_gpio_config(mhl_ctrl, 1);
	if (rc) {
		pr_err("%s: gpio init failed [%d]\n",
			__func__, rc);
		goto failed_probe;
	}

	/*
	 * Other initializations
	 * such tx specific
	 */
	mhl_ctrl->disc_enabled = false;
	INIT_WORK(&mhl_ctrl->mhl_msc_send_work, mhl_msc_send_work);
	mhl_ctrl->cur_state = POWER_STATE_D0_MHL;
	INIT_LIST_HEAD(&mhl_ctrl->list_cmd);
	init_completion(&mhl_ctrl->msc_cmd_done);
	spin_lock_init(&mhl_ctrl->lock);
	mhl_ctrl->msc_send_workqueue = create_singlethread_workqueue
		("mhl_msc_cmd_queue");

	mhl_ctrl->input = input_allocate_device();
	if (mhl_ctrl->input) {
		int i;
		struct input_dev *input = mhl_ctrl->input;

		mhl_ctrl->rcp_key_code_tbl = vmalloc(
			sizeof(support_rcp_key_code_tbl));
		if (!mhl_ctrl->rcp_key_code_tbl) {
			pr_err("%s: no alloc mem for rcp keycode tbl\n",
			       __func__);
			return -ENOMEM;
		}

		mhl_ctrl->rcp_key_code_tbl_len = sizeof(
			support_rcp_key_code_tbl);
		memcpy(mhl_ctrl->rcp_key_code_tbl,
		       &support_rcp_key_code_tbl[0],
		       mhl_ctrl->rcp_key_code_tbl_len);

		input->phys = "cbus/input0";
		input->id.bustype = BUS_VIRTUAL;
		input->id.vendor  = 0x1095;
		input->id.product = 0x8334;
		input->id.version = 0xA;

		input->name = "mhl-rcp";

		input->keycode = support_rcp_key_code_tbl;
		input->keycodesize = sizeof(u16);
		input->keycodemax = ARRAY_SIZE(support_rcp_key_code_tbl);

		input->evbit[0] = EV_KEY;
		for (i = 0; i < ARRAY_SIZE(support_rcp_key_code_tbl); i++) {
			if (support_rcp_key_code_tbl[i] > 1)
				input_set_capability(input, EV_KEY,
					support_rcp_key_code_tbl[i]);
		}

		if (input_register_device(input) < 0) {
			pr_warn("%s: failed to register input device\n",
				__func__);
			input_free_device(input);
			mhl_ctrl->input = NULL;
		}
	}

	rc = mhl_tx_chip_init(mhl_ctrl);
	if (rc) {
		pr_err("%s: tx chip init failed [%d]\n",
			__func__, rc);
		goto failed_probe;
	}

	init_completion(&mhl_ctrl->rgnd_done);

	pr_debug("%s: IRQ from GPIO INTR = %d\n",
		__func__, mhl_ctrl->i2c_handle->irq);
	pr_debug("%s: Driver name = [%s]\n", __func__,
		client->dev.driver->name);
	rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
				   &mhl_tx_isr,
				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
				 client->dev.driver->name, mhl_ctrl);
	if (rc) {
		pr_err("request_threaded_irq failed, status: %d\n",
		       rc);
		goto failed_probe;
	} else {
		pr_debug("request_threaded_irq succeeded\n");
	}

	mhl_ctrl->mhl_psy.name = "ext-vbus";
	mhl_ctrl->mhl_psy.type = POWER_SUPPLY_TYPE_USB_DCP;
	mhl_ctrl->mhl_psy.supplied_to = mhl_pm_power_supplied_to;
	mhl_ctrl->mhl_psy.num_supplicants = ARRAY_SIZE(
					mhl_pm_power_supplied_to);
	mhl_ctrl->mhl_psy.properties = mhl_pm_power_props;
	mhl_ctrl->mhl_psy.num_properties = ARRAY_SIZE(mhl_pm_power_props);
	mhl_ctrl->mhl_psy.get_property = mhl_power_get_property;
	mhl_ctrl->mhl_psy.set_property = mhl_power_set_property;

	rc = power_supply_register(&client->dev, &mhl_ctrl->mhl_psy);
	if (rc < 0) {
		dev_err(&client->dev, "%s:power_supply_register ext_vbus_psy failed\n",
			__func__);
		goto failed_probe;
	}

	hdmi_mhl_ops = devm_kzalloc(&client->dev,
				    sizeof(struct msm_hdmi_mhl_ops),
				    GFP_KERNEL);
	if (!hdmi_mhl_ops) {
		pr_err("%s: alloc hdmi mhl ops failed\n", __func__);
		rc = -ENOMEM;
		goto failed_probe_pwr;
	}

	pr_debug("%s: i2c client addr is [%x]\n", __func__, client->addr);
	if (mhl_ctrl->pdata->hdmi_pdev) {
		rc = msm_hdmi_register_mhl(mhl_ctrl->pdata->hdmi_pdev,
					   hdmi_mhl_ops, mhl_ctrl);
		if (rc) {
			pr_err("%s: register with hdmi failed\n", __func__);
			rc = -EPROBE_DEFER;
			goto failed_probe_pwr;
		}
	}

	if (!hdmi_mhl_ops || !hdmi_mhl_ops->tmds_enabled ||
	    !hdmi_mhl_ops->set_mhl_max_pclk) {
		pr_err("%s: func ptr is NULL\n", __func__);
		rc = -EINVAL;
		goto failed_probe_pwr;
	}
	mhl_ctrl->hdmi_mhl_ops = hdmi_mhl_ops;

	rc = hdmi_mhl_ops->set_mhl_max_pclk(
		mhl_ctrl->pdata->hdmi_pdev, MAX_MHL_PCLK);
	if (rc) {
		pr_err("%s: can't set max mhl pclk\n", __func__);
		goto failed_probe_pwr;
	}

	mhl_info = devm_kzalloc(&client->dev, sizeof(*mhl_info), GFP_KERNEL);
	if (!mhl_info) {
		pr_err("%s: alloc mhl info failed\n", __func__);
		rc = -ENOMEM;
		goto failed_probe_pwr;
	}

	mhl_info->ctxt = mhl_ctrl;
	mhl_info->notify = mhl_sii_device_discovery;
	if (msm_register_usb_ext_notification(mhl_info)) {
		pr_err("%s: register for usb notifcn failed\n", __func__);
		rc = -EPROBE_DEFER;
		goto failed_probe_pwr;
	}
	mhl_ctrl->mhl_info = mhl_info;
	mhl_register_msc(mhl_ctrl);
	return 0;

failed_probe_pwr:
	power_supply_unregister(&mhl_ctrl->mhl_psy);
failed_probe:
	free_irq(mhl_ctrl->i2c_handle->irq, mhl_ctrl);
	mhl_gpio_config(mhl_ctrl, 0);
	mhl_vreg_config(mhl_ctrl, 0);
	/* do not deep-free */
	if (mhl_info)
		devm_kfree(&client->dev, mhl_info);
failed_dt_data:
	if (pdata)
		devm_kfree(&client->dev, pdata);
failed_no_mem:
	if (mhl_ctrl)
		devm_kfree(&client->dev, mhl_ctrl);
	mhl_info = NULL;
	pdata = NULL;
	mhl_ctrl = NULL;
	pr_err("%s: PROBE FAILED, rc=%d\n", __func__, rc);
	return rc;
}
Exemple #3
0
static int mhl_i2c_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	int rc = 0;
	struct mhl_tx_platform_data *pdata = NULL;
	struct mhl_tx_ctrl *mhl_ctrl;
	struct usb_ext_notification *mhl_info = NULL;

	mhl_ctrl = devm_kzalloc(&client->dev, sizeof(*mhl_ctrl), GFP_KERNEL);
	if (!mhl_ctrl) {
		pr_err("%s: FAILED: cannot alloc hdmi tx ctrl\n", __func__);
		rc = -ENOMEM;
		goto failed_no_mem;
	}

	if (client->dev.of_node) {
		pdata = devm_kzalloc(&client->dev,
			     sizeof(struct mhl_tx_platform_data), GFP_KERNEL);
		if (!pdata) {
			dev_err(&client->dev, "Failed to allocate memory\n");
			rc = -ENOMEM;
			goto failed_no_mem;
		}

		rc = mhl_tx_get_dt_data(&client->dev, pdata);
		if (rc) {
			pr_err("%s: FAILED: parsing device tree data; rc=%d\n",
				__func__, rc);
			goto failed_dt_data;
		}
		mhl_ctrl->i2c_handle = client;
		mhl_ctrl->pdata = pdata;
		i2c_set_clientdata(client, mhl_ctrl);
	}

	/*
	 * Regulator init
	 */
	rc = mhl_vreg_config(mhl_ctrl, 1);
	if (rc) {
		pr_err("%s: vreg init failed [%d]\n",
			__func__, rc);
		goto failed_probe;
	}

	/*
	 * GPIO init
	 */
	rc = mhl_gpio_config(mhl_ctrl, 1);
	if (rc) {
		pr_err("%s: gpio init failed [%d]\n",
			__func__, rc);
		goto failed_probe;
	}

	/*
	 * Other initializations
	 * such tx specific
	 */
	mhl_ctrl->disc_enabled = false;
	rc = mhl_tx_chip_init(mhl_ctrl);
	if (rc) {
		pr_err("%s: tx chip init failed [%d]\n",
			__func__, rc);
		goto failed_probe;
	}

	init_completion(&mhl_ctrl->rgnd_done);

	pr_debug("%s: IRQ from GPIO INTR = %d\n",
		__func__, mhl_ctrl->i2c_handle->irq);
	pr_debug("%s: Driver name = [%s]\n", __func__,
		client->dev.driver->name);
	rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
				   &mhl_tx_isr,
				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
				 client->dev.driver->name, mhl_ctrl);
	if (rc) {
		pr_err("request_threaded_irq failed, status: %d\n",
			rc);
		goto failed_probe;
	} else {
		pr_debug("request_threaded_irq succeeded\n");
	}

	mhl_ctrl->mhl_psy.name = "ext-vbus";
	mhl_ctrl->mhl_psy.type = POWER_SUPPLY_TYPE_USB_DCP;
	mhl_ctrl->mhl_psy.supplied_to = mhl_pm_power_supplied_to;
	mhl_ctrl->mhl_psy.num_supplicants = ARRAY_SIZE(
					mhl_pm_power_supplied_to);
	mhl_ctrl->mhl_psy.properties = mhl_pm_power_props;
	mhl_ctrl->mhl_psy.num_properties = ARRAY_SIZE(mhl_pm_power_props);
	mhl_ctrl->mhl_psy.get_property = mhl_power_get_property;
	mhl_ctrl->mhl_psy.set_property = mhl_power_set_property;

	rc = power_supply_register(&client->dev, &mhl_ctrl->mhl_psy);
	if (rc < 0) {
		dev_err(&client->dev, "%s:power_supply_register ext_vbus_psy failed\n",
			__func__);
		goto failed_probe;
	}

	pr_debug("%s: i2c client addr is [%x]\n", __func__, client->addr);

	mhl_info = devm_kzalloc(&client->dev, sizeof(*mhl_info), GFP_KERNEL);
	if (!mhl_info) {
		pr_err("%s: alloc mhl info failed\n", __func__);
		goto failed_probe;
	}

	mhl_info->ctxt = mhl_ctrl;
	mhl_info->notify = mhl_sii_device_discovery;
	if (msm_register_usb_ext_notification(mhl_info)) {
		pr_err("%s: register for usb notifcn failed\n", __func__);
		goto failed_probe;
	}
	mhl_ctrl->mhl_info = mhl_info;
	return 0;
failed_probe:
	mhl_gpio_config(mhl_ctrl, 0);
	mhl_vreg_config(mhl_ctrl, 0);
	/* do not deep-free */
	if (mhl_info)
		devm_kfree(&client->dev, mhl_info);
failed_dt_data:
	if (pdata)
		devm_kfree(&client->dev, pdata);
failed_no_mem:
	if (mhl_ctrl)
		devm_kfree(&client->dev, mhl_ctrl);
	pr_err("%s: PROBE FAILED, rc=%d\n", __func__, rc);
	return rc;
}