coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fimd.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <device/mmio.h>
4 #include <console/console.h>
5 #include <soc/clk.h>
6 #include <soc/dp.h>
7 #include <soc/fimd.h>
8 #include <soc/periph.h>
9 #include <soc/sysreg.h>
10 
11 /* fairly useful debugging stuff. */
12 #if 0
13 static inline void fwadl(unsigned long l,void *v) {
14  writel(l, v);
15  printk(BIOS_SPEW, "W %p %p\n", v, (void *)l);
16 }
17 #define lwritel(a,b) fwadl((unsigned long)(a), (void *)(b))
18 
19 static inline unsigned long fradl(void *v) {
20  unsigned long l = readl(v);
21  printk(BIOS_SPEW, "R %p %p\n", v, (void *)l);
22  return l;
23 }
24 
25 #define lreadl(a) fradl((void *)(a))
26 
27 #else
28 #define lwritel(a,b) write32((void *)(b), (unsigned long)(a))
29 #define lreadl(a) read32((void *)(a))
30 #endif
31 
32 /* not sure where we want this so ... */
33 static unsigned long get_lcd_clk(void)
34 {
35  u32 pclk, sclk;
36  unsigned int sel;
37  unsigned int ratio;
38 
39  /*
40  * CLK_SRC_DISP10
41  * CLKMUX_FIMD1 [4]
42  * 0: SCLK_RPLL
43  * 1: SCLK_SPLL
44  */
45  sel = lreadl(&exynos_clock->clk_src_disp10);
46  sel &= (1 << 4);
47 
48  if (sel){
49  sclk = get_pll_clk(SPLL);
50  } else {
51  sclk = get_pll_clk(RPLL);
52  }
53 
54  /*
55  * CLK_DIV_DISP10
56  * FIMD1_RATIO [3:0]
57  */
58  ratio = lreadl(&exynos_clock->clk_div_disp10);
59  ratio = ratio & 0xf;
60 
61  pclk = sclk / (ratio + 1);
62 
63  return pclk;
64 }
65 
66 static void exynos_fimd_set_dualrgb(vidinfo_t *vid, unsigned int enabled)
67 {
68  unsigned int cfg = 0;
69  printk(BIOS_SPEW, "%s %s\n", __func__, enabled ? "enabled" : "not enabled");
70  if (enabled) {
73 
74  /* in case of Line Split mode, MAIN_CNT doesn't need to be set. */
75  cfg |= EXYNOS_DUALRGB_SUB_CNT(vid->vl_col / 2) |
77  }
78 
79  lwritel(cfg, &FIMD_CTRL->dualrgb);
80 }
81 
82 static void exynos_fimd_set_dp_clkcon(unsigned int enabled)
83 {
84  unsigned int cfg = 0;
85 
86  if (enabled){
88  }
89 
90  lwritel(cfg, &FIMD_CTRL->dp_mie_clkcon);
91 }
92 
93 static void exynos_fimd_set_par(vidinfo_t *vid, unsigned int win_id)
94 {
95  unsigned int cfg = 0;
96  printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
97  /* set window control */
98  cfg = lreadl(&FIMD_CTRL->wincon0 +
99  EXYNOS_WINCON(win_id));
100 
105 
106  /* DATAPATH is DMA */
108 
110 
111  /* dma burst is 16 */
113 
115 
116  lwritel(cfg, &FIMD_CTRL->wincon0 +
117  EXYNOS_WINCON(win_id));
118 
119  /* set window position to x=0, y=0*/
121  lwritel(cfg, &FIMD_CTRL->vidosd0a +
122  EXYNOS_VIDOSD(win_id));
123 
124  cfg = EXYNOS_VIDOSD_RIGHT_X(vid->vl_col - 1) |
125  EXYNOS_VIDOSD_BOTTOM_Y(vid->vl_row - 1) |
128 
129  lwritel(cfg, &FIMD_CTRL->vidosd0b +
130  EXYNOS_VIDOSD(win_id));
131  /* set window size for window0*/
132  cfg = EXYNOS_VIDOSD_SIZE(vid->vl_col * vid->vl_row);
133  lwritel(cfg, &FIMD_CTRL->vidosd0c +
134  EXYNOS_VIDOSD(win_id));
135 }
136 
138  void *screen_base, int win_id)
139 {
140  u32 start_addr, end_addr;
141  printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
142  start_addr = (u32)screen_base;
143  end_addr = start_addr + ((vid->vl_col * ((1<<vid->vl_bpix) / 8)) *
144  vid->vl_row);
145 
146  lwritel(start_addr, &FIMD_CTRL->vidw00add0b0 +
147  EXYNOS_BUFFER_OFFSET(win_id));
148  lwritel(end_addr, &FIMD_CTRL->vidw00add1b0 +
149  EXYNOS_BUFFER_OFFSET(win_id));
150 }
151 
153 {
154  unsigned int cfg = 0, div = 0, remainder = 0, remainder_div;
155  unsigned long pixel_clock;
156  unsigned long long src_clock;
157  printk(BIOS_SPEW, "%s\n", __func__);
158  if (vid->dual_lcd_enabled) {
159  pixel_clock = vid->vl_freq *
160  (vid->vl_hspw + vid->vl_hfpd +
161  vid->vl_hbpd + vid->vl_col / 2) *
162  (vid->vl_vspw + vid->vl_vfpd +
163  vid->vl_vbpd + vid->vl_row);
164  } else if (vid->interface_mode == FIMD_CPU_INTERFACE) {
165  pixel_clock = vid->vl_freq *
166  vid->vl_width * vid->vl_height *
167  (vid->cs_setup + vid->wr_setup +
168  vid->wr_act + vid->wr_hold + 1);
169  } else {
170  pixel_clock = vid->vl_freq *
171  (vid->vl_hspw + vid->vl_hfpd +
172  vid->vl_hbpd + vid->vl_col) *
173  (vid->vl_vspw + vid->vl_vfpd +
174  vid->vl_vbpd + vid->vl_row);
175  }
176  printk(BIOS_SPEW, "Pixel clock is %lx\n", pixel_clock);
177 
178  cfg = lreadl(&FIMD_CTRL->vidcon0);
184 
185  src_clock = (unsigned long long) get_lcd_clk();
186 
187  /* get quotient and remainder. */
188  remainder = src_clock % pixel_clock;
189  src_clock /= pixel_clock;
190 
191  div = src_clock;
192 
193  remainder *= 10;
194  remainder_div = remainder / pixel_clock;
195 
196  /* round about one places of decimals. */
197  if (remainder_div >= 5)
198  div++;
199 
200  /* in case of dual lcd mode. */
201  if (vid->dual_lcd_enabled)
202  div--;
203 
204  cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1);
205  lwritel(cfg, &FIMD_CTRL->vidcon0);
206 }
207 
209 {
210  unsigned int cfg = 0;
211  printk(BIOS_SPEW, "%s\n", __func__);
212  cfg = lreadl(&FIMD_CTRL->trigcon);
213 
215 
216  lwritel(cfg, &FIMD_CTRL->trigcon);
217 }
218 
220 {
221  unsigned int cfg = 0;
222  int status;
223  printk(BIOS_SPEW, "%s\n", __func__);
224  cfg = lreadl(&FIMD_CTRL->trigcon);
225 
226  /* frame done func is valid only when TRIMODE[0] is set to 1. */
227  status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) ==
229 
230  return status;
231 }
232 
233 static void exynos_fimd_lcd_on(void)
234 {
235  unsigned int cfg = 0;
236 
237  printk(BIOS_SPEW, "%s\n", __func__);
238  /* display on */
239  cfg = lreadl(&FIMD_CTRL->vidcon0);
241  lwritel(cfg, &FIMD_CTRL->vidcon0);
242 }
243 
244 static void exynos_fimd_window_on(unsigned int win_id)
245 {
246  unsigned int cfg = 0;
247  printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
248  /* enable window */
249  cfg = lreadl(&FIMD_CTRL->wincon0 +
250  EXYNOS_WINCON(win_id));
252  lwritel(cfg, &FIMD_CTRL->wincon0 +
253  EXYNOS_WINCON(win_id));
254 
255  cfg = lreadl(&FIMD_CTRL->winshmap);
256  cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id);
257  lwritel(cfg, &FIMD_CTRL->winshmap);
258  cfg = lreadl(&FIMD_CTRL->winshmap);
259 }
260 
262 {
263  unsigned int cfg = 0;
264  printk(BIOS_SPEW, "%s\n", __func__);
265 
266  cfg = lreadl(&FIMD_CTRL->vidcon0);
268  lwritel(cfg, &FIMD_CTRL->vidcon0);
269 }
270 
271 void exynos_fimd_window_off(unsigned int win_id)
272 {
273  unsigned int cfg = 0;
274  printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
275 
276  cfg = lreadl(&FIMD_CTRL->wincon0 +
277  EXYNOS_WINCON(win_id));
279  lwritel(cfg, &FIMD_CTRL->wincon0 +
280  EXYNOS_WINCON(win_id));
281 
282  cfg = lreadl(&FIMD_CTRL->winshmap);
283  cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id);
284  lwritel(cfg, &FIMD_CTRL->winshmap);
285 }
286 
287 static void exynos5_set_system_display(void)
288 {
289  unsigned int cfg = 0;
290 
291  /*
292  * system register path set
293  * 0: MIE/MDNIE
294  * 1: FIMD Bypass
295  */
297  cfg |= (1 << 15);
299 }
300 
302 {
303  unsigned int cfg = 0, rgb_mode;
304  struct exynos_fb *fimd;
305 
306  fimd = (void *)(FIMD_CTRL_ADDR + EXYNOS5_LCD_IF_BASE_OFFSET);
307 
308  printk(BIOS_SPEW, "%s\n", __func__);
310 
311  rgb_mode = vid->rgb_mode;
312 
313  if (vid->interface_mode == FIMD_RGB_INTERFACE) {
314  printk(BIOS_SPEW, "%s FIMD_RGB_INTERFACE\n", __func__);
315 
317  lwritel(cfg, &FIMD_CTRL->vidcon0);
318 
319  cfg = lreadl(&FIMD_CTRL->vidcon2);
320  cfg &= ~(EXYNOS_VIDCON2_WB_MASK |
324  lwritel(cfg, &FIMD_CTRL->vidcon2);
325 
326  /* set polarity */
327  cfg = 0;
328  if (!vid->vl_clkp)
330  if (!vid->vl_hsp)
332  if (!vid->vl_vsp)
334  if (!vid->vl_dp)
336 
337  lwritel(cfg, &fimd->vidcon1);
338 
339  /* set timing */
340  cfg = EXYNOS_VIDTCON0_VFPD(vid->vl_vfpd - 1);
341  cfg |= EXYNOS_VIDTCON0_VBPD(vid->vl_vbpd - 1);
342  cfg |= EXYNOS_VIDTCON0_VSPW(vid->vl_vspw - 1);
343  lwritel(cfg, &fimd->vidtcon0);
344 
345  cfg = EXYNOS_VIDTCON1_HFPD(vid->vl_hfpd - 1);
346  cfg |= EXYNOS_VIDTCON1_HBPD(vid->vl_hbpd - 1);
347  cfg |= EXYNOS_VIDTCON1_HSPW(vid->vl_hspw - 1);
348 
349  lwritel(cfg, &fimd->vidtcon1);
350 
351  /* set lcd size */
352  cfg = EXYNOS_VIDTCON2_HOZVAL(vid->vl_col - 1) |
353  EXYNOS_VIDTCON2_LINEVAL(vid->vl_row - 1) |
354  EXYNOS_VIDTCON2_HOZVAL_E(vid->vl_col - 1) |
355  EXYNOS_VIDTCON2_LINEVAL_E(vid->vl_row - 1);
356 
357  lwritel(cfg, &fimd->vidtcon2);
358  }
359 
360  /* set display mode */
361  cfg = lreadl(&FIMD_CTRL->vidcon0);
363  cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT);
364  lwritel(cfg, &FIMD_CTRL->vidcon0);
365 
366  /* set par */
367  exynos_fimd_set_par(vid, vid->win_id);
368 
369  /* set memory address */
370  exynos_fimd_set_buffer_address(vid, vid->screen_base, vid->win_id);
371 
372  /* set buffer size */
373  cfg = EXYNOS_VIDADDR_PAGEWIDTH(vid->vl_col * (1<<vid->vl_bpix) / 8) |
374  EXYNOS_VIDADDR_PAGEWIDTH_E(vid->vl_col * (1<<vid->vl_bpix) / 8) |
377 
378  lwritel(cfg, &FIMD_CTRL->vidw00add2 +
379  EXYNOS_BUFFER_SIZE(vid->win_id));
380 
381  /* set clock */
383 
384  /* set rgb mode to dual lcd. */
385  exynos_fimd_set_dualrgb(vid, vid->dual_lcd_enabled);
386 
387  /* display on */
389 
390  /* window on */
391  exynos_fimd_window_on(vid->win_id);
392 
393  exynos_fimd_set_dp_clkcon(vid->dp_enabled);
395  printk(BIOS_SPEW, "%s: done\n", __func__);
396 }
397 
399 {
400  printk(BIOS_SPEW, "%s\n", __func__);
401  return vid->vl_col * vid->vl_row * ((1<<vid->vl_bpix) / 8);
402 }
403 
405 {
406  int i;
407  printk(BIOS_SPEW, "%s\n", __func__);
408 
409  for (i = 0; i < 4; i++)
411 }
#define printk(level,...)
Definition: stdlib.h:16
uint16_t vid
Definition: tis.c:15
static struct exynos5_clock *const exynos_clock
Definition: clk.h:446
#define RPLL
Definition: clk.h:20
#define SPLL
Definition: clk.h:21
#define EXYNOS_WINCON(x)
Definition: dp.h:876
#define EXYNOS_VIDTCON2_HOZVAL_E(x)
Definition: dp.h:973
#define EXYNOS_VIDCON0_PNRMODE_SHIFT
Definition: dp.h:904
#define EXYNOS_VIDCON1_IVDEN_INVERT
Definition: dp.h:931
#define EXYNOS_VIDTCON0_VSPW(x)
Definition: dp.h:961
#define EXYNOS_VIDCON0_CLKVALUP_ALWAYS
Definition: dp.h:905
#define EXYNOS_VIDOSD_RIGHT_X_E(x)
Definition: dp.h:1051
#define EXYNOS_WINCON_HAWSWP_ENABLE
Definition: dp.h:993
#define EXYNOS_VIDCON1_IVSYNC_INVERT
Definition: dp.h:929
#define EXYNOS_WINCON_BPPMODE_16BPP_565
Definition: dp.h:1015
#define EXYNOS_VIDTCON2_LINEVAL_E(x)
Definition: dp.h:972
#define EXYNOS5_LCD_IF_BASE_OFFSET
Definition: dp.h:871
#define EXYNOS_VIDCON2_WB_DISABLE
Definition: dp.h:937
#define EXYNOS_VIDADDR_OFFSIZE(x)
Definition: dp.h:1075
#define EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK
Definition: dp.h:945
#define EXYNOS_DUALRGB_LINESPLIT
Definition: dp.h:1146
#define EXYNOS_I80STATUS_TRIG_DONE
Definition: dp.h:1166
#define EXYNOS_VIDOSD_SIZE(x)
Definition: dp.h:1055
#define EXYNOS_VIDCON2_TVFORMATSEL_MASK
Definition: dp.h:942
#define EXYNOS_DUALRGB_VDEN_EN_ENABLE
Definition: dp.h:1150
#define EXYNOS_VIDCON0_VCLKEN_MASK
Definition: dp.h:911
#define EXYNOS_DUALRGB_SUB_CNT(x)
Definition: dp.h:1148
#define EXYNOS_I80SOFT_TRIG_EN
Definition: dp.h:1164
#define EXYNOS_VIDCON1_IHSYNC_INVERT
Definition: dp.h:927
#define EXYNOS_WINCON_DATAPATH_DMA
Definition: dp.h:976
#define EXYNOS_VIDCON0_VCLKEN_NORMAL
Definition: dp.h:909
#define EXYNOS_VIDCON0_ENVID_F_ENABLE
Definition: dp.h:920
#define EXYNOS_BUFFER_SIZE(x)
Definition: dp.h:879
#define EXYNOS_VIDCON0_CLKSEL_SCLK
Definition: dp.h:916
#define EXYNOS_VIDCON2_WB_MASK
Definition: dp.h:939
#define EXYNOS_I80START_TRIG
Definition: dp.h:1165
#define EXYNOS_WINCON_WSWP_ENABLE
Definition: dp.h:996
#define EXYNOS_VIDOSD_LEFT_X(x)
Definition: dp.h:1047
#define EXYNOS_VIDADDR_OFFSIZE_E(x)
Definition: dp.h:1077
#define EXYNOS_VIDTCON0_VFPD(x)
Definition: dp.h:960
#define EXYNOS_DP_CLK_ENABLE
Definition: dp.h:1170
#define EXYNOS_DUALRGB_MAIN_CNT(x)
Definition: dp.h:1151
#define EXYNOS_VIDOSD_TOP_Y(x)
Definition: dp.h:1048
#define EXYNOS_WINCON_BURSTLEN_MASK
Definition: dp.h:1004
#define EXYNOS_VIDTCON1_HBPD(x)
Definition: dp.h:965
#define EXYNOS_WINSHMAP_CH_ENABLE(x)
Definition: dp.h:1041
#define EXYNOS_VIDOSD(x)
Definition: dp.h:877
#define EXYNOS_VIDCON0_CLKDIR_MASK
Definition: dp.h:914
#define EXYNOS_VIDOSD_BOTTOM_Y(x)
Definition: dp.h:1050
#define EXYNOS_VIDCON0_ENVID_F_DISABLE
Definition: dp.h:921
#define EXYNOS_VIDADDR_PAGEWIDTH(x)
Definition: dp.h:1076
#define EXYNOS_BUFFER_OFFSET(x)
Definition: dp.h:878
#define EXYNOS_VIDCON1_IVCLK_RISING_EDGE
Definition: dp.h:925
#define EXYNOS_WINSHMAP_CH_DISABLE(x)
Definition: dp.h:1042
#define EXYNOS_WINCON_DATAPATH_MASK
Definition: dp.h:978
#define EXYNOS_VIDTCON1_HSPW(x)
Definition: dp.h:967
#define EXYNOS_WINCON_ENWIN_ENABLE
Definition: dp.h:1030
#define EXYNOS_WINCON_ENWIN_DISABLE
Definition: dp.h:1029
#define EXYNOS_VIDTCON0_VBPD(x)
Definition: dp.h:959
#define EXYNOS_VIDCON0_ENVID_ENABLE
Definition: dp.h:918
#define EXYNOS_WINCON_BPPMODE_MASK
Definition: dp.h:1024
#define EXYNOS_VIDTCON1_HFPD(x)
Definition: dp.h:966
#define EXYNOS_VIDCON0_CLKSEL_MASK
Definition: dp.h:917
#define EXYNOS_VIDOSD_BOTTOM_Y_E(x)
Definition: dp.h:1052
#define EXYNOS_VIDCON0_CLKDIR_DIVIDED
Definition: dp.h:913
#define EXYNOS_WINCON_INRGB_MASK
Definition: dp.h:1000
#define EXYNOS_VIDCON0_CLKVAL_F(x)
Definition: dp.h:908
#define EXYNOS_VIDCON0_CLKVALUP_MASK
Definition: dp.h:907
#define EXYNOS_WINCON_BURSTLEN_16WORD
Definition: dp.h:1001
#define EXYNOS_WINCON_BYTESWP_ENABLE
Definition: dp.h:990
#define EXYNOS_VIDTCON2_HOZVAL(x)
Definition: dp.h:971
#define EXYNOS_WINCON_BITSWP_ENABLE
Definition: dp.h:987
#define EXYNOS_VIDADDR_PAGEWIDTH_E(x)
Definition: dp.h:1078
#define EXYNOS_VIDOSD_RIGHT_X(x)
Definition: dp.h:1049
#define EXYNOS_VIDTCON2_LINEVAL(x)
Definition: dp.h:970
#define EXYNOS_VIDCON0_ENVID_DISABLE
Definition: dp.h:919
#define EXYNOS_VIDCON0_VIDOUT_RGB
Definition: dp.h:891
#define EXYNOS_VIDCON0_PNRMODE_MASK
Definition: dp.h:903
#define EXYNOS_DUALRGB_BYPASS_DUAL
Definition: dp.h:1143
#define FIMD_CTRL
Definition: fimd.h:127
@ FIMD_RGB_INTERFACE
Definition: fimd.h:131
@ FIMD_CPU_INTERFACE
Definition: fimd.h:132
#define FIMD_CTRL_ADDR
Definition: fimd.h:126
static void exynos5_set_system_display(void)
Definition: fimd.c:287
static unsigned long get_lcd_clk(void)
Definition: fimd.c:33
static void exynos_fimd_window_on(unsigned int win_id)
Definition: fimd.c:244
void exynos_fimd_lcd_init(vidinfo_t *vid)
Definition: fimd.c:301
void exynos_set_trigger(void)
Definition: fimd.c:208
#define lwritel(a, b)
Definition: fimd.c:28
static void exynos_fimd_lcd_on(void)
Definition: fimd.c:233
void exynos_fimd_lcd_off(void)
Definition: fimd.c:261
static void exynos_fimd_set_dp_clkcon(unsigned int enabled)
Definition: fimd.c:82
unsigned long exynos_fimd_calc_fbsize(vidinfo_t *vid)
Definition: fimd.c:398
static void exynos_fimd_set_buffer_address(vidinfo_t *vid, void *screen_base, int win_id)
Definition: fimd.c:137
static void exynos_fimd_set_clock(vidinfo_t *vid)
Definition: fimd.c:152
void exynos_fimd_lcd_disable(void)
Definition: fimd.c:404
int exynos_is_i80_frame_done(void)
Definition: fimd.c:219
static void exynos_fimd_set_par(vidinfo_t *vid, unsigned int win_id)
Definition: fimd.c:93
#define lreadl(a)
Definition: fimd.c:29
static void exynos_fimd_set_dualrgb(vidinfo_t *vid, unsigned int enabled)
Definition: fimd.c:66
void exynos_fimd_window_off(unsigned int win_id)
Definition: fimd.c:271
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
static struct exynos5_sysreg *const exynos_sysreg
Definition: sysreg.h:20
unsigned long get_pll_clk(int pllreg)
Definition: clock.c:156
uint32_t u32
Definition: stdint.h:51
unsigned int disp1blk_cfg
Definition: sysreg.h:14
Definition: dp.h:737
u32 vidcon1
Definition: dp.h:739
u32 vidtcon1
Definition: dp.h:743
u32 vidtcon0
Definition: dp.h:742
u32 vidtcon2
Definition: dp.h:744
Definition: fimd.h:142