]>
Commit | Line | Data |
---|---|---|
d1dacf77 TD |
1 | /* |
2 | * (C) Copyright 2011 | |
3 | * Matthias Weisser <[email protected]> | |
4 | * | |
5 | * SPDX-License-Identifier: GPL-2.0+ | |
6 | * | |
7 | * imx25lcdc.c - Graphic interface for i.MX25 lcd controller | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
11 | ||
12 | #include <malloc.h> | |
13 | #include <asm/io.h> | |
14 | #include <asm/arch/imx-regs.h> | |
15 | #include <video_fb.h> | |
16 | #include "videomodes.h" | |
17 | ||
18 | /* | |
19 | * 4MB (at the end of system RAM) | |
20 | */ | |
21 | #define VIDEO_MEM_SIZE 0x400000 | |
22 | ||
23 | #define FB_SYNC_CLK_INV (1<<16) /* pixel clock inverted */ | |
24 | ||
25 | /* | |
26 | * Graphic Device | |
27 | */ | |
28 | static GraphicDevice imx25fb; | |
29 | ||
30 | void *video_hw_init(void) | |
31 | { | |
32 | struct lcdc_regs *lcdc = (struct lcdc_regs *)IMX_LCDC_BASE; | |
33 | struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; | |
34 | GraphicDevice *pGD = &imx25fb; | |
35 | char *s; | |
36 | u32 *videomem; | |
37 | ||
38 | memset(pGD, 0, sizeof(GraphicDevice)); | |
39 | ||
40 | pGD->gdfIndex = GDF_16BIT_565RGB; | |
41 | pGD->gdfBytesPP = 2; | |
42 | pGD->memSize = VIDEO_MEM_SIZE; | |
43 | pGD->frameAdrs = PHYS_SDRAM + PHYS_SDRAM_SIZE - VIDEO_MEM_SIZE; | |
44 | ||
45 | videomem = (u32 *)pGD->frameAdrs; | |
46 | ||
47 | s = getenv("videomode"); | |
48 | if (s != NULL) { | |
49 | struct ctfb_res_modes var_mode; | |
50 | u32 lsr, lpcr, lhcr, lvcr; | |
51 | unsigned long div; | |
52 | int bpp; | |
53 | ||
54 | /* Disable all clocks of the LCDC */ | |
55 | writel(readl(&ccm->cgr0) & ~((1<<7) | (1<<24)), &ccm->cgr0); | |
56 | writel(readl(&ccm->cgr1) & ~(1<<29), &ccm->cgr1); | |
57 | ||
58 | bpp = video_get_params(&var_mode, s); | |
59 | ||
60 | if (bpp == 0) { | |
61 | var_mode.xres = 320; | |
62 | var_mode.yres = 240; | |
63 | var_mode.pixclock = 154000; | |
64 | var_mode.left_margin = 68; | |
65 | var_mode.right_margin = 20; | |
66 | var_mode.upper_margin = 4; | |
67 | var_mode.lower_margin = 18; | |
68 | var_mode.hsync_len = 40; | |
69 | var_mode.vsync_len = 6; | |
70 | var_mode.sync = 0; | |
71 | var_mode.vmode = 0; | |
72 | } | |
73 | ||
74 | /* Fill memory with white */ | |
75 | memset(videomem, 0xFF, var_mode.xres * var_mode.yres * 2); | |
76 | ||
77 | imx25fb.winSizeX = var_mode.xres; | |
78 | imx25fb.winSizeY = var_mode.yres; | |
79 | ||
80 | /* LCD base clock is 66.6MHZ. We do calculations in kHz */ | |
81 | div = 66000 / (1000000000L / var_mode.pixclock); | |
82 | if (div > 63) | |
83 | div = 63; | |
84 | if (0 == div) | |
85 | div = 1; | |
86 | ||
87 | lsr = ((var_mode.xres / 16) << 20) | | |
88 | var_mode.yres; | |
89 | lpcr = (1 << 31) | | |
90 | (1 << 30) | | |
91 | (5 << 25) | | |
92 | (1 << 23) | | |
93 | (1 << 22) | | |
94 | (1 << 19) | | |
95 | (1 << 7) | | |
96 | div; | |
97 | lhcr = (var_mode.right_margin << 0) | | |
98 | (var_mode.left_margin << 8) | | |
99 | (var_mode.hsync_len << 26); | |
100 | ||
101 | lvcr = (var_mode.lower_margin << 0) | | |
102 | (var_mode.upper_margin << 8) | | |
103 | (var_mode.vsync_len << 26); | |
104 | ||
105 | writel((uint32_t)videomem, &lcdc->lssar); | |
106 | writel(lsr, &lcdc->lsr); | |
107 | writel(var_mode.xres * 2 / 4, &lcdc->lvpwr); | |
108 | writel(lpcr, &lcdc->lpcr); | |
109 | writel(lhcr, &lcdc->lhcr); | |
110 | writel(lvcr, &lcdc->lvcr); | |
111 | writel(0x00040060, &lcdc->ldcr); | |
112 | ||
113 | writel(0xA90300, &lcdc->lpccr); | |
114 | ||
115 | /* Ensable all clocks of the LCDC */ | |
116 | writel(readl(&ccm->cgr0) | ((1<<7) | (1<<24)), &ccm->cgr0); | |
117 | writel(readl(&ccm->cgr1) | (1<<29), &ccm->cgr1); | |
118 | } | |
119 | ||
120 | return pGD; | |
121 | } |