writel(ctrl1, mxsfb->base + LCDC_CTRL1);
writel(ctrl, mxsfb->base + LCDC_CTRL);
+ ctrl = readl(mxsfb->base + LCDC_CTRL);
+ ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
return 0;
}
{
u32 reg;
+ if (mxsfb->enabled)
+ return;
+
if (mxsfb->clk_disp_axi)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
mxsfb_enable_axi_clk(mxsfb);
+ writel(CTRL2_OUTSTANDING_REQS__REQ_16,
+ mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
reg |= VDCTRL4_SYNC_SIGNALS_ON;
writel(reg, mxsfb->base + LCDC_VDCTRL4);
+ writel(CTRL_MASTER, mxsfb->base + LCDC_CTRL + REG_SET);
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+
+ writel(CTRL1_RECOVERY_ON_UNDERFLOW, mxsfb->base + LCDC_CTRL1 + REG_SET);
+
+ mxsfb->enabled = true;
}
static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
{
u32 reg;
+ if (!mxsfb->enabled)
+ return;
+
+ writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
/*
* Even if we disable the controller here, it will still continue
* until its FIFOs are running out of data
readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN),
0, 1000);
+ writel(CTRL_MASTER, mxsfb->base + LCDC_CTRL + REG_CLR);
+
reg = readl(mxsfb->base + LCDC_VDCTRL4);
reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
writel(reg, mxsfb->base + LCDC_VDCTRL4);
mxsfb_disable_axi_clk(mxsfb);
- clk_disable_unprepare(mxsfb->clk);
if (mxsfb->clk_disp_axi)
clk_disable_unprepare(mxsfb->clk_disp_axi);
+ clk_disable_unprepare(mxsfb->clk);
+
+ mxsfb->enabled = false;
}
/*
{
struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+ u32 hbp = m->crtc_hblank_end - m->crtc_hsync_end;
+ u32 vbp = m->crtc_vblank_end - m->crtc_vsync_end;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),
mxsfb->base + LCDC_VDCTRL2);
- writel(SET_HOR_WAIT_CNT(m->crtc_htotal - m->crtc_hsync_start) |
- SET_VERT_WAIT_CNT(m->crtc_vtotal - m->crtc_vsync_start),
+ writel(SET_HOR_WAIT_CNT(hbp + hsync_pulse_len) |
+ SET_VERT_WAIT_CNT(vbp + vsync_pulse_len),
mxsfb->base + LCDC_VDCTRL3);
writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
mxsfb->base + LCDC_VDCTRL4);
+ if (mxsfb->gem != NULL) {
+ writel(mxsfb->gem->paddr,
+ mxsfb->base + mxsfb->devdata->next_buf);
+ mxsfb->gem = NULL;
+ }
+
mxsfb_disable_axi_clk(mxsfb);
}
void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
{
+ writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
mxsfb_enable_controller(mxsfb);
}
struct drm_framebuffer *fb = pipe->plane.state->fb;
struct drm_pending_vblank_event *event;
struct drm_gem_cma_object *gem;
+ u32 val;
if (!crtc)
return;
+
spin_lock_irq(&crtc->dev->event_lock);
event = crtc->state->event;
if (event) {
return;
gem = drm_fb_cma_get_gem_obj(fb, 0);
+ pr_info("GEM paddr=0x%llx\n", gem->paddr);
+
+ if (!mxsfb->enabled) {
+ mxsfb->gem = gem;
+ return;
+ }
mxsfb_enable_axi_clk(mxsfb);
writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf);
mxsfb_disable_axi_clk(mxsfb);
+
+ val = readl(mxsfb->base + mxsfb->devdata->cur_buf);
+ pr_info("REG[%02X]=%08x\n", mxsfb->devdata->cur_buf, val);
+ val = readl(mxsfb->base + mxsfb->devdata->next_buf);
+ pr_info("REG[%02X]=%08x\n", mxsfb->devdata->next_buf, val);
}
if (ret)
return ret;
- mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
- mxsfb->connector.polled = 0;
- drm_connector_helper_add(&mxsfb->connector,
- &mxsfb_panel_connector_helper_funcs);
- ret = drm_connector_init(drm, &mxsfb->connector,
- &mxsfb_panel_connector_funcs,
- DRM_MODE_CONNECTOR_Unknown);
- if (!ret)
- mxsfb->panel = panel;
+ if (mxsfb->panel) {
+ mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
+ mxsfb->connector.polled = 0;
+ drm_connector_helper_add(&mxsfb->connector,
+ &mxsfb_panel_connector_helper_funcs);
+ ret = drm_connector_init(drm, &mxsfb->connector,
+ &mxsfb_panel_connector_funcs,
+ DRM_MODE_CONNECTOR_Unknown);
+ }
return ret;
}
#define LCDC_CTRL 0x00
#define LCDC_CTRL1 0x10
+#define LCDC_V4_CTRL2 0x20
#define LCDC_V3_TRANSFER_COUNT 0x20
#define LCDC_V4_TRANSFER_COUNT 0x30
#define LCDC_V4_CUR_BUF 0x40
#define LCDC_V4_NEXT_BUF 0x50
#define LCDC_V3_CUR_BUF 0x30
#define LCDC_V3_NEXT_BUF 0x40
+#define LCDC_TIMING 0x60
#define LCDC_VDCTRL0 0x70
#define LCDC_VDCTRL1 0x80
#define LCDC_VDCTRL2 0x90
#define LCDC_VDCTRL3 0xa0
#define LCDC_VDCTRL4 0xb0
+#define LCDC_DVICTRL0 0xc0
+#define LCDC_DVICTRL1 0xd0
+#define LCDC_DVICTRL2 0xe0
+#define LCDC_DVICTRL3 0xf0
+#define LCDC_DVICTRL4 0x100
+#define LCDC_V4_DATA 0x180
+#define LCDC_V3_DATA 0x1b0
#define LCDC_V4_DEBUG0 0x1d0
#define LCDC_V3_DEBUG0 0x1f0
+#define LCDC_AS_CTRL 0x210
+#define LCDC_AS_BUF 0x220
+#define LCDC_AS_NEXT_BUF 0x230
#define CTRL_SFTRST (1 << 31)
#define CTRL_CLKGATE (1 << 30)
#define CTRL_DF24 (1 << 1)
#define CTRL_RUN (1 << 0)
+#define CTRL1_RECOVERY_ON_UNDERFLOW (1 << 24)
#define CTRL1_FIFO_CLEAR (1 << 21)
#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13)
#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
+#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
+
#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)