This commit is contained in:
Tom Rini
2020-04-20 08:45:27 -04:00
92 changed files with 3152 additions and 491 deletions

View File

@@ -69,6 +69,22 @@ config CLK_IMX8MP
help
This enables support clock driver for i.MX8MP platforms.
config SPL_CLK_IMXRT1020
bool "SPL clock support for i.MXRT1020"
depends on ARCH_IMXRT && SPL
select SPL_CLK
select SPL_CLK_CCF
help
This enables SPL DM/DTS support for clock driver in i.MXRT1020
config CLK_IMXRT1020
bool "Clock support for i.MXRT1020"
depends on ARCH_IMXRT
select CLK
select CLK_CCF
help
This enables support clock driver for i.MXRT1020 platforms.
config SPL_CLK_IMXRT1050
bool "SPL clock support for i.MXRT1050"
depends on ARCH_IMXRT && SPL

View File

@@ -17,4 +17,5 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MN) += clk-imx8mn.o clk-pll14xx.o \
obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \
clk-composite-8m.o
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o

View File

@@ -0,0 +1,227 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright(C) 2020
* Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com>
*/
#include <common.h>
#include <clk.h>
#include <clk-uclass.h>
#include <dm.h>
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
#include <dt-bindings/clock/imxrt1020-clock.h>
#include "clk.h"
static ulong imxrt1020_clk_get_rate(struct clk *clk)
{
struct clk *c;
int ret;
debug("%s(#%lu)\n", __func__, clk->id);
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
return clk_get_rate(c);
}
static ulong imxrt1020_clk_set_rate(struct clk *clk, unsigned long rate)
{
struct clk *c;
int ret;
debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
return clk_set_rate(c, rate);
}
static int __imxrt1020_clk_enable(struct clk *clk, bool enable)
{
struct clk *c;
int ret;
debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
if (enable)
ret = clk_enable(c);
else
ret = clk_disable(c);
return ret;
}
static int imxrt1020_clk_disable(struct clk *clk)
{
return __imxrt1020_clk_enable(clk, 0);
}
static int imxrt1020_clk_enable(struct clk *clk)
{
return __imxrt1020_clk_enable(clk, 1);
}
static struct clk_ops imxrt1020_clk_ops = {
.set_rate = imxrt1020_clk_set_rate,
.get_rate = imxrt1020_clk_get_rate,
.enable = imxrt1020_clk_enable,
.disable = imxrt1020_clk_disable,
};
static const char * const pll2_bypass_sels[] = {"pll2_sys", "osc", };
static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "osc", };
static const char *const pre_periph_sels[] = { "pll2_sys", "pll2_pfd3_297m", "pll3_pfd3_454_74m", "arm_podf", };
static const char *const periph_sels[] = { "pre_periph_sel", "todo", };
static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
static const char *const lpuart_sels[] = { "pll3_80m", "osc", };
static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", };
static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", };
static int imxrt1020_clk_probe(struct udevice *dev)
{
void *base;
/* Anatop clocks */
base = (void *)ANATOP_BASE_ADDR;
clk_dm(IMXRT1020_CLK_PLL2_SYS,
imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_sys", "osc",
base + 0x30, 0x1));
clk_dm(IMXRT1020_CLK_PLL3_USB_OTG,
imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc",
base + 0x10, 0x1));
/* PLL bypass out */
clk_dm(IMXRT1020_CLK_PLL2_BYPASS,
imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1,
pll2_bypass_sels,
ARRAY_SIZE(pll2_bypass_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMXRT1020_CLK_PLL3_BYPASS,
imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1,
pll3_bypass_sels,
ARRAY_SIZE(pll3_bypass_sels),
CLK_SET_RATE_PARENT));
clk_dm(IMXRT1020_CLK_PLL3_80M,
imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6));
clk_dm(IMXRT1020_CLK_PLL2_PFD0_352M,
imx_clk_pfd("pll2_pfd0_352m", "pll2_sys", base + 0x100, 0));
clk_dm(IMXRT1020_CLK_PLL2_PFD1_594M,
imx_clk_pfd("pll2_pfd1_594m", "pll2_sys", base + 0x100, 1));
clk_dm(IMXRT1020_CLK_PLL2_PFD2_396M,
imx_clk_pfd("pll2_pfd2_396m", "pll2_sys", base + 0x100, 2));
clk_dm(IMXRT1020_CLK_PLL2_PFD3_297M,
imx_clk_pfd("pll2_pfd3_297m", "pll2_sys", base + 0x100, 3));
clk_dm(IMXRT1020_CLK_PLL3_PFD1_664_62M,
imx_clk_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", base + 0xf0, 1));
clk_dm(IMXRT1020_CLK_PLL3_PFD3_454_74M,
imx_clk_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", base + 0xf0, 3));
/* CCM clocks */
base = dev_read_addr_ptr(dev);
if (base == (void *)FDT_ADDR_T_NONE)
return -EINVAL;
clk_dm(IMXRT1020_CLK_PRE_PERIPH_SEL,
imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2,
pre_periph_sels, ARRAY_SIZE(pre_periph_sels)));
clk_dm(IMXRT1020_CLK_PERIPH_SEL,
imx_clk_mux("periph_sel", base + 0x14, 25, 1,
periph_sels, ARRAY_SIZE(periph_sels)));
clk_dm(IMXRT1020_CLK_USDHC1_SEL,
imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1,
usdhc_sels, ARRAY_SIZE(usdhc_sels)));
clk_dm(IMXRT1020_CLK_USDHC2_SEL,
imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1,
usdhc_sels, ARRAY_SIZE(usdhc_sels)));
clk_dm(IMXRT1020_CLK_LPUART_SEL,
imx_clk_mux("lpuart_sel", base + 0x24, 6, 1,
lpuart_sels, ARRAY_SIZE(lpuart_sels)));
clk_dm(IMXRT1020_CLK_SEMC_ALT_SEL,
imx_clk_mux("semc_alt_sel", base + 0x14, 7, 1,
semc_alt_sels, ARRAY_SIZE(semc_alt_sels)));
clk_dm(IMXRT1020_CLK_SEMC_SEL,
imx_clk_mux("semc_sel", base + 0x14, 6, 1,
semc_sels, ARRAY_SIZE(semc_sels)));
clk_dm(IMXRT1020_CLK_AHB_PODF,
imx_clk_divider("ahb_podf", "periph_sel",
base + 0x14, 10, 3));
clk_dm(IMXRT1020_CLK_USDHC1_PODF,
imx_clk_divider("usdhc1_podf", "usdhc1_sel",
base + 0x24, 11, 3));
clk_dm(IMXRT1020_CLK_USDHC2_PODF,
imx_clk_divider("usdhc2_podf", "usdhc2_sel",
base + 0x24, 16, 3));
clk_dm(IMXRT1020_CLK_LPUART_PODF,
imx_clk_divider("lpuart_podf", "lpuart_sel",
base + 0x24, 0, 6));
clk_dm(IMXRT1020_CLK_SEMC_PODF,
imx_clk_divider("semc_podf", "semc_sel",
base + 0x14, 16, 3));
clk_dm(IMXRT1020_CLK_USDHC1,
imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2));
clk_dm(IMXRT1020_CLK_USDHC2,
imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4));
clk_dm(IMXRT1020_CLK_LPUART1,
imx_clk_gate2("lpuart1", "lpuart_podf", base + 0x7c, 24));
clk_dm(IMXRT1020_CLK_SEMC,
imx_clk_gate2("semc", "semc_podf", base + 0x74, 4));
#ifdef CONFIG_SPL_BUILD
struct clk *clk, *clk1;
clk_get_by_id(IMXRT1020_CLK_SEMC_SEL, &clk1);
clk_get_by_id(IMXRT1020_CLK_SEMC_ALT_SEL, &clk);
clk_set_parent(clk1, clk);
/* Configure PLL3_USB_OTG to 480MHz */
clk_get_by_id(IMXRT1020_CLK_PLL3_USB_OTG, &clk);
clk_enable(clk);
clk_set_rate(clk, 480000000UL);
clk_get_by_id(IMXRT1020_CLK_PLL3_BYPASS, &clk1);
clk_set_parent(clk1, clk);
clk_get_by_id(IMXRT1020_CLK_PLL2_PFD3_297M, &clk);
clk_set_rate(clk, 297000000UL);
clk_get_by_id(IMXRT1020_CLK_PLL2_SYS, &clk);
clk_enable(clk);
clk_set_rate(clk, 528000000UL);
clk_get_by_id(IMXRT1020_CLK_PLL2_BYPASS, &clk1);
clk_set_parent(clk1, clk);
#endif
return 0;
}
static const struct udevice_id imxrt1020_clk_ids[] = {
{ .compatible = "fsl,imxrt1020-ccm" },
{ },
};
U_BOOT_DRIVER(imxrt1020_clk) = {
.name = "clk_imxrt1020",
.id = UCLASS_CLK,
.of_match = imxrt1020_clk_ids,
.ops = &imxrt1020_clk_ops,
.probe = imxrt1020_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@@ -71,11 +71,30 @@ static int imxrt1050_clk_enable(struct clk *clk)
return __imxrt1050_clk_enable(clk, 1);
}
static int imxrt1050_clk_set_parent(struct clk *clk, struct clk *parent)
{
struct clk *c, *cp;
int ret;
debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
ret = clk_get_by_id(parent->id, &cp);
if (ret)
return ret;
return clk_set_parent(c, cp);
}
static struct clk_ops imxrt1050_clk_ops = {
.set_rate = imxrt1050_clk_set_rate,
.get_rate = imxrt1050_clk_get_rate,
.enable = imxrt1050_clk_enable,
.disable = imxrt1050_clk_disable,
.set_parent = imxrt1050_clk_set_parent,
};
static const char * const pll_ref_sels[] = {"osc", "dummy", };
@@ -90,7 +109,7 @@ static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
static const char *const lpuart_sels[] = { "pll3_80m", "osc", };
static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", };
static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", };
static const char *const lcdif_sels[] = { "pll2_sys", "pll3_pfd3_454_74m", "pll5_video:", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_664_62m"};
static const char *const lcdif_sels[] = { "pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_664_62m"};
static int imxrt1050_clk_probe(struct udevice *dev)
{
@@ -238,9 +257,9 @@ static int imxrt1050_clk_probe(struct udevice *dev)
clk_dm(IMXRT1050_CLK_LCDIF,
imx_clk_gate2("lcdif", "lcdif_podf", base + 0x70, 28));
#ifdef CONFIG_SPL_BUILD
struct clk *clk, *clk1;
#ifdef CONFIG_SPL_BUILD
/* bypass pll1 before setting its rate */
clk_get_by_id(IMXRT1050_CLK_PLL1_REF_SEL, &clk);
clk_get_by_id(IMXRT1050_CLK_PLL1_BYPASS, &clk1);
@@ -271,7 +290,14 @@ static int imxrt1050_clk_probe(struct udevice *dev)
clk_get_by_id(IMXRT1050_CLK_PLL3_BYPASS, &clk1);
clk_set_parent(clk1, clk);
#else
/* Set PLL5 for LCDIF to its default 650Mhz */
clk_get_by_id(IMXRT1050_CLK_PLL5_VIDEO, &clk);
clk_enable(clk);
clk_set_rate(clk, 650000000UL);
clk_get_by_id(IMXRT1050_CLK_PLL5_BYPASS, &clk1);
clk_set_parent(clk1, clk);
#endif
return 0;

View File

@@ -25,6 +25,7 @@
#define PLL_DENOM_OFFSET 0x20
#define BM_PLL_POWER (0x1 << 12)
#define BM_PLL_ENABLE (0x1 << 13)
#define BM_PLL_LOCK (0x1 << 31)
struct clk_pllv3 {
@@ -32,6 +33,7 @@ struct clk_pllv3 {
void __iomem *base;
u32 power_bit;
bool powerup_set;
u32 enable_bit;
u32 div_mask;
u32 div_shift;
};
@@ -83,6 +85,9 @@ static int clk_pllv3_generic_enable(struct clk *clk)
val |= pll->power_bit;
else
val &= ~pll->power_bit;
val |= pll->enable_bit;
writel(val, pll->base);
return 0;
@@ -98,6 +103,9 @@ static int clk_pllv3_generic_disable(struct clk *clk)
val &= ~pll->power_bit;
else
val |= pll->power_bit;
val &= ~pll->enable_bit;
writel(val, pll->base);
return 0;
@@ -238,6 +246,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
return ERR_PTR(-ENOMEM);
pll->power_bit = BM_PLL_POWER;
pll->enable_bit = BM_PLL_ENABLE;
switch (type) {
case IMX_PLLV3_GENERIC:

View File

@@ -41,7 +41,7 @@ static int pfuze100_write(struct udevice *dev, uint reg, const uint8_t *buff,
static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
{
if (dm_i2c_read(dev, reg, buff, len)) {
pr_err("read error from device: %p register: %#x!\n", dev, reg);
debug("read error from device: %p register: %#x!\n", dev, reg);
return -EIO;
}

View File

@@ -5,6 +5,7 @@
* Copyright (C) 2011-2013 Marek Vasut <marex@denx.de>
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <env.h>
#include <dm/device_compat.h>
@@ -52,14 +53,34 @@ __weak void mxsfb_system_setup(void)
* le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0
*/
static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp)
static void mxs_lcd_init(struct udevice *dev, u32 fb_addr,
struct display_timing *timings, int bpp)
{
struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
const enum display_flags flags = timings->flags;
uint32_t word_len = 0, bus_width = 0;
uint8_t valid_data = 0;
uint32_t vdctrl0;
#if CONFIG_IS_ENABLED(CLK)
struct clk per_clk;
int ret;
ret = clk_get_by_name(dev, "per", &per_clk);
if (ret) {
dev_err(dev, "Failed to get mxs clk: %d\n", ret);
return;
}
ret = clk_set_rate(&per_clk, timings->pixelclock.typ);
if (ret < 0) {
dev_err(dev, "Failed to set mxs clk: %d\n", ret);
return;
}
#else
/* Kick in the LCDIF clock */
mxs_set_lcdclk(MXS_LCDIF_BASE, PS2KHZ(mode->pixclock));
mxs_set_lcdclk(MXS_LCDIF_BASE, timings->pixelclock.typ / 1000);
#endif
/* Restart the LCDIF block */
mxs_reset_block(&regs->hw_lcdif_ctrl_reg);
@@ -96,25 +117,36 @@ static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp)
mxsfb_system_setup();
writel((mode->yres << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | mode->xres,
&regs->hw_lcdif_transfer_count);
writel((timings->vactive.typ << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) |
timings->hactive.typ, &regs->hw_lcdif_transfer_count);
writel(LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL |
LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT |
LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
mode->vsync_len, &regs->hw_lcdif_vdctrl0);
writel(mode->upper_margin + mode->lower_margin +
mode->vsync_len + mode->yres,
vdctrl0 = LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL |
LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT |
LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
timings->vsync_len.typ;
if(flags & DISPLAY_FLAGS_HSYNC_HIGH)
vdctrl0 |= LCDIF_VDCTRL0_HSYNC_POL;
if(flags & DISPLAY_FLAGS_VSYNC_HIGH)
vdctrl0 |= LCDIF_VDCTRL0_VSYNC_POL;
if(flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
vdctrl0 |= LCDIF_VDCTRL0_DOTCLK_POL;
if(flags & DISPLAY_FLAGS_DE_HIGH)
vdctrl0 |= LCDIF_VDCTRL0_ENABLE_POL;
writel(vdctrl0, &regs->hw_lcdif_vdctrl0);
writel(timings->vback_porch.typ + timings->vfront_porch.typ +
timings->vsync_len.typ + timings->vactive.typ,
&regs->hw_lcdif_vdctrl1);
writel((mode->hsync_len << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) |
(mode->left_margin + mode->right_margin +
mode->hsync_len + mode->xres),
writel((timings->hsync_len.typ << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) |
(timings->hback_porch.typ + timings->hfront_porch.typ +
timings->hsync_len.typ + timings->hactive.typ),
&regs->hw_lcdif_vdctrl2);
writel(((mode->left_margin + mode->hsync_len) <<
writel(((timings->hback_porch.typ + timings->hsync_len.typ) <<
LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET) |
(mode->upper_margin + mode->vsync_len),
(timings->vback_porch.typ + timings->vsync_len.typ),
&regs->hw_lcdif_vdctrl3);
writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | mode->xres,
writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | timings->hactive.typ,
&regs->hw_lcdif_vdctrl4);
writel(fb_addr, &regs->hw_lcdif_cur_buf);
@@ -135,10 +167,11 @@ static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp)
writel(LCDIF_CTRL_RUN, &regs->hw_lcdif_ctrl_set);
}
static int mxs_probe_common(struct ctfb_res_modes *mode, int bpp, u32 fb)
static int mxs_probe_common(struct udevice *dev, struct display_timing *timings,
int bpp, u32 fb)
{
/* Start framebuffer */
mxs_lcd_init(fb, mode, bpp);
mxs_lcd_init(dev, fb, timings, bpp);
#ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
/*
@@ -204,6 +237,7 @@ void *video_hw_init(void)
char *penv;
void *fb = NULL;
struct ctfb_res_modes mode;
struct display_timing timings;
puts("Video: ");
@@ -260,7 +294,9 @@ void *video_hw_init(void)
printf("%s\n", panel.modeIdent);
ret = mxs_probe_common(&mode, bpp, (u32)fb);
video_ctfb_mode_to_display_timing(&mode, &timings);
ret = mxs_probe_common(NULL, &timings, bpp, (u32)fb);
if (ret)
goto dealloc_fb;
@@ -314,7 +350,6 @@ static int mxs_video_probe(struct udevice *dev)
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
struct ctfb_res_modes mode;
struct display_timing timings;
u32 bpp = 0;
u32 fb_start, fb_end;
@@ -327,17 +362,7 @@ static int mxs_video_probe(struct udevice *dev)
if (ret)
return ret;
mode.xres = timings.hactive.typ;
mode.yres = timings.vactive.typ;
mode.left_margin = timings.hback_porch.typ;
mode.right_margin = timings.hfront_porch.typ;
mode.upper_margin = timings.vback_porch.typ;
mode.lower_margin = timings.vfront_porch.typ;
mode.hsync_len = timings.hsync_len.typ;
mode.vsync_len = timings.vsync_len.typ;
mode.pixclock = HZ2PS(timings.pixelclock.typ);
ret = mxs_probe_common(&mode, bpp, plat->base);
ret = mxs_probe_common(dev, &timings, bpp, plat->base);
if (ret)
return ret;
@@ -358,8 +383,8 @@ static int mxs_video_probe(struct udevice *dev)
return -EINVAL;
}
uc_priv->xsize = mode.xres;
uc_priv->ysize = mode.yres;
uc_priv->xsize = timings.hactive.typ;
uc_priv->ysize = timings.vactive.typ;
/* Enable dcache for the frame buffer */
fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
@@ -420,6 +445,7 @@ static const struct udevice_id mxs_video_ids[] = {
{ .compatible = "fsl,imx23-lcdif" },
{ .compatible = "fsl,imx28-lcdif" },
{ .compatible = "fsl,imx7ulp-lcdif" },
{ .compatible = "fsl,imxrt-lcdif" },
{ /* sentinel */ }
};

View File

@@ -615,35 +615,6 @@ static void sunxi_lcdc_backlight_enable(void)
gpio_direction_output(pin, PWM_ON);
}
static void sunxi_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode,
struct display_timing *timing)
{
timing->pixelclock.typ = mode->pixclock_khz * 1000;
timing->hactive.typ = mode->xres;
timing->hfront_porch.typ = mode->right_margin;
timing->hback_porch.typ = mode->left_margin;
timing->hsync_len.typ = mode->hsync_len;
timing->vactive.typ = mode->yres;
timing->vfront_porch.typ = mode->lower_margin;
timing->vback_porch.typ = mode->upper_margin;
timing->vsync_len.typ = mode->vsync_len;
timing->flags = 0;
if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
else
timing->flags |= DISPLAY_FLAGS_HSYNC_LOW;
if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
else
timing->flags |= DISPLAY_FLAGS_VSYNC_LOW;
if (mode->vmode == FB_VMODE_INTERLACED)
timing->flags |= DISPLAY_FLAGS_INTERLACED;
}
static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
bool for_ext_vga_dac)
{
@@ -673,7 +644,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
sunxi_is_composite());
sunxi_ctfb_mode_to_display_timing(mode, &timing);
video_ctfb_mode_to_display_timing(mode, &timing);
lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
}
@@ -689,7 +660,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
struct display_timing timing;
sunxi_ctfb_mode_to_display_timing(mode, &timing);
video_ctfb_mode_to_display_timing(mode, &timing);
lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
sunxi_is_composite());

View File

@@ -444,3 +444,32 @@ int video_edid_dtd_to_ctfb_res_modes(struct edid_detailed_timing *t,
return 0;
}
void video_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode,
struct display_timing *timing)
{
timing->pixelclock.typ = mode->pixclock_khz * 1000;
timing->hactive.typ = mode->xres;
timing->hfront_porch.typ = mode->right_margin;
timing->hback_porch.typ = mode->left_margin;
timing->hsync_len.typ = mode->hsync_len;
timing->vactive.typ = mode->yres;
timing->vfront_porch.typ = mode->lower_margin;
timing->vback_porch.typ = mode->upper_margin;
timing->vsync_len.typ = mode->vsync_len;
timing->flags = 0;
if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
else
timing->flags |= DISPLAY_FLAGS_HSYNC_LOW;
if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
else
timing->flags |= DISPLAY_FLAGS_VSYNC_LOW;
if (mode->vmode == FB_VMODE_INTERLACED)
timing->flags |= DISPLAY_FLAGS_INTERLACED;
}

View File

@@ -92,3 +92,14 @@ int video_get_option_int(const char *options, const char *name, int def);
int video_edid_dtd_to_ctfb_res_modes(struct edid_detailed_timing *t,
struct ctfb_res_modes *mode);
/**
* video_ctfb_mode_to_display_timing() - Convert a ctfb(Cathode Tube Frame
* Buffer)_res_modes struct to a
* display_timing struct.
*
* @mode: Input ctfb_res_modes structure pointer to be converted
* from
* @timing: Output display_timing structure pointer to be converted to
*/
void video_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode,
struct display_timing *timing);