Ejemplo n.º 1
0
static int cat66121_hdmi_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
    int rc = 0;
	struct rk_hdmi_platform_data *pdata = client->dev.platform_data;
	
	cat66121_hdmi = kzalloc(sizeof(struct cat66121_hdmi_pdata), GFP_KERNEL);
	if(!cat66121_hdmi)
	{
        dev_err(&client->dev, "no memory for state\n");
    	return -ENOMEM;
    }
	cat66121_hdmi->client = client;
	i2c_set_clientdata(client, cat66121_hdmi);
	
	hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);
	if(!hdmi)
	{
    	dev_err(&client->dev, "cat66121 hdmi kmalloc fail!");
    	goto err_kzalloc_hdmi;
	}
	memset(hdmi, 0, sizeof(struct hdmi));
	hdmi->dev = &client->dev;
	
	if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
		hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
	else
		hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
	if(hdmi->lcdc == NULL)
	{
		dev_err(hdmi->dev, "can not connect to video source lcdc\n");
		rc = -ENXIO;
		goto err_request_lcdc;
	}
	if(pdata->io_init){
		if(pdata->io_init()<0){
			dev_err(&client->dev, "fail to rst chip\n");
			goto err_request_lcdc;
		}
	}
	if(cat66121_detect_device()!=1){
		dev_err(hdmi->dev, "can't find it6610 device \n");
		rc = -ENXIO;
		goto err_request_lcdc;
	}

	hdmi->xscale = 100;
	hdmi->yscale = 100;
	hdmi->insert = cat66121_hdmi_sys_insert;
	hdmi->remove = cat66121_hdmi_sys_remove;
	hdmi->control_output = cat66121_hdmi_sys_enalbe_output;
	hdmi->config_video = cat66121_hdmi_sys_config_video;
	hdmi->config_audio = cat66121_hdmi_sys_config_audio;
	hdmi->detect_hotplug = cat66121_hdmi_sys_detect_hpd;
	hdmi->read_edid = cat66121_hdmi_sys_read_edid;
	hdmi_sys_init();
	
	hdmi->workqueue = create_singlethread_workqueue("hdmi");
	INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
	
	#ifdef CONFIG_HAS_EARLYSUSPEND
	hdmi->early_suspend.suspend = hdmi_early_suspend;
	hdmi->early_suspend.resume = hdmi_early_resume;
	hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;
	register_early_suspend(&hdmi->early_suspend);
	#endif
	
	hdmi_register_display_sysfs(hdmi, NULL);
	#ifdef CONFIG_SWITCH
	hdmi->switch_hdmi.name="hdmi";
	switch_dev_register(&(hdmi->switch_hdmi));
	#endif
		
	spin_lock_init(&hdmi->irq_lock);
	mutex_init(&hdmi->enable_mutex);
	

	cat66121_hdmi_sys_init();
#ifdef HDMI_DEBUG
	device_create_file(&(client->dev), &hdmi_attrs[0]);
#endif

#ifdef HDMI_USE_IRQ
	if(client->irq != INVALID_GPIO) {
		INIT_WORK(&cat66121_hdmi->irq_work, cat66121_irq_work_func);
		schedule_work(&cat66121_hdmi->irq_work);
		if((rc = gpio_request(client->irq, "hdmi gpio")) < 0)
	    {
	        dev_err(&client->dev, "fail to request gpio %d\n", client->irq);
	        goto err_request_lcdc;
	    }

		schedule_delayed_work(&check_status_work, msecs_to_jiffies(5000));
	    hdmi->irq = gpio_to_irq(client->irq);
		cat66121_hdmi->gpio = client->irq;
	    gpio_pull_updown(client->irq, GPIOPullUp);
	    gpio_direction_input(client->irq);
	    if((rc = request_irq(hdmi->irq, cat66121_irq, IRQF_TRIGGER_FALLING, NULL, hdmi)) < 0)
	    {
	        dev_err(&client->dev, "fail to request hdmi irq\n");
	        goto err_request_irq;
	    }
	}
	else
#else
	{
		cat66121_hdmi->workqueue = create_singlethread_workqueue("cat66121 irq");
		INIT_DELAYED_WORK(&(cat66121_hdmi->delay_work), cat66121_irq_work_func);
		cat66121_irq_work_func(NULL);
	}
#endif

	dev_info(&client->dev, "cat66121 hdmi i2c probe ok\n");
	
	g_hdmi_data = pdata;
    return 0;
	
err_request_irq:
	gpio_free(client->irq);
err_request_lcdc:
	kfree(hdmi);
	hdmi = NULL;
