예제 #1
0
파일: s5p_cec.c 프로젝트: asmalldev/linux
static int s5p_cec_remove(struct platform_device *pdev)
{
	struct s5p_cec_dev *cec = platform_get_drvdata(pdev);

	cec_unregister_adapter(cec->adap);
	cec_notifier_put(cec->notifier);
	pm_runtime_disable(&pdev->dev);
	return 0;
}
예제 #2
0
static int tegra_cec_remove(struct platform_device *pdev)
{
	struct tegra_cec *cec = platform_get_drvdata(pdev);

	clk_disable_unprepare(cec->clk);

	cec_unregister_adapter(cec->adap);
	cec_notifier_put(cec->notifier);

	return 0;
}
예제 #3
0
파일: ao-cec.c 프로젝트: avagin/linux
static int meson_ao_cec_remove(struct platform_device *pdev)
{
	struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);

	clk_disable_unprepare(ao_cec->core);

	cec_unregister_adapter(ao_cec->adap);

	cec_notifier_put(ao_cec->notify);

	return 0;
}
예제 #4
0
파일: cros-ec-cec.c 프로젝트: avagin/linux
static int cros_ec_cec_remove(struct platform_device *pdev)
{
	struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);
	struct device *dev = &pdev->dev;
	int ret;

	ret = blocking_notifier_chain_unregister(
			&cros_ec_cec->cros_ec->event_notifier,
			&cros_ec_cec->notifier);

	if (ret) {
		dev_err(dev, "failed to unregister notifier\n");
		return ret;
	}

	cec_unregister_adapter(cros_ec_cec->adap);

	if (cros_ec_cec->notify)
		cec_notifier_put(cros_ec_cec->notify);

	return 0;
}
예제 #5
0
파일: ao-cec.c 프로젝트: avagin/linux
static int meson_ao_cec_probe(struct platform_device *pdev)
{
	struct meson_ao_cec_device *ao_cec;
	struct device *hdmi_dev;
	struct resource *res;
	int ret, irq;

	hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);

	if (IS_ERR(hdmi_dev))
		return PTR_ERR(hdmi_dev);

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

	spin_lock_init(&ao_cec->cec_reg_lock);

	ao_cec->notify = cec_notifier_get(hdmi_dev);
	if (!ao_cec->notify)
		return -ENOMEM;

	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
					    "meson_ao_cec",
					    CEC_CAP_LOG_ADDRS |
					    CEC_CAP_TRANSMIT |
					    CEC_CAP_RC |
					    CEC_CAP_PASSTHROUGH,
					    1); /* Use 1 for now */
	if (IS_ERR(ao_cec->adap)) {
		ret = PTR_ERR(ao_cec->adap);
		goto out_probe_notify;
	}

	ao_cec->adap->owner = THIS_MODULE;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	ao_cec->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(ao_cec->base)) {
		ret = PTR_ERR(ao_cec->base);
		goto out_probe_adapter;
	}

	irq = platform_get_irq(pdev, 0);
	ret = devm_request_threaded_irq(&pdev->dev, irq,
					meson_ao_cec_irq,
					meson_ao_cec_irq_thread,
					0, NULL, ao_cec);
	if (ret) {
		dev_err(&pdev->dev, "irq request failed\n");
		goto out_probe_adapter;
	}

	ao_cec->core = devm_clk_get(&pdev->dev, "core");
	if (IS_ERR(ao_cec->core)) {
		dev_err(&pdev->dev, "core clock request failed\n");
		ret = PTR_ERR(ao_cec->core);
		goto out_probe_adapter;
	}

	ret = clk_prepare_enable(ao_cec->core);
	if (ret) {
		dev_err(&pdev->dev, "core clock enable failed\n");
		goto out_probe_adapter;
	}

	ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
	if (ret) {
		dev_err(&pdev->dev, "core clock set rate failed\n");
		goto out_probe_clk;
	}

	device_reset_optional(&pdev->dev);

	ao_cec->pdev = pdev;
	platform_set_drvdata(pdev, ao_cec);

	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
	if (ret < 0) {
		cec_notifier_put(ao_cec->notify);
		goto out_probe_clk;
	}

	/* Setup Hardware */
	writel_relaxed(CEC_GEN_CNTL_RESET,
		       ao_cec->base + CEC_GEN_CNTL_REG);

	cec_register_cec_notifier(ao_cec->adap, ao_cec->notify);

	return 0;

out_probe_clk:
	clk_disable_unprepare(ao_cec->core);

out_probe_adapter:
	cec_delete_adapter(ao_cec->adap);

out_probe_notify:
	cec_notifier_put(ao_cec->notify);

	dev_err(&pdev->dev, "CEC controller registration failed\n");

	return ret;
}
예제 #6
0
static int tegra_cec_probe(struct platform_device *pdev)
{
	struct platform_device *hdmi_dev;
	struct device_node *np;
	struct tegra_cec *cec;
	struct resource *res;
	int ret = 0;

	np = of_parse_phandle(pdev->dev.of_node, "hdmi-phandle", 0);

	if (!np) {
		dev_err(&pdev->dev, "Failed to find hdmi node in device tree\n");
		return -ENODEV;
	}
	hdmi_dev = of_find_device_by_node(np);
	if (hdmi_dev == NULL)
		return -EPROBE_DEFER;

	cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL);

	if (!cec)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	if (!res) {
		dev_err(&pdev->dev,
			"Unable to allocate resources for device\n");
		return -EBUSY;
	}

	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
		pdev->name)) {
		dev_err(&pdev->dev,
			"Unable to request mem region for device\n");
		return -EBUSY;
	}

	cec->tegra_cec_irq = platform_get_irq(pdev, 0);

	if (cec->tegra_cec_irq <= 0)
		return -EBUSY;

	cec->cec_base = devm_ioremap_nocache(&pdev->dev, res->start,
					     resource_size(res));

	if (!cec->cec_base) {
		dev_err(&pdev->dev, "Unable to grab IOs for device\n");
		return -EBUSY;
	}

	cec->clk = devm_clk_get(&pdev->dev, "cec");

	if (IS_ERR_OR_NULL(cec->clk)) {
		dev_err(&pdev->dev, "Can't get clock for CEC\n");
		return -ENOENT;
	}

	clk_prepare_enable(cec->clk);

	/* set context info. */
	cec->dev = &pdev->dev;

	platform_set_drvdata(pdev, cec);

	ret = devm_request_threaded_irq(&pdev->dev, cec->tegra_cec_irq,
		tegra_cec_irq_handler, tegra_cec_irq_thread_handler,
		0, "cec_irq", &pdev->dev);

	if (ret) {
		dev_err(&pdev->dev,
			"Unable to request interrupt for device\n");
		goto clk_error;
	}

	cec->notifier = cec_notifier_get(&hdmi_dev->dev);
	if (!cec->notifier) {
		ret = -ENOMEM;
		goto clk_error;
	}

	cec->adap = cec_allocate_adapter(&tegra_cec_ops, cec, TEGRA_CEC_NAME,
			CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL,
			CEC_MAX_LOG_ADDRS);
	if (IS_ERR(cec->adap)) {
		ret = -ENOMEM;
		dev_err(&pdev->dev, "Couldn't create cec adapter\n");
		goto cec_error;
	}
	ret = cec_register_adapter(cec->adap, &pdev->dev);
	if (ret) {
		dev_err(&pdev->dev, "Couldn't register device\n");
		goto cec_error;
	}

	cec_register_cec_notifier(cec->adap, cec->notifier);

	return 0;

cec_error:
	if (cec->notifier)
		cec_notifier_put(cec->notifier);
	cec_delete_adapter(cec->adap);
clk_error:
	clk_disable_unprepare(cec->clk);
	return ret;
}