From 0a5cfb3adbfb937fca2583ca380c6340a31c1fc3 Mon Sep 17 00:00:00 2001 From: wycwyhwyq <5f20.6d9b@gmail.com> Date: Mon, 25 Nov 2024 18:30:03 +0800 Subject: [PATCH] drivers: k230: Fix vo resolution bug Signed-off-by: wycwyhwyq <5f20.6d9b@gmail.com> --- drivers/gpu/drm/canaan/canaan_dsi.c | 136 +++++++++++++++++----------- drivers/gpu/drm/canaan/canaan_vo.c | 43 ++++----- 2 files changed, 106 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/canaan/canaan_dsi.c b/drivers/gpu/drm/canaan/canaan_dsi.c index cebb0e827c2d..9f5353408632 100644 --- a/drivers/gpu/drm/canaan/canaan_dsi.c +++ b/drivers/gpu/drm/canaan/canaan_dsi.c @@ -68,7 +68,7 @@ #define TXPHY_445_5_M (295) #define TXPHY_445_5_N (15) -#define TXPHY_445_5_VOC (0x17) +#define TXPHY_445_5_VOC (0x19) #define TXPHY_445_5_HS_FREQ (0x96) #define TXPHY_891_M (295) @@ -206,8 +206,8 @@ static u32 canaan_dsi_get_hcomponent_lbcc(struct canaan_dsi *dsi, lbcc = hcomponent * dsi->phy_freq / 8; - frac = lbcc % mode->clock; - lbcc = lbcc / mode->clock; + frac = lbcc % dsi->clk_freq; + lbcc = lbcc / dsi->clk_freq; if (frac) lbcc++; @@ -313,6 +313,72 @@ static void canaan_mipi_dsi_set_test_mode(struct canaan_dsi *dsi) dsi_write(dsi, VID_MODE_CFG, reg); } +static int canaan_dsi_clk_cfg(struct canaan_dsi *dsi, u32 clk) +{ + struct mipi_dsi_device *device = dsi->device; + u32 val, div, phy_clk_freq, voc_freq, i, m, n = 0, voc; + u64 cmp, tmp, diff, closest = 100000000; + void *dis_clk; + + div = DIV64_U64_ROUND_CLOSEST(594000, clk); + dsi->clk_freq = 594000 / div; + phy_clk_freq = dsi->clk_freq * 3 * 8 / device->lanes / 2; + if (phy_clk_freq > 1250000 || phy_clk_freq < 40000) + return -1; + else if (phy_clk_freq < 55000) + voc = 0x3f; + else if (phy_clk_freq < 82500) + voc = 0x37; + else if (phy_clk_freq < 110000) + voc = 0x2f; + else if (phy_clk_freq < 165000) + voc = 0x27; + else if (phy_clk_freq < 220000) + voc = 0x1f; + else if (phy_clk_freq < 330000) + voc = 0x17; + else if (phy_clk_freq < 440000) + voc = 0x0f; + else if (phy_clk_freq < 660000) + voc = 0x07; + else if (phy_clk_freq < 1149000) + voc = 0x03; + else + voc = 0x01; + + voc_freq = phy_clk_freq * (1 << (voc >> 4)); + cmp = voc_freq * 1000 / 24; + for (i = 1; i <= 16; i++) { + tmp = cmp * i + 500000; + val = tmp / 1000000; + if (val > 625) + continue; + tmp = val * 1000000 / i; + diff = abs(cmp - tmp); + if (closest > diff) { + closest = diff; + n = i; + m = val; + if (diff == 0) + break; + } + } + if (!n) + return -1; + dsi->phy_freq = 24000 * 2 * m / n / (1 << (voc >> 4)); + + dis_clk = ioremap(0x91100000, 0x1000); + val = readl(dis_clk + 0x78); + val = (val & ~(GENMASK(10, 3))) | ((div - 1) << 3); + val = val | (1 << 31); + writel(val, dis_clk + 0x78); + iounmap(dis_clk); + + k230_dsi_config_4lan_phy(dsi, m - 2, n - 1, voc, 0x96); + + return 0; +} + static void canaan_dsi_encoder_enable(struct drm_encoder *encoder) { struct canaan_dsi *dsi = encoder_to_canaan_dsi(encoder); @@ -324,56 +390,9 @@ static void canaan_dsi_encoder_enable(struct drm_encoder *encoder) DRM_DEBUG_DRIVER("Enabling DSI output\n"); dev_vdbg(dsi->dev, "DSI encoder enable %u\n", adjusted_mode->clock); - switch (adjusted_mode->clock) { - case 74250: - // 74.25M - k230_dsi_config_4lan_phy(dsi, TXPHY_445_5_M, TXPHY_445_5_N, - TXPHY_445_5_VOC, TXPHY_445_5_HS_FREQ); - // set clk todo - dsi->phy_freq = 445500; - dsi->clk_freq = 74250; - break; - case 148500: { - // 144.5M - void *dis_clk = ioremap(0x91100000, 0x1000); - u32 reg = 0; - u32 div = 3; - - reg = readl(dis_clk + 0x78); - reg = (reg & ~(GENMASK(10, 3))) | - (div << 3); // 8M = pll1(2376) / 4 / 66 - reg = reg | (1 << 31); - writel(reg, dis_clk + 0x78); - - k230_dsi_config_4lan_phy(dsi, TXPHY_891_M, TXPHY_891_N, - TXPHY_891_VOC, TXPHY_891_HS_FREQ); - // set clk todo - dsi->phy_freq = 890666; - dsi->clk_freq = 14850; - break; - } - case 39600: { - void *dis_clk = ioremap(0x91100000, 0x1000); - u32 reg = 0; - u32 div = 14; - - reg = readl(dis_clk + 0x78); - reg = (reg & ~(GENMASK(10, 3))) | - (div << 3); // 8M = pll1(2376) / 4 / 66 - reg = reg | (1 << 31); - writel(reg, dis_clk + 0x78); - // 475.5M - k230_dsi_config_4lan_phy(dsi, TXPHY_475_M, TXPHY_475_N, - TXPHY_475_VOC, TXPHY_475_HS_FREQ); - // set clk todo - dsi->phy_freq = 475200; - dsi->clk_freq = 39600; - break; - } - default: + if (canaan_dsi_clk_cfg(dsi, adjusted_mode->clock)) dev_err(dsi->dev, "MIPI clock not support\n"); - break; - } + // set dsi lan num canaan_dsi_set_lan_num(dsi, device->lanes); // set lpdt @@ -420,6 +439,18 @@ static void canaan_dsi_encoder_disable(struct drm_encoder *encoder) } } +bool canaan_dsi_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + u32 div; + + div = DIV64_U64_ROUND_CLOSEST(594000, mode->clock); + adjusted_mode->clock = 594000 / div; + + return true; +} + static int canaan_dsi_get_modes(struct drm_connector *connector) { struct canaan_dsi *dsi = connector_to_canaan_dsi(connector); @@ -453,6 +484,7 @@ static const struct drm_connector_funcs canaan_dsi_connector_funcs = { }; static const struct drm_encoder_helper_funcs canaan_dsi_enc_helper_funcs = { + .mode_fixup = canaan_dsi_encoder_mode_fixup, .disable = canaan_dsi_encoder_disable, .enable = canaan_dsi_encoder_enable, }; diff --git a/drivers/gpu/drm/canaan/canaan_vo.c b/drivers/gpu/drm/canaan/canaan_vo.c index e37facde4649..0bcb30b81376 100644 --- a/drivers/gpu/drm/canaan/canaan_vo.c +++ b/drivers/gpu/drm/canaan/canaan_vo.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -495,32 +496,28 @@ static irqreturn_t canaan_vo_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static void canaan_vo_set_vtth_intr(struct canaan_vo *vo, bool status, u32 vpos) -{ - u32 reg = 0; - - reg = (reg & ~(BIT_MASK(20))) | (status << 20); - if (status != 0) - reg = (reg & ~(GENMASK(12, 0))) | (vpos << 0); - - canaan_vo_write(vo, VO_DISP_IRQ1_CTL, reg); -} - int canaan_vo_enable_vblank(struct canaan_vo *vo) { + u32 val; + atomic_set(&vo->vsync_enabled, 1); - canaan_vo_set_vtth_intr(vo, 1, vo->vth_line); - // canaan_vo_write(vo, VO_REG_LOAD_CTL, 0x11); + val = canaan_vo_read(vo, VO_DISP_IRQ1_CTL); + val |= (1 << 20); + canaan_vo_write(vo, VO_DISP_IRQ1_CTL, val); + return 0; } void canaan_vo_disable_vblank(struct canaan_vo *vo) { + u32 val; + atomic_set(&vo->vsync_enabled, 0); - canaan_vo_set_vtth_intr(vo, 0, vo->vth_line); - // canaan_vo_write(vo, VO_REG_LOAD_CTL, 0x11); + val = canaan_vo_read(vo, VO_DISP_IRQ1_CTL); + val &= ~(1 << 20); + canaan_vo_write(vo, VO_DISP_IRQ1_CTL, val); } static void canaan_vo_init(struct canaan_vo *vo) @@ -595,9 +592,6 @@ static void canaan_vo_init(struct canaan_vo *vo) canaan_vo_write(vo, VO_HSCALE_BASE + ((i * 4 + 2) << 2), H_Coef[i * 3 + 2]); } - - // // set vline irq - // canaan_vo_set_vtth_intr(vo, 1, 11); } static void canaan_vo_set_timing(struct canaan_vo *vo, @@ -650,6 +644,9 @@ static void canaan_vo_set_timing(struct canaan_vo *vo, reg = 0; reg = (hact - 1) + ((vact - 1) << 16) + (0x1 << 15); canaan_vo_write(vo, 0x780, reg); // enalbe remap 0x77f8437 + + reg = 32 - __builtin_clz(vtotal) - 1; + canaan_vo_write(vo, VO_DISP_IRQ1_CTL, reg); } void canaan_vo_enable_crtc(struct canaan_vo *vo, @@ -669,7 +666,13 @@ void canaan_vo_enable_crtc(struct canaan_vo *vo, void canaan_vo_disable_crtc(struct canaan_vo *vo, struct canaan_crtc *canaan_crtc) { - // canaan_vo_write(vo, VO_REG_LOAD_CTL, 0x0); + void *rst; + + rst = ioremap(0x91101090, 4); + writel(0x0, rst); + fsleep(1000); + writel(0xffffffff, rst); + iounmap(rst); } void canaan_vo_flush_config(struct canaan_vo *vo) @@ -809,10 +812,8 @@ static int canaan_vo_bind(struct device *dev, struct device *master, void *data) } of_property_read_u32(np, "background", &vo->background); - of_property_read_u32(np, "vth_line", &vo->vth_line); dev_info(vo->dev, "background color is %x\n", vo->background); - dev_info(vo->dev, "vth_line line is %x\n", vo->vth_line); atomic_set(&vo->vsync_enabled, 0); vo->irq = platform_get_irq(pdev, 0);