static int anx7808_i2c_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{

	struct anx7808_data *anx7808;
	struct anx7808_platform_data *pdata;
	int ret = 0;
	int sbl_cable_type = 0;

#ifdef SP_REGISTER_SET_TEST
	val_SP_TX_LT_CTRL_REG0 = 0x19;
	val_SP_TX_LT_CTRL_REG10 = 0x00;
	val_SP_TX_LT_CTRL_REG11 = 0x00;
	val_SP_TX_LT_CTRL_REG2 = 0x36;
	val_SP_TX_LT_CTRL_REG12 = 0x00;
	val_SP_TX_LT_CTRL_REG1 = 0x26;
	val_SP_TX_LT_CTRL_REG6 = 0x3c;
	val_SP_TX_LT_CTRL_REG16 = 0x18;
	val_SP_TX_LT_CTRL_REG5 = 0x28;
	val_SP_TX_LT_CTRL_REG8 = 0x2F;
	val_SP_TX_LT_CTRL_REG15 = 0x10;
	val_SP_TX_LT_CTRL_REG18 = 0x1F;
#endif
	if (!i2c_check_functionality(client->adapter,
		I2C_FUNC_SMBUS_I2C_BLOCK)) {
		pr_err("%s: i2c bus does not support the anx7808\n", __func__);
		ret = -ENODEV;
		goto exit;
	}

	anx7808 = kzalloc(sizeof(struct anx7808_data), GFP_KERNEL);
	if (!anx7808) {
		pr_err("%s: failed to allocate driver data\n", __func__);
		ret = -ENOMEM;
		goto exit;
	}

	if (client->dev.of_node) {
		pdata = devm_kzalloc(&client->dev,
							 sizeof(struct anx7808_platform_data),
							 GFP_KERNEL);
		if (!pdata) {
			pr_err("%s: Failed to allocate memory\n", __func__);
			return -ENOMEM;
		}
		client->dev.platform_data = pdata;
	/* device tree parsing function call */
		ret = anx7808_parse_dt(&client->dev, pdata);
		if (ret != 0) /* if occurs error */
			goto err0;

		anx7808->pdata = pdata;
	} else {
		anx7808->pdata = client->dev.platform_data;
	}

	/* to access global platform data */
	g_pdata = anx7808->pdata;

	anx7808_client = client;

	mutex_init(&anx7808->lock);

	if (!anx7808->pdata) {
		ret = -EINVAL;
		goto err0;
	}

	ret = anx7808_init_gpio(anx7808);
	if (ret) {
		pr_err("%s: failed to initialize gpio\n", __func__);
		goto err0;
	}

	INIT_DELAYED_WORK(&anx7808->work, anx7808_work_func);
	INIT_DELAYED_WORK(&anx7808->dwc3_ref_clk_work, dwc3_ref_clk_work_func);

	anx7808->workqueue = create_singlethread_workqueue("anx7808_work");
	if (anx7808->workqueue == NULL) {
		pr_err("%s: failed to create work queue\n", __func__);
		ret = -ENOMEM;
		goto err1;
	}

	anx7808->pdata->avdd_power(1);
	anx7808->pdata->dvdd_power(1);

	ret = anx7808_system_init();
	if (ret) {
		pr_err("%s: failed to initialize anx7808\n", __func__);
		goto err2;
	}

	client->irq = gpio_to_irq(anx7808->pdata->gpio_cbl_det);
	if (client->irq < 0) {
		pr_err("%s : failed to get gpio irq\n", __func__);
		goto err2;
	}

	wake_lock_init(&anx7808->slimport_lock,
				WAKE_LOCK_SUSPEND,
				"slimport_wake_lock");

	sbl_cable_type = anx7808_get_sbl_cable_type();

	if ((lge_get_laf_mode() != LGE_LAF_MODE_LAF) &&
		(sbl_cable_type != CBL_910K)) {

		ret = request_threaded_irq(client->irq, NULL, anx7808_cbl_det_isr,
						IRQF_TRIGGER_RISING
						| IRQF_TRIGGER_FALLING
						| IRQF_ONESHOT,
						"anx7808", anx7808);
		if (ret  < 0) {
			pr_err("%s : failed to request irq\n", __func__);
			goto err2;
		}

		ret = irq_set_irq_wake(client->irq, 1);
		if (ret  < 0) {
			pr_err("%s : Request irq for cable detect", __func__);
			pr_err("interrupt wake set fail\n");
			goto err3;
		}

		ret = enable_irq_wake(client->irq);
		if (ret  < 0) {
			pr_err("%s : Enable irq for cable detect", __func__);
			pr_err("interrupt wake enable fail\n");
			goto err3;
		}
	} else {
		pr_err("%s %s : %s, Disable cbl det irq!!\n", LOG_TAG, __func__,
			sbl_cable_type == CBL_910K ? "910K Cable Connected" : "Laf Mode");
	}

	ret = create_sysfs_interfaces(&client->dev);
	if (ret < 0) {
		pr_err("%s : sysfs register failed", __func__);
		goto err3;
	}
#ifdef CONFIG_SLIMPORT_DYNAMIC_HPD
	hdmi_slimport_ops = devm_kzalloc(&client->dev,
				    sizeof(struct msm_hdmi_slimport_ops),
				    GFP_KERNEL);
	if (!hdmi_slimport_ops) {
		pr_err("%s: alloc hdmi slimport ops failed\n", __func__);
		ret = -ENOMEM;
		goto err3;
	}

	if (anx7808->pdata->hdmi_pdev) {
		ret = msm_hdmi_register_slimport(anx7808->pdata->hdmi_pdev,
					   hdmi_slimport_ops, anx7808);
		if (ret) {
			pr_err("%s: register with hdmi failed\n", __func__);
			ret = -EPROBE_DEFER;
			goto err3;
		}
	}
#endif

	goto exit;

err3:
	free_irq(client->irq, anx7808);
err2:
	destroy_workqueue(anx7808->workqueue);
err1:
	anx7808_free_gpio(anx7808);
err0:
	anx7808_client = NULL;
	kfree(anx7808);
exit:
	return ret;
}
Exemple #2
0
static int anx7808_i2c_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct anx7808_data *anx7808;
	struct anx7808_platform_data *pdata;
	struct device_node *dev_node = client->dev.of_node;
	struct msm_hdmi_sp_ops *hdmi_sp_ops = NULL;
	int ret = 0;

	if (!i2c_check_functionality(client->adapter,
			I2C_FUNC_SMBUS_I2C_BLOCK)) {
		pr_err("i2c bus does not support anx7808\n");
		ret = -ENODEV;
		goto exit;
	}

	anx7808 = kzalloc(sizeof(struct anx7808_data), GFP_KERNEL);
	if (!anx7808) {
		pr_err("failed to allocate driver data\n");
		ret = -ENOMEM;
		goto exit;
	}

	anx7808->client = client;
	i2c_set_clientdata(client, anx7808);

	if (dev_node) {
		ret = anx7808_parse_dt(dev_node, anx7808);
		if (ret) {
			pr_err("failed to parse dt\n");
			goto err0;
		}
	} else {
		pdata = client->dev.platform_data;
		if (pdata == NULL) {
			pr_err("no platform data.\n");
			goto err0;
		}

		anx7808->gpio_p_dwn = pdata->gpio_p_dwn;
		anx7808->gpio_reset = pdata->gpio_reset;
		anx7808->gpio_int = pdata->gpio_int;
		anx7808->gpio_cbl_det = pdata->gpio_cbl_det;
		anx7808->vdd10_name = pdata->vdd10_name;
		anx7808->vdd10_name = pdata->avdd33_name;
	}

	/* initialize hdmi_sp_ops */
	hdmi_sp_ops = devm_kzalloc(&client->dev,
				   sizeof(struct msm_hdmi_sp_ops),
				   GFP_KERNEL);
	if (!hdmi_sp_ops) {
		pr_err("alloc hdmi sp ops failed\n");
		goto err0;
	}

	if (anx7808->hdmi_pdev) {
		ret = msm_hdmi_register_sp(anx7808->hdmi_pdev,
					  hdmi_sp_ops);
		if (ret) {
			pr_err("register with hdmi_failed\n");
			goto err0;
		}
	}

	anx7808->hdmi_sp_ops = hdmi_sp_ops;

	the_chip = anx7808;

	mutex_init(&anx7808->lock);
	init_completion(&init_aux_ch_completion);
	ret = anx7808_init_gpio(anx7808);
	if (ret) {
		pr_err("failed to initialize gpio\n");
		goto err0;
	}

	INIT_DELAYED_WORK(&anx7808->work, anx7808_work_func);

	anx7808->workqueue = create_singlethread_workqueue("anx7808_work");
	if (!anx7808->workqueue) {
		pr_err("failed to create work queue\n");
		ret = -ENOMEM;
		goto err1;
	}

	ret = anx7808_avdd_3p3_power(anx7808, true);
	if (ret)
		goto err2;

	ret = anx7808_vdd_1p0_power(anx7808, false);
	if (ret)
		goto err3;

	ret = anx7808_system_init();
	if (ret) {
		pr_err("failed to initialize anx7808\n");
		goto err4;
	}

	client->irq = gpio_to_irq(anx7808->gpio_cbl_det);
	if (client->irq < 0) {
		pr_err("failed to get gpio irq\n");
		goto err4;
	}

	wake_lock_init(&anx7808->slimport_lock, WAKE_LOCK_SUSPEND,
				"slimport_wake_lock");

	ret = request_threaded_irq(client->irq, NULL, anx7808_cbl_det_isr,
					IRQF_TRIGGER_RISING
					| IRQF_TRIGGER_FALLING
					| IRQF_ONESHOT,
					"anx7808", anx7808);
	if (ret  < 0) {
		pr_err("failed to request irq\n");
		goto err5;
	}

	disable_irq(client->irq);
	ret = enable_irq_wake(client->irq);
	if (ret  < 0) {
		pr_err("interrupt wake enable fail\n");
		goto err6;
	}

	anx7808_setup_video_mode_lut();
	anx7808_get_usb_clk(client);

	return 0;

err6:
	free_irq(client->irq, anx7808);
err5:
	wake_lock_destroy(&anx7808->slimport_lock);
err4:
	if (!anx7808->vdd_reg)
		regulator_put(anx7808->vdd_reg);
err3:
	if (!anx7808->avdd_reg)
		regulator_put(anx7808->avdd_reg);
err2:
	destroy_workqueue(anx7808->workqueue);
err1:
	anx7808_free_gpio(anx7808);
err0:
	the_chip = NULL;
	kfree(anx7808);
exit:
	return ret;
}