[PATCH 44/57] fbdev: sh_mobile_meram: Add struct sh_mobile_meram_icb

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

 



The new structure stores ICB parameters for ICBs.

Instead of modifying the struct sh_mobile_meram_cfg instances passed by
callers, store the ICB parameters internally and make the public API
take const pointers to sh_mobile_meram_cfg.

Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
---
 drivers/video/sh_mobile_meram.c |  178 ++++++++++++++++++++-------------------
 include/video/sh_mobile_meram.h |   12 +--
 2 files changed, 94 insertions(+), 96 deletions(-)

diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 7af2ffe..cddb180 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -100,14 +100,38 @@ static unsigned long icb_regs[] = {
 };
 #define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
 
+/*
+ * sh_mobile_meram_icb - MERAM ICB information
+ * @regs: Registers cache
+ * @region: Start and end addresses of the MERAM region
+ * @cache_unit: Bytes to cache per ICB
+ * @pixelformat: Video pixel format of the data stored in the ICB
+ * @current_reg: Which of Start Address Register A (0) or B (1) is in use
+ */
+struct sh_mobile_meram_icb {
+	unsigned long regs[ICB_REGS_SIZE];
+
+	unsigned long region;
+	unsigned int cache_unit;
+	unsigned int pixelformat;
+	unsigned int current_reg;
+};
+
+/*
+ * sh_mobile_meram_priv - MERAM device
+ * @base: Registers base address
+ * @regs: Registers cache
+ * @lock: Protects used_icb and icbs
+ * @used_icb: Bitmask of used ICBs
+ * @icbs: ICBs
+ */
 struct sh_mobile_meram_priv {
-	void __iomem	*base;
-	struct mutex	lock;
-	unsigned long	used_icb;
-	unsigned int	used_meram_cache_regions;
-	unsigned long	used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
-	unsigned long	cmn_saved_regs[CMN_REGS_SIZE];
-	unsigned long	icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM];
+	void __iomem *base;
+	unsigned long regs[CMN_REGS_SIZE];
+
+	struct mutex lock;
+	unsigned long used_icb;
+	struct sh_mobile_meram_icb icbs[SH_MOBILE_MERAM_ICB_NUM];
 };
 
 /* settings */
@@ -157,7 +181,7 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
  */
 
 static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv,
-				      struct sh_mobile_meram_icb_cfg *new)
+				      const struct sh_mobile_meram_icb_cfg *new)
 {
 	unsigned int used_start, used_end, meram_start, meram_end;
 	unsigned int i;
@@ -167,17 +191,20 @@ static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv,
 		return 1;
 
 	if (test_bit(new->marker_icb, &priv->used_icb) ||
-			test_bit(new->cache_icb,  &priv->used_icb))
+	    test_bit(new->cache_icb,  &priv->used_icb))
 		return  1;
 
-	for (i = 0; i < priv->used_meram_cache_regions; i++) {
-		used_start = MERAM_CACHE_START(priv->used_meram_cache[i]);
-		used_end   = MERAM_CACHE_END(priv->used_meram_cache[i]);
+	for (i = 0; i < SH_MOBILE_MERAM_ICB_NUM; i++) {
+		if (!test_bit(i, &priv->used_icb))
+			continue;
+
+		used_start = MERAM_CACHE_START(priv->icbs[i].region);
+		used_end   = MERAM_CACHE_END(priv->icbs[i].region);
 		meram_start = new->meram_offset;
 		meram_end   = new->meram_offset + new->meram_size;
 
 		if ((meram_start >= used_start && meram_start < used_end) ||
-			(meram_end > used_start && meram_end < used_end))
+		    (meram_end > used_start && meram_end < used_end))
 			return 1;
 	}
 
