Skip to content

Commit

Permalink
drivers: k230: Fix vo resolution bug
Browse files Browse the repository at this point in the history
Signed-off-by: wycwyhwyq <[email protected]>
  • Loading branch information
wycwyhwyq committed Nov 25, 2024
1 parent f050fc6 commit 3be9f96
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 73 deletions.
142 changes: 90 additions & 52 deletions drivers/gpu/drm/canaan/canaan_dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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++;

Expand Down Expand Up @@ -313,6 +313,78 @@ 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;
cmp = cmp * 1000;
cmp = div64_u64(cmp, 24);
for (i = 1; i <= 16; i++) {
tmp = cmp * i + 500000;
val = div64_u64(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;
voc_freq = 24000;
voc_freq = voc_freq * 2 * m;
voc_freq = div64_u64(voc_freq, n);
voc_freq = div64_u64(voc_freq, (1 << (voc >> 4)));
dsi->phy_freq = voc_freq;

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);
Expand All @@ -324,56 +396,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
Expand Down Expand Up @@ -420,6 +445,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);
Expand Down Expand Up @@ -453,6 +490,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,
};
Expand Down
43 changes: 22 additions & 21 deletions drivers/gpu/drm/canaan/canaan_vo.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/delay.h>

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 3be9f96

Please sign in to comment.