[PATCH 02/02] [omapzoom]ARM-OMAP3-Automatic_TV_detection

From: Castaneda Gonzalez, Axel
Date: Mon Oct 06 2008 - 13:16:20 EST


From: Axel Castaneda Gonzalez<x0055901@xxxxxx>

ARM: OMAP3: Automatic TV detection

This patch provides automatic TV detection support
on omapzoom display driver. When a stream is run on
video1, video2 is automatically linked and displayed on TV.

User can enable or disable this bind to TV, through the
use of /sys/class/display_control/omap_disp_control/tv_state,
automatic detection/switching is only enabled when this sysfs
entry is populated with 1 and a TV is connected to S-Video port.

Signed-off-by: Axel Castaneda Gonzalez<x0055901@xxxxxx>
---
media/video/omap/omap24xxvout.c | 139 ++++++++++++++++++++++++++++++++++++-
media/video/omap/omap24xxvoutdef.h | 6 +
video/omap/omap_disp_out.c | 36 ++++++++-
3 files changed, 173 insertions(+), 8 deletions(-)

Index: git-ti-omap34tree/drivers/media/video/omap/omap24xxvout.c
===================================================================
--- git-ti-omap34tree.orig/drivers/media/video/omap/omap24xxvout.c
+++ git-ti-omap34tree/drivers/media/video/omap/omap24xxvout.c
@@ -134,6 +134,7 @@ static int rotation_support = -1;
#define SMS_RGB_PIXSIZE 2
#define SMS_YUYV_PIXSIZE 4
#define VRFB_TX_TIMEOUT 1000
+#define AUTO_VIDEO_LINK 2

#ifdef CONFIG_FB_OMAP_720P_STREAMING
#define VID_MAX_WIDTH HD_720P_WIDTH /* Largest width */
@@ -143,6 +144,8 @@ static int rotation_support = -1;
#define VID_MAX_HEIGHT WVGA_SQUARE_HEIGHT_R90 /* Largest height */
#endif

+static int prev_output_dev = -1;
+
static struct omap24xxvout_device *saved_v1out, *saved_v2out;

#define STREAMING_IS_ON() ((saved_v1out && saved_v1out->streaming) || \
@@ -156,6 +159,7 @@ static struct omap24xxvout_device *saved
*/

static int vout_linked;
+int tv_state;
static spinlock_t vout_link_lock;

static struct videobuf_queue_ops dummy_vbq_ops;
@@ -315,6 +319,112 @@ omap24xxvout_sync (struct omap24xxvout_d
dest->rotation, dest->mirror);
}