err_kzalloc_hdmi:
	kfree(cat66121_hdmi);
	cat66121_hdmi = NULL;
	dev_err(&client->dev, "cat66121 hdmi probe error\n");
	return rc;

}
Ejemplo n.º 2
0
static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
{
	int ret;
        struct rk616_hdmi *rk616_hdmi;
        struct resource __maybe_unused *mem;
        struct resource __maybe_unused *res;

        rk616_hdmi = devm_kzalloc(&pdev->dev, sizeof(*rk616_hdmi), GFP_KERNEL);
        if(!rk616_hdmi)
	{
		dev_err(&pdev->dev, ">>rk616_hdmi kmalloc fail!");
		return -ENOMEM;
	}
        hdmi = &rk616_hdmi->g_hdmi;

#ifdef CONFIG_ARCH_RK3026
	rk616_hdmi->rk616_drv = NULL;
#else
	rk616_hdmi->rk616_drv = dev_get_drvdata(pdev->dev.parent);
	if(!(rk616_hdmi->rk616_drv))
	{
		dev_err(&pdev->dev,"null mfd device rk616!\n");
		return -ENODEV;
	}

#endif

	hdmi->dev = &pdev->dev;
	platform_set_drvdata(pdev, hdmi);

	if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
		hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
	else
		hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
	if(hdmi->lcdc == NULL)
	{
		dev_err(hdmi->dev, "can not connect to video source lcdc\n");
		ret = -ENXIO;
		goto err0;
	}
	hdmi->xscale = 100;
	hdmi->yscale = 100;


	hdmi_sys_init();

	hdmi->workqueue = create_singlethread_workqueue("hdmi");
	INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);

#ifdef CONFIG_HAS_EARLYSUSPEND
	hdmi->early_suspend.suspend = hdmi_early_suspend;
	hdmi->early_suspend.resume = hdmi_early_resume;
	hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;
	register_early_suspend(&hdmi->early_suspend);
#endif

#ifdef CONFIG_SWITCH
	hdmi->switch_hdmi.name="hdmi";
	switch_dev_register(&(hdmi->switch_hdmi));
#endif

	spin_lock_init(&hdmi->irq_lock);
	mutex_init(&hdmi->enable_mutex);

	INIT_DELAYED_WORK(&rk616_hdmi->rk616_delay_work, rk616_delay_work_func);

	/* get the IRQ */
	// if(rk616->pdata->hdmi_irq != INVALID_GPIO)
        
#ifdef CONFIG_ARCH_RK3026
        hdmi->hclk = clk_get(NULL,"pclk_hdmi");
        if(IS_ERR(hdmi->hclk)) {
                dev_err(hdmi->dev, "Unable to get hdmi hclk\n");
                ret = -ENXIO;
                goto err0;
        }
        clk_enable(hdmi->hclk);
        
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(hdmi->dev, "Unable to get register resource\n");
                ret = -ENXIO;
                goto err0;
        }
        hdmi->regbase_phy = res->start;
        hdmi->regsize_phy = (res->end - res->start) + 1;
        mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);
        if (!mem) {
                dev_err(hdmi->dev, "failed to request mem region for hdmi\n");
                ret = -ENOENT;
                goto err0;
        }
        
        printk("res->start = 0x%x\n, xhc-------res->end = 0x%x\n", res->start, res->end);
        hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);
        if (!hdmi->regbase) {
                dev_err(hdmi->dev, "cannot ioremap registers\n");
                ret = -ENXIO;
                goto err1;
        }
        
        // rk30_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_HDMI_DDCSDA);
        // rk30_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_HDMI_DDCSCL);
        // rk30_mux_api_set(GPIO0B7_HDMI_HOTPLUGIN_NAME, GPIO0B_HDMI_HOTPLUGIN);
        iomux_set(HDMI_DDCSDA);
        iomux_set(HDMI_DDCSCL);
        iomux_set(HDMI_HOTPLUGIN);
        
        ret = rk616_hdmi_initial();
        /* get the IRQ */
        hdmi->irq = platform_get_irq(pdev, 0);
        if(hdmi->irq <= 0) {
                dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
                hdmi->irq = 0;
        } else {               
                /* request the IRQ */
                ret = request_irq(hdmi->irq, rk616_hdmi_irq, 0, dev_name(&pdev->dev), hdmi);
                if (ret) {
                        dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
                        goto err1;
                }
        }
