Commit 2bd4e58c authored by Lad, Prabhakar's avatar Lad, Prabhakar Committed by Mauro Carvalho Chehab

[media] media: davinci: vpif: display: separate out subdev from output

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: default avatarLad, Prabhakar <prabhakar.lad@ti.com>
Signed-off-by: default avatarManjunath Hadli <manjunath.hadli@ti.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Acked-by: default avatarSekhar Nori <nsekhar@ti.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent c389648a
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <mach/spi.h> #include <mach/spi.h>
#include <media/tvp514x.h> #include <media/tvp514x.h>
#include <media/adv7343.h>
#define DA850_EVM_PHY_ID "davinci_mdio-0:00" #define DA850_EVM_PHY_ID "davinci_mdio-0:00"
#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8)
...@@ -1259,16 +1260,38 @@ static struct vpif_subdev_info da850_vpif_subdev[] = { ...@@ -1259,16 +1260,38 @@ static struct vpif_subdev_info da850_vpif_subdev[] = {
}, },
}; };
static const char const *vpif_output[] = { static const struct vpif_output da850_ch0_outputs[] = {
"Composite", {
"S-Video", .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 = { static struct vpif_display_config da850_vpif_display_config = {
.subdevinfo = da850_vpif_subdev, .subdevinfo = da850_vpif_subdev,
.subdev_count = ARRAY_SIZE(da850_vpif_subdev), .subdev_count = ARRAY_SIZE(da850_vpif_subdev),
.output = vpif_output, .chan_config[0] = {
.output_count = ARRAY_SIZE(vpif_output), .outputs = da850_ch0_outputs,
.output_count = ARRAY_SIZE(da850_ch0_outputs),
},
.card_name = "DA850/OMAP-L138 Video Display", .card_name = "DA850/OMAP-L138 Video Display",
}; };
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/i2c/pcf857x.h> #include <linux/i2c/pcf857x.h>
#include <media/tvp514x.h> #include <media/tvp514x.h>
#include <media/adv7343.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
...@@ -496,18 +497,49 @@ static struct vpif_subdev_info dm646x_vpif_subdev[] = { ...@@ -496,18 +497,49 @@ static struct vpif_subdev_info dm646x_vpif_subdev[] = {
}, },
}; };
static const char *output[] = { static const struct vpif_output dm6467_ch0_outputs[] = {
"Composite", {
"Component", .output = {
"S-Video", .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 = { static struct vpif_display_config dm646x_vpif_display_config = {
.set_clock = set_vpif_clock, .set_clock = set_vpif_clock,
.subdevinfo = dm646x_vpif_subdev, .subdevinfo = dm646x_vpif_subdev,
.subdev_count = ARRAY_SIZE(dm646x_vpif_subdev), .subdev_count = ARRAY_SIZE(dm646x_vpif_subdev),
.output = output, .chan_config[0] = {
.output_count = ARRAY_SIZE(output), .outputs = dm6467_ch0_outputs,
.output_count = ARRAY_SIZE(dm6467_ch0_outputs),
},
.card_name = "DM646x EVM", .card_name = "DM646x EVM",
}; };
......
...@@ -308,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) ...@@ -308,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
channel2_intr_assert(); channel2_intr_assert();
channel2_intr_enable(1); channel2_intr_enable(1);
enable_channel2(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); channel2_clipping_enable(1);
} }
...@@ -317,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) ...@@ -317,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
channel3_intr_assert(); channel3_intr_assert();
channel3_intr_enable(1); channel3_intr_enable(1);
enable_channel3(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); channel3_clipping_enable(1);
} }
...@@ -1174,14 +1174,16 @@ static int vpif_streamoff(struct file *file, void *priv, ...@@ -1174,14 +1174,16 @@ static int vpif_streamoff(struct file *file, void *priv,
if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
/* disable channel */ /* disable channel */
if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { 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); channel2_clipping_enable(0);
enable_channel2(0); enable_channel2(0);
channel2_intr_enable(0); channel2_intr_enable(0);
} }
if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
(2 == common->started)) { (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); channel3_clipping_enable(0);
enable_channel3(0); enable_channel3(0);
channel3_intr_enable(0); channel3_intr_enable(0);
...@@ -1214,41 +1216,118 @@ static int vpif_enum_output(struct file *file, void *fh, ...@@ -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_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"); vpif_dbg(1, debug, "Invalid output index\n");
return -EINVAL; return -EINVAL;
} }
strcpy(output->name, config->output[output->index]); *output = chan_cfg->outputs[output->index].output;
output->type = V4L2_OUTPUT_TYPE_ANALOG; return 0;
output->std = VPIF_V4L2_STD; }
/**
* 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; return 0;
} }
static int vpif_s_output(struct file *file, void *priv, unsigned int i) 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 vpif_fh *fh = priv;
struct channel_obj *ch = fh->channel; struct channel_obj *ch = fh->channel;
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; 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) { if (common->started) {
vpif_err("Streaming in progress\n"); vpif_err("Streaming in progress\n");
return -EBUSY; return -EBUSY;
} }
ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, return vpif_set_output(config, ch, i);
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;
} }
static int vpif_g_output(struct file *file, void *priv, unsigned int *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, ...@@ -1291,9 +1370,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
{ {
struct vpif_fh *fh = priv; struct vpif_fh *fh = priv;
struct channel_obj *ch = fh->channel; struct channel_obj *ch = fh->channel;
int ret;
return v4l2_subdev_call(vpif_obj.sd[ch->output_idx], ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
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, ...@@ -1320,12 +1402,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
/* Configure subdevice timings, if any */ /* Configure subdevice timings, if any */
ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings); ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
if (ret == -ENOIOCTLCMD) { if (ret == -ENOIOCTLCMD || ret == -ENODEV)
vpif_dbg(2, debug, "Custom DV timings not supported by " ret = 0;
"subdevice\n"); if (ret < 0) {
return -ENODATA;
}
if (ret < 0 && ret != -ENODEV) {
vpif_dbg(2, debug, "Error setting custom DV timings\n"); vpif_dbg(2, debug, "Error setting custom DV timings\n");
return ret; return ret;
} }
...@@ -1531,9 +1610,6 @@ static struct video_device vpif_video_template = { ...@@ -1531,9 +1610,6 @@ static struct video_device vpif_video_template = {
.name = "vpif", .name = "vpif",
.fops = &vpif_fops, .fops = &vpif_fops,
.ioctl_ops = &vpif_ioctl_ops, .ioctl_ops = &vpif_ioctl_ops,
.tvnorms = VPIF_V4L2_STD,
.current_norm = V4L2_STD_625_50,
}; };
/*Configure the channels, buffer sizei, request irq */ /*Configure the channels, buffer sizei, request irq */
...@@ -1756,6 +1832,11 @@ static __init int vpif_probe(struct platform_device *pdev) ...@@ -1756,6 +1832,11 @@ static __init int vpif_probe(struct platform_device *pdev)
ch->video_dev->lock = &common->lock; ch->video_dev->lock = &common->lock;
video_set_drvdata(ch->video_dev, ch); 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 */ /* register video device */
vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
(int)ch, (int)&ch->video_dev); (int)ch, (int)&ch->video_dev);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#define VPIF_CAPTURE_MAX_CHANNELS 2 #define VPIF_CAPTURE_MAX_CHANNELS 2
#define VPIF_DISPLAY_MAX_CHANNELS 2
enum vpif_if_type { enum vpif_if_type {
VPIF_IF_BT656, VPIF_IF_BT656,
...@@ -39,15 +40,25 @@ struct vpif_subdev_info { ...@@ -39,15 +40,25 @@ struct vpif_subdev_info {
struct i2c_board_info board_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 { struct vpif_display_config {
int (*set_clock)(int, int); int (*set_clock)(int, int);
struct vpif_subdev_info *subdevinfo; struct vpif_subdev_info *subdevinfo;
int subdev_count; int subdev_count;
const char **output; struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
int output_count;
const char *card_name; const char *card_name;
bool ch2_clip_en;
bool ch3_clip_en;
}; };
struct vpif_input { struct vpif_input {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment