aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c32
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h2
-rw-r--r--drivers/video/sh_mobile_meram.c176
-rw-r--r--include/video/sh_mobile_meram.h21
4 files changed, 110 insertions, 121 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 98e81b31fbc4..e593e8188720 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -1104,7 +1104,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
1104 /* Compute frame buffer base address and pitch for each channel. */ 1104 /* Compute frame buffer base address and pitch for each channel. */
1105 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1105 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1106 int pixelformat; 1106 int pixelformat;
1107 void *meram; 1107 void *cache;
1108 1108
1109 ch = &priv->ch[k]; 1109 ch = &priv->ch[k];
1110 if (!ch->enabled) 1110 if (!ch->enabled)
@@ -1119,12 +1119,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
1119 ch->cfg->meram_cfg == NULL) 1119 ch->cfg->meram_cfg == NULL)
1120 continue; 1120 continue;
1121 1121
1122 /* we need to de-init configured ICBs before we can 1122 /* Free the allocated MERAM cache. */
1123 * re-initialize them. 1123 if (ch->cache) {
1124 */ 1124 mdev->ops->cache_free(mdev, ch->cache);
1125 if (ch->meram) { 1125 ch->cache = NULL;
1126 mdev->ops->meram_unregister(mdev, ch->meram);
1127 ch->meram = NULL;
1128 } 1126 }
1129 1127
1130 switch (ch->format->fourcc) { 1128 switch (ch->format->fourcc) {
@@ -1146,14 +1144,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
1146 break; 1144 break;
1147 } 1145 }
1148 1146
1149 meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg, 1147 cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg,
1150 ch->pitch, ch->yres, pixelformat, 1148 ch->pitch, ch->yres, pixelformat,
1151 &ch->line_size); 1149 &ch->line_size);
1152 if (!IS_ERR(meram)) { 1150 if (!IS_ERR(cache)) {
1153 mdev->ops->meram_update(mdev, meram, 1151 mdev->ops->cache_update(mdev, cache,
1154 ch->base_addr_y, ch->base_addr_c, 1152 ch->base_addr_y, ch->base_addr_c,
1155 &ch->base_addr_y, &ch->base_addr_c); 1153 &ch->base_addr_y, &ch->base_addr_c);
1156 ch->meram = meram; 1154 ch->cache = cache;
1157 } 1155 }
1158 } 1156 }
1159 1157
@@ -1223,12 +1221,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
1223 1221
1224 sh_mobile_lcdc_display_off(ch); 1222 sh_mobile_lcdc_display_off(ch);
1225 1223
1226 /* disable the meram */ 1224 /* Free the MERAM cache. */
1227 if (ch->meram) { 1225 if (ch->cache) {
1228 struct sh_mobile_meram_info *mdev; 1226 struct sh_mobile_meram_info *mdev;
1229 mdev = priv->meram_dev; 1227 mdev = priv->meram_dev;
1230 mdev->ops->meram_unregister(mdev, ch->meram); 1228 mdev->ops->cache_free(mdev, ch->cache);
1231 ch->meram = 0; 1229 ch->cache = 0;
1232 } 1230 }
1233 1231
1234 } 1232 }
@@ -1839,11 +1837,11 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
1839 base_addr_c += var->xoffset; 1837 base_addr_c += var->xoffset;
1840 } 1838 }
1841 1839
1842 if (ch->meram) { 1840 if (ch->cache) {
1843 struct sh_mobile_meram_info *mdev; 1841 struct sh_mobile_meram_info *mdev;
1844 1842
1845 mdev = priv->meram_dev; 1843 mdev = priv->meram_dev;
1846 mdev->ops->meram_update(mdev, ch->meram, 1844 mdev->ops->cache_update(mdev, ch->cache,
1847 base_addr_y, base_addr_c, 1845 base_addr_y, base_addr_c,
1848 &base_addr_y, &base_addr_c); 1846 &base_addr_y, &base_addr_c);
1849 } 1847 }
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 5c3bddd2cb72..e53cd1171072 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -59,7 +59,7 @@ struct sh_mobile_lcdc_chan {
59 unsigned long *reg_offs; 59 unsigned long *reg_offs;
60 unsigned long ldmt1r_value; 60 unsigned long ldmt1r_value;
61 unsigned long enabled; /* ME and SE in LDCNT2R */ 61 unsigned long enabled; /* ME and SE in LDCNT2R */
62 void *meram; 62 void *cache;
63 63
64 struct mutex open_lock; /* protects the use counter */ 64 struct mutex open_lock; /* protects the use counter */
65 int use_count; 65 int use_count;
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 82ba830bf95d..4aa3fcb87f17 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -194,13 +194,13 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
194} 194}
195 195
196/* ----------------------------------------------------------------------------- 196/* -----------------------------------------------------------------------------
197 * Allocation 197 * LCDC cache planes allocation, init, cleanup and free
198 */ 198 */
199 199
200/* Allocate ICBs and MERAM for a plane. */ 200/* Allocate ICBs and MERAM for a plane. */
201static int __meram_alloc(struct sh_mobile_meram_priv *priv, 201static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
202 struct sh_mobile_meram_fb_plane *plane, 202 struct sh_mobile_meram_fb_plane *plane,
203 size_t size) 203 size_t size)
204{ 204{
205 unsigned long mem; 205 unsigned long mem;
206 unsigned long idx; 206 unsigned long idx;
@@ -229,8 +229,8 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv,
229} 229}
230 230
231/* Free ICBs and MERAM for a plane. */ 231/* Free ICBs and MERAM for a plane. */
232static void __meram_free(struct sh_mobile_meram_priv *priv, 232static void meram_plane_free(struct sh_mobile_meram_priv *priv,
233 struct sh_mobile_meram_fb_plane *plane) 233 struct sh_mobile_meram_fb_plane *plane)
234{ 234{
235 gen_pool_free(priv->pool, priv->meram + plane->marker->offset, 235 gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
236 plane->marker->size * 1024); 236 plane->marker->size * 1024);
@@ -248,62 +248,6 @@ static int is_nvcolor(int cspace)
248 return 0; 248 return 0;
249} 249}
250 250
251/* Allocate memory for the ICBs and mark them as used. */
252static struct sh_mobile_meram_fb_cache *
253meram_alloc(struct sh_mobile_meram_priv *priv,
254 const struct sh_mobile_meram_cfg *cfg,
255 int pixelformat)
256{
257 struct sh_mobile_meram_fb_cache *cache;
258 unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
259 int ret;
260
261 if (cfg->icb[0].meram_size == 0)
262 return ERR_PTR(-EINVAL);
263
264 if (nplanes == 2 && cfg->icb[1].meram_size == 0)
265 return ERR_PTR(-EINVAL);
266
267 cache = kzalloc(sizeof(*cache), GFP_KERNEL);
268 if (cache == NULL)
269 return ERR_PTR(-ENOMEM);
270
271 cache->nplanes = nplanes;
272
273 ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size);
274 if (ret < 0)
275 goto error;
276
277 cache->planes[0].marker->current_reg = 1;
278 cache->planes[0].marker->pixelformat = pixelformat;
279
280 if (cache->nplanes == 1)
281 return cache;
282
283 ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size);
284 if (ret < 0) {
285 __meram_free(priv, &cache->planes[0]);
286 goto error;
287 }
288
289 return cache;
290
291error:
292 kfree(cache);
293 return ERR_PTR(-ENOMEM);
294}
295
296/* Unmark the specified ICB as used. */
297static void meram_free(struct sh_mobile_meram_priv *priv,
298 struct sh_mobile_meram_fb_cache *cache)
299{
300 __meram_free(priv, &cache->planes[0]);
301 if (cache->nplanes == 2)
302 __meram_free(priv, &cache->planes[1]);
303
304 kfree(cache);
305}
306
307/* Set the next address to fetch. */ 251/* Set the next address to fetch. */
308static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, 252static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
309 struct sh_mobile_meram_fb_cache *cache, 253 struct sh_mobile_meram_fb_cache *cache,
@@ -355,10 +299,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
355 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) 299 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
356 300
357/* Initialize MERAM. */ 301/* Initialize MERAM. */
358static int meram_init(struct sh_mobile_meram_priv *priv, 302static int meram_plane_init(struct sh_mobile_meram_priv *priv,
359 struct sh_mobile_meram_fb_plane *plane, 303 struct sh_mobile_meram_fb_plane *plane,
360 unsigned int xres, unsigned int yres, 304 unsigned int xres, unsigned int yres,
361 unsigned int *out_pitch) 305 unsigned int *out_pitch)
362{ 306{
363 struct sh_mobile_meram_icb *marker = plane->marker; 307 struct sh_mobile_meram_icb *marker = plane->marker;
364 unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres); 308 unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
@@ -427,8 +371,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
427 return 0; 371 return 0;
428} 372}
429 373
430static void meram_deinit(struct sh_mobile_meram_priv *priv, 374static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
431 struct sh_mobile_meram_fb_plane *plane) 375 struct sh_mobile_meram_fb_plane *plane)
432{ 376{
433 /* disable ICB */ 377 /* disable ICB */
434 meram_write_icb(priv->base, plane->cache->index, MExxCTL, 378 meram_write_icb(priv->base, plane->cache->index, MExxCTL,
@@ -441,18 +385,60 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
441} 385}
442 386
443/* ----------------------------------------------------------------------------- 387/* -----------------------------------------------------------------------------
444 * Registration/unregistration 388 * LCDC cache operations
445 */ 389 */
446 390
447static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, 391/* Allocate memory for the ICBs and mark them as used. */
448 const struct sh_mobile_meram_cfg *cfg, 392static struct sh_mobile_meram_fb_cache *
449 unsigned int xres, unsigned int yres, 393meram_cache_alloc(struct sh_mobile_meram_priv *priv,
450 unsigned int pixelformat, 394 const struct sh_mobile_meram_cfg *cfg,
451 unsigned int *pitch) 395 int pixelformat)
396{
397 unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
398 struct sh_mobile_meram_fb_cache *cache;
399 int ret;
400
401 cache = kzalloc(sizeof(*cache), GFP_KERNEL);
402 if (cache == NULL)
403 return ERR_PTR(-ENOMEM);
404
405 cache->nplanes = nplanes;
406
407 ret = meram_plane_alloc(priv, &cache->planes[0],
408 cfg->icb[0].meram_size);
409 if (ret < 0)
410 goto error;
411
412 cache->planes[0].marker->current_reg = 1;
413 cache->planes[0].marker->pixelformat = pixelformat;
414
415 if (cache->nplanes == 1)
416 return cache;
417
418 ret = meram_plane_alloc(priv, &cache->planes[1],
419 cfg->icb[1].meram_size);
420 if (ret < 0) {
421 meram_plane_free(priv, &cache->planes[0]);
422 goto error;
423 }
424
425 return cache;
426
427error:
428 kfree(cache);
429 return ERR_PTR(-ENOMEM);
430}
431
432static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
433 const struct sh_mobile_meram_cfg *cfg,
434 unsigned int xres, unsigned int yres,
435 unsigned int pixelformat,
436 unsigned int *pitch)
452{ 437{
453 struct sh_mobile_meram_fb_cache *cache; 438 struct sh_mobile_meram_fb_cache *cache;
454 struct sh_mobile_meram_priv *priv = pdata->priv; 439 struct sh_mobile_meram_priv *priv = pdata->priv;
455 struct platform_device *pdev = pdata->pdev; 440 struct platform_device *pdev = pdata->pdev;
441 unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
456 unsigned int out_pitch; 442 unsigned int out_pitch;
457 443
458 if (pixelformat != SH_MOBILE_MERAM_PF_NV && 444 if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
@@ -469,10 +455,16 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
469 return ERR_PTR(-EINVAL); 455 return ERR_PTR(-EINVAL);
470 } 456 }
471 457
458 if (cfg->icb[0].meram_size == 0)
459 return ERR_PTR(-EINVAL);
460
461 if (nplanes == 2 && cfg->icb[1].meram_size == 0)
462 return ERR_PTR(-EINVAL);
463
472 mutex_lock(&priv->lock); 464 mutex_lock(&priv->lock);
473 465
474 /* We now register the ICBs and allocate the MERAM regions. */ 466 /* We now register the ICBs and allocate the MERAM regions. */
475 cache = meram_alloc(priv, cfg, pixelformat); 467 cache = meram_cache_alloc(priv, cfg, pixelformat);
476 if (IS_ERR(cache)) { 468 if (IS_ERR(cache)) {
477 dev_err(&pdev->dev, "MERAM allocation failed (%ld).", 469 dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
478 PTR_ERR(cache)); 470 PTR_ERR(cache));
@@ -480,14 +472,14 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
480 } 472 }
481 473
482 /* initialize MERAM */ 474 /* initialize MERAM */
483 meram_init(priv, &cache->planes[0], xres, yres, &out_pitch); 475 meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
484 *pitch = out_pitch; 476 *pitch = out_pitch;
485 if (pixelformat == SH_MOBILE_MERAM_PF_NV) 477 if (pixelformat == SH_MOBILE_MERAM_PF_NV)
486 meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2, 478 meram_plane_init(priv, &cache->planes[1],
487 &out_pitch); 479 xres, (yres + 1) / 2, &out_pitch);
488 else if (pixelformat == SH_MOBILE_MERAM_PF_NV24) 480 else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
489 meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2, 481 meram_plane_init(priv, &cache->planes[1],
490 &out_pitch); 482 2 * xres, (yres + 1) / 2, &out_pitch);
491 483
492err: 484err:
493 mutex_unlock(&priv->lock); 485 mutex_unlock(&priv->lock);
@@ -495,25 +487,29 @@ err:
495} 487}
496 488
497static void 489static void
498sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data) 490sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
499{ 491{
500 struct sh_mobile_meram_fb_cache *cache = data; 492 struct sh_mobile_meram_fb_cache *cache = data;
501 struct sh_mobile_meram_priv *priv = pdata->priv; 493 struct sh_mobile_meram_priv *priv = pdata->priv;
502 494
503 mutex_lock(&priv->lock); 495 mutex_lock(&priv->lock);
504 496
505 /* deinit & free */ 497 /* Cleanup and free. */
506 meram_deinit(priv, &cache->planes[0]); 498 meram_plane_cleanup(priv, &cache->planes[0]);
507 if (cache->nplanes == 2) 499 meram_plane_free(priv, &cache->planes[0]);
508 meram_deinit(priv, &cache->planes[1]);
509 500
510 meram_free(priv, cache); 501 if (cache->nplanes == 2) {
502 meram_plane_cleanup(priv, &cache->planes[1]);
503 meram_plane_free(priv, &cache->planes[1]);
504 }
505
506 kfree(cache);
511 507
512 mutex_unlock(&priv->lock); 508 mutex_unlock(&priv->lock);
513} 509}
514 510
515static void 511static void
516sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data, 512sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
517 unsigned long base_addr_y, unsigned long base_addr_c, 513 unsigned long base_addr_y, unsigned long base_addr_c,
518 unsigned long *icb_addr_y, unsigned long *icb_addr_c) 514 unsigned long *icb_addr_y, unsigned long *icb_addr_c)
519{ 515{
@@ -530,9 +526,9 @@ sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
530 526
531static struct sh_mobile_meram_ops sh_mobile_meram_ops = { 527static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
532 .module = THIS_MODULE, 528 .module = THIS_MODULE,
533 .meram_register = sh_mobile_meram_register, 529 .cache_alloc = sh_mobile_cache_alloc,
534 .meram_unregister = sh_mobile_meram_unregister, 530 .cache_free = sh_mobile_cache_free,
535 .meram_update = sh_mobile_meram_update, 531 .cache_update = sh_mobile_cache_update,
536}; 532};
537 533
538/* ----------------------------------------------------------------------------- 534/* -----------------------------------------------------------------------------
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index 29b2fd3b147e..8a5afaf2c6dc 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -41,19 +41,14 @@ struct sh_mobile_meram_cfg {
41struct module; 41struct module;
42struct sh_mobile_meram_ops { 42struct sh_mobile_meram_ops {
43 struct module *module; 43 struct module *module;
44 /* register usage of meram */ 44
45 void *(*meram_register)(struct sh_mobile_meram_info *meram_dev, 45 /* LCDC cache management */
46 const struct sh_mobile_meram_cfg *cfg, 46 void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev,
47 unsigned int xres, unsigned int yres, 47 const struct sh_mobile_meram_cfg *cfg,
48 unsigned int pixelformat, 48 unsigned int xres, unsigned int yres,
49 unsigned int *pitch); 49 unsigned int pixelformat, unsigned int *pitch);
50 50 void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data);
51 /* unregister usage of meram */ 51 void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data,
52 void (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
53 void *data);
54
55 /* update meram settings */
56 void (*meram_update)(struct sh_mobile_meram_info *meram_dev, void *data,
57 unsigned long base_addr_y, 52 unsigned long base_addr_y,
58 unsigned long base_addr_c, 53 unsigned long base_addr_c,
59 unsigned long *icb_addr_y, 54 unsigned long *icb_addr_y,