aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/zoran/zoran_card.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/zoran/zoran_card.c')
-rw-r--r--drivers/staging/media/zoran/zoran_card.c398
1 files changed, 253 insertions, 145 deletions
diff --git a/drivers/staging/media/zoran/zoran_card.c b/drivers/staging/media/zoran/zoran_card.c
index f259585b0689..26f978a1cc72 100644
--- a/drivers/staging/media/zoran/zoran_card.c
+++ b/drivers/staging/media/zoran/zoran_card.c
@@ -29,6 +29,9 @@
#include "zoran.h"
#include "zoran_card.h"
#include "zoran_device.h"
+#include "zr36016.h"
+#include "zr36050.h"
+#include "zr36060.h"
extern const struct zoran_format zoran_formats[];
@@ -36,17 +39,6 @@ static int card[BUZ_MAX] = { [0 ... (BUZ_MAX - 1)] = -1 };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "Card type");
-/*
- * The video mem address of the video card. The driver has a little database
- * for some videocards to determine it from there. If your video card is not
- * in there you have either to give it to the driver as a parameter or set
- * in a VIDIOCSFBUF ioctl
- */
-
-static unsigned long vidmem; /* default = 0 - Video memory base address */
-module_param_hw(vidmem, ulong, iomem, 0444);
-MODULE_PARM_DESC(vidmem, "Default video memory base address");
-
/* Default input and video norm at startup of the driver. */
static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */
@@ -68,20 +60,6 @@ static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX - 1)] = -1 };
module_param_array(video_nr, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
-int v4l_nbufs = 4;
-int v4l_bufsize = 864; /* Everybody should be able to work with this setting */
-module_param(v4l_nbufs, int, 0644);
-MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
-module_param(v4l_bufsize, int, 0644);
-MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)");
-
-int jpg_nbufs = 32;
-int jpg_bufsize = 512; /* max size for 100% quality full-PAL frame */
-module_param(jpg_nbufs, int, 0644);
-MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use");
-module_param(jpg_bufsize, int, 0644);
-MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)");
-
/* 1=Pass through TV signal when device is not used */
/* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
int pass_through;
@@ -266,6 +244,96 @@ static const char *codecid_to_modulename(u16 codecid)
return name;
}
+static int codec_init(struct zoran *zr, u16 codecid)
+{
+ switch (codecid) {
+ case CODEC_TYPE_ZR36060:
+#ifdef CONFIG_VIDEO_ZORAN_ZR36060
+ return zr36060_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36060 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ case CODEC_TYPE_ZR36050:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ return zr36050_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36050 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ case CODEC_TYPE_ZR36016:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ return zr36016_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36016 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ }
+
+ pci_err(zr->pci_dev, "unknown codec id %x\n", codecid);
+ return -EINVAL;
+}
+
+static void codec_exit(struct zoran *zr, u16 codecid)
+{
+ switch (codecid) {
+ case CODEC_TYPE_ZR36060:
+#ifdef CONFIG_VIDEO_ZORAN_ZR36060
+ zr36060_cleanup_module();
+#endif
+ break;
+ case CODEC_TYPE_ZR36050:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ zr36050_cleanup_module();
+#endif
+ break;
+ case CODEC_TYPE_ZR36016:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ zr36016_cleanup_module();
+#endif
+ break;
+ }
+}
+
+static int videocodec_init(struct zoran *zr)
+{
+ const char *codec_name, *vfe_name;
+ int result;
+
+ codec_name = codecid_to_modulename(zr->card.video_codec);
+ if (codec_name) {
+ result = codec_init(zr, zr->card.video_codec);
+ if (result < 0) {
+ pci_err(zr->pci_dev, "failed to load video codec %s: %d\n",
+ codec_name, result);
+ return result;
+ }
+ }
+ vfe_name = codecid_to_modulename(zr->card.video_vfe);
+ if (vfe_name) {
+ result = codec_init(zr, zr->card.video_vfe);
+ if (result < 0) {
+ pci_err(zr->pci_dev, "failed to load video vfe %s: %d\n",
+ vfe_name, result);
+ if (codec_name)
+ codec_exit(zr, zr->card.video_codec);
+ return result;
+ }
+ }
+ return 0;
+}
+
+static void videocodec_exit(struct zoran *zr)
+{
+ if (zr->card.video_codec != CODEC_TYPE_NONE)
+ codec_exit(zr, zr->card.video_codec);
+ if (zr->card.video_vfe != CODEC_TYPE_NONE)
+ codec_exit(zr, zr->card.video_vfe);
+}
+
// struct tvnorm {
// u16 wt, wa, h_start, h_sync_start, ht, ha, v_start;
// };
@@ -803,6 +871,99 @@ int zoran_check_jpg_settings(struct zoran *zr,
return 0;
}
+static int zoran_init_video_device(struct zoran *zr, struct video_device *video_dev, int dir)
+{
+ int err;
+
+ /* Now add the template and register the device unit. */
+ *video_dev = zoran_template;
+ video_dev->v4l2_dev = &zr->v4l2_dev;
+ video_dev->lock = &zr->lock;
+ video_dev->device_caps = V4L2_CAP_STREAMING | dir;
+
+ strscpy(video_dev->name, ZR_DEVNAME(zr), sizeof(video_dev->name));
+ /*
+ * It's not a mem2mem device, but you can both capture and output from one and the same
+ * device. This should really be split up into two device nodes, but that's a job for
+ * another day.
+ */
+ video_dev->vfl_dir = VFL_DIR_M2M;
+ zoran_queue_init(zr, &zr->vq, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+ err = video_register_device(video_dev, VFL_TYPE_VIDEO, video_nr[zr->id]);
+ if (err < 0)
+ return err;
+ video_set_drvdata(video_dev, zr);
+ return 0;
+}
+
+static void zoran_exit_video_devices(struct zoran *zr)
+{
+ video_unregister_device(zr->video_dev);
+ kfree(zr->video_dev);
+}
+
+static int zoran_init_video_devices(struct zoran *zr)
+{
+ int err;
+
+ zr->video_dev = video_device_alloc();
+ if (!zr->video_dev)
+ return -ENOMEM;
+
+ err = zoran_init_video_device(zr, zr->video_dev, V4L2_CAP_VIDEO_CAPTURE);
+ if (err)
+ kfree(zr->video_dev);
+ return err;
+}
+
+/*
+ * v4l2_device_unregister() will care about removing zr->encoder/zr->decoder
+ * via v4l2_i2c_subdev_unregister()
+ */
+static int zoran_i2c_init(struct zoran *zr)
+{
+ int err;
+
+ pci_info(zr->pci_dev, "Initializing i2c bus...\n");
+
+ err = zoran_register_i2c(zr);
+ if (err) {
+ pci_err(zr->pci_dev, "%s - cannot initialize i2c bus\n", __func__);
+ return err;
+ }
+
+ zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
+ zr->card.i2c_decoder, 0,
+ zr->card.addrs_decoder);
+ if (!zr->decoder) {
+ pci_err(zr->pci_dev, "Fail to get decoder %s\n", zr->card.i2c_decoder);
+ err = -EINVAL;
+ goto error_decoder;
+ }
+
+ if (zr->card.i2c_encoder) {
+ zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
+ zr->card.i2c_encoder, 0,
+ zr->card.addrs_encoder);
+ if (!zr->encoder) {
+ pci_err(zr->pci_dev, "Fail to get encoder %s\n", zr->card.i2c_encoder);
+ err = -EINVAL;
+ goto error_decoder;
+ }
+ }
+ return 0;
+
+error_decoder:
+ zoran_unregister_i2c(zr);
+ return err;
+}
+
+static void zoran_i2c_exit(struct zoran *zr)
+{
+ zoran_unregister_i2c(zr);
+}
+
void zoran_open_init_params(struct zoran *zr)
{
int i;
@@ -874,17 +1035,11 @@ static int zr36057_init(struct zoran *zr)
zoran_open_init_params(zr);
/* allocate memory *before* doing anything to the hardware in case allocation fails */
- zr->video_dev = video_device_alloc();
- if (!zr->video_dev) {
- err = -ENOMEM;
- goto exit;
- }
zr->stat_com = dma_alloc_coherent(&zr->pci_dev->dev,
BUZ_NUM_STAT_COM * sizeof(u32),
&zr->p_sc, GFP_KERNEL);
if (!zr->stat_com) {
- err = -ENOMEM;
- goto exit_video;
+ return -ENOMEM;
}
for (j = 0; j < BUZ_NUM_STAT_COM; j++)
zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
@@ -897,26 +1052,9 @@ static int zr36057_init(struct zoran *zr)
goto exit_statcom;
}
- /* Now add the template and register the device unit. */
- *zr->video_dev = zoran_template;
- zr->video_dev->v4l2_dev = &zr->v4l2_dev;
- zr->video_dev->lock = &zr->lock;
- zr->video_dev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
-
- strscpy(zr->video_dev->name, ZR_DEVNAME(zr), sizeof(zr->video_dev->name));
- /*
- * It's not a mem2mem device, but you can both capture and output from one and the same
- * device. This should really be split up into two device nodes, but that's a job for
- * another day.
- */
- zr->video_dev->vfl_dir = VFL_DIR_M2M;
-
- zoran_queue_init(zr, &zr->vq);
-
- err = video_register_device(zr->video_dev, VFL_TYPE_VIDEO, video_nr[zr->id]);
- if (err < 0)
+ err = zoran_init_video_devices(zr);
+ if (err)
goto exit_statcomb;
- video_set_drvdata(zr->video_dev, zr);
zoran_init_hardware(zr);
if (!pass_through) {
@@ -931,9 +1069,6 @@ exit_statcomb:
dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2, zr->stat_comb, zr->p_scb);
exit_statcom:
dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32), zr->stat_com, zr->p_sc);
-exit_video:
- kfree(zr->video_dev);
-exit:
return err;
}
@@ -945,6 +1080,8 @@ static void zoran_remove(struct pci_dev *pdev)
if (!zr->initialized)
goto exit_free;
+ debugfs_remove_recursive(zr->dbgfs_dir);
+
zoran_queue_exit(zr);
/* unregister videocodec bus */
@@ -952,9 +1089,10 @@ static void zoran_remove(struct pci_dev *pdev)
videocodec_detach(zr->codec);
if (zr->vfe)
videocodec_detach(zr->vfe);
+ videocodec_exit(zr);
/* unregister i2c bus */
- zoran_unregister_i2c(zr);
+ zoran_i2c_exit(zr);
/* disable PCI bus-mastering */
zoran_set_pci_master(zr, 0);
/* put chip into reset */
@@ -965,7 +1103,7 @@ static void zoran_remove(struct pci_dev *pdev)
dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2, zr->stat_comb, zr->p_scb);
pci_release_regions(pdev);
pci_disable_device(zr->pci_dev);
- video_unregister_device(zr->video_dev);
+ zoran_exit_video_devices(zr);
exit_free:
v4l2_ctrl_handler_free(&zr->hdl);
v4l2_device_unregister(&zr->v4l2_dev);
@@ -1051,6 +1189,39 @@ static const struct v4l2_ctrl_ops zoran_video_ctrl_ops = {
.s_ctrl = zoran_video_set_ctrl,
};
+static int zoran_debugfs_show(struct seq_file *seq, void *v)
+{
+ struct zoran *zr = seq->private;
+
+ seq_printf(seq, "Running mode %x\n", zr->running);
+ seq_printf(seq, "Codec mode %x\n", zr->codec_mode);
+ seq_printf(seq, "Norm %llx\n", zr->norm);
+ seq_printf(seq, "Input %d\n", zr->input);
+ seq_printf(seq, "Buffersize %d\n", zr->buffer_size);
+
+ seq_printf(seq, "V4L width %dx%d\n", zr->v4l_settings.width, zr->v4l_settings.height);
+ seq_printf(seq, "V4L bytesperline %d\n", zr->v4l_settings.bytesperline);
+
+ seq_printf(seq, "JPG decimation %u\n", zr->jpg_settings.decimation);
+ seq_printf(seq, "JPG hor_dcm %u\n", zr->jpg_settings.hor_dcm);
+ seq_printf(seq, "JPG ver_dcm %u\n", zr->jpg_settings.ver_dcm);
+ seq_printf(seq, "JPG tmp_dcm %u\n", zr->jpg_settings.tmp_dcm);
+ seq_printf(seq, "JPG odd_even %u\n", zr->jpg_settings.odd_even);
+ seq_printf(seq, "JPG crop %dx%d %d %d\n",
+ zr->jpg_settings.img_x,
+ zr->jpg_settings.img_y,
+ zr->jpg_settings.img_width,
+ zr->jpg_settings.img_height);
+
+ seq_printf(seq, "Prepared %u\n", zr->prepared);
+ seq_printf(seq, "Queued %u\n", zr->queued);
+
+ videocodec_debugfs_show(seq);
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(zoran_debugfs);
+
/*
* Scan for a Buz card (actually for the PCI controller ZR36057),
* request the irq and map the io memory
@@ -1063,14 +1234,22 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct videocodec_master *master_vfe = NULL;
struct videocodec_master *master_codec = NULL;
int card_num;
- const char *codec_name, *vfe_name;
unsigned int nr;
int err;
+ pci_info(pdev, "Zoran MJPEG board driver version %s\n", ZORAN_VERSION);
+
+ /* some mainboards might not do PCI-PCI data transfer well */
+ if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
+ pci_warn(pdev, "%s: chipset does not support reliable PCI-PCI DMA\n",
+ ZORAN_NAME);
+
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (err)
- return -ENODEV;
- vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
+ return err;
+ err = vb2_dma_contig_set_max_seg_size(&pdev->dev, U32_MAX);
+ if (err)
+ return err;
nr = zoran_num++;
if (nr >= BUZ_MAX) {
@@ -1174,41 +1353,15 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
zr36057_restart(zr);
- /* i2c */
- pci_info(zr->pci_dev, "Initializing i2c bus...\n");
- if (zoran_register_i2c(zr) < 0) {
- pci_err(pdev, "%s - can't initialize i2c bus\n", __func__);
+ err = zoran_i2c_init(zr);
+ if (err)
goto zr_free_irq;
- }
-
- zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
- zr->card.i2c_decoder, 0,
- zr->card.addrs_decoder);
-
- if (zr->card.i2c_encoder)
- zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
- zr->card.i2c_encoder, 0,
- zr->card.addrs_encoder);
pci_info(zr->pci_dev, "Initializing videocodec bus...\n");
-
- if (zr->card.video_codec) {
- codec_name = codecid_to_modulename(zr->card.video_codec);
- if (codec_name) {
- result = request_module(codec_name);
- if (result)
- pci_err(pdev, "failed to load modules %s: %d\n", codec_name, result);
- }
- }
- if (zr->card.video_vfe) {
- vfe_name = codecid_to_modulename(zr->card.video_vfe);
- if (vfe_name) {
- result = request_module(vfe_name);
- if (result < 0)
- pci_err(pdev, "failed to load modules %s: %d\n", vfe_name, result);
- }
- }
+ err = videocodec_init(zr);
+ if (err)
+ goto zr_unreg_i2c;
/* reset JPEG codec */
jpeg_codec_sleep(zr, 1);
@@ -1218,15 +1371,15 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (zr->card.video_codec != 0) {
master_codec = zoran_setup_videocodec(zr, zr->card.video_codec);
if (!master_codec)
- goto zr_unreg_i2c;
+ goto zr_unreg_videocodec;
zr->codec = videocodec_attach(master_codec);
if (!zr->codec) {
pci_err(pdev, "%s - no codec found\n", __func__);
- goto zr_unreg_i2c;
+ goto zr_unreg_videocodec;
}
if (zr->codec->type != zr->card.video_codec) {
pci_err(pdev, "%s - wrong codec\n", __func__);
- goto zr_detach_codec;
+ goto zr_unreg_videocodec;
}
}
if (zr->card.video_vfe != 0) {
@@ -1253,14 +1406,19 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
zr->map_mode = ZORAN_MAP_MODE_RAW;
+ zr->dbgfs_dir = debugfs_create_dir(ZR_DEVNAME(zr), NULL);
+ debugfs_create_file("debug", 0444, zr->dbgfs_dir, zr,
+ &zoran_debugfs_fops);
return 0;
zr_detach_vfe:
videocodec_detach(zr->vfe);
zr_detach_codec:
videocodec_detach(zr->codec);
+zr_unreg_videocodec:
+ videocodec_exit(zr);
zr_unreg_i2c:
- zoran_unregister_i2c(zr);
+ zoran_i2c_exit(zr);
zr_free_irq:
btwrite(0, ZR36057_SPGPPCR);
pci_free_irq(zr->pci_dev, 0, zr);
@@ -1281,54 +1439,4 @@ static struct pci_driver zoran_driver = {
.remove = zoran_remove,
};
-static int __init zoran_init(void)
-{
- int res;
-
- pr_info("Zoran MJPEG board driver version %s\n", ZORAN_VERSION);
-
- /* check the parameters we have been given, adjust if necessary */
- if (v4l_nbufs < 2)
- v4l_nbufs = 2;
- if (v4l_nbufs > VIDEO_MAX_FRAME)
- v4l_nbufs = VIDEO_MAX_FRAME;
- /* The user specifies the in KB, we want them in byte (and page aligned) */
- v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024);
- if (v4l_bufsize < 32768)
- v4l_bufsize = 32768;
- /* 2 MB is arbitrary but sufficient for the maximum possible images */
- if (v4l_bufsize > 2048 * 1024)
- v4l_bufsize = 2048 * 1024;
- if (jpg_nbufs < 4)
- jpg_nbufs = 4;
- if (jpg_nbufs > BUZ_MAX_FRAME)
- jpg_nbufs = BUZ_MAX_FRAME;
- jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024);
- if (jpg_bufsize < 8192)
- jpg_bufsize = 8192;
- if (jpg_bufsize > (512 * 1024))
- jpg_bufsize = 512 * 1024;
- /* Use parameter for vidmem or try to find a video card */
- if (vidmem)
- pr_info("%s: Using supplied video memory base address @ 0x%lx\n", ZORAN_NAME, vidmem);
-
- /* some mainboards might not do PCI-PCI data transfer well */
- if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
- pr_warn("%s: chipset does not support reliable PCI-PCI DMA\n", ZORAN_NAME);
-
- res = pci_register_driver(&zoran_driver);
- if (res) {
- pr_err("Unable to register ZR36057 driver\n");
- return res;
- }
-
- return 0;
-}
-
-static void __exit zoran_exit(void)
-{
- pci_unregister_driver(&zoran_driver);
-}
-
-module_init(zoran_init);
-module_exit(zoran_exit);
+module_pci_driver(zoran_driver);