summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/imx/lcdif/lcdif-common.c58
-rw-r--r--drivers/gpu/imx/lcdif/lcdif-regs.h16
-rw-r--r--include/video/imx-lcdif.h2
3 files changed, 76 insertions, 0 deletions
diff --git a/drivers/gpu/imx/lcdif/lcdif-common.c b/drivers/gpu/imx/lcdif/lcdif-common.c
index a5f4e8bc58c1..af3ad161413d 100644
--- a/drivers/gpu/imx/lcdif/lcdif-common.c
+++ b/drivers/gpu/imx/lcdif/lcdif-common.c
@@ -377,6 +377,64 @@ void lcdif_set_fb_addr(struct lcdif_soc *lcdif, int id, u32 addr)
}
EXPORT_SYMBOL(lcdif_set_fb_addr);
+void lcdif_set_fb_hcrop(struct lcdif_soc *lcdif, u32 src_w,
+ u32 fb_w, bool crop)
+{
+ u32 mask_cnt, htotal, hcount;
+ u32 vdctrl2, vdctrl3, vdctrl4, transfer_count;
+ u32 pigeon_12_0, pigeon_12_1, pigeon_12_2;
+
+ if (!crop) {
+ writel(0x0, lcdif->base + HW_EPDC_PIGEON_12_0);
+ writel(0x0, lcdif->base + HW_EPDC_PIGEON_12_1);
+
+ return;
+ }
+
+ /* transfer_count's hcount, vdctrl2's htotal and vdctrl4's
+ * H_VALID_DATA_CNT should use fb width instead of hactive
+ * when requires cropping.
+ * */
+ transfer_count = readl(lcdif->base + LCDIF_TRANSFER_COUNT);
+ hcount = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+
+ transfer_count &= ~TRANSFER_COUNT_SET_HCOUNT(0xffff);
+ transfer_count |= TRANSFER_COUNT_SET_HCOUNT(fb_w);
+ writel(transfer_count, lcdif->base + LCDIF_TRANSFER_COUNT);
+
+ vdctrl2 = readl(lcdif->base + LCDIF_VDCTRL2);
+ htotal = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2);
+ htotal += fb_w - hcount;
+ vdctrl2 &= ~VDCTRL2_SET_HSYNC_PERIOD(0x3ffff);
+ vdctrl2 |= VDCTRL2_SET_HSYNC_PERIOD(htotal);
+ writel(vdctrl2, lcdif->base + LCDIF_VDCTRL2);
+
+ vdctrl4 = readl(lcdif->base + LCDIF_VDCTRL4);
+ vdctrl4 &= ~SET_DOTCLK_H_VALID_DATA_CNT(0x3ffff);
+ vdctrl4 |= SET_DOTCLK_H_VALID_DATA_CNT(fb_w);
+ writel(vdctrl4, lcdif->base + LCDIF_VDCTRL4);
+
+ /* configure related pigeon registers */
+ vdctrl3 = readl(lcdif->base + LCDIF_VDCTRL3);
+ mask_cnt = GET_HOR_WAIT_CNT(vdctrl3) - 5;
+
+ pigeon_12_0 = PIGEON_12_0_SET_STATE_MASK(0x24) |
+ PIGEON_12_0_SET_MASK_CNT(mask_cnt) |
+ PIGEON_12_0_SET_MASK_CNT_SEL(0x6) |
+ PIGEON_12_0_POL_ACTIVE_LOW |
+ PIGEON_12_0_EN;
+ writel(pigeon_12_0, lcdif->base + HW_EPDC_PIGEON_12_0);
+
+ pigeon_12_1 = PIGEON_12_1_SET_CLR_CNT(src_w) |
+ PIGEON_12_1_SET_SET_CNT(0x0);
+ writel(pigeon_12_1, lcdif->base + HW_EPDC_PIGEON_12_1);
+
+ pigeon_12_2 = 0x0;
+ writel(pigeon_12_2, lcdif->base + HW_EPDC_PIGEON_12_2);
+}
+EXPORT_SYMBOL(lcdif_set_fb_hcrop);
+
+
void lcdif_set_mode(struct lcdif_soc *lcdif, struct videomode *vmode)
{
const struct of_device_id *of_id =
diff --git a/drivers/gpu/imx/lcdif/lcdif-regs.h b/drivers/gpu/imx/lcdif/lcdif-regs.h
index 0cfec71d6af1..de2f1c55591c 100644
--- a/drivers/gpu/imx/lcdif/lcdif-regs.h
+++ b/drivers/gpu/imx/lcdif/lcdif-regs.h
@@ -32,6 +32,11 @@
#define LCDIF_VDCTRL3 0xa0
#define LCDIF_VDCTRL4 0xb0
+/* pigeon registers for crop */
+#define HW_EPDC_PIGEON_12_0 0xb00
+#define HW_EPDC_PIGEON_12_1 0xb10
+#define HW_EPDC_PIGEON_12_2 0xb20
+
/* reg bit manipulation */
#define REG_MASK(e, s) (((1 << ((e) - (s) + 1)) - 1) << (s))
#define REG_PUT(x, e, s) (((x) << (s)) & REG_MASK(e, s))
@@ -115,6 +120,17 @@
#define VDCTRL4_SYNC_SIGNALS_ON BIT(18)
#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
+#define PIGEON_12_0_SET_STATE_MASK(x) REG_PUT((x), 31, 24)
+#define PIGEON_12_0_SET_MASK_CNT(x) REG_PUT((x), 23, 12)
+#define PIGEON_12_0_SET_MASK_CNT_SEL(x) REG_PUT((x), 11, 8)
+#define PIGEON_12_0_SET_OFFSET(x) REG_PUT((x), 7, 4)
+#define PIGEON_12_0_SET_INC_SEL(x) REG_PUT((x), 3, 2)
+#define PIGEON_12_0_POL_ACTIVE_LOW BIT(1)
+#define PIGEON_12_0_EN BIT(0)
+
+#define PIGEON_12_1_SET_CLR_CNT(x) REG_PUT((x), 31, 16)
+#define PIGEON_12_1_SET_SET_CNT(x) REG_PUT((x), 15, 0)
+
#define STMLCDIF_8BIT 1 /* pixel data bus to the display is of 8 bit width */
#define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
#define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
diff --git a/include/video/imx-lcdif.h b/include/video/imx-lcdif.h
index ed43e80bdd2b..6597e46d5ca1 100644
--- a/include/video/imx-lcdif.h
+++ b/include/video/imx-lcdif.h
@@ -32,6 +32,8 @@ int lcdif_get_bus_fmt_from_pix_fmt(struct lcdif_soc *lcdif,
int lcdif_set_pix_fmt(struct lcdif_soc *lcdif, u32 format);
void lcdif_set_fb_addr(struct lcdif_soc *lcdif, int id, u32 addr);
void lcdif_set_mode(struct lcdif_soc *lcdif, struct videomode *vmode);
+void lcdif_set_fb_hcrop(struct lcdif_soc *lcdif, u32 src_w,
+ u32 fb_w, bool crop);
void lcdif_enable_controller(struct lcdif_soc *lcdif);
void lcdif_disable_controller(struct lcdif_soc *lcdif);
void lcdif_dump_registers(struct lcdif_soc *lcdif);