@@ -189,22 +216,18 @@ static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv,
  */
 
 static inline void meram_mark(struct sh_mobile_meram_priv *priv,
-			      struct sh_mobile_meram_icb_cfg *new)
+			      const struct sh_mobile_meram_icb_cfg *new,
+			      int pixelformat)
 {
-	unsigned int n;
-
-	if (new->marker_icb < 0 || new->cache_icb < 0)
-		return;
-
 	__set_bit(new->marker_icb, &priv->used_icb);
 	__set_bit(new->cache_icb, &priv->used_icb);
 
-	n = priv->used_meram_cache_regions;
-
-	priv->used_meram_cache[n] = MERAM_CACHE_SET(new->meram_offset,
-						    new->meram_size);
-
-	priv->used_meram_cache_regions++;
+	priv->icbs[new->marker_icb].region = MERAM_CACHE_SET(new->meram_offset,
+							     new->meram_size);
+	priv->icbs[new->cache_icb].region = MERAM_CACHE_SET(new->meram_offset,
+							    new->meram_size);
+	priv->icbs[new->marker_icb].current_reg = 1;
+	priv->icbs[new->marker_icb].pixelformat = pixelformat;
 }
 
 /*
@@ -212,30 +235,10 @@ static inline void meram_mark(struct sh_mobile_meram_priv *priv,
  */
 
 static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
-				struct sh_mobile_meram_icb_cfg *icb)
+				const struct sh_mobile_meram_icb_cfg *icb)
 {
-	unsigned long pattern;
-	unsigned int i;
-
-	if (icb->marker_icb < 0 || icb->cache_icb < 0)
-		return;
-
 	__clear_bit(icb->marker_icb, &priv->used_icb);
 	__clear_bit(icb->cache_icb, &priv->used_icb);
-
-	pattern = MERAM_CACHE_SET(icb->meram_offset, icb->meram_size);
-	for (i = 0; i < priv->used_meram_cache_regions; i++) {
-		if (priv->used_meram_cache[i] == pattern) {
-			while (i < priv->used_meram_cache_regions - 1) {
-				priv->used_meram_cache[i] =
-					priv->used_meram_cache[i + 1] ;
-				i++;
-			}
-			priv->used_meram_cache[i] = 0;
-			priv->used_meram_cache_regions--;
-			break;
-		}
-	}
 }
 
 /*
@@ -244,7 +247,7 @@ static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
 static inline int is_nvcolor(int cspace)
 {
 	if (cspace == SH_MOBILE_MERAM_PF_NV ||
-			cspace == SH_MOBILE_MERAM_PF_NV24)
+	    cspace == SH_MOBILE_MERAM_PF_NV24)
 		return 1;
 	return 0;
 }
@@ -253,46 +256,51 @@ static inline int is_nvcolor(int cspace)
  * set the next address to fetch
  */
 static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
-				       struct sh_mobile_meram_cfg *cfg,
+				       const struct sh_mobile_meram_cfg *cfg,
 				       unsigned long base_addr_y,
 				       unsigned long base_addr_c)
 {
+	struct sh_mobile_meram_icb *icb = &priv->icbs[cfg->icb[0].marker_icb];
 	unsigned long target;
 
-	cfg->current_reg ^= 1;
-	target = cfg->current_reg ? MExxSARB : MExxSARA;
+	icb->current_reg ^= 1;
+	target = icb->current_reg ? MExxSARB : MExxSARA;
 
 	/* set the next address to fetch */
-	meram_write_icb(priv->base, cfg->icb[0].cache_icb,  target,
+	meram_write_icb(priv->base, cfg->icb[0].cache_icb, target,
 			base_addr_y);
 	meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
-			base_addr_y + cfg->icb[0].cache_unit);
+			base_addr_y +
+			priv->icbs[cfg->icb[0].marker_icb].cache_unit);
 
-	if (is_nvcolor(cfg->pixelformat)) {
+	if (is_nvcolor(icb->pixelformat)) {
 		meram_write_icb(priv->base, cfg->icb[1].cache_icb,  target,
 				base_addr_c);
 		meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
-				base_addr_c + cfg->icb[1].cache_unit);
+				base_addr_c +
+				priv->icbs[cfg->icb[1].marker_icb].cache_unit);
 	}
 }
 
 /*
  * get the next ICB address
  */
