コード例 #1
0
static int __devinit hdmi_probe(struct platform_device *pdev)
{
	struct s5p_hdmi_platdata *pdata;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	int ret;

	dev_dbg(dev, "probe start\n");

	hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(dev, "out of memory\n");
		ret = -ENOMEM;
		goto fail;
	}

	hdmi_dev->dev = dev;

	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_hdev;

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(dev, "get hdmi memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "hdmi register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* mapping HDMIPHY_APB registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (res == NULL) {
		dev_err(dev, "get hdmiphy memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->phy_regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->phy_regs == NULL) {
		dev_err(dev, "hdmiphy register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* External hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(dev, "get external interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->ext_irq = res->start;

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (res == NULL) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->int_irq = res->start;

	INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
	INIT_DELAYED_WORK(&hdmi_dev->hdmi_probe_work, hdmiphy_poweroff_work);
	INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);
	mutex_init(&hdmi_dev->mutex);

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail_lock;
	}

	pdata = pdev->dev.platform_data;
	dev_info(dev, "hdmi ip version = %d\n", pdata->ip_ver);

	/* store hdmi platform data to hdmi context */
	hdmi_dev->pdata = pdata;

	if (soc_is_exynos5250()) {
		drv_data = (struct hdmi_driver_data *)
			platform_get_device_id(pdev)->driver_data;
		dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

		phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
		if (phy_adapter == NULL) {
			dev_err(dev, "adapter request failed\n");
			ret = -ENXIO;
			goto fail_vdev;
		}

		hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
				phy_adapter, &hdmiphy_info, NULL);
		/* on failure or not adapter is no longer useful */
		i2c_put_adapter(phy_adapter);
		if (hdmi_dev->phy_sd == NULL) {
			dev_err(dev, "missing subdev for hdmiphy\n");
			ret = -ENODEV;
			goto fail_vdev;
		}
	}

	hdmi_dev->hpd_switch.name = "hdmi";
	ret = switch_dev_register(&hdmi_dev->hpd_switch);
	if (ret) {
		dev_err(dev, "request switch class failed.\n");
		goto fail_vdev;
	}

	ret = request_irq(hdmi_dev->int_irq, hdmi_irq_handler,
			0, "hdmi-int", hdmi_dev);
	if (ret) {
		dev_err(dev, "request int interrupt failed.\n");
		goto fail_switch;
	}
	disable_irq(hdmi_dev->int_irq);

	s5p_v4l2_int_src_ext_hpd();
	ret = request_irq(hdmi_dev->ext_irq, hdmi_irq_handler_ext,
			IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
	if (ret) {
		dev_err(dev, "request ext interrupt failed.\n");
		goto fail_ext;
	}

	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);

	/* default audio configuration : disable audio */
	hdmi_dev->audio_enable = 0;
	hdmi_dev->audio_channel_count = 2;
	//hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->sample_rate = 48000;
	hdmi_dev->sample_size = DEFAULT_SAMPLE_SIZE;
	hdmi_dev->color_range = HDMI_RGB709_0_255;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* default aspect ratio is 16:9 */
	hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

	/* default HDMI streaming is stoped */
	hdmi_dev->streaming = HDMI_STOP;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_irq;

	hdmi_entity_info_print(hdmi_dev);

	pm_runtime_enable(dev);

	//if {(edid_supports_hdmi(hdmi_dev)) {
#if 1 
		/* initialize hdcp resource */
		ret = hdcp_prepare(hdmi_dev);
		if (ret)
			goto fail_irq;
#endif
//	}

	/* work after booting */
	queue_delayed_work(system_nrt_wq, &hdmi_dev->hdmi_probe_work,
					msecs_to_jiffies(1500));
	queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
					msecs_to_jiffies(1500));

	dev_info(dev, "probe sucessful\n");

	hdmi_debugfs_init(hdmi_dev);

	return 0;

fail_irq:
	free_irq(hdmi_dev->ext_irq, hdmi_dev);

fail_ext:
	free_irq(hdmi_dev->int_irq, hdmi_dev);

