20 #define DRIVER_NAME "mxsfb"
42 #include <linux/module.h>
43 #include <linux/kernel.h>
56 #define LCDC_CTRL 0x00
57 #define LCDC_CTRL1 0x10
58 #define LCDC_V4_CTRL2 0x20
59 #define LCDC_V3_TRANSFER_COUNT 0x20
60 #define LCDC_V4_TRANSFER_COUNT 0x30
61 #define LCDC_V4_CUR_BUF 0x40
62 #define LCDC_V4_NEXT_BUF 0x50
63 #define LCDC_V3_CUR_BUF 0x30
64 #define LCDC_V3_NEXT_BUF 0x40
65 #define LCDC_TIMING 0x60
66 #define LCDC_VDCTRL0 0x70
67 #define LCDC_VDCTRL1 0x80
68 #define LCDC_VDCTRL2 0x90
69 #define LCDC_VDCTRL3 0xa0
70 #define LCDC_VDCTRL4 0xb0
71 #define LCDC_DVICTRL0 0xc0
72 #define LCDC_DVICTRL1 0xd0
73 #define LCDC_DVICTRL2 0xe0
74 #define LCDC_DVICTRL3 0xf0
75 #define LCDC_DVICTRL4 0x100
76 #define LCDC_V4_DATA 0x180
77 #define LCDC_V3_DATA 0x1b0
78 #define LCDC_V4_DEBUG0 0x1d0
79 #define LCDC_V3_DEBUG0 0x1f0
81 #define CTRL_SFTRST (1 << 31)
82 #define CTRL_CLKGATE (1 << 30)
83 #define CTRL_BYPASS_COUNT (1 << 19)
84 #define CTRL_VSYNC_MODE (1 << 18)
85 #define CTRL_DOTCLK_MODE (1 << 17)
86 #define CTRL_DATA_SELECT (1 << 16)
87 #define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
88 #define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
89 #define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
90 #define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
91 #define CTRL_MASTER (1 << 5)
92 #define CTRL_DF16 (1 << 3)
93 #define CTRL_DF18 (1 << 2)
94 #define CTRL_DF24 (1 << 1)
95 #define CTRL_RUN (1 << 0)
97 #define CTRL1_FIFO_CLEAR (1 << 21)
98 #define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
99 #define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
101 #define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
102 #define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
103 #define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
104 #define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
107 #define VDCTRL0_ENABLE_PRESENT (1 << 28)
108 #define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
109 #define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
110 #define VDCTRL0_DOTCLK_ACT_FAILING (1 << 25)
111 #define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
112 #define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
113 #define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
114 #define VDCTRL0_HALF_LINE (1 << 19)
115 #define VDCTRL0_HALF_LINE_MODE (1 << 18)
116 #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
117 #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
119 #define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
120 #define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
122 #define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
123 #define VDCTRL3_VSYNC_ONLY (1 << 28)
124 #define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
125 #define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
126 #define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
127 #define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
129 #define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29)
130 #define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7)
131 #define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
132 #define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
134 #define DEBUG0_HSYNC (1 < 26)
135 #define DEBUG0_VSYNC (1 < 25)
174 #define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
175 #define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
183 .hs_wdth_mask = 0xff,
192 .hs_wdth_mask = 0x3fff,
198 #define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
203 return (val & host->
devdata->hs_wdth_mask) <<
209 return (val >> host->
devdata->hs_wdth_shift) &
271 return chan << bf->
offset;
297 pr_debug(
"Unsupported LCD bus width mapping\n");
327 static void mxsfb_enable_controller(
struct fb_info *fb_info)
334 clk_prepare_enable(host->
clk);
350 static void mxsfb_disable_controller(
struct fb_info *fb_info)
374 clk_disable_unprepare(host->
clk);
379 static int mxsfb_set_par(
struct fb_info *fb_info)
383 int line_size, fb_size;
386 line_size = fb_info->
var.xres * (fb_info->
var.bits_per_pixel >> 3);
387 fb_size = fb_info->
var.yres_virtual * line_size;
389 if (fb_size > fb_info->
fix.smem_len)
392 fb_info->
fix.line_length = line_size;
401 mxsfb_disable_controller(fb_info);
410 switch (fb_info->
var.bits_per_pixel) {
412 dev_dbg(&host->
pdev->dev,
"Setting up RGB565 mode\n");
417 dev_dbg(&host->
pdev->dev,
"Setting up RGB888/666 mode\n");
422 "Unsupported LCD bus width mapping\n");
439 dev_dbg(&host->
pdev->dev,
"Unhandled color depth of %u\n",
440 fb_info->
var.bits_per_pixel);
466 writel(fb_info->
var.upper_margin + fb_info->
var.vsync_len +
467 fb_info->
var.lower_margin + fb_info->
var.yres,
471 writel(set_hsync_pulse_width(host, fb_info->
var.hsync_len) |
473 fb_info->
var.hsync_len + fb_info->
var.right_margin +
478 fb_info->
var.hsync_len) |
480 fb_info->
var.vsync_len),
489 fb_info->
fix.line_length * fb_info->
var.yoffset,
493 mxsfb_enable_controller(fb_info);
508 if (fb_info->
var.grayscale)
509 red = green = blue = (19595 * red + 38470 * green +
512 switch (fb_info->
fix.visual) {
521 val = chan_to_field(red, &fb_info->
var.red);
522 val |= chan_to_field(green, &fb_info->
var.green);
523 val |= chan_to_field(blue, &fb_info->
var.blue);
538 static int mxsfb_blank(
int blank,
struct fb_info *fb_info)
548 mxsfb_disable_controller(fb_info);
553 mxsfb_enable_controller(fb_info);
560 struct fb_info *fb_info)
568 offset = fb_info->
fix.line_length * var->
yoffset;
577 static struct fb_ops mxsfb_ops = {
579 .fb_check_var = mxsfb_check_var,
580 .fb_set_par = mxsfb_set_par,
581 .fb_setcolreg = mxsfb_setcolreg,
582 .fb_blank = mxsfb_blank,
583 .fb_pan_display = mxsfb_pan_display,
591 struct fb_info *fb_info = &host->
fb_info;
594 unsigned long pa, fbsize;
628 vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
645 pr_debug(
"Reconstructed video mode:\n");
646 pr_debug(
"%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
657 fb_info->
fix.line_length =
vmode.xres * (bits_per_pixel >> 3);
660 fbsize = fb_info->
fix.line_length *
vmode.yres;
661 if (pa < fb_info->fix.smem_start)
663 if (pa + fbsize > fb_info->
fix.smem_start + fb_info->
fix.smem_len)
665 ofs = pa - fb_info->
fix.smem_start;
671 line_count = fb_info->
fix.smem_len / fb_info->
fix.line_length;
672 fb_info->
fix.ypanstep = 1;
674 clk_prepare_enable(host->
clk);
682 struct fb_info *fb_info = &host->
fb_info;
687 unsigned fb_size = pdata->
fb_size;
689 fb_info->
fbops = &mxsfb_ops;
693 fb_info->
fix.ypanstep = 1;
716 fb_virt =
ioremap(fb_phys, fb_size);
736 if (mxsfb_restore_mode(host))
737 memset(fb_virt, 0, fb_size);
744 struct fb_info *fb_info = &host->
fb_info;
769 { .compatible =
"fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
770 { .compatible =
"fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
793 dev_err(&pdev->
dev,
"No platformdata. Giving up\n");
799 dev_err(&pdev->
dev,
"Cannot get memory IO resource\n");
808 dev_err(&pdev->
dev,
"Failed to allocate fbdev\n");
810 goto error_alloc_info;
823 platform_set_drvdata(pdev, host);
827 pinctrl = devm_pinctrl_get_select_default(&pdev->
dev);
828 if (IS_ERR(pinctrl)) {
829 ret = PTR_ERR(pinctrl);
834 if (IS_ERR(host->
clk)) {
835 ret = PTR_ERR(host->
clk);
840 "panel-enable-gpios", 0, &flags);
841 if (gpio_is_valid(panel_enable)) {
849 "failed to request gpio %d: %d\n",
851 goto error_panel_enable;
858 goto error_pseudo_pallette;
863 ret = mxsfb_init_fbinfo(host);
875 mxsfb_check_var(&fb_info->
var, fb_info);
877 platform_set_drvdata(pdev, fb_info);
881 dev_err(&pdev->
dev,
"Failed to register framebuffer\n");
887 mxsfb_set_par(fb_info);
888 mxsfb_enable_controller(fb_info);
897 clk_disable_unprepare(host->
clk);
901 error_pseudo_pallette:
917 struct fb_info *fb_info = platform_get_drvdata(pdev);
922 mxsfb_disable_controller(fb_info);
926 mxsfb_free_videomem(host);
933 platform_set_drvdata(pdev,
NULL);
940 struct fb_info *fb_info = platform_get_drvdata(pdev);
951 .probe = mxsfb_probe,
953 .shutdown = mxsfb_shutdown,
957 .of_match_table = mxsfb_dt_ids,