diff options
author | Lad, Prabhakar <prabhakar.lad@ti.com> | 2012-09-25 07:11:49 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-05 21:12:27 -0400 |
commit | 2bd4e58c9d00325b7a850b2ac73fd902e9148b77 (patch) | |
tree | ef3242b551f05c3a54533e4a21ff21acd9a3b137 /drivers/media/platform/davinci | |
parent | c389648a927bada928c854dccccf0301317784eb (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>
Diffstat (limited to 'drivers/media/platform/davinci')
-rw-r--r-- | drivers/media/platform/davinci/vpif_display.c | 141 |
1 files changed, 111 insertions, 30 deletions
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 6229e4844bed..ae8329d79242 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 | */ | ||
1243 | static int | ||
1244 | vpif_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 | */ | ||
1277 | static 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 | ||
1230 | static int vpif_s_output(struct file *file, void *priv, unsigned int i) | 1312 | static 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 | ||
1254 | static int vpif_g_output(struct file *file, void *priv, unsigned int *i) | 1333 | 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 | { | 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); |