fail_switch:
	switch_dev_unregister(&hdmi_dev->hpd_switch);

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail_lock:
	mutex_destroy(&hdmi_dev->mutex);

fail_regs:
	iounmap(hdmi_dev->regs);

fail_init:
	hdmi_resources_cleanup(hdmi_dev);

fail_hdev:
	kfree(hdmi_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}
コード例 #2
0
static int hdmi_probe(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct resource *res;
    struct hdmi_device *hdmi_dev = NULL;
    int ret;

    dev_info(dev, "probe start\n");

    hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_device), GFP_KERNEL);
    if (!hdmi_dev) {
        dev_err(&pdev->dev, "no memory for hdmi device\n");
        return -ENOMEM;
    }
    hdmi_dev->dev = dev;

    /* store platform data ptr to mixer context */
    of_property_read_u32(dev->of_node, "ip_ver", &hdmi_dev->ip_ver);
    dev_info(dev, "HDMI ip version %d\n", hdmi_dev->ip_ver);

    /* mapping HDMI registers */
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!res) {
        dev_err(dev, "get hdmi memory resource failed.\n");
        return -ENXIO;
    }
    hdmi_dev->regs = devm_request_and_ioremap(&pdev->dev, res);
    if (hdmi_dev->regs == NULL) {
        dev_err(dev, "failed to claim register region for hdmi\n");
        return -ENOENT;
    }

    /* mapping HDMIPHY_APB registers */
    res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
    if (!res) {
        dev_err(dev, "get hdmiphy memory resource failed.\n");
        return -ENXIO;
    }
    hdmi_dev->phy_regs = devm_request_and_ioremap(&pdev->dev, res);
    if (hdmi_dev->phy_regs == NULL) {
        dev_err(dev, "failed to claim register region for hdmiphy\n");
        return -ENOENT;
    }

    /* Internal hpd */
    res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    if (!res) {
        dev_err(dev, "get internal interrupt resource failed.\n");
        return -ENXIO;
    }
    ret = devm_request_irq(dev, res->start, hdmi_irq_handler,
                           0, "hdmi-int", hdmi_dev);
    if (ret) {
        dev_err(dev, "request int interrupt failed.\n");
        return ret;
    } else {
        hdmi_dev->int_irq = res->start;
        disable_irq(hdmi_dev->int_irq);
        dev_info(dev, "success request hdmi-int irq\n");
    }

    /* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
    strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
            sizeof(hdmi_dev->v4l2_dev.name));
    /* passing NULL owner prevents driver from erasing drvdata */
    ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
    if (ret) {
        dev_err(dev, "could not register v4l2 device.\n");
        goto fail;
    }

    INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
    INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);

    /* setting the clocks */
    ret = hdmi_resources_init(hdmi_dev);
    if (ret)
        goto fail_vdev;

    /* HDMI pin control */
    hdmi_dev->pinctrl = devm_pinctrl_get(dev);
    if (IS_ERR(hdmi_dev->pinctrl)) {
        dev_err(dev, "could not set hdmi internal hpd pins\n");
        goto fail_clk;
    } else {
        hdmi_dev->pin_int =
            pinctrl_lookup_state(hdmi_dev->pinctrl, "hdmi_hdmi_hpd");
        if(IS_ERR(hdmi_dev->pin_int)) {
            dev_err(dev, "could not get hdmi internal hpd pin state\n");
            goto fail_clk;
        }
        hdmi_dev->pin_ext =
            pinctrl_lookup_state(hdmi_dev->pinctrl, "hdmi_ext_hpd");
        if(IS_ERR(hdmi_dev->pin_ext)) {
            dev_err(dev, "could not get hdmi external hpd pin state\n");
            goto fail_clk;
        }
    }

    /* setting the GPIO */
    ret = hdmi_set_gpio(hdmi_dev);
    if (ret) {
        dev_err(dev, "failed to get GPIO\n");
        goto fail_clk;
    }

    /* register the switch device for HPD */
    hdmi_dev->hpd_switch.name = "hdmi";
    ret = switch_dev_register(&hdmi_dev->hpd_switch);
    if (ret) {
        dev_err(dev, "request switch class failed.\n");
        goto fail_gpio;
    }
    dev_info(dev, "success register switch device\n");

    /* External hpd */
    hdmi_dev->ext_irq = gpio_to_irq(hdmi_dev->res.gpio_hpd);
    ret = devm_request_irq(dev, hdmi_dev->ext_irq, hdmi_irq_handler_ext,
                           IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
    if (ret) {
        dev_err(dev, "request ext interrupt failed.\n");
        goto fail_switch;
    } else {
        dev_info(dev, "success request hdmi-ext irq\n");
    }

#ifdef CONFIG_SEC_MHL_SUPPORT
    hdmi_dev->audio_ch_switch.name = "ch_hdmi_audio";
    ret  = switch_dev_register(&hdmi_dev->audio_ch_switch);
    if (ret) {
        dev_err(dev, "request hdmi_audio_switch class failed.\n");
        goto fail_switch;
    }
#endif

    mutex_init(&hdmi_dev->mutex);
    hdmi_dev->cur_timings =
        hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].dv_timings;
    hdmi_dev->cur_conf = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].conf;

    /* default audio configuration : disable audio */
    hdmi_dev->audio_enable = 1;
    hdmi_dev->audio_channel_count = 2;
    hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
    hdmi_dev->color_range = HDMI_RGB709_0_255;
    hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
    hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

    /* hdmi audio master clock */
    ret = hdmi_get_audio_master(hdmi_dev);
    if (ret) {
        hdmi_dev->audio_master_clk = 0;
        dev_warn(dev, "failed to get audio master information\n");
    }

    /* default aspect ratio is 16:9 */
    hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

    /* default HDMI streaming is stoped */
    hdmi_dev->streaming = HDMI_STOP;

    /* register hdmi subdev as entity */
    ret = hdmi_register_entity(hdmi_dev);
    if (ret)
        goto fail_mutex;

    hdmi_entity_info_print(hdmi_dev);

    pm_runtime_enable(dev);

    /* initialize hdcp resource */
    ret = hdcp_prepare(hdmi_dev);
    if (ret)
        goto fail_mutex;

    /* work after booting */
    queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
                       msecs_to_jiffies(1500));

    /* mapping SYSTEM registers */
    ret = hdmi_get_sysreg_addr(hdmi_dev);
    if (ret)
        goto fail_mutex;

    dev_info(dev, "probe sucessful\n");

    hdmi_debugfs_init(hdmi_dev);

    return 0;