#else
        ret = rk616_hdmi_initial();
        if(rk616_hdmi->rk616_drv->pdata->hdmi_irq != INVALID_GPIO) {               
                INIT_WORK(&rk616_hdmi->rk616_irq_work_struct, rk616_irq_work_func);
                ret = gpio_request(rk616_hdmi->rk616_drv->pdata->hdmi_irq,"rk616_hdmi_irq");
                if(ret < 0) {
                        dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
                }
                gpio_direction_input(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
                hdmi->irq = gpio_to_irq(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
                if(hdmi->irq <= 0) {
                        dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
                        ret = -ENXIO;
                        goto err1;
                }
                
                /* request the IRQ */
                ret = request_irq(hdmi->irq, rk616_hdmi_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), &rk616_hdmi->rk616_irq_work_struct);
                if (ret) {
                        dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
                        goto err1;
                }
        } else {                
                /* use roll polling method */
                hdmi->irq = 0;
        }

#endif
	hdmi_register_display_sysfs(hdmi, NULL);

#if defined(CONFIG_DEBUG_FS)
	if(rk616_hdmi->rk616_drv && rk616_hdmi->rk616_drv->debugfs_dir) {
		debugfs_create_file("hdmi", S_IRUSR, rk616_hdmi->rk616_drv->debugfs_dir, rk616_hdmi->rk616_drv, &rk616_hdmi_reg_fops);
	} else {
                rk616_hdmi->debugfs_dir = debugfs_create_dir("rk616", NULL);
                if (IS_ERR(rk616_hdmi->debugfs_dir)) {
                        dev_err(hdmi->dev,"failed to create debugfs dir for rk616!\n");
                } else {
                        debugfs_create_file("hdmi", S_IRUSR, rk616_hdmi->debugfs_dir, rk616_hdmi, &rk616_hdmi_reg_fops);
                }
        }
#endif
	//rk616_delay_work_func(NULL);
	queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, msecs_to_jiffies(0));
	dev_info(hdmi->dev, "rk616 hdmi probe success.\n");
	return 0;
err1:
#ifdef CONFIG_SWITCH
	switch_dev_unregister(&(hdmi->switch_hdmi));
#endif
	hdmi_unregister_display_sysfs(hdmi);
#ifdef CONFIG_HAS_EARLYSUSPEND
	unregister_early_suspend(&hdmi->early_suspend);
