Ejemplo n.º 1
0
static void hdmi_power_off_core(struct omap_dss_device *dssdev)
{
	hdmi_runtime_put();
	regulator_disable(hdmi.vdda_hdmi_dac_reg);
	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
	gpio_set_value(hdmi.ls_oe_gpio, 0);
}
Ejemplo n.º 2
0
static void hdmi_power_off_core(struct omap_dss_device *dssdev)
{
	hdmi.core_enabled = false;

	hdmi_runtime_put();
	regulator_disable(hdmi.vdda_reg);
}
Ejemplo n.º 3
0
static void hdmi_power_off(struct omap_dss_device *dssdev)
{
	dss_mgr_disable(dssdev->manager);

	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
	hdmi_runtime_put();
}
Ejemplo n.º 4
0
void hdmi_dump_regs(struct seq_file *s)
{
	mutex_lock(&hdmi.lock);

	if (hdmi_runtime_get())
		return;

	hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
	hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
	hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
	hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);
}
Ejemplo n.º 5
0
static int read_edid(u8 *buf, int len)
{
	int r;

	mutex_lock(&hdmi.lock);

	r = hdmi_runtime_get();
	BUG_ON(r);

	r = hdmi4_read_edid(&hdmi.core,  buf, len);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);

	return r;
}
Ejemplo n.º 6
0
bool omapdss_hdmi_detect(void)
{
	int r;

	mutex_lock(&hdmi.lock);

	r = hdmi_runtime_get();
	BUG_ON(r);

	r = hdmi.ip_data.ops->detect(&hdmi.ip_data);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);

	return r == 1;
}
Ejemplo n.º 7
0
Archivo: hdmi.c Proyecto: FoundYa/linux
static void hdmi_power_off(struct omap_dss_device *dssdev)
{
	struct omap_overlay_manager *mgr = dssdev->output->manager;

	dss_mgr_disable(mgr);

	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
	hdmi_runtime_put();

	regulator_disable(hdmi.vdda_hdmi_dac_reg);

	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
	gpio_set_value(hdmi.ls_oe_gpio, 0);
}
Ejemplo n.º 8
0
int omapdss_hdmi_read_edid(u8 *buf, int len)
{
	int r;

	mutex_lock(&hdmi.lock);

	r = hdmi_runtime_get();
	BUG_ON(r);

	r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);

	return r;
}
Ejemplo n.º 9
0
static void hdmi_dump_regs(struct seq_file *s)
{
	mutex_lock(&hdmi.lock);

	if (hdmi_runtime_get()) {
		mutex_unlock(&hdmi.lock);
		return;
	}

	hdmi_wp_dump(&hdmi.wp, s);
	hdmi_pll_dump(&hdmi.pll, s);
	hdmi_phy_dump(&hdmi.phy, s);
	hdmi5_core_dump(&hdmi.core, s);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);
}
Ejemplo n.º 10
0
static int hdcp_wq_start_authentication(void)
{
	int status = 0;
	struct hdmi_ip_data *ip_data;

	HDCP_DBG("hdcp_wq_start_authentication %ums\n",
		jiffies_to_msecs(jiffies));

	if (hdmi_runtime_get()) {
		HDCP_ERR("%s Error enabling clocks\n", __func__);
		return -EINVAL;
	}

	ip_data = get_hdmi_ip_data();
	if (ip_data->ops->hdcp_enable)
		ip_data->ops->hdcp_enable(ip_data);
	else
		status = -EINVAL;

	hdmi_runtime_put();
	return status;
}
Ejemplo n.º 11
0
static int read_edid(u8 *buf, int len)
{
	int r;
	int idlemode;

	mutex_lock(&hdmi.lock);

	r = hdmi_runtime_get();
	BUG_ON(r);

	idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
	/* No-idle mode */
	REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);

	r = hdmi5_read_edid(&hdmi.core,  buf, len);

	REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);

	hdmi_runtime_put();
	mutex_unlock(&hdmi.lock);

	return r;
}
Ejemplo n.º 12
0
static void __exit hdcp_exit(void)
{
	HDCP_DBG("hdcp_exit() %ums\n", jiffies_to_msecs(jiffies));

	mutex_lock(&hdcp.lock);

	kfree(hdcp.en_ctrl);

	if (hdmi_runtime_get()) {
		HDCP_ERR("%s Error enabling clocks\n", __func__);
		goto err_handling;
	}

	/* Un-register HDCP callbacks to HDMI library */
	omapdss_hdmi_register_hdcp_callbacks(NULL, NULL, NULL);

	hdmi_runtime_put();

err_handling:
	misc_deregister(hdcp.mdev);
	kfree(hdcp.mdev);

	iounmap(hdcp.deshdcp_base_addr);

	if (cpu_is_omap44xx())
		iounmap(hdcp.hdmi_wp_base_addr);

	kfree(hdcp.hdcp_work);
	destroy_workqueue(hdcp.workqueue);

	mutex_unlock(&hdcp.lock);

	mutex_destroy(&hdcp.lock);

	mutex_destroy(&hdcp.re_entrant_lock);
}
Ejemplo n.º 13
0
static int hdmi_audio_register(struct device *dev)
{
	struct omap_hdmi_audio_pdata pdata = {
		.dev = dev,
		.dss_version = omapdss_get_version(),
		.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
		.ops = &hdmi_audio_ops,
	};

	hdmi.audio_pdev = platform_device_register_data(
		dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,
		&pdata, sizeof(pdata));

	if (IS_ERR(hdmi.audio_pdev))
		return PTR_ERR(hdmi.audio_pdev);

	hdmi_runtime_get();
	hdmi.wp_idlemode =
		REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
	hdmi_runtime_put();

	return 0;
}

/* HDMI HW IP initialisation */
static int hdmi5_bind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);
	int r;
	int irq;

	hdmi.pdev = pdev;
	dev_set_drvdata(&pdev->dev, &hdmi);

	mutex_init(&hdmi.lock);
	spin_lock_init(&hdmi.audio_playing_lock);

	if (pdev->dev.of_node) {
		r = hdmi_probe_of(pdev);
		if (r)
			return r;
	}

	r = hdmi_wp_init(pdev, &hdmi.wp);
	if (r)
		return r;

	r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp);
	if (r)
		return r;

	r = hdmi_phy_init(pdev, &hdmi.phy);
	if (r)
		goto err;

	r = hdmi5_core_init(pdev, &hdmi.core);
	if (r)
		goto err;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		DSSERR("platform_get_irq failed\n");
		r = -ENODEV;
		goto err;
	}

	r = devm_request_threaded_irq(&pdev->dev, irq,
			NULL, hdmi_irq_handler,
			IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
	if (r) {
		DSSERR("HDMI IRQ request failed\n");
		goto err;
	}

	pm_runtime_enable(&pdev->dev);

	hdmi_init_output(pdev);

	r = hdmi_audio_register(&pdev->dev);
	if (r) {
		DSSERR("Registering HDMI audio failed %d\n", r);
		hdmi_uninit_output(pdev);
		pm_runtime_disable(&pdev->dev);
		return r;
	}

	dss_debugfs_create_file("hdmi", hdmi_dump_regs);

	return 0;
err:
	hdmi_pll_uninit(&hdmi.pll);
	return r;
}

static void hdmi5_unbind(struct device *dev, struct device *master, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);

	if (hdmi.audio_pdev)
		platform_device_unregister(hdmi.audio_pdev);

	hdmi_uninit_output(pdev);

	hdmi_pll_uninit(&hdmi.pll);

	pm_runtime_disable(&pdev->dev);
}

static const struct component_ops hdmi5_component_ops = {
	.bind	= hdmi5_bind,
	.unbind	= hdmi5_unbind,
};

static int hdmi5_probe(struct platform_device *pdev)
{
	return component_add(&pdev->dev, &hdmi5_component_ops);
}