fail_mutex:
    mutex_destroy(&hdmi_dev->mutex);

fail_switch:
    switch_dev_unregister(&hdmi_dev->hpd_switch);

fail_gpio:
    gpio_free(hdmi_dev->res.gpio_hpd);
    gpio_free(hdmi_dev->res.gpio_ls);
    gpio_free(hdmi_dev->res.gpio_dcdc);

fail_clk:
    hdmi_resources_cleanup(hdmi_dev);

fail_vdev:
    v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail:
    dev_err(dev, "probe failed\n");
    return ret;
}
コード例 #3
0
static int hdmi_probe(struct platform_device *pdev)
{
	struct s5p_hdmi_platdata *pdata = NULL;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	int ret;

	dev_info(dev, "probe start\n");

	hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_device), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(&pdev->dev, "no memory for hdmi device\n");
		return -ENOMEM;
	}
	hdmi_dev->dev = dev;

	hdmi_dev->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!hdmi_dev->pdata) {
		dev_err(&pdev->dev, "no memory for state\n");
		return -ENOMEM;
	}

	/* store platform data ptr to mixer context */
	if (dev->of_node) {
		of_property_read_u32(dev->of_node, "ip_ver", &hdmi_dev->pdata->ip_ver);
		pdata = hdmi_dev->pdata;
	} else {
		hdmi_dev->pdata = dev->platform_data;
		pdata = hdmi_dev->pdata;
	}
	dev_info(dev, "HDMI ip version %d\n", pdata->ip_ver);

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "get hdmi memory resource failed.\n");
		return -ENXIO;
	}
	hdmi_dev->regs = devm_request_and_ioremap(&pdev->dev, res);
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "failed to claim register region for hdmi\n");
		return -ENOENT;
	}

	/* mapping HDMIPHY_APB registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!res) {
		dev_err(dev, "get hdmiphy memory resource failed.\n");
		return -ENXIO;
	}
	hdmi_dev->phy_regs = devm_request_and_ioremap(&pdev->dev, res);
	if (hdmi_dev->phy_regs == NULL) {
		dev_err(dev, "failed to claim register region for hdmiphy\n");
		return -ENOENT;
	}

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		return -ENXIO;
	}
	ret = devm_request_irq(dev, res->start, hdmi_irq_handler,
			0, "hdmi-int", hdmi_dev);
	if (ret) {
		dev_err(dev, "request int interrupt failed.\n");
		return ret;
	} else {
		hdmi_dev->int_irq = res->start;
		disable_irq(hdmi_dev->int_irq);
		dev_info(dev, "success request hdmi-int irq\n");
	}

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail;
	}

	INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
	INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);

	/* setting the clocks */
	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_vdev;

	/* setting the GPIO */
	ret = hdmi_set_gpio(hdmi_dev);
	if (ret) {
		dev_err(dev, "failed to get GPIO\n");
		goto fail_clk;
	}

	/* External hpd */
	hdmi_dev->ext_irq = gpio_to_irq(hdmi_dev->res.gpio_hpd);
	ret = devm_request_irq(dev, hdmi_dev->ext_irq, hdmi_irq_handler_ext,
			IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
	if (ret) {
		dev_err(dev, "request ext interrupt failed.\n");
		goto fail_gpio;
	} else {
		dev_info(dev, "success request hdmi-ext irq\n");
	}

	hdmi_dev->hpd_switch.name = "hdmi";
	ret = switch_dev_register(&hdmi_dev->hpd_switch);
	if (ret) {
		dev_err(dev, "request switch class failed.\n");
		goto fail_gpio;
	}

	mutex_init(&hdmi_dev->mutex);

	if (soc_is_exynos5250()) {
		drv_data = (struct hdmi_driver_data *)
			platform_get_device_id(pdev)->driver_data;
		dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

		phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
		if (phy_adapter == NULL) {
			dev_err(dev, "adapter request failed\n");
			ret = -ENXIO;
			goto fail_switch;
		}

		hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
				phy_adapter, &hdmiphy_info, NULL);
		/* on failure or not adapter is no longer useful */
		i2c_put_adapter(phy_adapter);
		if (hdmi_dev->phy_sd == NULL) {
			dev_err(dev, "missing subdev for hdmiphy\n");
			ret = -ENODEV;
			goto fail_switch;
		}
	}

	hdmi_dev->cur_timings =
		hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].dv_timings;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].conf;

	/* default audio configuration : enable audio */
	hdmi_dev->audio_enable = 1;
	hdmi_dev->audio_channel_count = 2;
	hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->color_range = HDMI_RGB709_0_255;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* default aspect ratio is 16:9 */
	hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

	/* default HDMI streaming is stoped */
	hdmi_dev->streaming = HDMI_STOP;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_switch;

	hdmi_entity_info_print(hdmi_dev);

	pm_runtime_enable(dev);

	/* initialize hdcp resource */
	ret = hdcp_prepare(hdmi_dev);
	if (ret)
		goto fail_switch;

	/* work after booting */
	queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
					msecs_to_jiffies(1500));
	/* TODO : Check the PHY power off is implemented at pm_domains
	 * If not, PHY power off should be applied at here */

	dev_info(dev, "probe sucessful\n");

	hdmi_debugfs_init(hdmi_dev);

	return 0;

fail_switch:
	switch_dev_unregister(&hdmi_dev->hpd_switch);
	mutex_destroy(&hdmi_dev->mutex);

fail_gpio:
	gpio_free(hdmi_dev->res.gpio_hpd);
	gpio_free(hdmi_dev->res.gpio_ls);
	gpio_free(hdmi_dev->res.gpio_dcdc);

fail_clk:
	hdmi_resources_cleanup(hdmi_dev);

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}
コード例 #4
0
ファイル: hdmi_drv.c プロジェクト: advx9600/kernel-4.4-RuiEr
static int __devinit hdmi_probe(struct platform_device *pdev)
{
	struct s5p_hdmi_platdata *pdata;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	struct generic_pm_domain *genpd;
	int ret;

	dev_dbg(dev, "probe start\n");

	hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(dev, "out of memory\n");
		ret = -ENOMEM;
		goto fail;
	}

	hdmi_dev->dev = dev;

	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_hdev;

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(dev, "get memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* External hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(dev, "get external interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->ext_irq = res->start;

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (res == NULL) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->int_irq = res->start;

	INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
	INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);
	mutex_init(&hdmi_dev->mutex);

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail_regs;
	}

	drv_data = (struct hdmi_driver_data *)
		platform_get_device_id(pdev)->driver_data;
	dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

	phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
	if (phy_adapter == NULL) {
		dev_err(dev, "adapter request failed\n");
		ret = -ENXIO;
		goto fail_vdev;
	}

	hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
		phy_adapter, &hdmiphy_info, NULL);
	/* on failure or not adapter is no longer useful */
	i2c_put_adapter(phy_adapter);
	if (hdmi_dev->phy_sd == NULL) {
		dev_err(dev, "missing subdev for hdmiphy\n");
		ret = -ENODEV;
		goto fail_vdev;
	}

	pdata = pdev->dev.platform_data;

	/* HDMI PHY power off
	 * HDMI PHY is on as default configuration
	 * So, HDMI PHY must be turned off if it's not used */
	if (pdata->hdmiphy_enable)
		pdata->hdmiphy_enable(pdev, 1);
	v4l2_subdev_call(hdmi_dev->phy_sd, core, s_power, 0);
	if (pdata->hdmiphy_enable)
		pdata->hdmiphy_enable(pdev, 0);

#ifdef CONFIG_PM_GENERIC_DOMAINS
	genpd = dev_to_genpd(hdmi_dev->dev);
	if (IS_ERR(genpd)) {
		dev_err(dev, "failed get genpd\n");
		goto fail_vdev;
	}
	genpd->domain.ops.suspend = hdmi_suspend;
	genpd->domain.ops.resume = hdmi_resume;
#endif

	pm_runtime_enable(dev);

	hdmi_dev->hpd_switch.name = "hdmi";
	switch_dev_register(&hdmi_dev->hpd_switch);
	hdmi_dev->hpd_audio_switch.name = "hdmi_audio";
	switch_dev_register(&hdmi_dev->hpd_audio_switch);

	ret = request_irq(hdmi_dev->int_irq, hdmi_irq_handler,
			0, "hdmi-int", hdmi_dev);
	if (ret) {
		dev_err(dev, "request int interrupt failed.\n");
		goto fail_vdev;
	}
	disable_irq(hdmi_dev->int_irq);

	s5p_v4l2_int_src_ext_hpd();
	ret = request_irq(hdmi_dev->ext_irq, hdmi_irq_handler_ext,
			IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
	if (ret) {
		dev_err(dev, "request ext interrupt failed.\n");
		goto fail_ext;
	}

	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);

	/* default audio configuration : disable audio */
	hdmi_dev->audio_enable = 0;
	hdmi_dev->audio_channel_count = 2;
	hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->color_range = 3;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* default aspect ratio is 16:9 */
	hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_irq;

	hdmi_entity_info_print(hdmi_dev);

	/* initialize hdcp resource */
	ret = hdcp_prepare(hdmi_dev);
	if (ret)
		goto fail_irq;

	queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
					  msecs_to_jiffies(1000));

	dev_info(dev, "probe sucessful\n");

	hdmi_debugfs_init(hdmi_dev);

	return 0;

fail_irq:
	free_irq(hdmi_dev->ext_irq, hdmi_dev);

fail_ext:
	free_irq(hdmi_dev->int_irq, hdmi_dev);

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail_regs:
	iounmap(hdmi_dev->regs);

