Пример #1
0
static int hdmi_sys_detect_status(struct hdmi *hdmi, int cur_status)
{
	int rc, hpd, state = cur_status;
	
	rc = hdmi->ops->detect_hpd(hdmi, &hpd);
//	hdmi_dbg(hdmi->dev, "hpd is %d\n", hpd);
	if(!rc && (hpd != hdmi->hpd_status))
	{
		if(hpd == HDMI_RECEIVER_REMOVE)
		{
			hdmi_dbg(hdmi->dev, "HDMI_UNPLUG\n");
			hdmi_sys_unplug(hdmi);
			if(hdmi->auto_switch)
			    rk_display_device_enable_other(hdmi->ddev);
			state = HDMI_INITIAL;
			if(hdmi->wait == 1) {	
				complete(&hdmi->complete);
				hdmi->wait = 0;
			}
			hdmi_sys_send_uevent(hdmi, KOBJ_REMOVE);
		}
		else if(hdmi->hpd_status == HDMI_RECEIVER_REMOVE)
			hdmi->hpd_status = HDMI_RECEIVER_INACTIVE;
	}
	if(state > SYSTEM_CONFIG && hdmi->ops->detect_sink)
	{
		rc = hdmi->ops->detect_sink(hdmi, &hpd);
//		hdmi_dbg(hdmi->dev, "sink is %d\n", hpd);
		if(hpd == HDMI_RECEIVER_INACTIVE)
		{
			hdmi->hpd_status = hpd;	
			hdmi_dbg(hdmi->dev, "HDMI_UNLINK\n");
			if(state > WAIT_RX_SENSE)
			{	
				if(hdmi->auto_switch)
				    rk_display_device_enable_other(hdmi->ddev);
	
				if(hdmi->wait == 1) {	
					complete(&hdmi->complete);
					hdmi->wait = 0;
				}
				if(state == PLAY_BACK)
					hdmi_sys_send_uevent(hdmi, KOBJ_REMOVE);
				state = WAIT_RX_SENSE;
			}
		}		
	}
	return state;
}
Пример #2
0
void hdmi_sys_remove(void)
{
	fb_destroy_modelist(&hdmi->edid.modelist);
	if(hdmi->edid.audio)
		kfree(hdmi->edid.audio);
	if(hdmi->edid.specs)
	{
		if(hdmi->edid.specs->modedb)
			kfree(hdmi->edid.specs->modedb);
		kfree(hdmi->edid.specs);
	}
	memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
	hdmi_init_modelist(hdmi);
	hdmi->display	= HDMI_DISABLE;
	rk_fb_switch_screen(hdmi->lcdc->screen, 0, HDMI_SOURCE_DEFAULT);
	hdmi_sys_send_uevent(KOBJ_REMOVE);
	#ifdef CONFIG_SWITCH
	switch_set_state(&(hdmi->switch_hdmi), 0);
	#endif
	#ifdef CONFIG_HDMI_RK30_CTL_CODEC
	codec_set_spk(1);
	#endif
}
Пример #3
0
void hdmi_work(struct work_struct *work)
{
	int hotplug, state_last;
	int rc = HDMI_ERROR_SUCESS, trytimes = 0;
	struct rk30_hdmi_video_para video;
	
	mutex_lock(&work_mutex);
	/* Process hdmi command */
	hdmi->state = hdmi_process_command();
	
	if(!hdmi->enable || hdmi->suspend) {
		mutex_unlock(&work_mutex);
		return;
	}
	hotplug = rk30_hdmi_detect_hotplug();
	hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __FUNCTION__, hotplug, hdmi->hotplug);
	
	if(hotplug != hdmi->hotplug)
	{
		if(hotplug  == HDMI_HPD_ACTIVED){
			hdmi->state = READ_PARSE_EDID;
		}
		else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
			hdmi_sys_remove();
			hdmi->hotplug = hotplug;
			if(hotplug == HDMI_HPD_REMOVED)
				hdmi_sys_sleep();
			else {
				hdmi->state = WAIT_HOTPLUG;
				rk30_hdmi_removed();
			}
			if(hdmi->wait == 1) {
				complete(&hdmi->complete);
				hdmi->wait = 0;	
			}
			mutex_unlock(&work_mutex);
			return;
		}
		else if(hotplug == HDMI_HPD_REMOVED) {
			hdmi->state = HDMI_SLEEP;
			rk30_hdmi_removed();
		}
		hdmi->hotplug  = hotplug;
	}
	else if(hotplug == HDMI_HPD_REMOVED)
		hdmi_sys_sleep();
	
	do {
		hdmi_sys_show_state(hdmi->state);
		state_last = hdmi->state;
		switch(hdmi->state)
		{
			case READ_PARSE_EDID:
				rc = hdmi_sys_parse_edid(hdmi);
				if(rc == HDMI_ERROR_SUCESS)
				{
					hdmi->state = SYSTEM_CONFIG;	
					hdmi_sys_send_uevent(KOBJ_ADD);
					#ifdef CONFIG_SWITCH
					switch_set_state(&(hdmi->switch_hdmi), 1);
					#endif
					#ifdef CONFIG_HDMI_RK30_CTL_CODEC
					codec_set_spk(0);
					#endif
				}
				break;
			case SYSTEM_CONFIG:
				if(hdmi->autoconfig)	
					hdmi->vic = hdmi_find_best_mode(hdmi, 0);
				else
					hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
				rc = hdmi_switch_fb(hdmi, hdmi->vic);
				if(rc == HDMI_ERROR_SUCESS)
					hdmi->state = CONFIG_VIDEO;
				break;
			case CONFIG_VIDEO:
				hdmi->display = HDMI_DISABLE;
				video.vic = hdmi->vic;
				video.input_mode = VIDEO_INPUT_RGB_YCBCR_444;
				video.input_color = VIDEO_INPUT_COLOR_RGB;//VIDEO_INPUT_COLOR_YCBCR
				video.output_mode = hdmi->edid.sink_hdmi;
				
				if(hdmi->edid.ycbcr444)
					video.output_color = VIDEO_OUTPUT_YCBCR444;
				else if(hdmi->edid.ycbcr422)
					video.output_color = VIDEO_OUTPUT_YCBCR422;
				else
					video.output_color = VIDEO_OUTPUT_RGB444;
				// For DVI, output RGB
				if(hdmi->edid.sink_hdmi == 0)
					video.output_color = VIDEO_OUTPUT_RGB444;
				
				rc = rk30_hdmi_config_video(&video);
				if(rc == HDMI_ERROR_SUCESS)
				{
					if(hdmi->edid.sink_hdmi)
						hdmi->state = CONFIG_AUDIO;
					else
						hdmi->state = PLAY_BACK;
				}
				break;
			case CONFIG_AUDIO:
				rc = rk30_hdmi_config_audio(&(hdmi->audio));
							
				if(rc == HDMI_ERROR_SUCESS)
					hdmi->state = PLAY_BACK;
				break;
			case PLAY_BACK:
				if(hdmi->display != HDMI_ENABLE) {
					rk30_hdmi_control_output(HDMI_ENABLE);
					hdmi->display = HDMI_ENABLE;
					if(hdmi->hdcp_cb) {
						hdmi->hdcp_cb();
					}
				}
				
				if(hdmi->wait == 1) {	
					complete(&hdmi->complete);
					hdmi->wait = 0;						
				}
				break;
			default:
				break;
		}
		if(rc != HDMI_ERROR_SUCESS)
		{
			trytimes++;
			msleep(10);
		}
		if(hdmi->state != state_last) 
			trytimes = 0;
	
	}while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
	
	hdmi_dbg(hdmi->dev, "[%s] done\n", __FUNCTION__);
	mutex_unlock(&work_mutex);
}
Пример #4
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;
}