static int hdmi5_remove(struct platform_device *pdev)
{
	component_del(&pdev->dev, &hdmi5_component_ops);
	return 0;
}
Ejemplo n.º 14
0
static void omap4_hdcp_work_queue(struct work_struct *work)
{
        struct hdcp_worker_data *hdcp_w =
                container_of(work, struct hdcp_worker_data, dwork.work);
        int event = atomic_read(&hdcp_w->state);

        mutex_lock(&hdcp.lock);

        hdmi_runtime_get();

        HDCP_DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d auth=%d evt= %x %d"
            " hdcp_ctrl=%02x",
                jiffies_to_msecs(jiffies),
                hdcp.hdmi_state,
                hdcp.hdcp_state,
                hdcp.auth_state,
                (event & 0xFF00) >> 8,
                event & 0xFF,
                RD_REG_32(hdcp.hdmi_wp_base_addr + HDMI_IP_CORE_SYSTEM,
                          HDMI_IP_CORE_SYSTEM__HDCP_CTRL));

        /* Clear pending_wq_event
         * In case a delayed work is scheduled from the state machine
         * "pending_wq_event" is used to memorize pointer on the event to be
         * able to cancel any pending work in case HDCP is disabled
         */
        if (event & HDCP_WORKQUEUE_SRC)
                hdcp.pending_wq_event = 0;

        /* First handle HDMI state */
        if (event == HDCP_START_FRAME_EVENT) {
                hdcp.pending_start = 0;
                hdcp.hdmi_state = HDMI_STARTED;
        }
        /**********************/
        /* HDCP state machine */
        /**********************/
        switch (hdcp.hdcp_state) {

        /* State */
        /*********/
        case HDCP_DISABLED:
                /* HDCP enable control or re-authentication event */
                if (event == HDCP_ENABLE_CTL) {
                        if (hdcp.en_ctrl->nb_retry == 0)
                                hdcp.retry_cnt = HDCP_INFINITE_REAUTH;
                        else
                                hdcp.retry_cnt = hdcp.en_ctrl->nb_retry;

                        if (hdcp.hdmi_state == HDMI_STARTED)
                                omap4_hdcp_wq_start_authentication();
                        else
                                hdcp.hdcp_state = HDCP_ENABLE_PENDING;
                }

                break;

        /* State */
        /*********/
        case HDCP_ENABLE_PENDING:
                /* HDMI start frame event */
                if (event == HDCP_START_FRAME_EVENT)
                        omap4_hdcp_wq_start_authentication();

                break;

        /* State */
        /*********/
        case HDCP_AUTHENTICATION_START:
                /* Re-authentication */
                if (event == HDCP_AUTH_REATT_EVENT)
                        omap4_hdcp_wq_start_authentication();

                break;

        /* State */
        /*********/
        case HDCP_WAIT_R0_DELAY:
                /* R0 timer elapsed */
                if (event == HDCP_R0_EXP_EVENT)
                        hdcp_wq_check_r0();

                break;

        /* State */
        /*********/
        case HDCP_WAIT_KSV_LIST:
                /* Ri failure */
                if (event == HDCP_RI_FAIL_EVENT) {
                        printk(KERN_INFO "HDCP: Ri check failure\n");

                        hdcp_wq_authentication_failure();
                }
                /* KSV list ready event */
                else if (event == HDCP_KSV_LIST_RDY_EVENT)
                        hdcp_wq_step2_authentication();
                /* Timeout */
                else if (event == HDCP_KSV_TIMEOUT_EVENT) {
                        printk(KERN_INFO "HDCP: BCAPS polling timeout\n");
                        hdcp_wq_authentication_failure();
                }
                break;

        /* State */
        /*********/
        case HDCP_LINK_INTEGRITY_CHECK:
                /* Ri failure */
                if (event == HDCP_RI_FAIL_EVENT) {
                        printk(KERN_INFO "HDCP: Ri check failure\n");
                        hdcp_wq_authentication_failure();
                }
                break;

        default:
                printk(KERN_WARNING "HDCP: error - unknow HDCP state\n");
                break;
        }

        kfree(hdcp_w);
        hdcp_w = 0;
        if (event == HDCP_START_FRAME_EVENT)
                hdcp.pending_start = 0;
        if (event == HDCP_KSV_LIST_RDY_EVENT ||
            event == HDCP_R0_EXP_EVENT) {
                hdcp.pending_wq_event = 0;
        }

        HDCP_DBG("hdcp_work_queue() - END - %u hdmi=%d hdcp=%d auth=%d evt=%x %d ",
                jiffies_to_msecs(jiffies),
                hdcp.hdmi_state,
                hdcp.hdcp_state,
                hdcp.auth_state,
                (event & 0xFF00) >> 8,
                event & 0xFF);

        hdmi_runtime_put();
        mutex_unlock(&hdcp.lock);
}
Ejemplo n.º 15
0
static int __init hdcp_init(void)
{
	HDCP_DBG("hdcp_init() %ums\n", jiffies_to_msecs(jiffies));

	if (cpu_is_omap44xx()) {
	        /* Map HDMI WP address */
	        hdcp.hdmi_wp_base_addr = ioremap(HDMI_WP, 0x1000);
	        if (!hdcp.hdmi_wp_base_addr) {
	                printk(KERN_ERR "HDCP: HDMI WP IOremap error\n");
	                return -EFAULT;
	        }
	} else {
		hdcp.hdmi_wp_base_addr = NULL;
	}

	hdcp.hdcp_work = kzalloc(sizeof(struct hdcp_worker_data), GFP_KERNEL);
	if (!hdcp.hdcp_work) {
		HDCP_ERR("Could not allocate HDCP worker  structure\n");
		goto err_alloc_work;
	}

	hdcp.mdev = kzalloc(sizeof(struct miscdevice), GFP_KERNEL);
	if (!hdcp.mdev) {
		HDCP_ERR("Could not allocate misc device memory\n");
		goto err_alloc_mdev;
	}

	/* Map DESHDCP in kernel address space */
	hdcp.deshdcp_base_addr = ioremap(DSS_SS_FROM_L3__DESHDCP, 0x34);

	if (!hdcp.deshdcp_base_addr) {
		HDCP_ERR("DESHDCP IOremap error\n");
		goto err_map_deshdcp;
	}

	mutex_init(&hdcp.lock);

	hdcp.mdev->minor = MISC_DYNAMIC_MINOR;
	hdcp.mdev->name = "hdcp";
	hdcp.mdev->mode = 0666;
	hdcp.mdev->fops = &hdcp_fops;

	if (misc_register(hdcp.mdev)) {
		HDCP_ERR("Could not add character driver\n");
		goto err_misc_register;
	}

	mutex_lock(&hdcp.lock);

        /* Variable init */
        hdcp.en_ctrl  = 0;
        hdcp.hdcp_state = HDCP_DISABLED;
        hdcp.pending_start = 0;
        hdcp.pending_wq_event = 0;
        hdcp.retry_cnt = 0;
        hdcp.auth_state = HDCP_STATE_DISABLED;
        hdcp.pending_disable = 0;
        hdcp.hdcp_up_event = 0;
        hdcp.hdcp_down_event = 0;
        hdcp_wait_re_entrance = 0;
        hdcp.hpd_low = 0;

        spin_lock_init(&hdcp.spinlock);

        init_completion(&hdcp_comp);

	hdcp.workqueue = create_singlethread_workqueue("hdcp");
	if (hdcp.workqueue == NULL) {
		HDCP_ERR("Could not create HDCP workqueue\n");
		goto err_add_driver;
	}

	INIT_DELAYED_WORK(&hdcp.hdcp_work->dwork, hdcp_work_queue);

	mutex_init(&hdcp.re_entrant_lock);

	if (hdmi_runtime_get()) {
		HDCP_ERR("%s Error enabling clocks\n", __func__);
		goto err_runtime;
	}

	/* Register HDCP callbacks to HDMI library */
	if (cpu_is_omap44xx())
		omapdss_hdmi_register_hdcp_callbacks(&omap4_hdcp_start_frame_cb,
				 &omap4_hdcp_3des_cb, &omap4_hdcp_irq_cb);
	else
		omapdss_hdmi_register_hdcp_callbacks(&hdcp_start_frame_cb,
				 &hdcp_3des_cb, &hdcp_irq_cb);

	hdmi_runtime_put();

        mutex_unlock(&hdcp.lock);

	hdcp_load_keys();

	return 0;

err_runtime:
	mutex_destroy(&hdcp.re_entrant_lock);

	destroy_workqueue(hdcp.workqueue);

err_add_driver:
	misc_deregister(hdcp.mdev);

	mutex_unlock(&hdcp.lock);

err_misc_register:
	mutex_destroy(&hdcp.lock);

	iounmap(hdcp.deshdcp_base_addr);

err_map_deshdcp:
	kfree(hdcp.mdev);

err_alloc_mdev:
	kfree(hdcp.hdcp_work);

err_alloc_work:
	if (cpu_is_omap44xx())
		iounmap(hdcp.hdmi_wp_base_addr);

	return -EFAULT;
}
Ejemplo n.º 16
0
static int hdmi_power_on(struct omap_dss_device *dssdev)
{
	int r, code = 0;
	struct omap_video_timings *p;
	unsigned long phy;

	r = hdmi_runtime_get();
	if (r)
		return r;

	dss_mgr_disable(dssdev->manager);

	p = &dssdev->panel.timings;

	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
		dssdev->panel.timings.x_res,
		dssdev->panel.timings.y_res);

	code = get_timings_index();
	update_hdmi_timings(&hdmi.ip_data.cfg, p, code);

	phy = p->pixel_clock;

	hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);

	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);

	/* config the PLL and PHY hdmi_set_pll_pwrfirst */
	r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
	if (r) {
		DSSDBG("Failed to lock PLL\n");
		goto err;
	}

	r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
	if (r) {
		DSSDBG("Failed to start PHY\n");
		goto err;
	}

	hdmi.ip_data.cfg.cm.mode = hdmi.mode;
	hdmi.ip_data.cfg.cm.code = hdmi.code;
	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);

	/* Make selection of HDMI in DSS */
	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);

	/* Select the dispc clock source as PRCM clock, to ensure that it is not
	 * DSI PLL source as the clock selected by DSI PLL might not be
	 * sufficient for the resolution selected / that can be changed
	 * dynamically by user. This can be moved to single location , say
	 * Boardfile.
	 */
	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);

	/* bypass TV gamma table */
	dispc_enable_gamma_table(0);

	/* tv size */
	dispc_set_digit_size(dssdev->panel.timings.x_res,
			dssdev->panel.timings.y_res);

	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);

	r = dss_mgr_enable(dssdev->manager);
	if (r)
		goto err_mgr_enable;

	return 0;

err_mgr_enable:
	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
err:
	hdmi_runtime_put();
	return -EIO;
}
Ejemplo n.º 17
0
Archivo: hdmi.c Proyecto: FoundYa/linux
static int hdmi_power_on(struct omap_dss_device *dssdev)
{
	int r;
	struct omap_video_timings *p;
	struct omap_overlay_manager *mgr = dssdev->output->manager;
	unsigned long phy;

	gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
	gpio_set_value(hdmi.ls_oe_gpio, 1);

	/* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
	udelay(300);

	r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
	if (r)
		goto err_vdac_enable;

	r = hdmi_runtime_get();
	if (r)
		goto err_runtime_get;

	dss_mgr_disable(mgr);

	p = &hdmi.ip_data.cfg.timings;

	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);

	phy = p->pixel_clock;

	hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);

	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);

	/* config the PLL and PHY hdmi_set_pll_pwrfirst */
	r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
	if (r) {
		DSSDBG("Failed to lock PLL\n");
		goto err_pll_enable;
	}

	r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
	if (r) {
		DSSDBG("Failed to start PHY\n");
		goto err_phy_enable;
	}

	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);

	/* Make selection of HDMI in DSS */
	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);

	/* Select the dispc clock source as PRCM clock, to ensure that it is not
	 * DSI PLL source as the clock selected by DSI PLL might not be
	 * sufficient for the resolution selected / that can be changed
	 * dynamically by user. This can be moved to single location , say
	 * Boardfile.
	 */
	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);

	/* bypass TV gamma table */
	dispc_enable_gamma_table(0);

	/* tv size */
	dss_mgr_set_timings(mgr, p);

	r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
	if (r)
		goto err_vid_enable;

	r = dss_mgr_enable(mgr);
	if (r)
		goto err_mgr_enable;

	return 0;

err_mgr_enable:
	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
err_vid_enable:
	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
err_phy_enable:
	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
err_pll_enable:
	hdmi_runtime_put();
err_runtime_get:
	regulator_disable(hdmi.vdda_hdmi_dac_reg);
err_vdac_enable:
	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
	gpio_set_value(hdmi.ls_oe_gpio, 0);
	return -EIO;
}