| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2011-09-08 19:06:27 +05:30
										 |  |  |  * hdmi_panel.c | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  |  * | 
					
						
							|  |  |  |  * HDMI library support functions for TI OMAP4 processors. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
 | 
					
						
							|  |  |  |  * Authors:	Mythri P k <mythripk@ti.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify it | 
					
						
							|  |  |  |  * under the terms of the GNU General Public License version 2 as published by | 
					
						
							|  |  |  |  * the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, but WITHOUT | 
					
						
							|  |  |  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | 
					
						
							|  |  |  |  * more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License along with | 
					
						
							|  |  |  |  * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/err.h>
 | 
					
						
							|  |  |  | #include <linux/io.h>
 | 
					
						
							|  |  |  | #include <linux/mutex.h>
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							| 
									
										
										
										
											2011-05-11 14:05:07 +03:00
										 |  |  | #include <video/omapdss.h>
 | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | #include <linux/slab.h>
 | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | #include "dss.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct { | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	/* This protects the panel ops, mainly when accessing the HDMI IP. */ | 
					
						
							|  |  |  | 	struct mutex lock; | 
					
						
							| 
									
										
										
										
											2012-05-09 21:09:50 -05:00
										 |  |  | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 | 
					
						
							|  |  |  | 	/* This protects the audio ops, specifically. */ | 
					
						
							|  |  |  | 	spinlock_t audio_lock; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | } hdmi; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int hdmi_panel_probe(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-08 16:50:42 +05:30
										 |  |  | 	/* Initialize default timings to VGA in DVI mode */ | 
					
						
							|  |  |  | 	const struct omap_video_timings default_timings = { | 
					
						
							|  |  |  | 		.x_res		= 640, | 
					
						
							|  |  |  | 		.y_res		= 480, | 
					
						
							|  |  |  | 		.pixel_clock	= 25175, | 
					
						
							|  |  |  | 		.hsw		= 96, | 
					
						
							|  |  |  | 		.hfp		= 16, | 
					
						
							|  |  |  | 		.hbp		= 48, | 
					
						
							|  |  |  | 		.vsw		= 2, | 
					
						
							|  |  |  | 		.vfp		= 11, | 
					
						
							|  |  |  | 		.vbp		= 31, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW, | 
					
						
							|  |  |  | 		.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		.interlace	= false, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 	DSSDBG("ENTER hdmi_panel_probe\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-08 16:50:42 +05:30
										 |  |  | 	dssdev->panel.timings = default_timings; | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", | 
					
						
							|  |  |  | 		dssdev->panel.timings.x_res, | 
					
						
							|  |  |  | 		dssdev->panel.timings.y_res); | 
					
						
							| 
									
										
										
										
											2012-08-08 16:50:42 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-22 11:33:32 +03:00
										 |  |  | 	omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_panel_remove(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-09 21:09:50 -05:00
										 |  |  | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 | 
					
						
							|  |  |  | static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							|  |  |  | 	spin_lock_irqsave(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* enable audio only if the display is active and supports audio */ | 
					
						
							|  |  |  | 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || | 
					
						
							|  |  |  | 	    !hdmi_mode_has_audio()) { | 
					
						
							|  |  |  | 		DSSERR("audio not supported or display is off\n"); | 
					
						
							|  |  |  | 		r = -EPERM; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = hdmi_audio_enable(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!r) | 
					
						
							|  |  |  | 		dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	spin_unlock_irqrestore(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock_irqsave(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hdmi_audio_disable(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_unlock_irqrestore(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int hdmi_panel_audio_start(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock_irqsave(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * No need to check the panel state. It was checked when trasitioning | 
					
						
							|  |  |  | 	 * to AUDIO_ENABLED. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) { | 
					
						
							|  |  |  | 		DSSERR("audio start from invalid state\n"); | 
					
						
							|  |  |  | 		r = -EPERM; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = hdmi_audio_start(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!r) | 
					
						
							|  |  |  | 		dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	spin_unlock_irqrestore(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock_irqsave(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hdmi_audio_stop(); | 
					
						
							|  |  |  | 	dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_unlock_irqrestore(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bool r = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!hdmi_mode_has_audio()) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = true; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int hdmi_panel_audio_config(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 		struct omap_dss_audio *audio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							|  |  |  | 	spin_lock_irqsave(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* config audio only if the display is active and supports audio */ | 
					
						
							|  |  |  | 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || | 
					
						
							|  |  |  | 	    !hdmi_mode_has_audio()) { | 
					
						
							|  |  |  | 		DSSERR("audio not supported or display is off\n"); | 
					
						
							|  |  |  | 		r = -EPERM; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = hdmi_audio_config(audio); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!r) | 
					
						
							|  |  |  | 		dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	spin_unlock_irqrestore(&hdmi.audio_lock, flags); | 
					
						
							|  |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return -EPERM; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int hdmi_panel_audio_start(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return -EPERM; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int hdmi_panel_audio_config(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 		struct omap_dss_audio *audio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return -EPERM; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | static int hdmi_panel_enable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r = 0; | 
					
						
							|  |  |  | 	DSSDBG("ENTER hdmi_panel_enable\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | 
					
						
							|  |  |  | 		r = -EINVAL; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-08 16:50:42 +05:30
										 |  |  | 	omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 	r = omapdss_hdmi_display_enable(dssdev); | 
					
						
							|  |  |  | 	if (r) { | 
					
						
							|  |  |  | 		DSSERR("failed to power on\n"); | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | err: | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_panel_disable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-09 21:09:50 -05:00
										 |  |  | 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * TODO: notify audio users that the display was disabled. For | 
					
						
							|  |  |  | 		 * now, disable audio locally to not break our audio state | 
					
						
							|  |  |  | 		 * machine. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		hdmi_panel_audio_disable(dssdev); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 		omapdss_hdmi_display_disable(dssdev); | 
					
						
							| 
									
										
										
										
											2012-05-09 21:09:50 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_get_timings(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 			struct omap_video_timings *timings) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	*timings = dssdev->panel.timings; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hdmi_set_timings(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 			struct omap_video_timings *timings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	DSSDBG("hdmi_set_timings\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-09 21:09:50 -05:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * TODO: notify audio users that there was a timings change. For | 
					
						
							|  |  |  | 	 * now, disable audio locally to not break our audio state machine. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	hdmi_panel_audio_disable(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-08 16:50:42 +05:30
										 |  |  | 	omapdss_hdmi_display_set_timing(dssdev, timings); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 	dssdev->panel.timings = *timings; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int hdmi_check_timings(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 			struct omap_video_timings *timings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DSSDBG("hdmi_check_timings\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	r = omapdss_hdmi_display_check_timing(dssdev, timings); | 
					
						
							| 
									
										
										
										
											2011-08-25 17:13:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-25 17:12:56 +03:00
										 |  |  | static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							| 
									
										
										
										
											2012-05-30 13:26:00 +03:00
										 |  |  | 	bool need_enable; | 
					
						
							| 
									
										
										
										
											2011-08-25 17:12:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-08-25 17:12:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-30 13:26:00 +03:00
										 |  |  | 	need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (need_enable) { | 
					
						
							| 
									
										
										
										
											2012-10-19 17:42:27 +03:00
										 |  |  | 		r = omapdss_hdmi_core_enable(dssdev); | 
					
						
							| 
									
										
										
										
											2011-08-25 17:12:56 +03:00
										 |  |  | 		if (r) | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = omapdss_hdmi_read_edid(buf, len); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-30 13:26:00 +03:00
										 |  |  | 	if (need_enable) | 
					
						
							| 
									
										
										
										
											2012-10-19 17:42:27 +03:00
										 |  |  | 		omapdss_hdmi_core_disable(dssdev); | 
					
						
							| 
									
										
										
										
											2011-08-25 17:12:56 +03:00
										 |  |  | err: | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-08-25 17:12:56 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | static bool hdmi_detect(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							| 
									
										
										
										
											2012-05-30 13:26:00 +03:00
										 |  |  | 	bool need_enable; | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_lock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-30 13:26:00 +03:00
										 |  |  | 	need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (need_enable) { | 
					
						
							| 
									
										
										
										
											2012-10-19 17:42:27 +03:00
										 |  |  | 		r = omapdss_hdmi_core_enable(dssdev); | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | 		if (r) | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = omapdss_hdmi_detect(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-30 13:26:00 +03:00
										 |  |  | 	if (need_enable) | 
					
						
							| 
									
										
										
										
											2012-10-19 17:42:27 +03:00
										 |  |  | 		omapdss_hdmi_core_disable(dssdev); | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | err: | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_unlock(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | static struct omap_dss_driver hdmi_driver = { | 
					
						
							|  |  |  | 	.probe		= hdmi_panel_probe, | 
					
						
							|  |  |  | 	.remove		= hdmi_panel_remove, | 
					
						
							|  |  |  | 	.enable		= hdmi_panel_enable, | 
					
						
							|  |  |  | 	.disable	= hdmi_panel_disable, | 
					
						
							|  |  |  | 	.get_timings	= hdmi_get_timings, | 
					
						
							|  |  |  | 	.set_timings	= hdmi_set_timings, | 
					
						
							|  |  |  | 	.check_timings	= hdmi_check_timings, | 
					
						
							| 
									
										
										
										
											2011-08-25 17:12:56 +03:00
										 |  |  | 	.read_edid	= hdmi_read_edid, | 
					
						
							| 
									
										
										
										
											2011-08-29 18:10:20 +03:00
										 |  |  | 	.detect		= hdmi_detect, | 
					
						
							| 
									
										
										
										
											2012-05-09 21:09:50 -05:00
										 |  |  | 	.audio_enable	= hdmi_panel_audio_enable, | 
					
						
							|  |  |  | 	.audio_disable	= hdmi_panel_audio_disable, | 
					
						
							|  |  |  | 	.audio_start	= hdmi_panel_audio_start, | 
					
						
							|  |  |  | 	.audio_stop	= hdmi_panel_audio_stop, | 
					
						
							|  |  |  | 	.audio_supported	= hdmi_panel_audio_supported, | 
					
						
							|  |  |  | 	.audio_config	= hdmi_panel_audio_config, | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 	.driver			= { | 
					
						
							|  |  |  | 		.name   = "hdmi_panel", | 
					
						
							|  |  |  | 		.owner  = THIS_MODULE, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hdmi_panel_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-25 19:29:06 -05:00
										 |  |  | 	mutex_init(&hdmi.lock); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-09 21:09:50 -05:00
										 |  |  | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
 | 
					
						
							|  |  |  | 	spin_lock_init(&hdmi.audio_lock); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-06 00:19:13 -06:00
										 |  |  | 	return omap_dss_register_driver(&hdmi_driver); | 
					
						
							| 
									
										
										
										
											2011-03-10 15:48:48 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hdmi_panel_exit(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	omap_dss_unregister_driver(&hdmi_driver); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |