12 #include <linux/device.h>
14 #include <linux/export.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
21 #include <linux/slab.h>
30 #define MEVCR1_RST (1 << 31)
31 #define MEVCR1_WD (1 << 30)
32 #define MEVCR1_AMD1 (1 << 29)
33 #define MEVCR1_AMD0 (1 << 28)
38 #define MExxCTL_BV (1 << 31)
39 #define MExxCTL_BSZ_SHIFT 28
40 #define MExxCTL_MSAR_MASK (0x7ff << MExxCTL_MSAR_SHIFT)
41 #define MExxCTL_MSAR_SHIFT 16
42 #define MExxCTL_NXT_MASK (0x1f << MExxCTL_NXT_SHIFT)
43 #define MExxCTL_NXT_SHIFT 11
44 #define MExxCTL_WD1 (1 << 10)
45 #define MExxCTL_WD0 (1 << 9)
46 #define MExxCTL_WS (1 << 8)
47 #define MExxCTL_CB (1 << 7)
48 #define MExxCTL_WBF (1 << 6)
49 #define MExxCTL_WF (1 << 5)
50 #define MExxCTL_RF (1 << 4)
51 #define MExxCTL_CM (1 << 3)
52 #define MExxCTL_MD_READ (1 << 0)
53 #define MExxCTL_MD_WRITE (2 << 0)
54 #define MExxCTL_MD_ICB_WB (3 << 0)
55 #define MExxCTL_MD_ICB (4 << 0)
56 #define MExxCTL_MD_FB (7 << 0)
57 #define MExxCTL_MD_MASK (7 << 0)
58 #define MExxBSIZE 0x404
59 #define MExxBSIZE_RCNT_SHIFT 28
60 #define MExxBSIZE_YSZM1_SHIFT 16
61 #define MExxBSIZE_XSZM1_SHIFT 0
62 #define MExxMNCF 0x408
63 #define MExxMNCF_KWBNM_SHIFT 28
64 #define MExxMNCF_KRBNM_SHIFT 24
65 #define MExxMNCF_BNM_SHIFT 16
66 #define MExxMNCF_XBV (1 << 15)
67 #define MExxMNCF_CPL_YCBCR444 (1 << 12)
68 #define MExxMNCF_CPL_YCBCR420 (2 << 12)
69 #define MExxMNCF_CPL_YCBCR422 (3 << 12)
70 #define MExxMNCF_CPL_MSK (3 << 12)
71 #define MExxMNCF_BL (1 << 2)
72 #define MExxMNCF_LNM_SHIFT 0
73 #define MExxSARA 0x410
74 #define MExxSARB 0x414
75 #define MExxSBSIZE 0x418
76 #define MExxSBSIZE_HDV (1 << 31)
77 #define MExxSBSIZE_HSZ16 (0 << 28)
78 #define MExxSBSIZE_HSZ32 (1 << 28)
79 #define MExxSBSIZE_HSZ64 (2 << 28)
80 #define MExxSBSIZE_HSZ128 (3 << 28)
81 #define MExxSBSIZE_SBSIZZ_SHIFT 0
83 #define MERAM_MExxCTL_VAL(next, addr) \
84 ((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
85 (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
86 #define MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
87 (((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
88 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
89 ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
91 static const unsigned long common_regs[] = {
96 #define MERAM_REGS_SIZE ARRAY_SIZE(common_regs)
98 static const unsigned long icb_regs[] = {
106 #define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
129 #define MERAM_ICB_NUM 32
164 #define MERAM_GRANULARITY 1024
165 #define MERAM_SEC_LINE 15
166 #define MERAM_LINE_WIDTH 2048
172 #define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20)
174 static inline void meram_write_icb(
void __iomem *base,
unsigned int idx,
175 unsigned int off,
unsigned long val)
180 static inline unsigned long meram_read_icb(
void __iomem *base,
unsigned int idx,
186 static inline void meram_write_reg(
void __iomem *base,
unsigned int off,
192 static inline unsigned long meram_read_reg(
void __iomem *base,
unsigned int off)
234 mem = meram_alloc(priv, size * 1024);
251 meram_free(priv, priv->
meram + plane->
marker->offset,
252 plane->
marker->size * 1024);
259 static int is_nvcolor(
int cspace)
270 unsigned long base_addr_y,
271 unsigned long base_addr_c)
280 meram_write_icb(priv->
base, cache->
planes[0].cache->index, target,
282 meram_write_icb(priv->
base, cache->
planes[0].marker->index, target,
283 base_addr_y + cache->
planes[0].marker->cache_unit);
286 meram_write_icb(priv->
base, cache->
planes[1].cache->index,
287 target, base_addr_c);
288 meram_write_icb(priv->
base, cache->
planes[1].marker->index,
289 target, base_addr_c +
290 cache->
planes[1].marker->cache_unit);
298 unsigned long *icb_addr_y,
unsigned long *icb_addr_c)
301 unsigned long icb_offset;
304 icb_offset = 0x80000000 | (icb->
current_reg << 29);
306 icb_offset = 0xc0000000 | (icb->
current_reg << 23);
308 *icb_addr_y = icb_offset | (cache->
planes[0].marker->index << 24);
310 *icb_addr_c = icb_offset
311 | (cache->
planes[1].marker->index << 24);
314 #define MERAM_CALC_BYTECOUNT(x, y) \
315 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
320 unsigned int xres,
unsigned int yres,
321 unsigned int *out_pitch)
326 unsigned int lcdc_pitch;
328 unsigned int line_cnt;
329 unsigned int save_lines;
332 lcdc_pitch = (xres - 1) | 1023;
333 lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1);
334 lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2);
338 if (lcdc_pitch == 8192 && yres >= 1024) {
340 line_cnt = total_byte_count >> 11;
347 *out_pitch = lcdc_pitch;
348 save_lines = plane->
marker->size / (lcdc_pitch >> 10) / 2;
351 bnm = (save_lines - 1) << 16;
368 plane->
cache->cache_unit = xres * save_lines;
369 plane->
marker->cache_unit = xres * save_lines;
383 plane->
marker->size / 2) |
399 plane->
cache->cache_unit = 0;
400 plane->
marker->cache_unit = 0;
412 return meram_alloc(priv, size);
421 meram_free(priv, mem, size);
431 unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
441 ret = meram_plane_alloc(priv, &cache->
planes[0],
442 cfg->
icb[0].meram_size);
446 cache->
planes[0].marker->current_reg = 1;
452 ret = meram_plane_alloc(priv, &cache->
planes[1],
453 cfg->
icb[1].meram_size);
455 meram_plane_free(priv, &cache->
planes[0]);
468 unsigned int xres,
unsigned int yres,
469 unsigned int pixelformat,
unsigned int *pitch)
474 unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
475 unsigned int out_pitch;
485 dev_dbg(&pdev->
dev,
"registering %dx%d (%s)", xres, yres,
486 !pixelformat ?
"yuv" :
"rgb");
490 dev_err(&pdev->
dev,
"width exceeding the limit (> 8192).");
494 if (cfg->
icb[0].meram_size == 0)
497 if (nplanes == 2 && cfg->
icb[1].meram_size == 0)
503 cache = meram_cache_alloc(priv, cfg, pixelformat);
505 dev_err(&pdev->
dev,
"MERAM allocation failed (%ld).",
511 meram_plane_init(priv, &cache->
planes[0], xres, yres, &out_pitch);
514 meram_plane_init(priv, &cache->
planes[1],
515 xres, (yres + 1) / 2, &out_pitch);
517 meram_plane_init(priv, &cache->
planes[1],
518 2 * xres, (yres + 1) / 2, &out_pitch);
535 meram_plane_cleanup(priv, &cache->
planes[0]);
536 meram_plane_free(priv, &cache->
planes[0]);
539 meram_plane_cleanup(priv, &cache->
planes[1]);
540 meram_plane_free(priv, &cache->
planes[1]);
551 unsigned long base_addr_y,
552 unsigned long base_addr_c,
553 unsigned long *icb_addr_y,
554 unsigned long *icb_addr_c)
561 meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
562 meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
572 static int sh_mobile_meram_suspend(
struct device *
dev)
579 priv->
regs[i] = meram_read_reg(priv->
base, common_regs[i]);
581 for (i = 0; i < 32; i++) {
586 meram_read_icb(priv->
base, i, icb_regs[j]);
596 static int sh_mobile_meram_resume(
struct device *dev)
602 for (i = 0; i < 32; i++) {
606 meram_write_icb(priv->
base, i, icb_regs[j],
607 priv->
icbs[i].regs[j]);
611 meram_write_reg(priv->
base, common_regs[i], priv->
regs[i]);
616 sh_mobile_meram_suspend,
617 sh_mobile_meram_resume,
NULL);
633 dev_err(&pdev->
dev,
"no platform data defined\n");
639 if (regs ==
NULL || meram ==
NULL) {
640 dev_err(&pdev->
dev,
"cannot get platform resources\n");
646 dev_err(&pdev->
dev,
"cannot allocate device data\n");
655 priv->
icbs[i].index = i;
662 dev_err(&pdev->
dev,
"MERAM registers region already claimed\n");
669 dev_err(&pdev->
dev,
"MERAM memory region already claimed\n");
690 error = gen_pool_add(priv->
pool, meram->
start, resource_size(meram),
699 platform_set_drvdata(pdev, priv);
702 dev_info(&pdev->
dev,
"sh_mobile_meram initialized.");
728 pm_runtime_disable(&pdev->
dev);
745 .name =
"sh_mobile_meram",
747 .pm = &sh_mobile_meram_dev_pm_ops,
749 .probe = sh_mobile_meram_probe,
750 .remove = sh_mobile_meram_remove,