+void omap24xxvout_set_link(struct omap24xxvout_device *vout, int link_status)
+{
+
+ int *link = &link_status;
+ spin_lock(&vout_link_lock);
+ if ((*link == 0) && (vout_linked == vout->vid))
+ vout_linked = -1;
+
+ omap2_disp_get_dss();
+
+ if ((*link == 1) && (vout_linked == -1 || vout_linked == vout->vid)) {
+ vout_linked = 2;
+ if (vout_linked == OMAP2_VIDEO2) {
+ /* sync V2 to V1 for img and crop */
+ omap24xxvout_sync(saved_v2out, saved_v1out);
+ } else {
+ /* sync V1 to V2 */
+ omap24xxvout_sync(saved_v1out, saved_v2out);
+ }
+ }
+
+ omap2_disp_put_dss();
+ spin_unlock(&vout_link_lock);
+}
+
+
+int omap24xxvout_streaming_link(struct omap24xxvout_device *vout,
+ struct omap24xxvout_fh *fh) {
+ if (vout->streaming)
+ return -EBUSY;
+
+ vout->streaming = fh;
+ omap2_disp_get_dss();
+
+ omap2_disp_config_vlayer(vout->vid, &vout->pix,
+ &vout->crop, &vout->win, vout->rotation,
+ vout->mirror);
+ omap2_disp_put_dss();
+ return 0;
+}
+
+
+int omap24xxvout_tv_link(void){
+
+ struct omap24xxvout_device *vout = NULL;
+ struct omap24xxvout_fh *fh;
+
+ vout = saved_v2out;
+
+ if (vout == NULL)
+ return -ENODEV;
+
+ /* for now, we only support single open */
+ if (vout->opened)
+ return -EBUSY;
+
+ vout->opened += 1;
+ if (!omap2_disp_request_layer(vout->vid)) {
+ vout->opened -= 1;
+ return -ENODEV;
+ }
+
+ omap2_disp_get_dss();
+
+ /* allocate per-filehandle data */
+ fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ omap2_disp_release_layer(vout->vid);
+ omap2_disp_put_dss();
+ vout->opened -= 1;
+ return -ENOMEM;
+ }
+
+ omap2_disp_put_dss();
+
+ omap24xxvout_set_link(vout, 1);
+ omap24xxvout_streaming_link(vout, fh);
+ return 0;
+}
+
+static int
+omap24xxvout_tv_link_release(void) {
+ struct omap24xxvout_device *vout = saved_v2out;
+
+ omap2_disp_get_dss();
+ vout->streaming = NULL;
+ omap2_disp_disable_layer(vout->vid);
+
+ if ((vout_linked != -1) && (vout->vid != vout_linked))
+ omap2_disp_disable_layer((vout->vid ==
+ OMAP2_VIDEO1) ? OMAP2_VIDEO2 : OMAP2_VIDEO1);
+
+ omap2_disp_release_layer(vout->vid);
+ omap2_disp_put_dss();
+ vout->opened -= 1;
+
+ /* need to remove the link when the either slave or master is gone */
+ spin_lock(&vout_link_lock);
+ omap24xxvout_set_link(vout, 0);
+ if (vout_linked != -1)
+ vout_linked = -1;
+
+ spin_unlock(&vout_link_lock);
+ return 0;
+}
+
static int
omap24xxvout_do_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
@@ -1017,10 +1127,25 @@ omap24xxvout_do_ioctl (struct inode *ino
int k;
if (vout->streaming)
return -EBUSY;
- /*
- * If rotation mode is selected then allocate a
- * dummy or hidden buffer to map the SMS virtual space
+
+ if (automatic_link && vout->vid == 1) {
+ tv_state = get_tv_state();
+ if (tv_state) {
+ prev_output_dev =
+ omap2_disp_get_output_dev(
+ AUTO_VIDEO_LINK);
+ if (prev_output_dev != OMAP2_OUTPUT_TV)
+ set_output_device("tv",
+ AUTO_VIDEO_LINK);
+ omap24xxvout_tv_link();
+ }
+ }
+
+ /*
+ * If rotation mode is selected then allocate a
+ * dummy or hidden buffer to map the SMS virtual space
*/
+
if (vout->vid != vout_linked){
if (vout->rotation >= 0){

@@ -1122,6 +1247,13 @@ omap24xxvout_do_ioctl (struct inode *ino
* stop streaming
*/

+ if (automatic_link && tv_state && vout->vid == 1) {
+ omap24xxvout_tv_link_release();
+ if (prev_output_dev == OMAP2_OUTPUT_LCD) {
+ set_output_device("lcd", AUTO_VIDEO_LINK);
+ prev_output_dev = -1;
+ }
+ }
if (vout->streaming == fh){
omap2_disp_disable_layer (vout->vid);
vout->streaming = NULL;
@@ -2273,6 +2405,7 @@ omap24xxvout_init (void)
omap2_disp_save_initstate(OMAP2_VIDEO2);
omap2_disp_put_dss();

+ tv_state = 0;
vout_linked = -1;
spin_lock_init (&vout_link_lock);
return 0;
Index: git-ti-omap34tree/drivers/video/omap/omap_disp_out.c
===================================================================
--- git-ti-omap34tree.orig/drivers/video/omap/omap_disp_out.c
+++ git-ti-omap34tree/drivers/video/omap/omap_disp_out.c
@@ -195,6 +195,8 @@ struct res_handle * tv_rhandle = NULL;
static struct spi_device *wvgalcd_spi;
#endif

+int automatic_link;
+
#ifdef CONFIG_OMAP2_LCD
static int dvi_in_use; /* dvi output flag */
static int lcd_in_use;
@@ -981,7 +983,7 @@ lcd_suspend(struct platform_device *odev
mdelay(40);
#endif
omap2_dss_rgb_disable();
-
+ automatic_link = 0;
return 0;
}

@@ -1862,20 +1864,44 @@ static void disable_tv_detect(void){
omap2_disp_put_all_clks();
}

-static ssize_t
-tv_state_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ssize_t
+set_output_device(const char *buffer, int layer) {
+ ssize_t ret;
+ if (strncmp(buffer, "lcd", 3) == 0)
+ ret = write_layer_out("lcd", 3, layer);
+ else if (strncmp(buffer, "tv", 2) == 0)
+ ret = write_layer_out("tv", 2, layer);
+ else
+ ret = -EINVAL;
+ return ret;
+}
+EXPORT_SYMBOL(set_output_device);
+
+int
+get_tv_state(void){
int tv_state;
+
enable_tv_detect();
msleep(TV_DETECT_DELAY);
tv_state = omap_get_gpio_datain(TV_INT_GPIO);
disable_tv_detect();
- return sprintf(buf, "%d\n", tv_state);
+ return tv_state;
+}
+EXPORT_SYMBOL(get_tv_state);
+
+static ssize_t
+tv_state_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ return sprintf(buf, "%d\n", get_tv_state());
}

static ssize_t
tv_state_store(struct device *dev, struct device_attribute *attr,
const char *buffer, size_t count) {
- return 0;
+ if (strncmp(buffer, "1", 1) == 0)
+ automatic_link = 1;
+ else if (strncmp(buffer, "0", 1) == 0)
+ automatic_link = 0;
+ return count;
}
#endif

Index: git-ti-omap34tree/drivers/media/video/omap/omap24xxvoutdef.h
===================================================================
--- git-ti-omap34tree.orig/drivers/media/video/omap/omap24xxvoutdef.h
+++ git-ti-omap34tree/drivers/media/video/omap/omap24xxvoutdef.h
@@ -102,6 +102,7 @@ struct omap24xxvout_fh {
struct videobuf_queue vbq;
};

+
#ifdef CONFIG_ARCH_OMAP34XX


@@ -174,4 +175,9 @@ struct omap3_aux_disp_fh {
};
#endif

+/* TV detection autoswitching support */
+ extern int automatic_link;
+ extern int get_tv_state(void);
+ extern ssize_t set_output_device(const char *buffer, int);
+
#endif /* ifndef OMAP24XXVOUTDEF_H */
--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/