commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=eb8d1ba3adfedaf38fb5e5987bb581ad2b643987 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk
dynamically create ppi instance, all ppi resource move to struct ppi_info, and use struct bfin_ppi_regs to access registers Signed-off-by: Scott Jiang <[email protected]> --- drivers/media/video/blackfin/Kconfig | 11 +- drivers/media/video/blackfin/Makefile | 4 +- drivers/media/video/blackfin/bfin_capture.c | 13 +- drivers/media/video/blackfin/ppi.c | 262 ++++++++++----------------- include/media/blackfin/bfin_capture.h | 2 + include/media/blackfin/ppi.h | 28 ++- 6 files changed, 128 insertions(+), 192 deletions(-) diff --git a/drivers/media/video/blackfin/Kconfig b/drivers/media/video/blackfin/Kconfig index e2ddfe5..2c6e921 100644 --- a/drivers/media/video/blackfin/Kconfig +++ b/drivers/media/video/blackfin/Kconfig @@ -7,13 +7,4 @@ config VIDEO_BLACKFIN_CAPTURE Choose PPI or EPPI as its interface. To compile this driver as a module, choose M here: the - module will be called bfin_capture. - -config VIDEO_BLACKFIN_PPI - tristate "Blackfin PPI Driver" - depends on VIDEO_BLACKFIN_CAPTURE - help - Support for Blackfin Parallel Peripheral Interface. - - To compile this driver as a module, choose M here: the - module will be called ppi. + module will be called bfin_video_capture. diff --git a/drivers/media/video/blackfin/Makefile b/drivers/media/video/blackfin/Makefile index 48bbb33..aa3a0a2 100644 --- a/drivers/media/video/blackfin/Makefile +++ b/drivers/media/video/blackfin/Makefile @@ -1,2 +1,2 @@ -obj-$(CONFIG_VIDEO_BLACKFIN_PPI) += ppi.o -obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_capture.o +bfin_video_capture-objs := bfin_capture.o ppi.o +obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c index db6f4ed..46b1cc3 100644 --- a/drivers/media/video/blackfin/bfin_capture.c +++ b/drivers/media/video/blackfin/bfin_capture.c @@ -48,7 +48,7 @@ #include <media/blackfin/bfin_capture.h> #define CAPTURE_DRV_NAME "bfin_capture" -#define BCAP_MIN_NUM_BUF 3 +#define BCAP_MIN_NUM_BUF 2 struct bcap_format { u8 *desc; @@ -160,7 +160,7 @@ static int bcap_open(struct file *file) return -ENODEV; } - bcap_fh = kmalloc(sizeof(*bcap_fh), GFP_KERNEL); + bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL); if (!bcap_fh) { v4l2_err(&bcap_dev->v4l2_dev, "unable to allocate memory for file handle object\n"); @@ -959,9 +959,9 @@ static int __devinit bcap_probe(struct platform_device *pdev) bcap_dev->cfg = config; - bcap_dev->ppi = bfin_get_ppi_if(); + bcap_dev->ppi = create_ppi_instance(config->ppi_info); if (!bcap_dev->ppi) { - v4l2_err(pdev->dev.driver, "Unable to get ppi\n"); + v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); ret = -ENODEV; goto err_free_dev; } @@ -970,7 +970,7 @@ static int __devinit bcap_probe(struct platform_device *pdev) bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); if (IS_ERR(bcap_dev->alloc_ctx)) { ret = PTR_ERR(bcap_dev->alloc_ctx); - goto err_free_dev; + goto err_free_ppi; } vfd = video_device_alloc(); @@ -1065,6 +1065,8 @@ err_release_vdev: video_device_release(bcap_dev->video_dev); err_cleanup_ctx: vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); +err_free_ppi: + delete_ppi_instance(bcap_dev->ppi); err_free_dev: kfree(bcap_dev); return ret; @@ -1079,6 +1081,7 @@ static int __devexit bcap_remove(struct platform_device *pdev) video_unregister_device(bcap_dev->video_dev); v4l2_device_unregister(v4l2_dev); vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); + delete_ppi_instance(bcap_dev->ppi); kfree(bcap_dev); return 0; } diff --git a/drivers/media/video/blackfin/ppi.c b/drivers/media/video/blackfin/ppi.c index e81af70..8139940 100644 --- a/drivers/media/video/blackfin/ppi.c +++ b/drivers/media/video/blackfin/ppi.c @@ -18,11 +18,11 @@ */ #include <linux/kernel.h> -#include <linux/module.h> +#include <linux/slab.h> #include <linux/ioport.h> #include <linux/platform_device.h> -#include <asm/io.h> +#include <asm/bfin_ppi.h> #include <asm/dma.h> #include <asm/cacheflush.h> #include <asm/blackfin.h> @@ -30,30 +30,14 @@ #include <media/blackfin/ppi.h> -#define regr(reg) readw((reg) + ppi_base) -#define regw(value, reg) writew(value, ((reg) + ppi_base)) - -#define REG_PPI_CONTROL 0x00 /* PPI Control */ -#define REG_PPI_STATUS 0x04 /* PPI Status */ -#define REG_PPI_COUNT 0x08 /* Transfer Count */ -#define REG_PPI_DELAY 0x0C /* Delay Count */ -#define REG_PPI_FRAME 0x10 /* Lines Per Frame */ - -static int ppi_attach_irq(struct ppi_if *intf, irq_handler_t handler); -static void ppi_detach_irq(struct ppi_if *intf); -static int ppi_start(struct ppi_if *intf); -static int ppi_stop(struct ppi_if *intf); -static int ppi_set_params(struct ppi_if *intf, struct ppi_params *params); -static void ppi_update_addr(struct ppi_if *intf, unsigned long addr); - -static const unsigned short ppi_req[] = { - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - 0, -}; +static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler); +static void ppi_detach_irq(struct ppi_if *ppi); +static int ppi_start(struct ppi_if *ppi); +static int ppi_stop(struct ppi_if *ppi); +static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params); +static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr); -static struct ppi_ops ppi_ops = { +static const struct ppi_ops ppi_ops = { .attach_irq = ppi_attach_irq, .detach_irq = ppi_detach_irq, .start = ppi_start, @@ -62,209 +46,159 @@ static struct ppi_ops ppi_ops = { .update_addr = ppi_update_addr, }; -static struct ppi_if ppi_intf = { - .ops = &ppi_ops, - .pin_req = ppi_req, -}; - -static void __iomem *ppi_base; -static resource_size_t res_start, res_len; - static irqreturn_t ppi_irq_err(int irq, void *dev_id) { + struct ppi_if *ppi = dev_id; + const struct ppi_info *info = ppi->info; unsigned short status; - status = regr(REG_PPI_STATUS); - if (printk_ratelimit()) - pr_info("%s: status = 0x%x\n", __func__, status); - - regw(0xff, REG_PPI_STATUS); + if (!strcmp(info->name, "ppi")) { + struct bfin_ppi_regs __iomem *reg = + (struct bfin_ppi_regs __iomem *)info->base; + status = bfin_read16(reg->status); + if (printk_ratelimit()) + pr_info("%s: status = 0x%x\n", __func__, status); + bfin_write16(®->status, 0xff); + } return IRQ_HANDLED; } -static int ppi_attach_irq(struct ppi_if *intf, irq_handler_t handler) +static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler) { - if (request_dma(intf->dma_ch, "PPI_DMA") < 0) { + const struct ppi_info *info = ppi->info; + + if (request_dma(info->dma_ch, "PPI_DMA") < 0) { pr_err("Unable to allocate DMA channel for PPI\n"); return -EBUSY; } - set_dma_callback(intf->dma_ch, handler, intf); + set_dma_callback(info->dma_ch, handler, ppi); - if (request_irq(intf->irq_err, ppi_irq_err, IRQF_DISABLED, - "PPI ERROR", intf)) { + if (request_irq(info->irq_err, ppi_irq_err, IRQF_DISABLED, + "PPI ERROR", ppi)) { pr_err("Unable to allocate IRQ for PPI\n"); - free_dma(intf->dma_ch); + free_dma(info->dma_ch); return -EBUSY; } return 0; } -static void ppi_detach_irq(struct ppi_if *intf) +static void ppi_detach_irq(struct ppi_if *ppi) { - free_irq(intf->irq_err, intf); - free_dma(intf->dma_ch); + const struct ppi_info *info = ppi->info; + + free_irq(info->irq_err, ppi); + free_dma(info->dma_ch); } -static int ppi_start(struct ppi_if *intf) +static int ppi_start(struct ppi_if *ppi) { + const struct ppi_info *info = ppi->info; + /* enable DMA */ - enable_dma(intf->dma_ch); + enable_dma(info->dma_ch); /* enable PPI */ - intf->ppi_control |= PORT_EN; - regw(intf->ppi_control, REG_PPI_CONTROL); + ppi->ppi_control |= PORT_EN; + if (!strcmp(info->name, "ppi")) { + struct bfin_ppi_regs __iomem *reg = + (struct bfin_ppi_regs __iomem *)info->base; + bfin_write16(®->control, ppi->ppi_control); + } SSYNC(); return 0; } -static int ppi_stop(struct ppi_if *intf) +static int ppi_stop(struct ppi_if *ppi) { + const struct ppi_info *info = ppi->info; + /* disable PPI */ - intf->ppi_control &= ~PORT_EN; - regw(intf->ppi_control, REG_PPI_CONTROL); + ppi->ppi_control &= ~PORT_EN; + if (!strcmp(info->name, "ppi")) { + struct bfin_ppi_regs __iomem *reg = + (struct bfin_ppi_regs __iomem *)info->base; + bfin_write16(®->control, ppi->ppi_control); + } /* disable DMA */ - clear_dma_irqstat(intf->dma_ch); - disable_dma(intf->dma_ch); + clear_dma_irqstat(info->dma_ch); + disable_dma(info->dma_ch); SSYNC(); return 0; } -static int ppi_set_params(struct ppi_if *intf, struct ppi_params *params) +static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) { - intf->bytes_per_line = params->width * params->bpp; - intf->lines_per_frame = params->height; + const struct ppi_info *info = ppi->info; + + ppi->bytes_per_line = params->width * params->bpp; + ppi->lines_per_frame = params->height; /* config DMA */ - intf->dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); + ppi->dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); if (params->ppi_control & DMA32) { - intf->dma_config |= WDSIZE_32; - set_dma_x_count(intf->dma_ch, intf->bytes_per_line >> 2); - set_dma_x_modify(intf->dma_ch, 4); - set_dma_y_modify(intf->dma_ch, 4); + ppi->dma_config |= WDSIZE_32; + set_dma_x_count(info->dma_ch, ppi->bytes_per_line >> 2); + set_dma_x_modify(info->dma_ch, 4); + set_dma_y_modify(info->dma_ch, 4); } else { - intf->dma_config |= WDSIZE_16; - set_dma_x_count(intf->dma_ch, intf->bytes_per_line >> 1); - set_dma_x_modify(intf->dma_ch, 2); - set_dma_y_modify(intf->dma_ch, 2); + ppi->dma_config |= WDSIZE_16; + set_dma_x_count(info->dma_ch, ppi->bytes_per_line >> 1); + set_dma_x_modify(info->dma_ch, 2); + set_dma_y_modify(info->dma_ch, 2); } - set_dma_y_count(intf->dma_ch, intf->lines_per_frame); - set_dma_config(intf->dma_ch, intf->dma_config); + set_dma_y_count(info->dma_ch, ppi->lines_per_frame); + set_dma_config(info->dma_ch, ppi->dma_config); /* config PPI */ - intf->ppi_control = params->ppi_control & ~PORT_EN; - regw(intf->ppi_control, REG_PPI_CONTROL); - regw(intf->bytes_per_line - 1, REG_PPI_COUNT); - regw(intf->lines_per_frame, REG_PPI_FRAME); + ppi->ppi_control = params->ppi_control & ~PORT_EN; + if (!strcmp(info->name, "ppi")) { + struct bfin_ppi_regs __iomem *reg = + (struct bfin_ppi_regs __iomem *)info->base; + bfin_write16(®->control, ppi->ppi_control); + bfin_write16(®->count, ppi->bytes_per_line - 1); + bfin_write16(®->frame, ppi->lines_per_frame); + } SSYNC(); return 0; } -static void ppi_update_addr(struct ppi_if *intf, unsigned long addr) +static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) { - set_dma_start_addr(intf->dma_ch, addr); + set_dma_start_addr(ppi->info->dma_ch, addr); } -struct ppi_if *bfin_get_ppi_if(void) +struct ppi_if *create_ppi_instance(const struct ppi_info *info) { - return &ppi_intf; -} -EXPORT_SYMBOL(bfin_get_ppi_if); + struct ppi_if *ppi; -static int __devinit ppi_probe(struct platform_device *pdev) -{ - int ret; - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENODEV; - goto err; - } - ppi_intf.dma_ch = res->start; + if ((info == NULL) || (info->name == NULL) || (info->pin_req == NULL)) + return NULL; - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, "no IRQ resource\n"); - ret = -ENODEV; - goto err; + if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { + pr_err("request peripheral failed\n"); + return NULL; } - ppi_intf.irq_err = res->start; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no MEM resource\n"); - ret = -ENODEV; - goto err; + ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); + if (ppi == NULL) { + peripheral_free_list(info->pin_req); + pr_err("unable to allocate memory for ppi handle\n"); + return NULL; } + ppi->ops = &ppi_ops; + ppi->info = info; - res_start = res->start; - res_len = res->end - res->start + 1; - res = request_mem_region(res_start, res_len, res->name); - if (!res) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - ret = -EBUSY; - goto err; - } - - ppi_base = ioremap(res_start, res_len); - if (!ppi_base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto err_mem; - } - - if (peripheral_request_list(ppi_intf.pin_req, KBUILD_MODNAME)) { - dev_err(&pdev->dev, "request peripheral failed\n"); - ret = -EBUSY; - goto err_ioremap; - } - - dev_info(&pdev->dev, "ppi probe success\n"); - return 0; -err_ioremap: - iounmap(ppi_base); -err_mem: - release_mem_region(res_start, res_len); -err: - return ret; + pr_info("ppi probe success\n"); + return ppi; } -static int __devexit ppi_remove(struct platform_device *pdev) +void delete_ppi_instance(struct ppi_if *ppi) { - peripheral_free_list(ppi_intf.pin_req); - iounmap(ppi_base); - release_mem_region(res_start, res_len); - return 0; + peripheral_free_list(ppi->info->pin_req); + kfree(ppi); } - -static struct platform_driver ppi_driver = { - .driver = { - .name = "ppi", - .owner = THIS_MODULE, - }, - .probe = ppi_probe, - .remove = __devexit_p(ppi_remove), -}; - -static int __init ppi_init(void) -{ - return platform_driver_register(&ppi_driver); -} - -static void __exit ppi_exit(void) -{ - platform_driver_unregister(&ppi_driver); -} - -device_initcall(ppi_init); -module_exit(ppi_exit); - -MODULE_DESCRIPTION("Analog Devices Parallel Peripheral Interface driver"); -MODULE_AUTHOR("Scott Jiang <[email protected]>"); -MODULE_LICENSE("GPL v2"); diff --git a/include/media/blackfin/bfin_capture.h b/include/media/blackfin/bfin_capture.h index f4f8510..0905837 100644 --- a/include/media/blackfin/bfin_capture.h +++ b/include/media/blackfin/bfin_capture.h @@ -24,6 +24,8 @@ struct bfin_capture_config { int i2c_adapter_id; /* i2c subdevice board info */ struct i2c_board_info board_info; + /* ppi board info */ + const struct ppi_info *ppi_info; /* ppi control */ unsigned short ppi_control; }; diff --git a/include/media/blackfin/ppi.h b/include/media/blackfin/ppi.h index c1b74b1..96f618e 100644 --- a/include/media/blackfin/ppi.h +++ b/include/media/blackfin/ppi.h @@ -32,26 +32,32 @@ struct ppi_params { }; struct ppi_ops { - int (*attach_irq)(struct ppi_if *intf, irq_handler_t handler); - void (*detach_irq)(struct ppi_if *intf); - int (*start)(struct ppi_if *intf); - int (*stop)(struct ppi_if *intf); - int (*set_params)(struct ppi_if *intf, struct ppi_params *params); - void (*update_addr)(struct ppi_if *intf, unsigned long addr); + int (*attach_irq)(struct ppi_if *ppi, irq_handler_t handler); + void (*detach_irq)(struct ppi_if *ppi); + int (*start)(struct ppi_if *ppi); + int (*stop)(struct ppi_if *ppi); + int (*set_params)(struct ppi_if *ppi, struct ppi_params *params); + void (*update_addr)(struct ppi_if *ppi, unsigned long addr); }; -struct ppi_if { +struct ppi_info { + const char *name; /* ppi or eppi */ int dma_ch; int irq_err; + unsigned long base; + const unsigned short *pin_req; +}; + +struct ppi_if { int dma_config; int bytes_per_line; int lines_per_frame; unsigned short ppi_control; - const unsigned short *pin_req; - struct ppi_ops *ops; + const struct ppi_ops *ops; + const struct ppi_info *info; void *priv; }; -struct ppi_if *bfin_get_ppi_if(void); - +struct ppi_if *create_ppi_instance(const struct ppi_info *info); +void delete_ppi_instance(struct ppi_if *ppi); #endif
_______________________________________________ Linux-kernel-commits mailing list [email protected] https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits
