Re: [PATCH 10/10 - v2] common vpss module for video drivers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

On Thu, Jun 11, 2009 at 9:00 PM, <m-karicheri2@xxxxxx> wrote:
> From: Muralidharan Karicheri <a0868495@xxxxxxxxxxxxxxxxxxxxxxxxxx>
>
> common voss module for video drivers
>
> This is a new module added for vpss library functions that are
> used for configuring vpss system module. All video drivers will
> include vpss.h header file and call functions defined in this
> module to configure vpss system module.
>
>
> Reviewed By "Hans Verkuil".
> Reviewed By "Laurent Pinchart".
>
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@xxxxxx>
> ---
>  drivers/media/video/davinci/vpss.c |  290 ++++++++++++++++++++++++++++++++++++
>  include/media/davinci/vpss.h       |   69 +++++++++
>  2 files changed, 359 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/davinci/vpss.c
>  create mode 100644 include/media/davinci/vpss.h
>
> diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c
> new file mode 100644
> index 0000000..def021e
> --- /dev/null
> +++ b/drivers/media/video/davinci/vpss.c
> @@ -0,0 +1,290 @@
> +/*
> + * Copyright (C) 2009 Texas Instruments.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * common vpss driver for all video drivers.
> + */
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/compiler.h>
> +#include <linux/io.h>
> +#include <mach/hardware.h>
> +#include <media/davinci/vpss.h>
> +
> +/* DM644x defines */
> +#define DM644X_SBL_PCR_VPSS            (4)
> +
> +/* vpss BL register offsets */
> +#define DM355_VPSSBL_CCDCMUX           0x1c
> +/* vpss CLK register offsets */
> +#define DM355_VPSSCLK_CLKCTRL          0x04
> +/* masks and shifts */
> +#define VPSS_HSSISEL_SHIFT             4
> +
> +/*
> + * vpss operations. Depends on platform. Not all functions are available
> + * on all platforms. The api, first check if a functio is available before
> + * invoking it. In the probe, the function ptrs are intialized based on
> + * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
> + */
> +struct vpss_hw_ops {
> +       /* enable clock */
> +       int (*enable_clock)(enum vpss_clock_sel clock_sel, int en);
> +       /* select input to ccdc */
> +       void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
> +       /* clear wbl overlflow bit */
> +       int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
> +};
> +
> +/* vpss configuration */
> +struct vpss_oper_config {
> +       __iomem void *vpss_bl_regs_base;
> +       __iomem void *vpss_regs_base;
> +       struct resource         *r1;
> +       resource_size_t         len1;
> +       struct resource         *r2;
> +       resource_size_t         len2;
> +       char vpss_name[32];
> +       spinlock_t vpss_lock;
> +       struct vpss_hw_ops hw_ops;
> +};
> +
> +static struct vpss_oper_config oper_cfg;
> +
> +/* register access routines */
> +static inline u32 bl_regr(u32 offset)
> +{
> +       return __raw_readl(oper_cfg.vpss_bl_regs_base + offset);
> +}
> +
> +static inline void bl_regw(u32 val, u32 offset)
> +{
> +       __raw_writel(val, oper_cfg.vpss_bl_regs_base + offset);
> +}
> +
> +static inline u32 vpss_regr(u32 offset)
> +{
> +       return __raw_readl(oper_cfg.vpss_regs_base + offset);
> +}
> +
> +static inline void vpss_regw(u32 val, u32 offset)
> +{
> +       __raw_writel(val, oper_cfg.vpss_regs_base + offset);
> +}
> +
> +static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
> +{
> +       bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
> +}
> +
> +int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
> +{
> +       if (!oper_cfg.hw_ops.select_ccdc_source)
> +               return -1;
> +
> +       dm355_select_ccdc_source(src_sel);
> +       return 0;
> +}
> +EXPORT_SYMBOL(vpss_select_ccdc_source);
> +
> +static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
> +{
> +       u32 mask = 1, val;
> +
> +       if (wbl_sel < VPSS_PCR_AEW_WBL_0 ||
> +           wbl_sel > VPSS_PCR_CCDC_WBL_O)
> +               return -1;
> +
> +       /* writing a 0 clear the overflow */
> +       mask = ~(mask << wbl_sel);
> +       val = bl_regr(DM644X_SBL_PCR_VPSS) & mask;
> +       bl_regw(val, DM644X_SBL_PCR_VPSS);
> +       return 0;
> +}
> +
> +int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
> +{
> +       if (!oper_cfg.hw_ops.clear_wbl_overflow)
> +               return -1;
> +
> +       return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel);
> +}
> +EXPORT_SYMBOL(vpss_clear_wbl_overflow);
> +
> +/*
> + *  dm355_enable_clock - Enable VPSS Clock
> + *  @clock_sel: CLock to be enabled/disabled
> + *  @en: enable/disable flag
> + *
> + *  This is called to enable or disable a vpss clock
> + */
> +static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en)
> +{
> +       unsigned long flags;
> +       u32 utemp, mask = 0x1, shift = 0;
> +
> +       switch (clock_sel) {
> +       case VPSS_VPBE_CLOCK:
> +               /* nothing since lsb */
> +               break;
> +       case VPSS_VENC_CLOCK_SEL:
> +               shift = 2;
> +               break;
> +       case VPSS_CFALD_CLOCK:
> +               shift = 3;
> +               break;
> +       case VPSS_H3A_CLOCK:
> +               shift = 4;
> +               break;
> +       case VPSS_IPIPE_CLOCK:
> +               shift = 5;
> +               break;
> +       case VPSS_CCDC_CLOCK:
> +               shift = 6;
> +               break;
> +       default:
> +               printk(KERN_ERR "dm355_enable_clock:"
> +                               " Invalid selector: %d\n", clock_sel);
> +               return -1;
> +       }
> +
> +       spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
> +       utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL);
> +       if (!en)
> +               utemp &= ~(mask << shift);
> +       else
> +               utemp |= (mask << shift);
> +
> +       vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL);
> +       spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
> +       return 0;
> +}
> +
> +int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en)
> +{
> +       if (!oper_cfg.hw_ops.enable_clock)
> +               return -1;
> +
> +       return oper_cfg.hw_ops.enable_clock(clock_sel, en);
> +}
> +EXPORT_SYMBOL(vpss_enable_clock);
> +
> +static int __init vpss_probe(struct platform_device *pdev)
> +{
> +       int                     status;
> +
> +       if (!pdev->dev.platform_data) {
> +               dev_err(&pdev->dev, "vpss, no platform data\n");
> +               return -ENOENT;
> +       }
> +
> +       strcpy(oper_cfg.vpss_name, pdev->dev.platform_data);
> +       dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name);
> +       oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!oper_cfg.r1)
> +               return -ENOENT;
> +
> +       oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1;
> +
> +       oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1,
> +                                        oper_cfg.r1->name);
> +       if (!oper_cfg.r1)
> +               return -EBUSY;
> +
> +       oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1);
> +       if (!oper_cfg.vpss_bl_regs_base) {
> +               status = -EBUSY;
> +               goto fail1;
> +       }
> +
> +       if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
> +               oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +               if (!oper_cfg.r2) {
> +                       status = -ENOENT;
> +                       goto fail2;
> +               }
> +               oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1;
> +               oper_cfg.r2 = request_mem_region(oper_cfg.r2->start,
> +                                                oper_cfg.len2,
> +                                                oper_cfg.r2->name);
> +               if (!oper_cfg.r2) {
> +                       status = -EBUSY;
> +                       goto fail2;
> +               }
> +
> +               oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start,
> +                                                 oper_cfg.len2);
> +               if (!oper_cfg.vpss_regs_base) {
> +                       status = -EBUSY;
> +                       goto fail3;
> +               }
> +       }
> +
> +       if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) {
> +               oper_cfg.hw_ops.enable_clock = dm355_enable_clock;
> +               oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source;
> +       } else if (!strcmp(oper_cfg.vpss_name, "dm644x_vpss"))
> +               oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow;
> +       else
> +               return -ENODEV;

Do you need clean up procedure if you return error here? I mean -
calls to release_mem_region, release_mem_region, etc

> +       spin_lock_init(&oper_cfg.vpss_lock);
> +       dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name);
> +       return 0;
> +fail3:
> +       release_mem_region(oper_cfg.r2->start, oper_cfg.len2);
> +fail2:
> +       iounmap(oper_cfg.vpss_bl_regs_base);
> +fail1:
> +       release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
> +       return status;
> +}


-- 
Best regards, Klimov Alexey
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux