d8bebe35b410e745dcade85ecb9826cff6aa7f9e
[sfrench/cifs-2.6.git] / drivers / video / fbdev / mxsfb.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2010 Juergen Beisert, Pengutronix
4  *
5  * This code is based on:
6  * Author: Vitaly Wool <vital@embeddedalley.com>
7  *
8  * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
9  * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
10  */
11
12 #define DRIVER_NAME "mxsfb"
13
14 /**
15  * @file
16  * @brief LCDIF driver for i.MX23 and i.MX28
17  *
18  * The LCDIF support four modes of operation
19  * - MPU interface (to drive smart displays) -> not supported yet
20  * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
21  * - Dotclock interface (to drive LC displays with RGB data and sync signals)
22  * - DVI (to drive ITU-R BT656)  -> not supported yet
23  *
24  * This driver depends on a correct setup of the pins used for this purpose
25  * (platform specific).
26  *
27  * For the developer: Don't forget to set the data bus width to the display
28  * in the imx_fb_videomode structure. You will else end up with ugly colours.
29  * If you fight against jitter you can vary the clock delay. This is a feature
30  * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
31  * the required value in the imx_fb_videomode structure.
32  */
33
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/of_device.h>
37 #include <linux/platform_device.h>
38 #include <linux/clk.h>
39 #include <linux/dma-mapping.h>
40 #include <linux/io.h>
41 #include <linux/fb.h>
42 #include <linux/regulator/consumer.h>
43 #include <video/of_display_timing.h>
44 #include <video/of_videomode.h>
45 #include <video/videomode.h>
46
47 #define REG_SET 4
48 #define REG_CLR 8
49
50 #define LCDC_CTRL                       0x00
51 #define LCDC_CTRL1                      0x10
52 #define LCDC_V4_CTRL2                   0x20
53 #define LCDC_V3_TRANSFER_COUNT          0x20
54 #define LCDC_V4_TRANSFER_COUNT          0x30
55 #define LCDC_V4_CUR_BUF                 0x40
56 #define LCDC_V4_NEXT_BUF                0x50
57 #define LCDC_V3_CUR_BUF                 0x30
58 #define LCDC_V3_NEXT_BUF                0x40
59 #define LCDC_TIMING                     0x60
60 #define LCDC_VDCTRL0                    0x70
61 #define LCDC_VDCTRL1                    0x80
62 #define LCDC_VDCTRL2                    0x90
63 #define LCDC_VDCTRL3                    0xa0
64 #define LCDC_VDCTRL4                    0xb0
65 #define LCDC_DVICTRL0                   0xc0
66 #define LCDC_DVICTRL1                   0xd0
67 #define LCDC_DVICTRL2                   0xe0
68 #define LCDC_DVICTRL3                   0xf0
69 #define LCDC_DVICTRL4                   0x100
70 #define LCDC_V4_DATA                    0x180
71 #define LCDC_V3_DATA                    0x1b0
72 #define LCDC_V4_DEBUG0                  0x1d0
73 #define LCDC_V3_DEBUG0                  0x1f0
74
75 #define CTRL_SFTRST                     (1 << 31)
76 #define CTRL_CLKGATE                    (1 << 30)
77 #define CTRL_BYPASS_COUNT               (1 << 19)
78 #define CTRL_VSYNC_MODE                 (1 << 18)
79 #define CTRL_DOTCLK_MODE                (1 << 17)
80 #define CTRL_DATA_SELECT                (1 << 16)
81 #define CTRL_SET_BUS_WIDTH(x)           (((x) & 0x3) << 10)
82 #define CTRL_GET_BUS_WIDTH(x)           (((x) >> 10) & 0x3)
83 #define CTRL_SET_WORD_LENGTH(x)         (((x) & 0x3) << 8)
84 #define CTRL_GET_WORD_LENGTH(x)         (((x) >> 8) & 0x3)
85 #define CTRL_MASTER                     (1 << 5)
86 #define CTRL_DF16                       (1 << 3)
87 #define CTRL_DF18                       (1 << 2)
88 #define CTRL_DF24                       (1 << 1)
89 #define CTRL_RUN                        (1 << 0)
90
91 #define CTRL1_FIFO_CLEAR                (1 << 21)
92 #define CTRL1_SET_BYTE_PACKAGING(x)     (((x) & 0xf) << 16)
93 #define CTRL1_GET_BYTE_PACKAGING(x)     (((x) >> 16) & 0xf)
94
95 #define TRANSFER_COUNT_SET_VCOUNT(x)    (((x) & 0xffff) << 16)
96 #define TRANSFER_COUNT_GET_VCOUNT(x)    (((x) >> 16) & 0xffff)
97 #define TRANSFER_COUNT_SET_HCOUNT(x)    ((x) & 0xffff)
98 #define TRANSFER_COUNT_GET_HCOUNT(x)    ((x) & 0xffff)
99
100
101 #define VDCTRL0_ENABLE_PRESENT          (1 << 28)
102 #define VDCTRL0_VSYNC_ACT_HIGH          (1 << 27)
103 #define VDCTRL0_HSYNC_ACT_HIGH          (1 << 26)
104 #define VDCTRL0_DOTCLK_ACT_FALLING      (1 << 25)
105 #define VDCTRL0_ENABLE_ACT_HIGH         (1 << 24)
106 #define VDCTRL0_VSYNC_PERIOD_UNIT       (1 << 21)
107 #define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT  (1 << 20)
108 #define VDCTRL0_HALF_LINE               (1 << 19)
109 #define VDCTRL0_HALF_LINE_MODE          (1 << 18)
110 #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
111 #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
112
113 #define VDCTRL2_SET_HSYNC_PERIOD(x)     ((x) & 0x3ffff)
114 #define VDCTRL2_GET_HSYNC_PERIOD(x)     ((x) & 0x3ffff)
115
116 #define VDCTRL3_MUX_SYNC_SIGNALS        (1 << 29)
117 #define VDCTRL3_VSYNC_ONLY              (1 << 28)
118 #define SET_HOR_WAIT_CNT(x)             (((x) & 0xfff) << 16)
119 #define GET_HOR_WAIT_CNT(x)             (((x) >> 16) & 0xfff)
120 #define SET_VERT_WAIT_CNT(x)            ((x) & 0xffff)
121 #define GET_VERT_WAIT_CNT(x)            ((x) & 0xffff)
122
123 #define VDCTRL4_SET_DOTCLK_DLY(x)       (((x) & 0x7) << 29) /* v4 only */
124 #define VDCTRL4_GET_DOTCLK_DLY(x)       (((x) >> 29) & 0x7) /* v4 only */
125 #define VDCTRL4_SYNC_SIGNALS_ON         (1 << 18)
126 #define SET_DOTCLK_H_VALID_DATA_CNT(x)  ((x) & 0x3ffff)
127
128 #define DEBUG0_HSYNC                    (1 < 26)
129 #define DEBUG0_VSYNC                    (1 < 25)
130
131 #define MIN_XRES                        120
132 #define MIN_YRES                        120
133
134 #define RED 0
135 #define GREEN 1
136 #define BLUE 2
137 #define TRANSP 3
138
139 #define STMLCDIF_8BIT  1 /** pixel data bus to the display is of 8 bit width */
140 #define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
141 #define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
142 #define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
143
144 #define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6)
145 #define MXSFB_SYNC_DOTCLK_FALLING_ACT   (1 << 7) /* negative edge sampling */
146
147 enum mxsfb_devtype {
148         MXSFB_V3,
149         MXSFB_V4,
150 };
151
152 /* CPU dependent register offsets */
153 struct mxsfb_devdata {
154         unsigned transfer_count;
155         unsigned cur_buf;
156         unsigned next_buf;
157         unsigned debug0;
158         unsigned hs_wdth_mask;
159         unsigned hs_wdth_shift;
160         unsigned ipversion;
161 };
162
163 struct mxsfb_info {
164         struct platform_device *pdev;
165         struct clk *clk;
166         struct clk *clk_axi;
167         struct clk *clk_disp_axi;
168         void __iomem *base;     /* registers */
169         unsigned allocated_size;
170         int enabled;
171         unsigned ld_intf_width;
172         unsigned dotclk_delay;
173         const struct mxsfb_devdata *devdata;
174         u32 sync;
175         struct regulator *reg_lcd;
176         int pre_init;
177 };
178
179 #define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
180 #define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
181
182 static const struct mxsfb_devdata mxsfb_devdata[] = {
183         [MXSFB_V3] = {
184                 .transfer_count = LCDC_V3_TRANSFER_COUNT,
185                 .cur_buf = LCDC_V3_CUR_BUF,
186                 .next_buf = LCDC_V3_NEXT_BUF,
187                 .debug0 = LCDC_V3_DEBUG0,
188                 .hs_wdth_mask = 0xff,
189                 .hs_wdth_shift = 24,
190                 .ipversion = 3,
191         },
192         [MXSFB_V4] = {
193                 .transfer_count = LCDC_V4_TRANSFER_COUNT,
194                 .cur_buf = LCDC_V4_CUR_BUF,
195                 .next_buf = LCDC_V4_NEXT_BUF,
196                 .debug0 = LCDC_V4_DEBUG0,
197                 .hs_wdth_mask = 0x3fff,
198                 .hs_wdth_shift = 18,
199                 .ipversion = 4,
200         },
201 };
202
203 /* mask and shift depends on architecture */
204 static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
205 {
206         return (val & host->devdata->hs_wdth_mask) <<
207                 host->devdata->hs_wdth_shift;
208 }
209
210 static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
211 {
212         return (val >> host->devdata->hs_wdth_shift) &
213                 host->devdata->hs_wdth_mask;
214 }
215
216 static const struct fb_bitfield def_rgb565[] = {
217         [RED] = {
218                 .offset = 11,
219                 .length = 5,
220         },
221         [GREEN] = {
222                 .offset = 5,
223                 .length = 6,
224         },
225         [BLUE] = {
226                 .offset = 0,
227                 .length = 5,
228         },
229         [TRANSP] = {    /* no support for transparency */
230                 .length = 0,
231         }
232 };
233
234 static const struct fb_bitfield def_rgb888[] = {
235         [RED] = {
236                 .offset = 16,
237                 .length = 8,
238         },
239         [GREEN] = {
240                 .offset = 8,
241                 .length = 8,
242         },
243         [BLUE] = {
244                 .offset = 0,
245                 .length = 8,
246         },
247         [TRANSP] = {    /* no support for transparency */
248                 .length = 0,
249         }
250 };
251
252 static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
253 {
254         chan &= 0xffff;
255         chan >>= 16 - bf->length;
256         return chan << bf->offset;
257 }
258
259 static int mxsfb_check_var(struct fb_var_screeninfo *var,
260                 struct fb_info *fb_info)
261 {
262         struct mxsfb_info *host = fb_info->par;
263         const struct fb_bitfield *rgb = NULL;
264
265         if (var->xres < MIN_XRES)
266                 var->xres = MIN_XRES;
267         if (var->yres < MIN_YRES)
268                 var->yres = MIN_YRES;
269
270         var->xres_virtual = var->xres;
271
272         var->yres_virtual = var->yres;
273
274         switch (var->bits_per_pixel) {
275         case 16:
276                 /* always expect RGB 565 */
277                 rgb = def_rgb565;
278                 break;
279         case 32:
280                 switch (host->ld_intf_width) {
281                 case STMLCDIF_8BIT:
282                         pr_debug("Unsupported LCD bus width mapping\n");
283                         break;
284                 case STMLCDIF_16BIT:
285                 case STMLCDIF_18BIT:
286                 case STMLCDIF_24BIT:
287                         /* real 24 bit */
288                         rgb = def_rgb888;
289                         break;
290                 }
291                 break;
292         default:
293                 pr_err("Unsupported colour depth: %u\n", var->bits_per_pixel);
294                 return -EINVAL;
295         }
296
297         /*
298          * Copy the RGB parameters for this display
299          * from the machine specific parameters.
300          */
301         var->red    = rgb[RED];
302         var->green  = rgb[GREEN];
303         var->blue   = rgb[BLUE];
304         var->transp = rgb[TRANSP];
305
306         return 0;
307 }
308
309 static inline void mxsfb_enable_axi_clk(struct mxsfb_info *host)
310 {
311         if (host->clk_axi)
312                 clk_prepare_enable(host->clk_axi);
313 }
314
315 static inline void mxsfb_disable_axi_clk(struct mxsfb_info *host)
316 {
317         if (host->clk_axi)
318                 clk_disable_unprepare(host->clk_axi);
319 }
320
321 static void mxsfb_enable_controller(struct fb_info *fb_info)
322 {
323         struct mxsfb_info *host = fb_info->par;
324         u32 reg;
325         int ret;
326
327         dev_dbg(&host->pdev->dev, "%s\n", __func__);
328
329         if (host->reg_lcd) {
330                 ret = regulator_enable(host->reg_lcd);
331                 if (ret) {
332                         dev_err(&host->pdev->dev,
333                                 "lcd regulator enable failed:   %d\n", ret);
334                         return;
335                 }
336         }
337
338         if (host->clk_disp_axi)
339                 clk_prepare_enable(host->clk_disp_axi);
340         clk_prepare_enable(host->clk);
341         clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
342
343         mxsfb_enable_axi_clk(host);
344
345         /* if it was disabled, re-enable the mode again */
346         writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
347
348         /* enable the SYNC signals first, then the DMA engine */
349         reg = readl(host->base + LCDC_VDCTRL4);
350         reg |= VDCTRL4_SYNC_SIGNALS_ON;
351         writel(reg, host->base + LCDC_VDCTRL4);
352
353         writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
354
355         host->enabled = 1;
356 }
357
358 static void mxsfb_disable_controller(struct fb_info *fb_info)
359 {
360         struct mxsfb_info *host = fb_info->par;
361         unsigned loop;
362         u32 reg;
363         int ret;
364
365         dev_dbg(&host->pdev->dev, "%s\n", __func__);
366
367         /*
368          * Even if we disable the controller here, it will still continue
369          * until its FIFOs are running out of data
370          */
371         writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR);
372
373         loop = 1000;
374         while (loop) {
375                 reg = readl(host->base + LCDC_CTRL);
376                 if (!(reg & CTRL_RUN))
377                         break;
378                 loop--;
379         }
380
381         reg = readl(host->base + LCDC_VDCTRL4);
382         writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
383
384         mxsfb_disable_axi_clk(host);
385
386         clk_disable_unprepare(host->clk);
387         if (host->clk_disp_axi)
388                 clk_disable_unprepare(host->clk_disp_axi);
389
390         host->enabled = 0;
391
392         if (host->reg_lcd) {
393                 ret = regulator_disable(host->reg_lcd);
394                 if (ret)
395                         dev_err(&host->pdev->dev,
396                                 "lcd regulator disable failed: %d\n", ret);
397         }
398 }
399
400 static int mxsfb_set_par(struct fb_info *fb_info)
401 {
402         struct mxsfb_info *host = fb_info->par;
403         u32 ctrl, vdctrl0, vdctrl4;
404         int line_size, fb_size;
405         int reenable = 0;
406
407         line_size =  fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
408         fb_size = fb_info->var.yres_virtual * line_size;
409
410         if (fb_size > fb_info->fix.smem_len)
411                 return -ENOMEM;
412
413         fb_info->fix.line_length = line_size;
414
415         if (host->pre_init) {
416                 mxsfb_enable_controller(fb_info);
417                 host->pre_init = 0;
418                 return 0;
419         }
420
421         /*
422          * It seems, you can't re-program the controller if it is still running.
423          * This may lead into shifted pictures (FIFO issue?).
424          * So, first stop the controller and drain its FIFOs
425          */
426         if (host->enabled) {
427                 reenable = 1;
428                 mxsfb_disable_controller(fb_info);
429         }
430
431         mxsfb_enable_axi_clk(host);
432
433         /* clear the FIFOs */
434         writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
435
436         ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
437                 CTRL_SET_BUS_WIDTH(host->ld_intf_width);
438
439         switch (fb_info->var.bits_per_pixel) {
440         case 16:
441                 dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
442                 ctrl |= CTRL_SET_WORD_LENGTH(0);
443                 writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
444                 break;
445         case 32:
446                 dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
447                 ctrl |= CTRL_SET_WORD_LENGTH(3);
448                 switch (host->ld_intf_width) {
449                 case STMLCDIF_8BIT:
450                         mxsfb_disable_axi_clk(host);
451                         dev_err(&host->pdev->dev,
452                                         "Unsupported LCD bus width mapping\n");
453                         return -EINVAL;
454                 case STMLCDIF_16BIT:
455                 case STMLCDIF_18BIT:
456                 case STMLCDIF_24BIT:
457                         /* real 24 bit */
458                         break;
459                 }
460                 /* do not use packed pixels = one pixel per word instead */
461                 writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
462                 break;
463         default:
464                 mxsfb_disable_axi_clk(host);
465                 dev_err(&host->pdev->dev, "Unhandled color depth of %u\n",
466                                 fb_info->var.bits_per_pixel);
467                 return -EINVAL;
468         }
469
470         writel(ctrl, host->base + LCDC_CTRL);
471
472         writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
473                         TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
474                         host->base + host->devdata->transfer_count);
475
476         vdctrl0 = VDCTRL0_ENABLE_PRESENT |      /* always in DOTCLOCK mode */
477                 VDCTRL0_VSYNC_PERIOD_UNIT |
478                 VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
479                 VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
480         if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT)
481                 vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
482         if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
483                 vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
484         if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
485                 vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
486         if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT)
487                 vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
488
489         writel(vdctrl0, host->base + LCDC_VDCTRL0);
490
491         /* frame length in lines */
492         writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
493                 fb_info->var.lower_margin + fb_info->var.yres,
494                 host->base + LCDC_VDCTRL1);
495
496         /* line length in units of clocks or pixels */
497         writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
498                 VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
499                 fb_info->var.hsync_len + fb_info->var.right_margin +
500                 fb_info->var.xres),
501                 host->base + LCDC_VDCTRL2);
502
503         writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
504                 fb_info->var.hsync_len) |
505                 SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
506                         fb_info->var.vsync_len),
507                 host->base + LCDC_VDCTRL3);
508
509         vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
510         if (mxsfb_is_v4(host))
511                 vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
512         writel(vdctrl4, host->base + LCDC_VDCTRL4);
513
514         writel(fb_info->fix.smem_start +
515                         fb_info->fix.line_length * fb_info->var.yoffset,
516                         host->base + host->devdata->next_buf);
517
518         mxsfb_disable_axi_clk(host);
519
520         if (reenable)
521                 mxsfb_enable_controller(fb_info);
522
523         return 0;
524 }
525
526 static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
527                 u_int transp, struct fb_info *fb_info)
528 {
529         unsigned int val;
530         int ret = -EINVAL;
531
532         /*
533          * If greyscale is true, then we convert the RGB value
534          * to greyscale no matter what visual we are using.
535          */
536         if (fb_info->var.grayscale)
537                 red = green = blue = (19595 * red + 38470 * green +
538                                         7471 * blue) >> 16;
539
540         switch (fb_info->fix.visual) {
541         case FB_VISUAL_TRUECOLOR:
542                 /*
543                  * 12 or 16-bit True Colour.  We encode the RGB value
544                  * according to the RGB bitfield information.
545                  */
546                 if (regno < 16) {
547                         u32 *pal = fb_info->pseudo_palette;
548
549                         val  = chan_to_field(red, &fb_info->var.red);
550                         val |= chan_to_field(green, &fb_info->var.green);
551                         val |= chan_to_field(blue, &fb_info->var.blue);
552
553                         pal[regno] = val;
554                         ret = 0;
555                 }
556                 break;
557
558         case FB_VISUAL_STATIC_PSEUDOCOLOR:
559         case FB_VISUAL_PSEUDOCOLOR:
560                 break;
561         }
562
563         return ret;
564 }
565
566 static int mxsfb_blank(int blank, struct fb_info *fb_info)
567 {
568         struct mxsfb_info *host = fb_info->par;
569
570         switch (blank) {
571         case FB_BLANK_POWERDOWN:
572         case FB_BLANK_VSYNC_SUSPEND:
573         case FB_BLANK_HSYNC_SUSPEND:
574         case FB_BLANK_NORMAL:
575                 if (host->enabled)
576                         mxsfb_disable_controller(fb_info);
577                 break;
578
579         case FB_BLANK_UNBLANK:
580                 if (!host->enabled)
581                         mxsfb_enable_controller(fb_info);
582                 break;
583         }
584         return 0;
585 }
586
587 static int mxsfb_pan_display(struct fb_var_screeninfo *var,
588                 struct fb_info *fb_info)
589 {
590         struct mxsfb_info *host = fb_info->par;
591         unsigned offset;
592
593         if (var->xoffset != 0)
594                 return -EINVAL;
595
596         offset = fb_info->fix.line_length * var->yoffset;
597
598         mxsfb_enable_axi_clk(host);
599
600         /* update on next VSYNC */
601         writel(fb_info->fix.smem_start + offset,
602                         host->base + host->devdata->next_buf);
603
604         mxsfb_disable_axi_clk(host);
605
606         return 0;
607 }
608
609 static struct fb_ops mxsfb_ops = {
610         .owner = THIS_MODULE,
611         .fb_check_var = mxsfb_check_var,
612         .fb_set_par = mxsfb_set_par,
613         .fb_setcolreg = mxsfb_setcolreg,
614         .fb_blank = mxsfb_blank,
615         .fb_pan_display = mxsfb_pan_display,
616         .fb_fillrect = cfb_fillrect,
617         .fb_copyarea = cfb_copyarea,
618         .fb_imageblit = cfb_imageblit,
619 };
620
621 static int mxsfb_restore_mode(struct fb_info *fb_info,
622                         struct fb_videomode *vmode)
623 {
624         struct mxsfb_info *host = fb_info->par;
625         unsigned period;
626         unsigned long pa, fbsize;
627         int bits_per_pixel, ofs, ret = 0;
628         u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
629
630         mxsfb_enable_axi_clk(host);
631
632         /* Only restore the mode when the controller is running */
633         ctrl = readl(host->base + LCDC_CTRL);
634         if (!(ctrl & CTRL_RUN)) {
635                 ret = -EINVAL;
636                 goto err;
637         }
638
639         vdctrl0 = readl(host->base + LCDC_VDCTRL0);
640         vdctrl2 = readl(host->base + LCDC_VDCTRL2);
641         vdctrl3 = readl(host->base + LCDC_VDCTRL3);
642         vdctrl4 = readl(host->base + LCDC_VDCTRL4);
643
644         transfer_count = readl(host->base + host->devdata->transfer_count);
645
646         vmode->xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
647         vmode->yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
648
649         switch (CTRL_GET_WORD_LENGTH(ctrl)) {
650         case 0:
651                 bits_per_pixel = 16;
652                 break;
653         case 3:
654                 bits_per_pixel = 32;
655                 break;
656         case 1:
657         default:
658                 ret = -EINVAL;
659                 goto err;
660         }
661
662         fb_info->var.bits_per_pixel = bits_per_pixel;
663
664         vmode->pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U);
665         vmode->hsync_len = get_hsync_pulse_width(host, vdctrl2);
666         vmode->left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode->hsync_len;
667         vmode->right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) -
668                 vmode->hsync_len - vmode->left_margin - vmode->xres;
669         vmode->vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
670         period = readl(host->base + LCDC_VDCTRL1);
671         vmode->upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode->vsync_len;
672         vmode->lower_margin = period - vmode->vsync_len -
673                 vmode->upper_margin - vmode->yres;
674
675         vmode->vmode = FB_VMODE_NONINTERLACED;
676
677         vmode->sync = 0;
678         if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
679                 vmode->sync |= FB_SYNC_HOR_HIGH_ACT;
680         if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
681                 vmode->sync |= FB_SYNC_VERT_HIGH_ACT;
682
683         pr_debug("Reconstructed video mode:\n");
684         pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
685                 vmode->xres, vmode->yres, vmode->hsync_len, vmode->left_margin,
686                 vmode->right_margin, vmode->vsync_len, vmode->upper_margin,
687                 vmode->lower_margin);
688         pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode->pixclock));
689
690         host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
691         host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
692
693         fb_info->fix.line_length = vmode->xres * (bits_per_pixel >> 3);
694
695         pa = readl(host->base + host->devdata->cur_buf);
696         fbsize = fb_info->fix.line_length * vmode->yres;
697         if (pa < fb_info->fix.smem_start) {
698                 ret = -EINVAL;
699                 goto err;
700         }
701         if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) {
702                 ret = -EINVAL;
703                 goto err;
704         }
705         ofs = pa - fb_info->fix.smem_start;
706         if (ofs) {
707                 memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
708                 writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
709         }
710
711         fb_info->fix.ypanstep = 1;
712
713         clk_prepare_enable(host->clk);
714         host->enabled = 1;
715
716 err:
717         if (ret)
718                 mxsfb_disable_axi_clk(host);
719
720         return ret;
721 }
722
723 static int mxsfb_init_fbinfo_dt(struct fb_info *fb_info,
724                                 struct fb_videomode *vmode)
725 {
726         struct mxsfb_info *host = fb_info->par;
727         struct fb_var_screeninfo *var = &fb_info->var;
728         struct device *dev = &host->pdev->dev;
729         struct device_node *np = host->pdev->dev.of_node;
730         struct device_node *display_np;
731         struct videomode vm;
732         u32 width;
733         int ret;
734
735         display_np = of_parse_phandle(np, "display", 0);
736         if (!display_np) {
737                 dev_err(dev, "failed to find display phandle\n");
738                 return -ENOENT;
739         }
740
741         ret = of_property_read_u32(display_np, "bus-width", &width);
742         if (ret < 0) {
743                 dev_err(dev, "failed to get property bus-width\n");
744                 goto put_display_node;
745         }
746
747         switch (width) {
748         case 8:
749                 host->ld_intf_width = STMLCDIF_8BIT;
750                 break;
751         case 16:
752                 host->ld_intf_width = STMLCDIF_16BIT;
753                 break;
754         case 18:
755                 host->ld_intf_width = STMLCDIF_18BIT;
756                 break;
757         case 24:
758                 host->ld_intf_width = STMLCDIF_24BIT;
759                 break;
760         default:
761                 dev_err(dev, "invalid bus-width value\n");
762                 ret = -EINVAL;
763                 goto put_display_node;
764         }
765
766         ret = of_property_read_u32(display_np, "bits-per-pixel",
767                                    &var->bits_per_pixel);
768         if (ret < 0) {
769                 dev_err(dev, "failed to get property bits-per-pixel\n");
770                 goto put_display_node;
771         }
772
773         ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE);
774         if (ret) {
775                 dev_err(dev, "failed to get videomode from DT\n");
776                 goto put_display_node;
777         }
778
779         ret = fb_videomode_from_videomode(&vm, vmode);
780         if (ret < 0)
781                 goto put_display_node;
782
783         if (vm.flags & DISPLAY_FLAGS_DE_HIGH)
784                 host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
785
786         /*
787          * The PIXDATA flags of the display_flags enum are controller
788          * centric, e.g. NEGEDGE means drive data on negative edge.
789          * However, the drivers flag is display centric: Sample the
790          * data on negative (falling) edge. Therefore, check for the
791          * POSEDGE flag:
792          * drive on positive edge => sample on negative edge
793          */
794         if (vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
795                 host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT;
796
797 put_display_node:
798         of_node_put(display_np);
799         return ret;
800 }
801
802 static int mxsfb_init_fbinfo(struct fb_info *fb_info,
803                         struct fb_videomode *vmode)
804 {
805         int ret;
806         struct mxsfb_info *host = fb_info->par;
807         struct device *dev = &host->pdev->dev;
808         struct fb_var_screeninfo *var = &fb_info->var;
809         dma_addr_t fb_phys;
810         void *fb_virt;
811         unsigned fb_size;
812
813         fb_info->fbops = &mxsfb_ops;
814         fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
815         strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id));
816         fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
817         fb_info->fix.ypanstep = 1;
818         fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
819         fb_info->fix.accel = FB_ACCEL_NONE;
820
821         ret = mxsfb_init_fbinfo_dt(fb_info, vmode);
822         if (ret)
823                 return ret;
824
825         var->nonstd = 0;
826         var->activate = FB_ACTIVATE_NOW;
827         var->accel_flags = 0;
828         var->vmode = FB_VMODE_NONINTERLACED;
829
830         /* Memory allocation for framebuffer */
831         fb_size = SZ_2M;
832         fb_virt = dma_alloc_wc(dev, PAGE_ALIGN(fb_size), &fb_phys, GFP_KERNEL);
833         if (!fb_virt)
834                 return -ENOMEM;
835
836         fb_info->fix.smem_start = fb_phys;
837         fb_info->screen_base = fb_virt;
838         fb_info->screen_size = fb_info->fix.smem_len = fb_size;
839
840         if (mxsfb_restore_mode(fb_info, vmode))
841                 memset(fb_virt, 0, fb_size);
842
843         return 0;
844 }
845
846 static void mxsfb_free_videomem(struct fb_info *fb_info)
847 {
848         struct mxsfb_info *host = fb_info->par;
849         struct device *dev = &host->pdev->dev;
850
851         dma_free_wc(dev, fb_info->screen_size, fb_info->screen_base,
852                     fb_info->fix.smem_start);
853 }
854
855 static const struct platform_device_id mxsfb_devtype[] = {
856         {
857                 .name = "imx23-fb",
858                 .driver_data = MXSFB_V3,
859         }, {
860                 .name = "imx28-fb",
861                 .driver_data = MXSFB_V4,
862         }, {
863                 /* sentinel */
864         }
865 };
866 MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
867
868 static const struct of_device_id mxsfb_dt_ids[] = {
869         { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
870         { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
871         { /* sentinel */ }
872 };
873 MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
874
875 static int mxsfb_probe(struct platform_device *pdev)
876 {
877         const struct of_device_id *of_id =
878                         of_match_device(mxsfb_dt_ids, &pdev->dev);
879         struct resource *res;
880         struct mxsfb_info *host;
881         struct fb_info *fb_info;
882         struct fb_videomode *mode;
883         int ret;
884
885         if (of_id)
886                 pdev->id_entry = of_id->data;
887
888         fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
889         if (!fb_info) {
890                 dev_err(&pdev->dev, "Failed to allocate fbdev\n");
891                 return -ENOMEM;
892         }
893
894         mode = devm_kzalloc(&pdev->dev, sizeof(struct fb_videomode),
895                         GFP_KERNEL);
896         if (mode == NULL)
897                 return -ENOMEM;
898
899         host = fb_info->par;
900
901         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
902         host->base = devm_ioremap_resource(&pdev->dev, res);
903         if (IS_ERR(host->base)) {
904                 ret = PTR_ERR(host->base);
905                 goto fb_release;
906         }
907
908         host->pdev = pdev;
909         platform_set_drvdata(pdev, host);
910
911         host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
912
913         host->clk = devm_clk_get(&host->pdev->dev, NULL);
914         if (IS_ERR(host->clk)) {
915                 ret = PTR_ERR(host->clk);
916                 goto fb_release;
917         }
918
919         host->clk_axi = devm_clk_get(&host->pdev->dev, "axi");
920         if (IS_ERR(host->clk_axi))
921                 host->clk_axi = NULL;
922
923         host->clk_disp_axi = devm_clk_get(&host->pdev->dev, "disp_axi");
924         if (IS_ERR(host->clk_disp_axi))
925                 host->clk_disp_axi = NULL;
926
927         host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");
928         if (IS_ERR(host->reg_lcd))
929                 host->reg_lcd = NULL;
930
931 #if defined(CONFIG_FB_PRE_INIT_FB)
932         host->pre_init = 1;
933 #endif
934
935         fb_info->pseudo_palette = devm_kcalloc(&pdev->dev, 16, sizeof(u32),
936                                                GFP_KERNEL);
937         if (!fb_info->pseudo_palette) {
938                 ret = -ENOMEM;
939                 goto fb_release;
940         }
941
942         ret = mxsfb_init_fbinfo(fb_info, mode);
943         if (ret != 0)
944                 goto fb_release;
945
946         fb_videomode_to_var(&fb_info->var, mode);
947
948         /* init the color fields */
949         mxsfb_check_var(&fb_info->var, fb_info);
950
951         platform_set_drvdata(pdev, fb_info);
952
953         ret = register_framebuffer(fb_info);
954         if (ret != 0) {
955                 dev_err(&pdev->dev,"Failed to register framebuffer\n");
956                 goto fb_destroy;
957         }
958
959         if (!host->enabled) {
960                 mxsfb_enable_axi_clk(host);
961                 writel(0, host->base + LCDC_CTRL);
962                 mxsfb_disable_axi_clk(host);
963                 mxsfb_set_par(fb_info);
964                 mxsfb_enable_controller(fb_info);
965         }
966
967         host->pre_init = 0;
968         dev_info(&pdev->dev, "initialized\n");
969
970         return 0;
971
972 fb_destroy:
973         if (host->enabled)
974                 clk_disable_unprepare(host->clk);
975 fb_release:
976         framebuffer_release(fb_info);
977
978         return ret;
979 }
980
981 static int mxsfb_remove(struct platform_device *pdev)
982 {
983         struct fb_info *fb_info = platform_get_drvdata(pdev);
984         struct mxsfb_info *host = fb_info->par;
985
986         if (host->enabled)
987                 mxsfb_disable_controller(fb_info);
988
989         unregister_framebuffer(fb_info);
990         mxsfb_free_videomem(fb_info);
991
992         framebuffer_release(fb_info);
993
994         return 0;
995 }
996
997 static void mxsfb_shutdown(struct platform_device *pdev)
998 {
999         struct fb_info *fb_info = platform_get_drvdata(pdev);
1000         struct mxsfb_info *host = fb_info->par;
1001
1002         mxsfb_enable_axi_clk(host);
1003
1004         /*
1005          * Force stop the LCD controller as keeping it running during reboot
1006          * might interfere with the BootROM's boot mode pads sampling.
1007          */
1008         writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
1009
1010         mxsfb_disable_axi_clk(host);
1011 }
1012
1013 static struct platform_driver mxsfb_driver = {
1014         .probe = mxsfb_probe,
1015         .remove = mxsfb_remove,
1016         .shutdown = mxsfb_shutdown,
1017         .id_table = mxsfb_devtype,
1018         .driver = {
1019                    .name = DRIVER_NAME,
1020                    .of_match_table = mxsfb_dt_ids,
1021         },
1022 };
1023
1024 module_platform_driver(mxsfb_driver);
1025
1026 MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
1027 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
1028 MODULE_LICENSE("GPL");