aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLad, Prabhakar <prabhakar.lad@ti.com>2012-09-25 07:11:49 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-10-05 21:12:27 -0400
commit2bd4e58c9d00325b7a850b2ac73fd902e9148b77 (patch)
treeef3242b551f05c3a54533e4a21ff21acd9a3b137
parentc389648a927bada928c854dccccf0301317784eb (diff)
[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: 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>
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c33
-rw-r--r--arch/arm/mach-davinci/board-dm646x-evm.c44
-rw-r--r--drivers/media/platform/davinci/vpif_display.c141
-rw-r--r--include/media/davinci/vpif_types.h19
4 files changed, 192 insertions, 45 deletions
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 8663df3d2a5..bc6b8c7b86c 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -46,6 +46,7 @@
46#include <mach/spi.h> 46#include <mach/spi.h>
47 47
48#include <media/tvp514x.h> 48#include <media/tvp514x.h>
49#include <media/adv7343.h>
49 50
50#define DA850_EVM_PHY_ID "davinci_mdio-0:00" 51#define DA850_EVM_PHY_ID "davinci_mdio-0:00"
51#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) 52#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8)
@@ -1259,16 +1260,38 @@ static struct vpif_subdev_info da850_vpif_subdev[] = {
1259 }, 1260 },
1260}; 1261};
1261 1262
1262static const char const *vpif_output[] = { 1263static const struct vpif_output da850_ch0_outputs[] = {
1263 "Composite", 1264 {
1264 "S-Video", 1265 .output = {
1266 .index = 0,
1267 .name = "Composite",
1268 .type = V4L2_OUTPUT_TYPE_ANALOG,
1269 .capabilities = V4L2_OUT_CAP_STD,
1270 .std = V4L2_STD_ALL,
1271 },
1272 .subdev_name = "adv7343",
1273 .output_route = ADV7343_COMPOSITE_ID,
1274 },
1275 {
1276 .output = {
1277 .index = 1,
1278 .name = "S-Video",
1279 .type = V4L2_OUTPUT_TYPE_ANALOG,
1280 .capabilities = V4L2_OUT_CAP_STD,
1281 .std = V4L2_STD_ALL,
1282 },
1283 .subdev_name = "adv7343",
1284 .output_route = ADV7343_SVIDEO_ID,
1285 },
1265}; 1286};
1266 1287
1267static struct vpif_display_config da850_vpif_display_config = { 1288static struct vpif_display_config da850_vpif_display_config = {
1268 .subdevinfo = da850_vpif_subdev, 1289 .subdevinfo = da850_vpif_subdev,
1269 .subdev_count = ARRAY_SIZE(da850_vpif_subdev), 1290 .subdev_count = ARRAY_SIZE(da850_vpif_subdev),
1270 .output = vpif_output, 1291 .chan_config[0] = {
1271 .output_count = ARRAY_SIZE(vpif_output), 1292 .outputs = da850_ch0_outputs,
1293 .output_count = ARRAY_SIZE(da850_ch0_outputs),
1294 },
1272 .card_name = "DA850/OMAP-L138 Video Display", 1295 .card_name = "DA850/OMAP-L138 Video Display",
1273}; 1296};
1274 1297
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 2647b8966dd..fac92f539da 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -26,6 +26,7 @@
26#include <linux/i2c/pcf857x.h> 26#include <linux/i2c/pcf857x.h>
27 27
28#include <media/tvp514x.h> 28#include <media/tvp514x.h>
29#include <media/adv7343.h>
29 30
30#include <linux/mtd/mtd.h> 31#include <linux/mtd/mtd.h>
31#include <linux/mtd/nand.h> 32#include <linux/mtd/nand.h>
@@ -496,18 +497,49 @@ static struct vpif_subdev_info dm646x_vpif_subdev[] = {
496 }, 497 },
497}; 498};
498 499
499static const char *output[] = { 500static const struct vpif_output dm6467_ch0_outputs[] = {
500 "Composite", 501 {
501 "Component", 502 .output = {
502 "S-Video", 503 .index = 0,
504 .name = "Composite",
505 .type = V4L2_OUTPUT_TYPE_ANALOG,
506 .capabilities = V4L2_OUT_CAP_STD,
507 .std = V4L2_STD_ALL,
508 },
509 .subdev_name = "adv7343",
510 .output_route = ADV7343_COMPOSITE_ID,
511 },
512 {
513 .output = {
514 .index = 1,
515 .name = "Component",
516 .type = V4L2_OUTPUT_TYPE_ANALOG,
517 .capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
518 },
519 .subdev_name = "adv7343",
520 .output_route = ADV7343_COMPONENT_ID,
521 },
522 {
523 .output = {
524 .index = 2,
525 .name = "S-Video",
526 .type = V4L2_OUTPUT_TYPE_ANALOG,
527 .capabilities = V4L2_OUT_CAP_STD,
528 .std = V4L2_STD_ALL,
529 },
530 .subdev_name = "adv7343",
531 .output_route = ADV7343_SVIDEO_ID,
532 },
503}; 533};
504 534
505static struct vpif_display_config dm646x_vpif_display_config = { 535static struct vpif_display_config dm646x_vpif_display_config = {
506 .set_clock = set_vpif_clock, 536 .set_clock = set_vpif_clock,
507 .subdevinfo = dm646x_vpif_subdev, 537 .subdevinfo = dm646x_vpif_subdev,
508 .subdev_count = ARRAY_SIZE(dm646x_vpif_subdev), 538 .subdev_count = ARRAY_SIZE(dm646x_vpif_subdev),
509 .output = output, 539 .chan_config[0] = {
510 .output_count = ARRAY_SIZE(output), 540 .outputs = dm6467_ch0_outputs,
541 .output_count = ARRAY_SIZE(dm6467_ch0_outputs),
542 },
511 .card_name = "DM646x EVM", 543 .card_name = "DM646x EVM",
512}; 544};
513 545
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 6229e4844be..ae8329d7924 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -308,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
308 channel2_intr_assert(); 308 channel2_intr_assert();
309 channel2_intr_enable(1); 309 channel2_intr_enable(1);
310 enable_channel2(1); 310 enable_channel2(1);
311 if (vpif_config_data->ch2_clip_en) 311 if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
312 channel2_clipping_enable(1); 312 channel2_clipping_enable(1);
313 } 313 }
314 314
@@ -317,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
317 channel3_intr_assert(); 317 channel3_intr_assert();
318 channel3_intr_enable(1); 318 channel3_intr_enable(1);
319 enable_channel3(1); 319 enable_channel3(1);
320 if (vpif_config_data->ch3_clip_en) 320 if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
321 channel3_clipping_enable(1); 321 channel3_clipping_enable(1);
322 } 322 }
323 323
@@ -1174,14 +1174,16 @@ static int vpif_streamoff(struct file *file, void *priv,
1174 if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 1174 if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1175 /* disable channel */ 1175 /* disable channel */
1176 if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { 1176 if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
1177 if (vpif_config_data->ch2_clip_en) 1177 if (vpif_config_data->
1178 chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
1178 channel2_clipping_enable(0); 1179 channel2_clipping_enable(0);
1179 enable_channel2(0); 1180 enable_channel2(0);
1180 channel2_intr_enable(0); 1181 channel2_intr_enable(0);
1181 } 1182 }
1182 if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || 1183 if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
1183 (2 == common->started)) { 1184 (2 == common->started)) {
1184 if (vpif_config_data->ch3_clip_en) 1185 if (vpif_config_data->
1186 chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
1185 channel3_clipping_enable(0); 1187 channel3_clipping_enable(0);
1186 enable_channel3(0); 1188 enable_channel3(0);
1187 channel3_intr_enable(0); 1189 channel3_intr_enable(0);
@@ -1214,41 +1216,118 @@ static int vpif_enum_output(struct file *file, void *fh,
1214{ 1216{
1215 1217
1216 struct vpif_display_config *config = vpif_dev->platform_data; 1218 struct vpif_display_config *config = vpif_dev->platform_data;
1219 struct vpif_display_chan_config *chan_cfg;
1220 struct vpif_fh *vpif_handler = fh;
1221 struct channel_obj *ch = vpif_handler->channel;
1217 1222
1218 if (output->index >= config->output_count) { 1223 chan_cfg = &config->chan_config[ch->channel_id];
1224 if (output->index >= chan_cfg->output_count) {
1219 vpif_dbg(1, debug, "Invalid output index\n"); 1225 vpif_dbg(1, debug, "Invalid output index\n");
1220 return -EINVAL; 1226 return -EINVAL;
1221 } 1227 }
1222 1228
1223 strcpy(output->name, config->output[output->index]); 1229 *output = chan_cfg->outputs[output->index].output;
1224 output->type = V4L2_OUTPUT_TYPE_ANALOG; 1230 return 0;
1225 output->std = VPIF_V4L2_STD; 1231}
1232
1233/**
1234 * vpif_output_to_subdev() - Maps output to sub device
1235 * @vpif_cfg - global config ptr
1236 * @chan_cfg - channel config ptr
1237 * @index - Given output index from application
1238 *
1239 * lookup the sub device information for a given output index.
1240 * we report all the output to application. output table also
1241 * has sub device name for the each output
1242 */
1243static int
1244vpif_output_to_subdev(struct vpif_display_config *vpif_cfg,
1245 struct vpif_display_chan_config *chan_cfg, int index)
1246{
1247 struct vpif_subdev_info *subdev_info;
1248 const char *subdev_name;
1249 int i;
1250
1251 vpif_dbg(2, debug, "vpif_output_to_subdev\n");
1252
1253 if (chan_cfg->outputs == NULL)
1254 return -1;
1255
1256 subdev_name = chan_cfg->outputs[index].subdev_name;
1257 if (subdev_name == NULL)
1258 return -1;
1259
1260 /* loop through the sub device list to get the sub device info */
1261 for (i = 0; i < vpif_cfg->subdev_count; i++) {
1262 subdev_info = &vpif_cfg->subdevinfo[i];
1263 if (!strcmp(subdev_info->name, subdev_name))
1264 return i;
1265 }
1266 return -1;
1267}
1268
1269/**
1270 * vpif_set_output() - Select an output
1271 * @vpif_cfg - global config ptr
1272 * @ch - channel
1273 * @index - Given output index from application
1274 *
1275 * Select the given output.
1276 */
1277static int vpif_set_output(struct vpif_display_config *vpif_cfg,
1278 struct channel_obj *ch, int index)
1279{
1280 struct vpif_display_chan_config *chan_cfg =
1281 &vpif_cfg->chan_config[ch->channel_id];
1282 struct vpif_subdev_info *subdev_info = NULL;
1283 struct v4l2_subdev *sd = NULL;
1284 u32 input = 0, output = 0;
1285 int sd_index;
1286 int ret;
1287
1288 sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index);
1289 if (sd_index >= 0) {
1290 sd = vpif_obj.sd[sd_index];
1291 subdev_info = &vpif_cfg->subdevinfo[sd_index];
1292 }
1226 1293
1294 if (sd) {
1295 input = chan_cfg->outputs[index].input_route;
1296 output = chan_cfg->outputs[index].output_route;
1297 ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);
1298 if (ret < 0 && ret != -ENOIOCTLCMD) {
1299 vpif_err("Failed to set output\n");
1300 return ret;
1301 }
1302
1303 }
1304 ch->output_idx = index;
1305 ch->sd = sd;
1306 if (chan_cfg->outputs != NULL)
1307 /* update tvnorms from the sub device output info */
1308 ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std;
1227 return 0; 1309 return 0;
1228} 1310}
1229 1311
1230static int vpif_s_output(struct file *file, void *priv, unsigned int i) 1312static int vpif_s_output(struct file *file, void *priv, unsigned int i)
1231{ 1313{
1314 struct vpif_display_config *config = vpif_dev->platform_data;
1315 struct vpif_display_chan_config *chan_cfg;
1232 struct vpif_fh *fh = priv; 1316 struct vpif_fh *fh = priv;
1233 struct channel_obj *ch = fh->channel; 1317 struct channel_obj *ch = fh->channel;
1234 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; 1318 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1235 int ret = 0; 1319
1320 chan_cfg = &config->chan_config[ch->channel_id];
1321
1322 if (i >= chan_cfg->output_count)
1323 return -EINVAL;
1236 1324
1237 if (common->started) { 1325 if (common->started) {
1238 vpif_err("Streaming in progress\n"); 1326 vpif_err("Streaming in progress\n");
1239 return -EBUSY; 1327 return -EBUSY;
1240 } 1328 }
1241 1329
1242 ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, 1330 return vpif_set_output(config, ch, i);
1243 s_routing, 0, i, 0);
1244
1245 if (ret < 0)
1246 vpif_err("Failed to set output standard\n");
1247
1248 ch->output_idx = i;
1249 if (vpif_obj.sd[i])
1250 ch->sd = vpif_obj.sd[i];
1251 return ret;
1252} 1331}
1253 1332
1254static int vpif_g_output(struct file *file, void *priv, unsigned int *i) 1333static 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{ 1370{
1292 struct vpif_fh *fh = priv; 1371 struct vpif_fh *fh = priv;
1293 struct channel_obj *ch = fh->channel; 1372 struct channel_obj *ch = fh->channel;
1373 int ret;
1294 1374
1295 return v4l2_subdev_call(vpif_obj.sd[ch->output_idx], 1375 ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
1296 video, enum_dv_timings, timings); 1376 if (ret == -ENOIOCTLCMD && ret == -ENODEV)
1377 return -EINVAL;
1378 return ret;
1297} 1379}
1298 1380
1299/** 1381/**
@@ -1320,12 +1402,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
1320 1402
1321 /* Configure subdevice timings, if any */ 1403 /* Configure subdevice timings, if any */
1322 ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings); 1404 ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
1323 if (ret == -ENOIOCTLCMD) { 1405 if (ret == -ENOIOCTLCMD || ret == -ENODEV)
1324 vpif_dbg(2, debug, "Custom DV timings not supported by " 1406 ret = 0;
1325 "subdevice\n"); 1407 if (ret < 0) {
1326 return -ENODATA;
1327 }
1328 if (ret < 0 && ret != -ENODEV) {
1329 vpif_dbg(2, debug, "Error setting custom DV timings\n"); 1408 vpif_dbg(2, debug, "Error setting custom DV timings\n");
1330 return ret; 1409 return ret;
1331 } 1410 }
@@ -1531,9 +1610,6 @@ static struct video_device vpif_video_template = {
1531 .name = "vpif", 1610 .name = "vpif",
1532 .fops = &vpif_fops, 1611 .fops = &vpif_fops,
1533 .ioctl_ops = &vpif_ioctl_ops, 1612 .ioctl_ops = &vpif_ioctl_ops,
1534 .tvnorms = VPIF_V4L2_STD,
1535 .current_norm = V4L2_STD_625_50,
1536
1537}; 1613};
1538 1614
1539/*Configure the channels, buffer sizei, request irq */ 1615/*Configure the channels, buffer sizei, request irq */
@@ -1756,6 +1832,11 @@ static __init int vpif_probe(struct platform_device *pdev)
1756 ch->video_dev->lock = &common->lock; 1832 ch->video_dev->lock = &common->lock;
1757 video_set_drvdata(ch->video_dev, ch); 1833 video_set_drvdata(ch->video_dev, ch);
1758 1834
1835 /* select output 0 */
1836 err = vpif_set_output(config, ch, 0);
1837 if (err)
1838 goto probe_out;
1839
1759 /* register video device */ 1840 /* register video device */
1760 vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", 1841 vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
1761 (int)ch, (int)&ch->video_dev); 1842 (int)ch, (int)&ch->video_dev);
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h
index 65e8fe17e11..3882e0675cc 100644
--- a/include/media/davinci/vpif_types.h
+++ b/include/media/davinci/vpif_types.h
@@ -20,6 +20,7 @@
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21 21
22#define VPIF_CAPTURE_MAX_CHANNELS 2 22#define VPIF_CAPTURE_MAX_CHANNELS 2
23#define VPIF_DISPLAY_MAX_CHANNELS 2
23 24
24enum vpif_if_type { 25enum vpif_if_type {
25 VPIF_IF_BT656, 26 VPIF_IF_BT656,
@@ -39,15 +40,25 @@ struct vpif_subdev_info {
39 struct i2c_board_info board_info; 40 struct i2c_board_info board_info;
40}; 41};
41 42
43struct vpif_output {
44 struct v4l2_output output;
45 const char *subdev_name;
46 u32 input_route;
47 u32 output_route;
48};
49
50struct vpif_display_chan_config {
51 const struct vpif_output *outputs;
52 int output_count;
53 bool clip_en;
54};
55
42struct vpif_display_config { 56struct vpif_display_config {
43 int (*set_clock)(int, int); 57 int (*set_clock)(int, int);
44 struct vpif_subdev_info *subdevinfo; 58 struct vpif_subdev_info *subdevinfo;
45 int subdev_count; 59 int subdev_count;
46 const char **output; 60 struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
47 int output_count;
48 const char *card_name; 61 const char *card_name;
49 bool ch2_clip_en;
50 bool ch3_clip_en;
51}; 62};
52 63
53struct vpif_input { 64struct vpif_input {