diff options
-rw-r--r-- | drivers/gpu/imx/lcdif/lcdif-common.c | 58 | ||||
-rw-r--r-- | drivers/gpu/imx/lcdif/lcdif-regs.h | 16 | ||||
-rw-r--r-- | include/video/imx-lcdif.h | 2 |
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); |