fail_init:
	hdmi_resources_cleanup(hdmi_dev);

fail_hdev:
	kfree(hdmi_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}
コード例 #5
0
ファイル: hdmi_drv.c プロジェクト: amuxtux/exynos4210
static int __devinit hdmi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	int ret;
	unsigned int irq_type;

	dev_dbg(dev, "probe start\n");

	hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(dev, "out of memory\n");
		ret = -ENOMEM;
		goto fail;
	}

	hdmi_dev->dev = dev;

	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_hdev;

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(dev, "get memory resource failed.\n");
		ret = -ENXIO;
		goto fail_init;
	}

	hdmi_dev->regs = ioremap(res->start, resource_size(res));
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "register mapping failed.\n");
		ret = -ENXIO;
		goto fail_hdev;
	}

	/* External hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(dev, "get external interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->ext_irq = res->start;

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (res == NULL) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		ret = -ENXIO;
		goto fail_regs;
	}
	hdmi_dev->int_irq = res->start;

	/* workqueue for HPD */
	hdmi_dev->hpd_wq = create_workqueue("hdmi-hpd");
	if (hdmi_dev->hpd_wq == NULL)
		ret = -ENXIO;
	INIT_WORK(&hdmi_dev->hpd_work, s5p_hpd_kobject_uevent);

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail_regs;
	}

	drv_data = (struct hdmi_driver_data *)
		platform_get_device_id(pdev)->driver_data;
	dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

	phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
	if (phy_adapter == NULL) {
		dev_err(dev, "adapter request failed\n");
		ret = -ENXIO;
		goto fail_vdev;
	}

	hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
		phy_adapter, &hdmiphy_info, NULL);
	/* on failure or not adapter is no longer useful */
	i2c_put_adapter(phy_adapter);
	if (hdmi_dev->phy_sd == NULL) {
		dev_err(dev, "missing subdev for hdmiphy\n");
		ret = -ENODEV;
		goto fail_vdev;
	}

	/* HDMI PHY power off
	 * HDMI PHY is on as default configuration
	 * So, HDMI PHY must be turned off if it's not used */
	clk_enable(hdmi_dev->res.hdmiphy);
	v4l2_subdev_call(hdmi_dev->phy_sd, core, s_power, 0);
	clk_disable(hdmi_dev->res.hdmiphy);

	pm_runtime_enable(dev);

	/* irq setting by TV power on/off status */
	if (!pm_runtime_suspended(hdmi_dev->dev)) {
		hdmi_dev->curr_irq = hdmi_dev->int_irq;
		irq_type = 0;
		s5p_v4l2_int_src_hdmi_hpd();
	} else {
		if (s5p_v4l2_hpd_read_gpio())
			atomic_set(&hdmi_dev->hpd_state, HPD_HIGH);
		else
			atomic_set(&hdmi_dev->hpd_state, HPD_LOW);
		hdmi_dev->curr_irq = hdmi_dev->ext_irq;
		irq_type = IRQ_TYPE_EDGE_BOTH;
		s5p_v4l2_int_src_ext_hpd();
	}

	hdmi_dev->hpd_user_checked = false;

	ret = request_irq(hdmi_dev->curr_irq, hdmi_irq_handler,
			irq_type, "hdmi", hdmi_dev);

	if (ret) {
		dev_err(dev, "request interrupt failed.\n");
		goto fail_vdev;
	}

	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);

	/* default audio configuration : enable audio */
	hdmi_dev->audio_enable = 1;
	hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_irq;

	hdmi_entity_info_print(hdmi_dev);

	/* initialize hdcp resource */
	ret = hdcp_prepare(hdmi_dev);
	if (ret)
		goto fail_irq;

	dev_info(dev, "probe sucessful\n");

	return 0;

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail_irq:
	free_irq(hdmi_dev->curr_irq, hdmi_dev);

fail_regs:
	iounmap(hdmi_dev->regs);

fail_init:
	hdmi_resources_cleanup(hdmi_dev);

fail_hdev:
	kfree(hdmi_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}