[media] media: davinci: vpif: display: separate out subdev from output
authorLad, Prabhakar <prabhakar.lad@ti.com>
Tue, 25 Sep 2012 11:11:49 +0000 (08:11 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 6 Oct 2012 01:12:27 +0000 (22:12 -0300)
vpif_display relied on a 1-1 mapping of output and subdev. This is not
necessarily the case. Separate the two. So there is a list of subdevs
and a list of outputs. Each output refers to a subdev and has routing
information. An output does not have to have a subdev.
The initial output for each channel is set to the fist output.
Currently missing is support for associating multiple subdevs with
an output.

Signed-off-by: Lad, Prabhakar <prabhakar.lad@ti.com>
Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
drivers/media/platform/davinci/vpif_display.c
include/media/davinci/vpif_types.h

index 8663df3..bc6b8c7 100644 (file)
@@ -46,6 +46,7 @@
 #include <mach/spi.h>
 
 #include <media/tvp514x.h>
+#include <media/adv7343.h>
 
 #define DA850_EVM_PHY_ID               "davinci_mdio-0:00"
 #define DA850_LCD_PWR_PIN              GPIO_TO_PIN(2, 8)
@@ -1259,16 +1260,38 @@ static struct vpif_subdev_info da850_vpif_subdev[] = {
        },
 };
 
-static const char const *vpif_output[] = {
-               "Composite",
-               "S-Video",
+static const struct vpif_output da850_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
 };
 
 static struct vpif_display_config da850_vpif_display_config = {
        .subdevinfo   = da850_vpif_subdev,
        .subdev_count = ARRAY_SIZE(da850_vpif_subdev),
-       .output       = vpif_output,
-       .output_count = ARRAY_SIZE(vpif_output),
+       .chan_config[0] = {
+               .outputs = da850_ch0_outputs,
+               .output_count = ARRAY_SIZE(da850_ch0_outputs),
+       },
        .card_name    = "DA850/OMAP-L138 Video Display",
 };
 
index 2647b89..fac92f5 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/i2c/pcf857x.h>
 
 #include <media/tvp514x.h>
+#include <media/adv7343.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -496,18 +497,49 @@ static struct vpif_subdev_info dm646x_vpif_subdev[] = {
        },
 };
 
-static const char *output[] = {
-       "Composite",
-       "Component",
-       "S-Video",
+static const struct vpif_output dm6467_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "Component",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPONENT_ID,
+       },
+       {
+               .output = {
+                       .index = 2,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
 };
 
 static struct vpif_display_config dm646x_vpif_display_config = {
        .set_clock      = set_vpif_clock,
        .subdevinfo     = dm646x_vpif_subdev,
        .subdev_count   = ARRAY_SIZE(dm646x_vpif_subdev),
-       .output         = output,
-       .output_count   = ARRAY_SIZE(output),
+       .chan_config[0] = {
+               .outputs = dm6467_ch0_outputs,
+               .output_count = ARRAY_SIZE(dm6467_ch0_outputs),
+       },
        .card_name      = "DM646x EVM",
 };
 
index 6229e48..ae8329d 100644 (file)
@@ -308,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel2_intr_assert();
                channel2_intr_enable(1);
                enable_channel2(1);
-               if (vpif_config_data->ch2_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                        channel2_clipping_enable(1);
        }
 
@@ -317,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel3_intr_assert();
                channel3_intr_enable(1);
                enable_channel3(1);
-               if (vpif_config_data->ch3_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                        channel3_clipping_enable(1);
        }
 
@@ -1174,14 +1174,16 @@ static int vpif_streamoff(struct file *file, void *priv,
        if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                /* disable channel */
                if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
-                       if (vpif_config_data->ch2_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                                channel2_clipping_enable(0);
                        enable_channel2(0);
                        channel2_intr_enable(0);
                }
                if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
                                        (2 == common->started)) {
-                       if (vpif_config_data->ch3_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                                channel3_clipping_enable(0);
                        enable_channel3(0);
                        channel3_intr_enable(0);
@@ -1214,41 +1216,118 @@ static int vpif_enum_output(struct file *file, void *fh,
 {
 
        struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
+       struct vpif_fh *vpif_handler = fh;
+       struct channel_obj *ch = vpif_handler->channel;
 
-       if (output->index >= config->output_count) {
+       chan_cfg = &config->chan_config[ch->channel_id];
+       if (output->index >= chan_cfg->output_count) {
                vpif_dbg(1, debug, "Invalid output index\n");
                return -EINVAL;
        }
 
-       strcpy(output->name, config->output[output->index]);
-       output->type = V4L2_OUTPUT_TYPE_ANALOG;
-       output->std = VPIF_V4L2_STD;
+       *output = chan_cfg->outputs[output->index].output;
+       return 0;
+}
+
+/**
+ * vpif_output_to_subdev() - Maps output to sub device
+ * @vpif_cfg - global config ptr
+ * @chan_cfg - channel config ptr
+ * @index - Given output index from application
+ *
+ * lookup the sub device information for a given output index.
+ * we report all the output to application. output table also
+ * has sub device name for the each output
+ */
+static int
+vpif_output_to_subdev(struct vpif_display_config *vpif_cfg,
+                     struct vpif_display_chan_config *chan_cfg, int index)
+{
+       struct vpif_subdev_info *subdev_info;
+       const char *subdev_name;
+       int i;
+
+       vpif_dbg(2, debug, "vpif_output_to_subdev\n");
+
+       if (chan_cfg->outputs == NULL)
+               return -1;
+
+       subdev_name = chan_cfg->outputs[index].subdev_name;
+       if (subdev_name == NULL)
+               return -1;
+
+       /* loop through the sub device list to get the sub device info */
+       for (i = 0; i < vpif_cfg->subdev_count; i++) {
+               subdev_info = &vpif_cfg->subdevinfo[i];
+               if (!strcmp(subdev_info->name, subdev_name))
+                       return i;
+       }
+       return -1;
+}
+
+/**
+ * vpif_set_output() - Select an output
+ * @vpif_cfg - global config ptr
+ * @ch - channel
+ * @index - Given output index from application
+ *
+ * Select the given output.
+ */
+static int vpif_set_output(struct vpif_display_config *vpif_cfg,
+                     struct channel_obj *ch, int index)
+{
+       struct vpif_display_chan_config *chan_cfg =
+               &vpif_cfg->chan_config[ch->channel_id];
+       struct vpif_subdev_info *subdev_info = NULL;
+       struct v4l2_subdev *sd = NULL;
+       u32 input = 0, output = 0;
+       int sd_index;
+       int ret;
+
+       sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index);
+       if (sd_index >= 0) {
+               sd = vpif_obj.sd[sd_index];
+               subdev_info = &vpif_cfg->subdevinfo[sd_index];
+       }
 
+       if (sd) {
+               input = chan_cfg->outputs[index].input_route;
+               output = chan_cfg->outputs[index].output_route;
+               ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       vpif_err("Failed to set output\n");
+                       return ret;
+               }
+
+       }
+       ch->output_idx = index;
+       ch->sd = sd;
+       if (chan_cfg->outputs != NULL)
+               /* update tvnorms from the sub device output info */
+               ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std;
        return 0;
 }
 
 static int vpif_s_output(struct file *file, void *priv, unsigned int i)
 {
+       struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       int ret = 0;
+
+       chan_cfg = &config->chan_config[ch->channel_id];
+
+       if (i >= chan_cfg->output_count)
+               return -EINVAL;
 
        if (common->started) {
                vpif_err("Streaming in progress\n");
                return -EBUSY;
        }
 
-       ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
-                                                       s_routing, 0, i, 0);
-
-       if (ret < 0)
-               vpif_err("Failed to set output standard\n");
-
-       ch->output_idx = i;
-       if (vpif_obj.sd[i])
-               ch->sd = vpif_obj.sd[i];
-       return ret;
+       return vpif_set_output(config, ch, i);
 }
 
 static int vpif_g_output(struct file *file, void *priv, unsigned int *i)
@@ -1291,9 +1370,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->output_idx],
-                       video, enum_dv_timings, timings);
+       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -EINVAL;
+       return ret;
 }
 
 /**
@@ -1320,12 +1402,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
 
        /* Configure subdevice timings, if any */
        ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD) {
-               vpif_dbg(2, debug, "Custom DV timings not supported by "
-                               "subdevice\n");
-               return -ENODATA;
-       }
-       if (ret < 0 && ret != -ENODEV) {
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               ret = 0;
+       if (ret < 0) {
                vpif_dbg(2, debug, "Error setting custom DV timings\n");
                return ret;
        }
@@ -1531,9 +1610,6 @@ static struct video_device vpif_video_template = {
        .name           = "vpif",
        .fops           = &vpif_fops,
        .ioctl_ops      = &vpif_ioctl_ops,
-       .tvnorms        = VPIF_V4L2_STD,
-       .current_norm   = V4L2_STD_625_50,
-
 };
 
 /*Configure the channels, buffer sizei, request irq */
@@ -1756,6 +1832,11 @@ static __init int vpif_probe(struct platform_device *pdev)
                ch->video_dev->lock = &common->lock;
                video_set_drvdata(ch->video_dev, ch);
 
+               /* select output 0 */
+               err = vpif_set_output(config, ch, 0);
+               if (err)
+                       goto probe_out;
+
                /* register video device */
                vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
                                (int)ch, (int)&ch->video_dev);
index 65e8fe1..3882e06 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 
 #define VPIF_CAPTURE_MAX_CHANNELS      2
+#define VPIF_DISPLAY_MAX_CHANNELS      2
 
 enum vpif_if_type {
        VPIF_IF_BT656,
@@ -39,15 +40,25 @@ struct vpif_subdev_info {
        struct i2c_board_info board_info;
 };
 
+struct vpif_output {
+       struct v4l2_output output;
+       const char *subdev_name;
+       u32 input_route;
+       u32 output_route;
+};
+
+struct vpif_display_chan_config {
+       const struct vpif_output *outputs;
+       int output_count;
+       bool clip_en;
+};
+
 struct vpif_display_config {
        int (*set_clock)(int, int);
        struct vpif_subdev_info *subdevinfo;
        int subdev_count;
-       const char **output;
-       int output_count;
+       struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
        const char *card_name;
-       bool ch2_clip_en;
-       bool ch3_clip_en;
 };
 
 struct vpif_input {