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(&reg->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(&reg->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(&reg->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(&reg->control, ppi->ppi_control);
+		bfin_write16(&reg->count, ppi->bytes_per_line - 1);
+		bfin_write16(&reg->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

Reply via email to