-static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
-					   struct sh_mobile_meram_cfg *cfg,
-					   unsigned long *icb_addr_y,
-					   unsigned long *icb_addr_c)
+static inline void
+meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
+			const struct sh_mobile_meram_cfg *cfg,
+			unsigned long *icb_addr_y, unsigned long *icb_addr_c)
 {
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+	struct sh_mobile_meram_icb *icb = &priv->icbs[cfg->icb[0].marker_icb];
 	unsigned long icb_offset;
 
 	if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
-		icb_offset = 0x80000000 | (cfg->current_reg << 29);
+		icb_offset = 0x80000000 | (icb->current_reg << 29);
 	else
-		icb_offset = 0xc0000000 | (cfg->current_reg << 23);
+		icb_offset = 0xc0000000 | (icb->current_reg << 23);
 
 	*icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
-	if (is_nvcolor(cfg->pixelformat))
+	if (is_nvcolor(icb->pixelformat))
 		*icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
 }
 
@@ -304,7 +312,7 @@ static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
  */
 
 static int meram_init(struct sh_mobile_meram_priv *priv,
-		      struct sh_mobile_meram_icb_cfg *icb,
+		      const struct sh_mobile_meram_icb_cfg *icb,
 		      unsigned int xres, unsigned int yres,
 		      unsigned int *out_pitch)
 {
@@ -352,7 +360,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
 	meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch);
 
 	/* save a cache unit size */
-	icb->cache_unit = xres * save_lines;
+	priv->icbs[icb->cache_icb].cache_unit = xres * save_lines;
+	priv->icbs[icb->marker_icb].cache_unit = xres * save_lines;
 
 	/*
 	 * Set MERAM for framebuffer
@@ -374,14 +383,16 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
 }
 
 static void meram_deinit(struct sh_mobile_meram_priv *priv,
-			 struct sh_mobile_meram_icb_cfg *icb)
+			 const struct sh_mobile_meram_icb_cfg *icb)
 {
 	/* disable ICB */
 	meram_write_icb(priv->base, icb->cache_icb,  MExxCTL,
 			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
 	meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
 			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
-	icb->cache_unit = 0;
+
+	priv->icbs[icb->cache_icb].cache_unit = 0;
+	priv->icbs[icb->marker_icb].cache_unit = 0;
 }
 
 /*
@@ -389,7 +400,7 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
  */
 
 static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
-				    struct sh_mobile_meram_cfg *cfg,
+				    const struct sh_mobile_meram_cfg *cfg,
 				    unsigned int xres, unsigned int yres,
 				    unsigned int pixelformat,
 				    unsigned long base_addr_y,
@@ -433,12 +444,6 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 
 	mutex_lock(&priv->lock);
 
-	if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
-		dev_err(&pdev->dev, "no more ICB available.");
-		error = -EINVAL;
-		goto err;
-	}
-
 	/* make sure that there's no overlaps */
 	if (meram_check_overlap(priv, &cfg->icb[0])) {
 		dev_err(&pdev->dev, "conflicting config detected.");
@@ -464,10 +469,9 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 	}
 
 	/* we now register the ICB */
-	cfg->pixelformat = pixelformat;
-	meram_mark(priv, &cfg->icb[0]);
+	meram_mark(priv, &cfg->icb[0], pixelformat);
 	if (is_nvcolor(pixelformat))
-		meram_mark(priv, &cfg->icb[1]);
+		meram_mark(priv, &cfg->icb[1], pixelformat);
 
 	/* initialize MERAM */
 	meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch);
@@ -479,7 +483,6 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 		meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2,
 			&out_pitch);
 
-	cfg->current_reg = 1;
 	meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
 	meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
 
@@ -492,19 +495,21 @@ err:
 }
 
 static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
-				      struct sh_mobile_meram_cfg *cfg)
+				      const struct sh_mobile_meram_cfg *cfg)
 {
 	struct sh_mobile_meram_priv *priv;
+	struct sh_mobile_meram_icb *icb;
 
 	if (!pdata || !pdata->priv || !cfg)
 		return -EINVAL;
 
 	priv = pdata->priv;
+	icb = &priv->icbs[cfg->icb[0].marker_icb];
 
 	mutex_lock(&priv->lock);
 
 	/* deinit & unmark */
-	if (is_nvcolor(cfg->pixelformat)) {
+	if (is_nvcolor(icb->pixelformat)) {
 		meram_deinit(priv, &cfg->icb[1]);
 		meram_unmark(priv, &cfg->icb[1]);
 	}
@@ -517,7 +522,7 @@ static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
 }
 
 static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
-				  struct sh_mobile_meram_cfg *cfg,
+				  const struct sh_mobile_meram_cfg *cfg,
 				  unsigned long base_addr_y,
 				  unsigned long base_addr_c,
 				  unsigned long *icb_addr_y,
@@ -547,18 +552,17 @@ static int sh_mobile_meram_runtime_suspend(struct device *dev)
 	unsigned int i, j;
 
 	for (i = 0; i < CMN_REGS_SIZE; i++)
-		priv->cmn_saved_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++) {
 		if (!test_bit(i, &priv->used_icb))
 			continue;
 		for (j = 0; j < ICB_REGS_SIZE; j++) {
-			priv->icb_saved_regs[i * ICB_REGS_SIZE + j] =
+			priv->icbs[i].regs[j] =
 				meram_read_icb(priv->base, i, icb_regs[j]);
 			/* Reset ICB on resume */
 			if (icb_regs[j] == MExxCTL)
-				priv->icb_saved_regs[i * ICB_REGS_SIZE + j] |=
+				priv->icbs[i].regs[j] |=
 					MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
 		}
 	}
@@ -574,15 +578,13 @@ static int sh_mobile_meram_runtime_resume(struct device *dev)
 	for (i = 0; i < 32; i++) {
 		if (!test_bit(i, &priv->used_icb))
 			continue;
-		for (j = 0; j < ICB_REGS_SIZE; j++) {
+		for (j = 0; j < ICB_REGS_SIZE; j++)
 			meram_write_icb(priv->base, i, icb_regs[j],
-			priv->icb_saved_regs[i * ICB_REGS_SIZE + j]);
-		}
+					priv->icbs[i].regs[j]);
 	}
 
 	for (i = 0; i < CMN_REGS_SIZE; i++)
-		meram_write_reg(priv->base, common_regs[i],
-				priv->cmn_saved_regs[i]);
+		meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
 	return 0;
 }
 
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index 6755e3f..05ca3f9 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -30,14 +30,10 @@ struct sh_mobile_meram_icb_cfg {
 	unsigned int cache_icb;		/* ICB # for Cache ICB */
 	unsigned int meram_offset;	/* MERAM Buffer Offset to use */
 	unsigned int meram_size;	/* MERAM Buffer Size to use */
-
-	unsigned int cache_unit;	/* bytes to cache per ICB */
 };
 
 struct sh_mobile_meram_cfg {
-	struct sh_mobile_meram_icb_cfg	icb[2];
-	int				pixelformat;
-	int				current_reg;
+	struct sh_mobile_meram_icb_cfg icb[2];
 };
 
 struct module;
@@ -45,7 +41,7 @@ struct sh_mobile_meram_ops {
 	struct module	*module;
 	/* register usage of meram */
 	int (*meram_register)(struct sh_mobile_meram_info *meram_dev,
-			      struct sh_mobile_meram_cfg *cfg,
+			      const struct sh_mobile_meram_cfg *cfg,
 			      unsigned int xres, unsigned int yres,
 			      unsigned int pixelformat,
 			      unsigned long base_addr_y,
@@ -56,11 +52,11 @@ struct sh_mobile_meram_ops {
 
 	/* unregister usage of meram */
 	int (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
-				struct sh_mobile_meram_cfg *cfg);
+				const struct sh_mobile_meram_cfg *cfg);
 
 	/* update meram settings */
 	int (*meram_update)(struct sh_mobile_meram_info *meram_dev,
-			    struct sh_mobile_meram_cfg *cfg,
+			    const struct sh_mobile_meram_cfg *cfg,
 			    unsigned long base_addr_y,
 			    unsigned long base_addr_c,
 			    unsigned long *icb_addr_y,
-- 
1.7.3.4

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


[Index of Archives]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Tourism]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux