Lines Matching +full:mode +full:- +full:reg

1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
14 #include <video/imx-ipu-v3.h>
15 #include "ipu-prv.h"
76 #define DI_SW_GEN0(gen) (0x000c + 4 * ((gen) - 1))
77 #define DI_SW_GEN1(gen) (0x0030 + 4 * ((gen) - 1))
78 #define DI_STP_REP(gen) (0x0148 + 4 * (((gen) - 1)/2))
125 return readl(di->base + offset); in ipu_di_read()
130 writel(value, di->base + offset); in ipu_di_write()
137 u32 reg; in ipu_di_data_wave_config() local
138 reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) | in ipu_di_data_wave_config()
140 ipu_di_write(di, reg, DI_DW_GEN(wave_gen)); in ipu_di_data_wave_config()
146 u32 reg; in ipu_di_data_pin_config() local
148 reg = ipu_di_read(di, DI_DW_GEN(wave_gen)); in ipu_di_data_pin_config()
149 reg &= ~(0x3 << (di_pin * 2)); in ipu_di_data_pin_config()
150 reg |= set << (di_pin * 2); in ipu_di_data_pin_config()
151 ipu_di_write(di, reg, DI_DW_GEN(wave_gen)); in ipu_di_data_pin_config()
159 u32 reg; in ipu_di_sync_config() local
166 if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) || in ipu_di_sync_config()
167 (c->repeat_count >= 0x1000) || in ipu_di_sync_config()
168 (c->cnt_up >= 0x400) || in ipu_di_sync_config()
169 (c->cnt_down >= 0x400)) { in ipu_di_sync_config()
170 dev_err(di->ipu->dev, "DI%d counters out of range.\n", in ipu_di_sync_config()
171 di->id); in ipu_di_sync_config()
175 reg = DI_SW_GEN0_RUN_COUNT(c->run_count) | in ipu_di_sync_config()
176 DI_SW_GEN0_RUN_SRC(c->run_src) | in ipu_di_sync_config()
177 DI_SW_GEN0_OFFSET_COUNT(c->offset_count) | in ipu_di_sync_config()
178 DI_SW_GEN0_OFFSET_SRC(c->offset_src); in ipu_di_sync_config()
179 ipu_di_write(di, reg, DI_SW_GEN0(wave_gen)); in ipu_di_sync_config()
181 reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) | in ipu_di_sync_config()
182 DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) | in ipu_di_sync_config()
184 c->cnt_polarity_trigger_src) | in ipu_di_sync_config()
185 DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) | in ipu_di_sync_config()
186 DI_SW_GEN1_CNT_DOWN(c->cnt_down) | in ipu_di_sync_config()
187 DI_SW_GEN1_CNT_UP(c->cnt_up); in ipu_di_sync_config()
190 if (c->repeat_count == 0) in ipu_di_sync_config()
191 reg |= DI_SW_GEN1_AUTO_RELOAD; in ipu_di_sync_config()
193 ipu_di_write(di, reg, DI_SW_GEN1(wave_gen)); in ipu_di_sync_config()
195 reg = ipu_di_read(di, DI_STP_REP(wave_gen)); in ipu_di_sync_config()
196 reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1))); in ipu_di_sync_config()
197 reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1)); in ipu_di_sync_config()
198 ipu_di_write(di, reg, DI_STP_REP(wave_gen)); in ipu_di_sync_config()
205 u32 h_total = sig->mode.hactive + sig->mode.hsync_len + in ipu_di_sync_config_interlaced()
206 sig->mode.hback_porch + sig->mode.hfront_porch; in ipu_di_sync_config_interlaced()
207 u32 v_total = sig->mode.vactive + sig->mode.vsync_len + in ipu_di_sync_config_interlaced()
208 sig->mode.vback_porch + sig->mode.vfront_porch; in ipu_di_sync_config_interlaced()
212 .run_count = v_total * 2 - 1, in ipu_di_sync_config_interlaced()
216 .run_count = h_total - 1, in ipu_di_sync_config_interlaced()
220 .cnt_down = sig->mode.hsync_len * 2, in ipu_di_sync_config_interlaced()
223 .run_count = v_total - 1, in ipu_di_sync_config_interlaced()
227 .cnt_down = sig->mode.vsync_len * 2, in ipu_di_sync_config_interlaced()
240 .offset_count = (sig->mode.vsync_len + in ipu_di_sync_config_interlaced()
241 sig->mode.vback_porch) / 2, in ipu_di_sync_config_interlaced()
243 .repeat_count = sig->mode.vactive / 2, in ipu_di_sync_config_interlaced()
248 .offset_count = sig->mode.hsync_len + in ipu_di_sync_config_interlaced()
249 sig->mode.hback_porch, in ipu_di_sync_config_interlaced()
251 .repeat_count = sig->mode.hactive, in ipu_di_sync_config_interlaced()
255 .run_count = h_total / 2 - 1, in ipu_di_sync_config_interlaced()
262 ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF); in ipu_di_sync_config_interlaced()
268 u32 h_total = sig->mode.hactive + sig->mode.hsync_len + in ipu_di_sync_config_noninterlaced()
269 sig->mode.hback_porch + sig->mode.hfront_porch; in ipu_di_sync_config_noninterlaced()
270 u32 v_total = sig->mode.vactive + sig->mode.vsync_len + in ipu_di_sync_config_noninterlaced()
271 sig->mode.vback_porch + sig->mode.vfront_porch; in ipu_di_sync_config_noninterlaced()
275 .run_count = h_total - 1, in ipu_di_sync_config_noninterlaced()
279 .run_count = h_total - 1, in ipu_di_sync_config_noninterlaced()
281 .offset_count = div * sig->v_to_h_sync, in ipu_di_sync_config_noninterlaced()
285 .cnt_down = sig->mode.hsync_len * 2, in ipu_di_sync_config_noninterlaced()
288 .run_count = v_total - 1, in ipu_di_sync_config_noninterlaced()
292 .cnt_down = sig->mode.vsync_len * 2, in ipu_di_sync_config_noninterlaced()
296 .offset_count = sig->mode.vsync_len + in ipu_di_sync_config_noninterlaced()
297 sig->mode.vback_porch, in ipu_di_sync_config_noninterlaced()
299 .repeat_count = sig->mode.vactive, in ipu_di_sync_config_noninterlaced()
304 .offset_count = sig->mode.hsync_len + in ipu_di_sync_config_noninterlaced()
305 sig->mode.hback_porch, in ipu_di_sync_config_noninterlaced()
307 .repeat_count = sig->mode.hactive, in ipu_di_sync_config_noninterlaced()
319 .run_count = h_total - 1, in ipu_di_sync_config_noninterlaced()
323 .run_count = v_total - 1, in ipu_di_sync_config_noninterlaced()
328 .offset_count = sig->mode.vsync_len + in ipu_di_sync_config_noninterlaced()
329 sig->mode.vback_porch, in ipu_di_sync_config_noninterlaced()
331 .repeat_count = sig->mode.vactive, in ipu_di_sync_config_noninterlaced()
335 .run_count = h_total - 1, in ipu_di_sync_config_noninterlaced()
337 .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */ in ipu_di_sync_config_noninterlaced()
341 .cnt_down = sig->mode.hsync_len * 2, in ipu_di_sync_config_noninterlaced()
345 .offset_count = sig->mode.hsync_len + in ipu_di_sync_config_noninterlaced()
346 sig->mode.hback_porch, in ipu_di_sync_config_noninterlaced()
348 .repeat_count = sig->mode.hactive, in ipu_di_sync_config_noninterlaced()
352 .run_count = v_total - 1, in ipu_di_sync_config_noninterlaced()
358 .cnt_down = sig->mode.vsync_len * 2, in ipu_di_sync_config_noninterlaced()
360 /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */ in ipu_di_sync_config_noninterlaced()
361 .run_count = h_total - 1, in ipu_di_sync_config_noninterlaced()
363 .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */ in ipu_di_sync_config_noninterlaced()
367 .cnt_down = sig->mode.hsync_len * 2, in ipu_di_sync_config_noninterlaced()
369 /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */ in ipu_di_sync_config_noninterlaced()
370 .run_count = v_total - 1, in ipu_di_sync_config_noninterlaced()
376 .cnt_down = sig->mode.vsync_len * 2, in ipu_di_sync_config_noninterlaced()
382 ipu_di_write(di, v_total - 1, DI_SCR_CONF); in ipu_di_sync_config_noninterlaced()
383 if (sig->hsync_pin == 2 && sig->vsync_pin == 3) in ipu_di_sync_config_noninterlaced()
396 if (sig->clkflags & IPU_DI_CLKMODE_EXT) { in ipu_di_config_clock()
402 clk = di->clk_di; in ipu_di_config_clock()
404 if (sig->clkflags & IPU_DI_CLKMODE_SYNC) { in ipu_di_config_clock()
424 clk_set_rate(clk, sig->mode.pixelclock); in ipu_di_config_clock()
427 div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock); in ipu_di_config_clock()
443 clkrate = clk_get_rate(di->clk_ipu); in ipu_di_config_clock()
444 div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock); in ipu_di_config_clock()
448 error = rate / (sig->mode.pixelclock / 1000); in ipu_di_config_clock()
450 dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %c%d.%d%%\n", in ipu_di_config_clock()
451 rate, div, error < 1000 ? '-' : '+', in ipu_di_config_clock()
452 abs(error - 1000) / 10, abs(error - 1000) % 10); in ipu_di_config_clock()
456 clk = di->clk_ipu; in ipu_di_config_clock()
463 clk = di->clk_di; in ipu_di_config_clock()
465 clk_set_rate(clk, sig->mode.pixelclock); in ipu_di_config_clock()
468 div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock); in ipu_di_config_clock()
475 di->clk_di_pixel = clk; in ipu_di_config_clock()
490 if (clk == di->clk_di) in ipu_di_config_clock()
494 dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n", in ipu_di_config_clock()
495 sig->mode.pixelclock, in ipu_di_config_clock()
496 clk_get_rate(di->clk_ipu), in ipu_di_config_clock()
497 clk_get_rate(di->clk_di), in ipu_di_config_clock()
498 clk == di->clk_di ? "DI" : "IPU", in ipu_di_config_clock()
499 clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4)); in ipu_di_config_clock()
503 * This function is called to adjust a video mode to IPU restrictions.
506 int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode) in ipu_di_adjust_videomode() argument
510 if (!IS_ALIGNED(mode->hactive, 8) && in ipu_di_adjust_videomode()
511 mode->hfront_porch < ALIGN(mode->hactive, 8) - mode->hactive) { in ipu_di_adjust_videomode()
512 …dev_err(di->ipu->dev, "hactive %d is not aligned to 8 and front porch is too small to compensate\n… in ipu_di_adjust_videomode()
513 mode->hactive); in ipu_di_adjust_videomode()
514 return -EINVAL; in ipu_di_adjust_videomode()
517 if (mode->vfront_porch >= 2) in ipu_di_adjust_videomode()
520 diff = 2 - mode->vfront_porch; in ipu_di_adjust_videomode()
522 if (mode->vback_porch >= diff) { in ipu_di_adjust_videomode()
523 mode->vfront_porch = 2; in ipu_di_adjust_videomode()
524 mode->vback_porch -= diff; in ipu_di_adjust_videomode()
525 } else if (mode->vsync_len > diff) { in ipu_di_adjust_videomode()
526 mode->vfront_porch = 2; in ipu_di_adjust_videomode()
527 mode->vsync_len = mode->vsync_len - diff; in ipu_di_adjust_videomode()
529 dev_warn(di->ipu->dev, "failed to adjust videomode\n"); in ipu_di_adjust_videomode()
530 return -EINVAL; in ipu_di_adjust_videomode()
533 dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n"); in ipu_di_adjust_videomode()
563 u32 reg; in ipu_di_init_sync_panel() local
567 dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n", in ipu_di_init_sync_panel()
568 di->id, sig->mode.hactive, sig->mode.vactive); in ipu_di_init_sync_panel()
570 dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n", in ipu_di_init_sync_panel()
571 clk_get_rate(di->clk_ipu), in ipu_di_init_sync_panel()
572 clk_get_rate(di->clk_di), in ipu_di_init_sync_panel()
573 sig->mode.pixelclock); in ipu_di_init_sync_panel()
586 ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1); in ipu_di_init_sync_panel()
592 if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) { in ipu_di_init_sync_panel()
603 if (di->id == 1) in ipu_di_init_sync_panel()
608 if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3)) in ipu_di_init_sync_panel()
612 if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) in ipu_di_init_sync_panel()
613 di_gen |= ipu_di_gen_polarity(sig->hsync_pin); in ipu_di_init_sync_panel()
614 if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) in ipu_di_init_sync_panel()
615 di_gen |= ipu_di_gen_polarity(sig->vsync_pin); in ipu_di_init_sync_panel()
617 if (sig->clk_pol) in ipu_di_init_sync_panel()
622 ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002, in ipu_di_init_sync_panel()
625 reg = ipu_di_read(di, DI_POL); in ipu_di_init_sync_panel()
626 reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15); in ipu_di_init_sync_panel()
628 if (sig->enable_pol) in ipu_di_init_sync_panel()
629 reg |= DI_POL_DRDY_POLARITY_15; in ipu_di_init_sync_panel()
630 if (sig->data_pol) in ipu_di_init_sync_panel()
631 reg |= DI_POL_DRDY_DATA_POLARITY; in ipu_di_init_sync_panel()
633 ipu_di_write(di, reg, DI_POL); in ipu_di_init_sync_panel()
645 WARN_ON(IS_ERR(di->clk_di_pixel)); in ipu_di_enable()
647 ret = clk_prepare_enable(di->clk_di_pixel); in ipu_di_enable()
651 ipu_module_enable(di->ipu, di->module); in ipu_di_enable()
659 WARN_ON(IS_ERR(di->clk_di_pixel)); in ipu_di_disable()
661 ipu_module_disable(di->ipu, di->module); in ipu_di_disable()
663 clk_disable_unprepare(di->clk_di_pixel); in ipu_di_disable()
671 return di->id; in ipu_di_get_num()
682 return ERR_PTR(-EINVAL); in ipu_di_get()
684 di = ipu->di_priv[disp]; in ipu_di_get()
688 if (di->inuse) { in ipu_di_get()
689 di = ERR_PTR(-EBUSY); in ipu_di_get()
693 di->inuse = true; in ipu_di_get()
705 di->inuse = false; in ipu_di_put()
718 return -ENODEV; in ipu_di_init()
722 return -ENOMEM; in ipu_di_init()
724 ipu->di_priv[id] = di; in ipu_di_init()
726 di->clk_di = devm_clk_get(dev, id ? "di1" : "di0"); in ipu_di_init()
727 if (IS_ERR(di->clk_di)) in ipu_di_init()
728 return PTR_ERR(di->clk_di); in ipu_di_init()
730 di->module = module; in ipu_di_init()
731 di->id = id; in ipu_di_init()
732 di->clk_ipu = clk_ipu; in ipu_di_init()
733 di->base = devm_ioremap(dev, base, PAGE_SIZE); in ipu_di_init()
734 if (!di->base) in ipu_di_init()
735 return -ENOMEM; in ipu_di_init()
740 id, base, di->base); in ipu_di_init()
741 di->inuse = false; in ipu_di_init()
742 di->ipu = ipu; in ipu_di_init()