aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx23885/cx23885-417.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-417.c')
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c141
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
1033static int cx23885_initialize_codec(struct cx23885_dev *dev) 1047static 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
1215static 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
1199static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) 1225static 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
1214static int vidioc_enum_input(struct file *file, void *priv, 1246static 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
1245static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) 1254static 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
1254static int vidioc_s_input(struct file *file, void *priv, unsigned int i) 1259static 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
1262static int vidioc_g_tuner(struct file *file, void *priv, 1264static 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
1311static int vidioc_s_frequency(struct file *file, void *priv, 1313static 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); 1319static 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
1340static int vidioc_s_ctrl(struct file *file, void *priv, 1327static 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
1351static int vidioc_querycap(struct file *file, void *priv, 1335static 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
1679static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { 1663static 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}