Loading drivers/video/sh_mobile_meram.c +44 −54 Original line number Original line Diff line number Diff line Loading @@ -9,16 +9,20 @@ * for more details. * for more details. */ */ #include <linux/device.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/pm_runtime.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <video/sh_mobile_meram.h> #include <video/sh_mobile_meram.h> /* meram registers */ /* ----------------------------------------------------------------------------- * MERAM registers */ #define MEVCR1 0x4 #define MEVCR1 0x4 #define MEVCR1_RST (1 << 31) #define MEVCR1_RST (1 << 31) #define MEVCR1_WD (1 << 30) #define MEVCR1_WD (1 << 30) Loading Loading @@ -81,14 +85,12 @@ ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) #define SH_MOBILE_MERAM_ICB_NUM 32 static const unsigned long common_regs[] = { static const unsigned long common_regs[] = { MEVCR1, MEVCR1, MEQSEL1, MEQSEL1, MEQSEL2, MEQSEL2, }; }; #define CMN_REGS_SIZE ARRAY_SIZE(common_regs) #define MERAM_REGS_SIZE ARRAY_SIZE(common_regs) static const unsigned long icb_regs[] = { static const unsigned long icb_regs[] = { MExxCTL, MExxCTL, Loading Loading @@ -117,6 +119,8 @@ struct sh_mobile_meram_icb { unsigned int current_reg; unsigned int current_reg; }; }; #define MERAM_ICB_NUM 32 /* /* * sh_mobile_meram_priv - MERAM device * sh_mobile_meram_priv - MERAM device * @base: Registers base address * @base: Registers base address Loading @@ -127,19 +131,19 @@ struct sh_mobile_meram_icb { */ */ struct sh_mobile_meram_priv { struct sh_mobile_meram_priv { void __iomem *base; void __iomem *base; unsigned long regs[CMN_REGS_SIZE]; unsigned long regs[MERAM_REGS_SIZE]; struct mutex lock; struct mutex lock; unsigned long used_icb; unsigned long used_icb; struct sh_mobile_meram_icb icbs[SH_MOBILE_MERAM_ICB_NUM]; struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM]; }; }; /* settings */ /* settings */ #define MERAM_SEC_LINE 15 #define MERAM_SEC_LINE 15 #define MERAM_LINE_WIDTH 2048 #define MERAM_LINE_WIDTH 2048 /* /* ----------------------------------------------------------------------------- * MERAM/ICB access functions * Registers access */ */ #define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) #define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) Loading Loading @@ -167,8 +171,8 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off) return ioread32(base + off); return ioread32(base + off); } } /* /* ----------------------------------------------------------------------------- * register ICB * Allocation */ */ #define MERAM_CACHE_START(p) ((p) >> 16) #define MERAM_CACHE_START(p) ((p) >> 16) Loading @@ -176,10 +180,7 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off) #define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \ #define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \ (((o) + (s) - 1) & 0xffff)) (((o) + (s) - 1) & 0xffff)) /* /* Check if there's no overlaps in MERAM allocation. */ * check if there's no overlaps in MERAM allocation. */ static int meram_check_overlap(struct sh_mobile_meram_priv *priv, static int meram_check_overlap(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *new) const struct sh_mobile_meram_icb_cfg *new) { { Loading @@ -194,7 +195,7 @@ static int meram_check_overlap(struct sh_mobile_meram_priv *priv, test_bit(new->cache_icb, &priv->used_icb)) test_bit(new->cache_icb, &priv->used_icb)) return 1; return 1; for (i = 0; i < SH_MOBILE_MERAM_ICB_NUM; i++) { for (i = 0; i < MERAM_ICB_NUM; i++) { if (!test_bit(i, &priv->used_icb)) if (!test_bit(i, &priv->used_icb)) continue; continue; Loading @@ -211,10 +212,7 @@ static int meram_check_overlap(struct sh_mobile_meram_priv *priv, return 0; return 0; } } /* /* Mark the specified ICB as used. */ * mark the specified ICB as used */ static void meram_mark(struct sh_mobile_meram_priv *priv, static void meram_mark(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *new, const struct sh_mobile_meram_icb_cfg *new, int pixelformat) int pixelformat) Loading @@ -230,10 +228,7 @@ static void meram_mark(struct sh_mobile_meram_priv *priv, priv->icbs[new->marker_icb].pixelformat = pixelformat; priv->icbs[new->marker_icb].pixelformat = pixelformat; } } /* /* Unmark the specified ICB as used. */ * unmark the specified ICB as used */ static void meram_unmark(struct sh_mobile_meram_priv *priv, static void meram_unmark(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *icb) const struct sh_mobile_meram_icb_cfg *icb) { { Loading @@ -241,9 +236,7 @@ static void meram_unmark(struct sh_mobile_meram_priv *priv, __clear_bit(icb->cache_icb, &priv->used_icb); __clear_bit(icb->cache_icb, &priv->used_icb); } } /* /* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */ * is this a YCbCr(NV12, NV16 or NV24) colorspace */ static int is_nvcolor(int cspace) static int is_nvcolor(int cspace) { { if (cspace == SH_MOBILE_MERAM_PF_NV || if (cspace == SH_MOBILE_MERAM_PF_NV || Loading @@ -252,9 +245,7 @@ static int is_nvcolor(int cspace) return 0; return 0; } } /* /* Set the next address to fetch. */ * set the next address to fetch */ static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_cfg *cfg, const struct sh_mobile_meram_cfg *cfg, unsigned long base_addr_y, unsigned long base_addr_y, Loading Loading @@ -282,9 +273,7 @@ static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, } } } } /* /* Get the next ICB address. */ * get the next ICB address */ static void static void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, const struct sh_mobile_meram_cfg *cfg, const struct sh_mobile_meram_cfg *cfg, Loading @@ -307,10 +296,7 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, #define MERAM_CALC_BYTECOUNT(x, y) \ #define MERAM_CALC_BYTECOUNT(x, y) \ (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) /* /* Initialize MERAM. */ * initialize MERAM */ static int meram_init(struct sh_mobile_meram_priv *priv, static int meram_init(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *icb, const struct sh_mobile_meram_icb_cfg *icb, unsigned int xres, unsigned int yres, unsigned int xres, unsigned int yres, Loading Loading @@ -395,8 +381,8 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv, priv->icbs[icb->marker_icb].cache_unit = 0; priv->icbs[icb->marker_icb].cache_unit = 0; } } /* /* ----------------------------------------------------------------------------- * register the ICB * Registration/unregistration */ */ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, Loading Loading @@ -545,13 +531,24 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, return 0; return 0; } } static struct sh_mobile_meram_ops sh_mobile_meram_ops = { .module = THIS_MODULE, .meram_register = sh_mobile_meram_register, .meram_unregister = sh_mobile_meram_unregister, .meram_update = sh_mobile_meram_update, }; /* ----------------------------------------------------------------------------- * Power management */ static int sh_mobile_meram_runtime_suspend(struct device *dev) static int sh_mobile_meram_runtime_suspend(struct device *dev) { { struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev); struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); unsigned int i, j; unsigned int i, j; for (i = 0; i < CMN_REGS_SIZE; i++) for (i = 0; i < MERAM_REGS_SIZE; i++) priv->regs[i] = meram_read_reg(priv->base, common_regs[i]); priv->regs[i] = meram_read_reg(priv->base, common_regs[i]); for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) { Loading Loading @@ -583,7 +580,7 @@ static int sh_mobile_meram_runtime_resume(struct device *dev) priv->icbs[i].regs[j]); priv->icbs[i].regs[j]); } } for (i = 0; i < CMN_REGS_SIZE; i++) for (i = 0; i < MERAM_REGS_SIZE; i++) meram_write_reg(priv->base, common_regs[i], priv->regs[i]); meram_write_reg(priv->base, common_regs[i], priv->regs[i]); return 0; return 0; } } Loading @@ -593,15 +590,8 @@ static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = { .runtime_resume = sh_mobile_meram_runtime_resume, .runtime_resume = sh_mobile_meram_runtime_resume, }; }; static struct sh_mobile_meram_ops sh_mobile_meram_ops = { /* ----------------------------------------------------------------------------- .module = THIS_MODULE, * Probe/remove and driver init/exit .meram_register = sh_mobile_meram_register, .meram_unregister = sh_mobile_meram_unregister, .meram_update = sh_mobile_meram_update, }; /* * initialize MERAM */ */ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) Loading Loading
drivers/video/sh_mobile_meram.c +44 −54 Original line number Original line Diff line number Diff line Loading @@ -9,16 +9,20 @@ * for more details. * for more details. */ */ #include <linux/device.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/pm_runtime.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <video/sh_mobile_meram.h> #include <video/sh_mobile_meram.h> /* meram registers */ /* ----------------------------------------------------------------------------- * MERAM registers */ #define MEVCR1 0x4 #define MEVCR1 0x4 #define MEVCR1_RST (1 << 31) #define MEVCR1_RST (1 << 31) #define MEVCR1_WD (1 << 30) #define MEVCR1_WD (1 << 30) Loading Loading @@ -81,14 +85,12 @@ ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) #define SH_MOBILE_MERAM_ICB_NUM 32 static const unsigned long common_regs[] = { static const unsigned long common_regs[] = { MEVCR1, MEVCR1, MEQSEL1, MEQSEL1, MEQSEL2, MEQSEL2, }; }; #define CMN_REGS_SIZE ARRAY_SIZE(common_regs) #define MERAM_REGS_SIZE ARRAY_SIZE(common_regs) static const unsigned long icb_regs[] = { static const unsigned long icb_regs[] = { MExxCTL, MExxCTL, Loading Loading @@ -117,6 +119,8 @@ struct sh_mobile_meram_icb { unsigned int current_reg; unsigned int current_reg; }; }; #define MERAM_ICB_NUM 32 /* /* * sh_mobile_meram_priv - MERAM device * sh_mobile_meram_priv - MERAM device * @base: Registers base address * @base: Registers base address Loading @@ -127,19 +131,19 @@ struct sh_mobile_meram_icb { */ */ struct sh_mobile_meram_priv { struct sh_mobile_meram_priv { void __iomem *base; void __iomem *base; unsigned long regs[CMN_REGS_SIZE]; unsigned long regs[MERAM_REGS_SIZE]; struct mutex lock; struct mutex lock; unsigned long used_icb; unsigned long used_icb; struct sh_mobile_meram_icb icbs[SH_MOBILE_MERAM_ICB_NUM]; struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM]; }; }; /* settings */ /* settings */ #define MERAM_SEC_LINE 15 #define MERAM_SEC_LINE 15 #define MERAM_LINE_WIDTH 2048 #define MERAM_LINE_WIDTH 2048 /* /* ----------------------------------------------------------------------------- * MERAM/ICB access functions * Registers access */ */ #define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) #define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) Loading Loading @@ -167,8 +171,8 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off) return ioread32(base + off); return ioread32(base + off); } } /* /* ----------------------------------------------------------------------------- * register ICB * Allocation */ */ #define MERAM_CACHE_START(p) ((p) >> 16) #define MERAM_CACHE_START(p) ((p) >> 16) Loading @@ -176,10 +180,7 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off) #define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \ #define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \ (((o) + (s) - 1) & 0xffff)) (((o) + (s) - 1) & 0xffff)) /* /* Check if there's no overlaps in MERAM allocation. */ * check if there's no overlaps in MERAM allocation. */ static int meram_check_overlap(struct sh_mobile_meram_priv *priv, static int meram_check_overlap(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *new) const struct sh_mobile_meram_icb_cfg *new) { { Loading @@ -194,7 +195,7 @@ static int meram_check_overlap(struct sh_mobile_meram_priv *priv, test_bit(new->cache_icb, &priv->used_icb)) test_bit(new->cache_icb, &priv->used_icb)) return 1; return 1; for (i = 0; i < SH_MOBILE_MERAM_ICB_NUM; i++) { for (i = 0; i < MERAM_ICB_NUM; i++) { if (!test_bit(i, &priv->used_icb)) if (!test_bit(i, &priv->used_icb)) continue; continue; Loading @@ -211,10 +212,7 @@ static int meram_check_overlap(struct sh_mobile_meram_priv *priv, return 0; return 0; } } /* /* Mark the specified ICB as used. */ * mark the specified ICB as used */ static void meram_mark(struct sh_mobile_meram_priv *priv, static void meram_mark(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *new, const struct sh_mobile_meram_icb_cfg *new, int pixelformat) int pixelformat) Loading @@ -230,10 +228,7 @@ static void meram_mark(struct sh_mobile_meram_priv *priv, priv->icbs[new->marker_icb].pixelformat = pixelformat; priv->icbs[new->marker_icb].pixelformat = pixelformat; } } /* /* Unmark the specified ICB as used. */ * unmark the specified ICB as used */ static void meram_unmark(struct sh_mobile_meram_priv *priv, static void meram_unmark(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *icb) const struct sh_mobile_meram_icb_cfg *icb) { { Loading @@ -241,9 +236,7 @@ static void meram_unmark(struct sh_mobile_meram_priv *priv, __clear_bit(icb->cache_icb, &priv->used_icb); __clear_bit(icb->cache_icb, &priv->used_icb); } } /* /* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */ * is this a YCbCr(NV12, NV16 or NV24) colorspace */ static int is_nvcolor(int cspace) static int is_nvcolor(int cspace) { { if (cspace == SH_MOBILE_MERAM_PF_NV || if (cspace == SH_MOBILE_MERAM_PF_NV || Loading @@ -252,9 +245,7 @@ static int is_nvcolor(int cspace) return 0; return 0; } } /* /* Set the next address to fetch. */ * set the next address to fetch */ static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_cfg *cfg, const struct sh_mobile_meram_cfg *cfg, unsigned long base_addr_y, unsigned long base_addr_y, Loading Loading @@ -282,9 +273,7 @@ static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, } } } } /* /* Get the next ICB address. */ * get the next ICB address */ static void static void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, const struct sh_mobile_meram_cfg *cfg, const struct sh_mobile_meram_cfg *cfg, Loading @@ -307,10 +296,7 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, #define MERAM_CALC_BYTECOUNT(x, y) \ #define MERAM_CALC_BYTECOUNT(x, y) \ (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) /* /* Initialize MERAM. */ * initialize MERAM */ static int meram_init(struct sh_mobile_meram_priv *priv, static int meram_init(struct sh_mobile_meram_priv *priv, const struct sh_mobile_meram_icb_cfg *icb, const struct sh_mobile_meram_icb_cfg *icb, unsigned int xres, unsigned int yres, unsigned int xres, unsigned int yres, Loading Loading @@ -395,8 +381,8 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv, priv->icbs[icb->marker_icb].cache_unit = 0; priv->icbs[icb->marker_icb].cache_unit = 0; } } /* /* ----------------------------------------------------------------------------- * register the ICB * Registration/unregistration */ */ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, Loading Loading @@ -545,13 +531,24 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, return 0; return 0; } } static struct sh_mobile_meram_ops sh_mobile_meram_ops = { .module = THIS_MODULE, .meram_register = sh_mobile_meram_register, .meram_unregister = sh_mobile_meram_unregister, .meram_update = sh_mobile_meram_update, }; /* ----------------------------------------------------------------------------- * Power management */ static int sh_mobile_meram_runtime_suspend(struct device *dev) static int sh_mobile_meram_runtime_suspend(struct device *dev) { { struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev); struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); unsigned int i, j; unsigned int i, j; for (i = 0; i < CMN_REGS_SIZE; i++) for (i = 0; i < MERAM_REGS_SIZE; i++) priv->regs[i] = meram_read_reg(priv->base, common_regs[i]); priv->regs[i] = meram_read_reg(priv->base, common_regs[i]); for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) { Loading Loading @@ -583,7 +580,7 @@ static int sh_mobile_meram_runtime_resume(struct device *dev) priv->icbs[i].regs[j]); priv->icbs[i].regs[j]); } } for (i = 0; i < CMN_REGS_SIZE; i++) for (i = 0; i < MERAM_REGS_SIZE; i++) meram_write_reg(priv->base, common_regs[i], priv->regs[i]); meram_write_reg(priv->base, common_regs[i], priv->regs[i]); return 0; return 0; } } Loading @@ -593,15 +590,8 @@ static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = { .runtime_resume = sh_mobile_meram_runtime_resume, .runtime_resume = sh_mobile_meram_runtime_resume, }; }; static struct sh_mobile_meram_ops sh_mobile_meram_ops = { /* ----------------------------------------------------------------------------- .module = THIS_MODULE, * Probe/remove and driver init/exit .meram_register = sh_mobile_meram_register, .meram_unregister = sh_mobile_meram_unregister, .meram_update = sh_mobile_meram_update, }; /* * initialize MERAM */ */ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) Loading