diff options
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-417.c')
-rw-r--r-- | drivers/media/video/cx23885/cx23885-417.c | 141 |
1 files changed, 67 insertions, 74 deletions
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 67c4a59bd882..f5c79e53e5a1 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -900,6 +900,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) | |||
900 | int i, retval = 0; | 900 | int i, retval = 0; |
901 | u32 value = 0; | 901 | u32 value = 0; |
902 | u32 gpio_output = 0; | 902 | u32 gpio_output = 0; |
903 | u32 gpio_value; | ||
903 | u32 checksum = 0; | 904 | u32 checksum = 0; |
904 | u32 *dataptr; | 905 | u32 *dataptr; |
905 | 906 | ||
@@ -907,7 +908,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) | |||
907 | 908 | ||
908 | /* Save GPIO settings before reset of APU */ | 909 | /* Save GPIO settings before reset of APU */ |
909 | retval |= mc417_memory_read(dev, 0x9020, &gpio_output); | 910 | retval |= mc417_memory_read(dev, 0x9020, &gpio_output); |
910 | retval |= mc417_memory_read(dev, 0x900C, &value); | 911 | retval |= mc417_memory_read(dev, 0x900C, &gpio_value); |
911 | 912 | ||
912 | retval = mc417_register_write(dev, | 913 | retval = mc417_register_write(dev, |
913 | IVTV_REG_VPU, 0xFFFFFFED); | 914 | IVTV_REG_VPU, 0xFFFFFFED); |
@@ -991,11 +992,18 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) | |||
991 | 992 | ||
992 | /* F/W power up disturbs the GPIOs, restore state */ | 993 | /* F/W power up disturbs the GPIOs, restore state */ |
993 | retval |= mc417_register_write(dev, 0x9020, gpio_output); | 994 | retval |= mc417_register_write(dev, 0x9020, gpio_output); |
994 | retval |= mc417_register_write(dev, 0x900C, value); | 995 | retval |= mc417_register_write(dev, 0x900C, gpio_value); |
995 | 996 | ||
996 | retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); | 997 | retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); |
997 | retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); | 998 | retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); |
998 | 999 | ||
1000 | /* Hardcoded GPIO's here */ | ||
1001 | retval |= mc417_register_write(dev, 0x9020, 0x4000); | ||
1002 | retval |= mc417_register_write(dev, 0x900C, 0x4000); | ||
1003 | |||
1004 | mc417_register_read(dev, 0x9020, &gpio_output); | ||
1005 | mc417_register_read(dev, 0x900C, &gpio_value); | ||
1006 | |||
999 | if (retval < 0) | 1007 | if (retval < 0) |
1000 | printk(KERN_ERR "%s: Error with mc417_register_write\n", | 1008 | printk(KERN_ERR "%s: Error with mc417_register_write\n", |
1001 | __func__); | 1009 | __func__); |
@@ -1015,6 +1023,12 @@ static void cx23885_codec_settings(struct cx23885_dev *dev) | |||
1015 | { | 1023 | { |
1016 | dprintk(1, "%s()\n", __func__); | 1024 | dprintk(1, "%s()\n", __func__); |
1017 | 1025 | ||
1026 | /* Dynamically change the height based on video standard */ | ||
1027 | if (dev->encodernorm.id & V4L2_STD_525_60) | ||
1028 | dev->ts1.height = 480; | ||
1029 | else | ||
1030 | dev->ts1.height = 576; | ||
1031 | |||
1018 | /* assign frame size */ | 1032 | /* assign frame size */ |
1019 | cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | 1033 | cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, |
1020 | dev->ts1.height, dev->ts1.width); | 1034 | dev->ts1.height, dev->ts1.width); |
@@ -1030,7 +1044,7 @@ static void cx23885_codec_settings(struct cx23885_dev *dev) | |||
1030 | cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); | 1044 | cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); |
1031 | } | 1045 | } |
1032 | 1046 | ||
1033 | static int cx23885_initialize_codec(struct cx23885_dev *dev) | 1047 | static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder) |
1034 | { | 1048 | { |
1035 | int version; | 1049 | int version; |
1036 | int retval; | 1050 | int retval; |
@@ -1112,9 +1126,11 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev) | |||
1112 | mc417_memory_write(dev, 2120, 0x00000080); | 1126 | mc417_memory_write(dev, 2120, 0x00000080); |
1113 | 1127 | ||
1114 | /* start capturing to the host interface */ | 1128 | /* start capturing to the host interface */ |
1115 | cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, | 1129 | if (startencoder) { |
1116 | CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); | 1130 | cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, |
1117 | msleep(10); | 1131 | CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); |
1132 | msleep(10); | ||
1133 | } | ||
1118 | 1134 | ||
1119 | return 0; | 1135 | return 0; |
1120 | } | 1136 | } |
@@ -1196,6 +1212,16 @@ static int cx23885_querymenu(struct cx23885_dev *dev, | |||
1196 | cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); | 1212 | cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); |
1197 | } | 1213 | } |
1198 | 1214 | ||
1215 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
1216 | { | ||
1217 | struct cx23885_fh *fh = file->private_data; | ||
1218 | struct cx23885_dev *dev = fh->dev; | ||
1219 | |||
1220 | call_all(dev, core, g_std, id); | ||
1221 | |||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1199 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) | 1225 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) |
1200 | { | 1226 | { |
1201 | struct cx23885_fh *fh = file->private_data; | 1227 | struct cx23885_fh *fh = file->private_data; |
@@ -1208,55 +1234,31 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) | |||
1208 | if (i == ARRAY_SIZE(cx23885_tvnorms)) | 1234 | if (i == ARRAY_SIZE(cx23885_tvnorms)) |
1209 | return -EINVAL; | 1235 | return -EINVAL; |
1210 | dev->encodernorm = cx23885_tvnorms[i]; | 1236 | dev->encodernorm = cx23885_tvnorms[i]; |
1237 | |||
1238 | /* Have the drier core notify the subdevices */ | ||
1239 | mutex_lock(&dev->lock); | ||
1240 | cx23885_set_tvnorm(dev, *id); | ||
1241 | mutex_unlock(&dev->lock); | ||
1242 | |||
1211 | return 0; | 1243 | return 0; |
1212 | } | 1244 | } |
1213 | 1245 | ||
1214 | static int vidioc_enum_input(struct file *file, void *priv, | 1246 | static int vidioc_enum_input(struct file *file, void *priv, |
1215 | struct v4l2_input *i) | 1247 | struct v4l2_input *i) |
1216 | { | 1248 | { |
1217 | struct cx23885_fh *fh = file->private_data; | 1249 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1218 | struct cx23885_dev *dev = fh->dev; | 1250 | dprintk(1, "%s()\n", __func__); |
1219 | struct cx23885_input *input; | 1251 | return cx23885_enum_input(dev, i); |
1220 | int n; | ||
1221 | |||
1222 | if (i->index >= 4) | ||
1223 | return -EINVAL; | ||
1224 | |||
1225 | input = &cx23885_boards[dev->board].input[i->index]; | ||
1226 | |||
1227 | if (input->type == 0) | ||
1228 | return -EINVAL; | ||
1229 | |||
1230 | /* FIXME | ||
1231 | * strcpy(i->name, input->name); */ | ||
1232 | strcpy(i->name, "unset"); | ||
1233 | |||
1234 | if (input->type == CX23885_VMUX_TELEVISION || | ||
1235 | input->type == CX23885_VMUX_CABLE) | ||
1236 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1237 | else | ||
1238 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
1239 | |||
1240 | for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++) | ||
1241 | i->std |= cx23885_tvnorms[n].id; | ||
1242 | return 0; | ||
1243 | } | 1252 | } |
1244 | 1253 | ||
1245 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 1254 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1246 | { | 1255 | { |
1247 | struct cx23885_fh *fh = file->private_data; | 1256 | return cx23885_get_input(file, priv, i); |
1248 | struct cx23885_dev *dev = fh->dev; | ||
1249 | |||
1250 | *i = dev->input; | ||
1251 | return 0; | ||
1252 | } | 1257 | } |
1253 | 1258 | ||
1254 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 1259 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) |
1255 | { | 1260 | { |
1256 | if (i >= 4) | 1261 | return cx23885_set_input(file, priv, i); |
1257 | return -EINVAL; | ||
1258 | |||
1259 | return 0; | ||
1260 | } | 1262 | } |
1261 | 1263 | ||
1262 | static int vidioc_g_tuner(struct file *file, void *priv, | 1264 | static int vidioc_g_tuner(struct file *file, void *priv, |
@@ -1309,43 +1311,25 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
1309 | } | 1311 | } |
1310 | 1312 | ||
1311 | static int vidioc_s_frequency(struct file *file, void *priv, | 1313 | static int vidioc_s_frequency(struct file *file, void *priv, |
1312 | struct v4l2_frequency *f) | 1314 | struct v4l2_frequency *f) |
1313 | { | 1315 | { |
1314 | struct cx23885_fh *fh = file->private_data; | 1316 | return cx23885_set_frequency(file, priv, f); |
1315 | struct cx23885_dev *dev = fh->dev; | 1317 | } |
1316 | |||
1317 | cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | ||
1318 | CX23885_END_NOW, CX23885_MPEG_CAPTURE, | ||
1319 | CX23885_RAW_BITS_NONE); | ||
1320 | |||
1321 | dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n", | ||
1322 | dev->tuner_type); | ||
1323 | dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n", | ||
1324 | f->tuner, f->type); | ||
1325 | if (UNSET == dev->tuner_type) | ||
1326 | return -EINVAL; | ||
1327 | if (f->tuner != 0) | ||
1328 | return -EINVAL; | ||
1329 | if (f->type != V4L2_TUNER_ANALOG_TV) | ||
1330 | return -EINVAL; | ||
1331 | dev->freq = f->frequency; | ||
1332 | |||
1333 | call_all(dev, tuner, s_frequency, f); | ||
1334 | 1318 | ||
1335 | cx23885_initialize_codec(dev); | 1319 | static int vidioc_g_ctrl(struct file *file, void *priv, |
1320 | struct v4l2_control *ctl) | ||
1321 | { | ||
1322 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | ||
1336 | 1323 | ||
1337 | return 0; | 1324 | return cx23885_get_control(dev, ctl); |
1338 | } | 1325 | } |
1339 | 1326 | ||
1340 | static int vidioc_s_ctrl(struct file *file, void *priv, | 1327 | static int vidioc_s_ctrl(struct file *file, void *priv, |
1341 | struct v4l2_control *ctl) | 1328 | struct v4l2_control *ctl) |
1342 | { | 1329 | { |
1343 | struct cx23885_fh *fh = file->private_data; | 1330 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1344 | struct cx23885_dev *dev = fh->dev; | ||
1345 | 1331 | ||
1346 | /* Update the A/V core */ | 1332 | return cx23885_set_control(dev, ctl); |
1347 | call_all(dev, core, s_ctrl, ctl); | ||
1348 | return 0; | ||
1349 | } | 1333 | } |
1350 | 1334 | ||
1351 | static int vidioc_querycap(struct file *file, void *priv, | 1335 | static int vidioc_querycap(struct file *file, void *priv, |
@@ -1636,7 +1620,7 @@ static ssize_t mpeg_read(struct file *file, char __user *data, | |||
1636 | /* Start mpeg encoder on first read. */ | 1620 | /* Start mpeg encoder on first read. */ |
1637 | if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { | 1621 | if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { |
1638 | if (atomic_inc_return(&dev->v4l_reader_count) == 1) { | 1622 | if (atomic_inc_return(&dev->v4l_reader_count) == 1) { |
1639 | if (cx23885_initialize_codec(dev) < 0) | 1623 | if (cx23885_initialize_codec(dev, 1) < 0) |
1640 | return -EINVAL; | 1624 | return -EINVAL; |
1641 | } | 1625 | } |
1642 | } | 1626 | } |
@@ -1677,6 +1661,8 @@ static struct v4l2_file_operations mpeg_fops = { | |||
1677 | }; | 1661 | }; |
1678 | 1662 | ||
1679 | static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | 1663 | static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { |
1664 | .vidioc_querystd = vidioc_g_std, | ||
1665 | .vidioc_g_std = vidioc_g_std, | ||
1680 | .vidioc_s_std = vidioc_s_std, | 1666 | .vidioc_s_std = vidioc_s_std, |
1681 | .vidioc_enum_input = vidioc_enum_input, | 1667 | .vidioc_enum_input = vidioc_enum_input, |
1682 | .vidioc_g_input = vidioc_g_input, | 1668 | .vidioc_g_input = vidioc_g_input, |
@@ -1686,6 +1672,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | |||
1686 | .vidioc_g_frequency = vidioc_g_frequency, | 1672 | .vidioc_g_frequency = vidioc_g_frequency, |
1687 | .vidioc_s_frequency = vidioc_s_frequency, | 1673 | .vidioc_s_frequency = vidioc_s_frequency, |
1688 | .vidioc_s_ctrl = vidioc_s_ctrl, | 1674 | .vidioc_s_ctrl = vidioc_s_ctrl, |
1675 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1689 | .vidioc_querycap = vidioc_querycap, | 1676 | .vidioc_querycap = vidioc_querycap, |
1690 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 1677 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, |
1691 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1678 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
@@ -1746,8 +1733,8 @@ static struct video_device *cx23885_video_dev_alloc( | |||
1746 | if (NULL == vfd) | 1733 | if (NULL == vfd) |
1747 | return NULL; | 1734 | return NULL; |
1748 | *vfd = *template; | 1735 | *vfd = *template; |
1749 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, | 1736 | snprintf(vfd->name, sizeof(vfd->name), "%s (%s)", |
1750 | type, cx23885_boards[tsport->dev->board].name); | 1737 | cx23885_boards[tsport->dev->board].name, type); |
1751 | vfd->parent = &pci->dev; | 1738 | vfd->parent = &pci->dev; |
1752 | vfd->release = video_device_release; | 1739 | vfd->release = video_device_release; |
1753 | return vfd; | 1740 | return vfd; |
@@ -1791,5 +1778,11 @@ int cx23885_417_register(struct cx23885_dev *dev) | |||
1791 | printk(KERN_INFO "%s: registered device %s [mpeg]\n", | 1778 | printk(KERN_INFO "%s: registered device %s [mpeg]\n", |
1792 | dev->name, video_device_node_name(dev->v4l_device)); | 1779 | dev->name, video_device_node_name(dev->v4l_device)); |
1793 | 1780 | ||
1781 | /* ST: Configure the encoder paramaters, but don't begin | ||
1782 | * encoding, this resolves an issue where the first time the | ||
1783 | * encoder is started video can be choppy. | ||
1784 | */ | ||
1785 | cx23885_initialize_codec(dev, 0); | ||
1786 | |||
1794 | return 0; | 1787 | return 0; |
1795 | } | 1788 | } |