#endif
err0:
	hdmi_dbg(hdmi->dev, "rk616 hdmi probe error.\n");
	kfree(hdmi);
	hdmi = NULL;
	return ret;
}
Ejemplo n.º 3
0
int HDMI_task(struct hdmi *hdmi)
{
	int rc, state, state_last, hpd, trytimes;
//	state = g_state;
//	hdmi_sys_show_state(hdmi, state);

	/* Process parametre changed */
	state = hdmi_sys_change(hdmi);
	
	/* Initialize hdmi chips when system start.*/
	if(state == HDMI_UNKNOWN)
	{
		rc = hdmi_sys_init(hdmi);
		state = WAIT_HOTPLUG;
	}
	
	if(!hdmi->enable)
		goto exit;

	/* Detect hdmi status */
	state = hdmi_sys_detect_status(hdmi, state);
	/* Process HDMI status machine */
	rc = 0;
	trytimes = 0;
	do
	{	
		state_last = state;

		switch(state)
		{
			case HDMI_INITIAL:
				rc = hdmi_sys_init(hdmi);
				if(rc == HDMI_ERROR_SUCESS)
				{
					hdmi->rate = 0;	
					state = WAIT_HOTPLUG;
				}
				else
					hdmi->rate = HDMI_TASK_INTERVAL;
				break;
			case WAIT_HOTPLUG:
				hdmi->rate = HDMI_TASK_INTERVAL;
				if(hdmi->hpd_status > HDMI_RECEIVER_REMOVE)
				{
					#ifdef HDMI_DEBUG_TIME
					hdmi_time_start = jiffies;
					#endif
							
					if(hdmi->ops->insert)
					{
						rc = hdmi->ops->insert(hdmi);
					}
					
					if(rc == HDMI_ERROR_SUCESS)
					{	
						state = READ_PARSE_EDID;
					}
					else
						hdmi->rate = HDMI_TASK_INTERVAL;	
				}
				break;
			case READ_PARSE_EDID:
				rc = hdmi_sys_parse_edid(hdmi);
				#ifdef HDMI_DEBUG_TIME
					hdmi_time_end = jiffies;
					if(hdmi_time_end > hdmi_time_start)
						hdmi_time_end -= hdmi_time_start;
					else
						hdmi_time_end += 0xFFFFFFFF - hdmi_time_start;
					dev_printk(KERN_INFO, hdmi->dev, "HDMI EDID parse cost %u ms\n", jiffies_to_msecs(hdmi_time_end));
				#endif
				if(rc == HDMI_ERROR_SUCESS)
				{
					hdmi->rate = 0;	
					state = WAIT_RX_SENSE;
					hdmi_sys_send_uevent(hdmi, KOBJ_ADD);
				}
				else
					hdmi->rate = HDMI_TASK_INTERVAL;
				break;
			case WAIT_RX_SENSE:
				if(hdmi->ops->detect_sink)
				{
					rc = hdmi->ops->detect_sink(hdmi, &hpd);
					hdmi->hpd_status = hpd;
					if(hpd == HDMI_RECEIVER_ACTIVE)
					{
						//Only when HDMI receiver is actived,
						//HDMI communication is successful.		
						state = WAIT_HDMI_ENABLE;		
						hdmi->rate = 0;
					}
					else
					{
						rc = HDMI_ERROR_FALSE;	
						hdmi->rate = HDMI_TASK_INTERVAL;	
					}	
				}
				else
				{
					hdmi->hpd_status = HDMI_RECEIVER_ACTIVE;
					hdmi->rate = 0;
					state = WAIT_HDMI_ENABLE;
					if(hdmi->auto_switch)
						hdmi_enable(hdmi);
				}
				#ifdef HDMI_DEBUG_TIME
				hdmi_time_end = jiffies;
				if(hdmi_time_end > hdmi_time_start)
					hdmi_time_end -= hdmi_time_start;
				else
					hdmi_time_end += 0xFFFFFFFF - hdmi_time_start;
				dev_printk(KERN_INFO, hdmi->dev, "HDMI sink enable cost %u ms\n", jiffies_to_msecs(hdmi_time_end));
				#endif
			
				break;
			case WAIT_HDMI_ENABLE:
				if(hdmi->config_set.display_on == HDMI_DISPLAY_OFF)
					hdmi->rate = HDMI_TASK_INTERVAL;
				else
					state = SYSTEM_CONFIG;
				break;
			case SYSTEM_CONFIG:
				if(hdmi->auto_switch)
				{
		    		rk_display_device_disable_other(hdmi->ddev);
		    		g_lcdcstatus = 1;
				}
				if(hdmi->auto_config)	
					hdmi->config_set.resolution = ext_hdmi_find_best_mode(hdmi, 0);
				else
					hdmi->config_set.resolution = ext_hdmi_find_best_mode(hdmi, hdmi->config_set.resolution);
				rc = ext_hdmi_switch_fb(hdmi, 1);
				#ifdef HDMI_DEBUG_TIME
					hdmi_time_end = jiffies;
					if(hdmi_time_end > hdmi_time_start)
						hdmi_time_end -= hdmi_time_start;
					else
						hdmi_time_end += 0xFFFFFFFF - hdmi_time_start;
					dev_printk(KERN_INFO, hdmi->dev, "HDMI configure LCD cost %u ms\n", jiffies_to_msecs(hdmi_time_end));
				#endif
				if(rc == HDMI_ERROR_SUCESS)
				{
					state = CONFIG_VIDEO;
					hdmi->rate = 0;
				}
				else
					hdmi->rate = HDMI_TASK_INTERVAL;
				break;
			case CONFIG_VIDEO:
				{
					hdmi->config_real.display_on = HDMI_DISABLE;
					if(hdmi->edid.is_hdmi) {
						if(hdmi->edid.ycbcr444)
							hdmi->config_set.color = HDMI_VIDEO_YCbCr444;
						else if(hdmi->edid.ycbcr422)
							hdmi->config_set.color = HDMI_VIDEO_YCbCr422;
						else
							hdmi->config_set.color = HDMI_VIDEO_RGB;
					}
					else
						hdmi->config_set.color = HDMI_VIDEO_RGB;
					if(hdmi->config_set.color > HDMI_VIDEO_RGB && (!hdmi->support_r2y))
						hdmi->config_set.color = HDMI_VIDEO_RGB;
					rc = hdmi->ops->config_video(hdmi, hdmi->config_set.resolution, HDMI_VIDEO_RGB, /*HDMI_VIDEO_RGB*/hdmi->config_set.color);
					#ifdef HDMI_DEBUG_TIME
						hdmi_time_end = jiffies;
						if(hdmi_time_end > hdmi_time_start)
							hdmi_time_end -= hdmi_time_start;
						else
							hdmi_time_end += 0xFFFFFFFF - hdmi_time_start;
						dev_printk(KERN_INFO, hdmi->dev, "HDMI configure VIDEO cost %u ms\n", jiffies_to_msecs(hdmi_time_end));
					#endif
				}
				if(rc == HDMI_ERROR_SUCESS)
				{
					hdmi->rate = 0;	
					if(hdmi->edid.is_hdmi)
						state = CONFIG_AUDIO;
					else
						state = PLAY_BACK;
				}
				else	
					hdmi->rate = HDMI_TASK_INTERVAL;
				break;
			case CONFIG_AUDIO:
				rc = hdmi->ops->config_audio(hdmi, &(hdmi->config_set.audio));
				#ifdef HDMI_DEBUG_TIME
					hdmi_time_end = jiffies;
					if(hdmi_time_end > hdmi_time_start)
						hdmi_time_end -= hdmi_time_start;
					else
						hdmi_time_end += 0xFFFFFFFF - hdmi_time_start;
					dev_printk(KERN_INFO, hdmi->dev, "HDMI configure Audio cost %u ms\n", jiffies_to_msecs(hdmi_time_end));
				#endif
							
				if(rc == HDMI_ERROR_SUCESS)
				{
					hdmi->rate = 0;	
					state = PLAY_BACK;
				}
				else	
					hdmi->rate = HDMI_TASK_INTERVAL;
				break;
#if 0	
			case HDCP_AUTHENTICATION:
				if(hdmi->ops->config_hdcp)
				{
					rc = hdmi->ops->config_hdcp(hdmi, hdmi->config_set.hdcp_on);	
					#ifdef HDMI_DEBUG_TIME
					hdmi_time_end = jiffies;
					if(hdmi_time_end > hdmi_time_start)
						hdmi_time_end -= hdmi_time_start;
					else
						hdmi_time_end += 0xFFFFFFFF - hdmi_time_start;
					dev_printk(KERN_INFO, hdmi->dev, "HDMI configure HDCP cost %u ms\n", jiffies_to_msecs(hdmi_time_end));
					#endif
				}
				if(rc == HDMI_ERROR_SUCESS)
				{	
					hdmi->rate = 0;	
					state = PLAY_BACK;
				}
				else
					hdmi->rate = HDMI_TASK_INTERVAL;
				break;
#endif
			case PLAY_BACK:				
//				if(hdmi->config_real.display_on != hdmi->config_set.display_on)
				if( memcmp(&(hdmi->config_real), &(hdmi->config_set), sizeof(struct hdmi_configs)) )
				{
					if(hdmi->config_set.display_on == HDMI_DISPLAY_ON)
					{	
						if(hdmi->ops->config_hdcp)
							rc = hdmi->ops->config_hdcp(hdmi, hdmi->config_set.hdcp_on);
						rc |= hdmi->ops->enable(hdmi, HDMI_ENABLE);
					}
					else
						rc = hdmi->ops->enable(hdmi, HDMI_DISABLE);
					if(rc == HDMI_ERROR_SUCESS)
					{
						#ifdef HDMI_DEBUG_TIME
						hdmi_time_end = jiffies;
						if(hdmi_time_end > hdmi_time_start)
							hdmi_time_end -= hdmi_time_start;
						else
							hdmi_time_end += 0xFFFFFFFF - hdmi_time_start;
						dev_printk(KERN_INFO, hdmi->dev, "HDMI configuration cost %u ms\n", jiffies_to_msecs(hdmi_time_end));
						#endif
						memcpy(&(hdmi->config_real), &(hdmi->config_set), sizeof(struct hdmi_configs));
					}
					if(hdmi->config_set.display_on == HDMI_DISABLE)	
						state = WAIT_HDMI_ENABLE;
				}
				if(hdmi->wait == 1) {	
					complete(&hdmi->complete);
					hdmi->wait = 0;						
				}
				hdmi->rate = HDMI_TASK_INTERVAL;
				break;
			default:
				state = HDMI_INITIAL;
				hdmi->rate = HDMI_TASK_INTERVAL;
				break;
		}
		if(rc != HDMI_ERROR_SUCESS)
		{
			trytimes++;
			msleep(10);
		}
		if(state != state_last)
		{
			trytimes = 0;	
			hdmi_sys_show_state(hdmi, state);
		}
	}while((state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);	
	
	if(trytimes == HDMI_MAX_TRY_TIMES)
	{
		if(hdmi->hpd_status)
		{
			if(state == CONFIG_AUDIO)
				state = HDCP_AUTHENTICATION;
			else if(state > WAIT_RX_SENSE)
			{	
				hdmi_sys_unplug(hdmi);
				if(hdmi->auto_switch && g_lcdcstatus)
				{
				    rk_display_device_enable_other(hdmi->ddev);
				    g_lcdcstatus = 0;
				}
				state = HDMI_UNKNOWN;
			}
		}
	}
	
exit:
	if(state != g_state)
		g_state = state;
	
	return 0;
}