diff options
Diffstat (limited to 'drivers/staging/media/zoran/zoran_card.c')
-rw-r--r-- | drivers/staging/media/zoran/zoran_card.c | 398 |
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); |