]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/video/mxc/ldb.c
video: mxc: ldb: add support for NL12880BC20 and VGA timings (used on Ka-Ro MB7 baseb...
[karo-tx-linux.git] / drivers / video / mxc / ldb.c
1 /*
2  * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
3  */
4
5 /*
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 /*!
22  * @file mxc_ldb.c
23  *
24  * @brief This file contains the LDB driver device interface and fops
25  * functions.
26  */
27 #include <linux/types.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/platform_device.h>
31 #include <linux/err.h>
32 #include <linux/clk.h>
33 #include <linux/console.h>
34 #include <linux/io.h>
35 #include <linux/ipu.h>
36 #include <linux/mxcfb.h>
37 #include <linux/regulator/consumer.h>
38 #include <linux/spinlock.h>
39 #include <linux/of_device.h>
40 #include <linux/mod_devicetable.h>
41 #include <video/of_display_timing.h>
42 #include <video/of_videomode.h>
43 #include <video/videomode.h>
44
45 #include "mxc_dispdrv.h"
46
47 #define DISPDRV_LDB     "ldb"
48
49 #define LDB_BGREF_RMODE_MASK            0x00008000
50 #define LDB_BGREF_RMODE_INT             0x00008000
51 #define LDB_BGREF_RMODE_EXT             0x0
52
53 #define LDB_DI1_VS_POL_MASK             0x00000400
54 #define LDB_DI1_VS_POL_ACT_LOW          0x00000400
55 #define LDB_DI1_VS_POL_ACT_HIGH         0x0
56 #define LDB_DI0_VS_POL_MASK             0x00000200
57 #define LDB_DI0_VS_POL_ACT_LOW          0x00000200
58 #define LDB_DI0_VS_POL_ACT_HIGH         0x0
59
60 #define LDB_BIT_MAP_CH1_MASK            0x00000100
61 #define LDB_BIT_MAP_CH1_JEIDA           0x00000100
62 #define LDB_BIT_MAP_CH1_SPWG            0x0
63 #define LDB_BIT_MAP_CH0_MASK            0x00000040
64 #define LDB_BIT_MAP_CH0_JEIDA           0x00000040
65 #define LDB_BIT_MAP_CH0_SPWG            0x0
66
67 #define LDB_DATA_WIDTH_CH1_MASK         0x00000080
68 #define LDB_DATA_WIDTH_CH1_24           0x00000080
69 #define LDB_DATA_WIDTH_CH1_18           0x0
70 #define LDB_DATA_WIDTH_CH0_MASK         0x00000020
71 #define LDB_DATA_WIDTH_CH0_24           0x00000020
72 #define LDB_DATA_WIDTH_CH0_18           0x0
73
74 #define LDB_CH1_MODE_MASK               0x0000000C
75 #define LDB_CH1_MODE_EN_TO_DI1          0x0000000C
76 #define LDB_CH1_MODE_EN_TO_DI0          0x00000004
77 #define LDB_CH1_MODE_DISABLE            0x0
78 #define LDB_CH0_MODE_MASK               0x00000003
79 #define LDB_CH0_MODE_EN_TO_DI1          0x00000003
80 #define LDB_CH0_MODE_EN_TO_DI0          0x00000001
81 #define LDB_CH0_MODE_DISABLE            0x0
82
83 #define LDB_SPLIT_MODE_EN               0x00000010
84
85 enum {
86         IMX6_LDB,
87 };
88
89 enum {
90         LDB_IMX6 = 1,
91 };
92
93 struct fsl_mxc_ldb_platform_data {
94         int devtype;
95         u32 ext_ref;
96 #define LDB_SPL_DI0     1
97 #define LDB_SPL_DI1     2
98 #define LDB_DUL_DI0     3
99 #define LDB_DUL_DI1     4
100 #define LDB_SIN0        5
101 #define LDB_SIN1        6
102 #define LDB_SEP0        7
103 #define LDB_SEP1        8
104         int mode;
105         int ipu_id;
106         int disp_id;
107
108         /*only work for separate mode*/
109         int sec_ipu_id;
110         int sec_disp_id;
111 };
112
113 struct ldb_data {
114         struct platform_device *pdev;
115         struct mxc_dispdrv_handle *disp_ldb;
116         uint32_t *reg;
117         uint32_t *control_reg;
118         uint32_t *gpr3_reg;
119         uint32_t control_reg_data;
120         struct regulator *lvds_bg_reg;
121         int mode;
122         bool inited;
123         struct ldb_setting {
124                 struct clk *di_clk;
125                 struct clk *ldb_di_clk;
126                 struct clk *div_3_5_clk;
127                 struct clk *div_7_clk;
128                 struct clk *div_sel_clk;
129                 bool active;
130                 bool clk_en;
131                 int ipu;
132                 int di;
133                 uint32_t ch_mask;
134                 uint32_t ch_val;
135         } setting[2];
136         struct notifier_block nb;
137 };
138
139 static int g_ldb_mode;
140
141 static struct fb_videomode ldb_modedb[] = {
142         {
143                 "LDB-WXGA", 60, 1280, 800, 14065,
144                 40, 40,
145                 10, 3,
146                 80, 10,
147                 0,
148                 FB_VMODE_NONINTERLACED,
149                 FB_MODE_IS_DETAILED,
150         },
151         {
152                 "LDB-XGA", 60, 1024, 768, 15385,
153                 220, 40,
154                 21, 7,
155                 60, 10,
156                 0,
157                 FB_VMODE_NONINTERLACED,
158                 FB_MODE_IS_DETAILED,
159         },
160         {
161                 "LDB-1080P60", 60, 1920, 1080, 7692,
162                 100, 40,
163                 30, 3,
164                 10, 2,
165                 0,
166                 FB_VMODE_NONINTERLACED,
167                 FB_MODE_IS_DETAILED,
168         },
169         {
170                 "LDB-NL12880BC20", 60, 1280, 800, KHZ2PICOS(71000),
171                 50, 50,
172                 5, 5,
173                 60, 13,
174                 0,
175                 FB_VMODE_NONINTERLACED,
176                 FB_MODE_IS_DETAILED,
177         },
178         {
179                 "LDB-VGA", 60, 640, 480, KHZ2PICOS(25200),
180                 48, 16,
181                 31, 12,
182                 96, 2,
183                 0,
184                 FB_VMODE_NONINTERLACED,
185                 FB_MODE_IS_DETAILED,
186         },
187 };
188 static int ldb_modedb_sz = ARRAY_SIZE(ldb_modedb);
189
190 static inline int is_imx6_ldb(struct fsl_mxc_ldb_platform_data *plat_data)
191 {
192         return (plat_data->devtype == LDB_IMX6);
193 }
194
195 static int bits_per_pixel(int pixel_fmt)
196 {
197         switch (pixel_fmt) {
198         case IPU_PIX_FMT_BGR24:
199         case IPU_PIX_FMT_RGB24:
200                 return 24;
201                 break;
202         case IPU_PIX_FMT_BGR666:
203         case IPU_PIX_FMT_RGB666:
204         case IPU_PIX_FMT_LVDS666:
205                 return 18;
206                 break;
207         default:
208                 break;
209         }
210         return 0;
211 }
212
213 static int valid_mode(int pixel_fmt)
214 {
215         return ((pixel_fmt == IPU_PIX_FMT_RGB24) ||
216                 (pixel_fmt == IPU_PIX_FMT_BGR24) ||
217                 (pixel_fmt == IPU_PIX_FMT_LVDS666) ||
218                 (pixel_fmt == IPU_PIX_FMT_RGB666) ||
219                 (pixel_fmt == IPU_PIX_FMT_BGR666));
220 }
221
222 static int parse_ldb_mode(char *mode)
223 {
224         int ldb_mode;
225
226         if (!strcmp(mode, "spl0"))
227                 ldb_mode = LDB_SPL_DI0;
228         else if (!strcmp(mode, "spl1"))
229                 ldb_mode = LDB_SPL_DI1;
230         else if (!strcmp(mode, "dul0"))
231                 ldb_mode = LDB_DUL_DI0;
232         else if (!strcmp(mode, "dul1"))
233                 ldb_mode = LDB_DUL_DI1;
234         else if (!strcmp(mode, "sin0"))
235                 ldb_mode = LDB_SIN0;
236         else if (!strcmp(mode, "sin1"))
237                 ldb_mode = LDB_SIN1;
238         else if (!strcmp(mode, "sep0"))
239                 ldb_mode = LDB_SEP0;
240         else if (!strcmp(mode, "sep1"))
241                 ldb_mode = LDB_SEP1;
242         else
243                 ldb_mode = -EINVAL;
244
245         return ldb_mode;
246 }
247
248 #ifndef MODULE
249 /*
250  *    "ldb=spl0/1"       --      split mode on DI0/1
251  *    "ldb=dul0/1"       --      dual mode on DI0/1
252  *    "ldb=sin0/1"       --      single mode on LVDS0/1
253  *    "ldb=sep0/1"       --      separate mode begin from LVDS0/1
254  *
255  *    There are two LVDS channels (LVDS0 and LVDS1) which can transfer video
256  *    data. These two channels can be used as split/dual/single/separate mode.
257  *
258  *    split mode means display data from DI0 or DI1 will be sent to both channels
259  *    LVDS0+LVDS1.
260  *    dual mode means display data from DI0 or DI1 will be duplicated on LVDS0
261  *    and LVDS1, i.e. LVDS0 and LVDS1 has the same content.
262  *    single mode means only work for DI0/DI1->LVDS0 or DI0/DI1->LVDS1.
263  *    separate mode means you can make DI0/DI1->LVDS0 and DI0/DI1->LVDS1 work
264  *    at the same time.
265  */
266 static int __init ldb_setup(char *options)
267 {
268         g_ldb_mode = parse_ldb_mode(options);
269         return (g_ldb_mode < 0) ? 0 : 1;
270 }
271 __setup("ldb=", ldb_setup);
272 #endif
273
274 static int ldb_get_of_property(struct platform_device *pdev,
275                                 struct fsl_mxc_ldb_platform_data *plat_data)
276 {
277         struct device_node *np = pdev->dev.of_node;
278         int err;
279         u32 ipu_id, disp_id;
280         u32 sec_ipu_id, sec_disp_id;
281         char *mode;
282         u32 ext_ref;
283
284         err = of_property_read_string(np, "mode", (const char **)&mode);
285         if (err) {
286                 dev_err(&pdev->dev, "get of property mode fail\n");
287                 return err;
288         }
289         err = of_property_read_u32(np, "ext_ref", &ext_ref);
290         if (err) {
291                 dev_err(&pdev->dev, "get of property ext_ref fail\n");
292                 return err;
293         }
294         err = of_property_read_u32(np, "ipu_id", &ipu_id);
295         if (err) {
296                 dev_err(&pdev->dev, "get of property ipu_id fail\n");
297                 return err;
298         }
299         err = of_property_read_u32(np, "disp_id", &disp_id);
300         if (err) {
301                 dev_err(&pdev->dev, "get of property disp_id fail\n");
302                 return err;
303         }
304         err = of_property_read_u32(np, "sec_ipu_id", &sec_ipu_id);
305         if (err) {
306                 dev_err(&pdev->dev, "get of property sec_ipu_id fail\n");
307                 return err;
308         }
309         err = of_property_read_u32(np, "sec_disp_id", &sec_disp_id);
310         if (err) {
311                 dev_err(&pdev->dev, "get of property sec_disp_id fail\n");
312                 return err;
313         }
314
315         plat_data->mode = parse_ldb_mode(mode);
316         plat_data->ext_ref = ext_ref;
317         plat_data->ipu_id = ipu_id;
318         plat_data->disp_id = disp_id;
319         plat_data->sec_ipu_id = sec_ipu_id;
320         plat_data->sec_disp_id = sec_disp_id;
321
322         return err;
323 }
324
325 static int find_ldb_setting(struct ldb_data *ldb, struct fb_info *fbi)
326 {
327         char *id_di[] = {
328                  "DISP3 BG",
329                  "DISP3 BG - DI1",
330                 };
331         char id[16];
332         int i;
333
334         for (i = 0; i < ARRAY_SIZE(id_di); i++) {
335                 if (ldb->setting[i].active) {
336                         strlcpy(id, id_di[ldb->setting[i].di], sizeof(id));
337                         id[4] += ldb->setting[i].ipu;
338                         if (!strcmp(id, fbi->fix.id))
339                                 return i;
340                 }
341         }
342         return -EINVAL;
343 }
344
345 static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi)
346 {
347         uint32_t reg, val;
348         uint32_t pixel_clk, rounded_pixel_clk;
349         struct clk *ldb_clk_parent;
350         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
351         int setting_idx, di;
352         int ret;
353
354         setting_idx = find_ldb_setting(ldb, fbi);
355         if (setting_idx < 0)
356                 return setting_idx;
357
358         di = ldb->setting[setting_idx].di;
359
360         /* restore channel mode setting */
361         val = readl(ldb->control_reg);
362         val |= ldb->setting[setting_idx].ch_val;
363         writel(val, ldb->control_reg);
364         dev_dbg(&ldb->pdev->dev, "LDB setup, control reg: 0x%08x\n",
365                         readl(ldb->control_reg));
366
367         /* vsync setup */
368         reg = readl(ldb->control_reg);
369         if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) {
370                 if (di == 0)
371                         reg = (reg & ~LDB_DI0_VS_POL_MASK)
372                                 | LDB_DI0_VS_POL_ACT_HIGH;
373                 else
374                         reg = (reg & ~LDB_DI1_VS_POL_MASK)
375                                 | LDB_DI1_VS_POL_ACT_HIGH;
376         } else {
377                 if (di == 0)
378                         reg = (reg & ~LDB_DI0_VS_POL_MASK)
379                                 | LDB_DI0_VS_POL_ACT_LOW;
380                 else
381                         reg = (reg & ~LDB_DI1_VS_POL_MASK)
382                                 | LDB_DI1_VS_POL_ACT_LOW;
383         }
384         writel(reg, ldb->control_reg);
385
386         /* clk setup */
387         if (ldb->setting[setting_idx].clk_en)
388                  clk_disable_unprepare(ldb->setting[setting_idx].ldb_di_clk);
389         pixel_clk = (PICOS2KHZ(fbi->var.pixclock)) * 1000UL;
390         ldb_clk_parent = clk_get_parent(ldb->setting[setting_idx].ldb_di_clk);
391         if (IS_ERR(ldb_clk_parent)) {
392                 dev_err(&ldb->pdev->dev, "get ldb di parent clk fail\n");
393                 return PTR_ERR(ldb_clk_parent);
394         }
395         if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1))
396                 ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7 / 2);
397         else
398                 ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7);
399         if (ret < 0) {
400                 dev_err(&ldb->pdev->dev, "set ldb parent clk fail:%d\n", ret);
401                 return ret;
402         }
403         rounded_pixel_clk = clk_round_rate(ldb->setting[setting_idx].ldb_di_clk,
404                                                 pixel_clk);
405         dev_dbg(&ldb->pdev->dev, "pixel_clk:%d, rounded_pixel_clk:%d\n",
406                         pixel_clk, rounded_pixel_clk);
407         ret = clk_set_rate(ldb->setting[setting_idx].ldb_di_clk,
408                                 rounded_pixel_clk);
409         if (ret < 0) {
410                 dev_err(&ldb->pdev->dev, "set ldb di clk fail:%d\n", ret);
411                 return ret;
412         }
413         ret = clk_prepare_enable(ldb->setting[setting_idx].ldb_di_clk);
414         if (ret < 0) {
415                 dev_err(&ldb->pdev->dev, "enable ldb di clk fail:%d\n", ret);
416                 return ret;
417         }
418
419         if (!ldb->setting[setting_idx].clk_en)
420                 ldb->setting[setting_idx].clk_en = true;
421
422         return 0;
423 }
424
425 int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v)
426 {
427         struct ldb_data *ldb = container_of(nb, struct ldb_data, nb);
428         struct fb_event *event = v;
429         struct fb_info *fbi = event->info;
430         int index;
431         uint32_t data;
432
433         index = find_ldb_setting(ldb, fbi);
434         if (index < 0)
435                 return 0;
436
437         fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var,
438                         &fbi->modelist);
439
440         if (!fbi->mode) {
441                 dev_warn(&ldb->pdev->dev,
442                                 "LDB: can not find mode for xres=%d, yres=%d\n",
443                                 fbi->var.xres, fbi->var.yres);
444                 if (ldb->setting[index].clk_en) {
445                         clk_disable(ldb->setting[index].ldb_di_clk);
446                         ldb->setting[index].clk_en = false;
447                         data = readl(ldb->control_reg);
448                         data &= ~ldb->setting[index].ch_mask;
449                         writel(data, ldb->control_reg);
450                 }
451                 return 0;
452         }
453
454         switch (val) {
455         case FB_EVENT_BLANK:
456         {
457                 if (*((int *)event->data) == FB_BLANK_UNBLANK) {
458                         if (!ldb->setting[index].clk_en) {
459                                 clk_enable(ldb->setting[index].ldb_di_clk);
460                                 ldb->setting[index].clk_en = true;
461                         }
462                 } else {
463                         if (ldb->setting[index].clk_en) {
464                                 clk_disable(ldb->setting[index].ldb_di_clk);
465                                 ldb->setting[index].clk_en = false;
466                                 data = readl(ldb->control_reg);
467                                 data &= ~ldb->setting[index].ch_mask;
468                                 writel(data, ldb->control_reg);
469                                 dev_dbg(&ldb->pdev->dev,
470                                         "LDB blank, control reg: 0x%08x\n",
471                                                 readl(ldb->control_reg));
472                         }
473                 }
474                 break;
475         }
476         case FB_EVENT_SUSPEND:
477                 if (ldb->setting[index].clk_en) {
478                         clk_disable(ldb->setting[index].ldb_di_clk);
479                         ldb->setting[index].clk_en = false;
480                 }
481                 break;
482         default:
483                 break;
484         }
485         return 0;
486 }
487
488 #define LVDS_MUX_CTL_WIDTH      2
489 #define LVDS_MUX_CTL_MASK       3
490 #define LVDS0_MUX_CTL_OFFS      6
491 #define LVDS1_MUX_CTL_OFFS      8
492 #define LVDS0_MUX_CTL_MASK      (LVDS_MUX_CTL_MASK << 6)
493 #define LVDS1_MUX_CTL_MASK      (LVDS_MUX_CTL_MASK << 8)
494 #define ROUTE_IPU_DI(ipu, di)   (((ipu << 1) | di) & LVDS_MUX_CTL_MASK)
495 static int ldb_ipu_ldb_route(int ipu, int di, struct ldb_data *ldb)
496 {
497         uint32_t reg;
498         int channel;
499         int shift;
500         int mode = ldb->mode;
501
502         reg = readl(ldb->gpr3_reg);
503         if (mode < LDB_SIN0) {
504                 reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
505                 reg |= (ROUTE_IPU_DI(ipu, di) << LVDS0_MUX_CTL_OFFS) |
506                         (ROUTE_IPU_DI(ipu, di) << LVDS1_MUX_CTL_OFFS);
507                 dev_dbg(&ldb->pdev->dev,
508                         "Dual/Split mode both channels route to IPU%d-DI%d\n",
509                         ipu + 1, di);
510         } else if ((mode == LDB_SIN0) || (mode == LDB_SIN1)) {
511                 reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
512                 channel = mode - LDB_SIN0;
513                 shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH;
514                 reg |= ROUTE_IPU_DI(ipu, di) << shift;
515                 dev_dbg(&ldb->pdev->dev,
516                         "Single mode channel %d route to IPU%d-DI%d\n",
517                                 channel, ipu + 1, di);
518         } else {
519                 static bool first = true;
520
521                 if (first) {
522                         if (mode == LDB_SEP0) {
523                                 reg &= ~LVDS0_MUX_CTL_MASK;
524                                 channel = 0;
525                         } else {
526                                 reg &= ~LVDS1_MUX_CTL_MASK;
527                                 channel = 1;
528                         }
529                         first = false;
530                 } else {
531                         if (mode == LDB_SEP0) {
532                                 reg &= ~LVDS1_MUX_CTL_MASK;
533                                 channel = 1;
534                         } else {
535                                 reg &= ~LVDS0_MUX_CTL_MASK;
536                                 channel = 0;
537                         }
538                 }
539
540                 shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH;
541                 reg |= ROUTE_IPU_DI(ipu, di) << shift;
542
543                 dev_dbg(&ldb->pdev->dev,
544                         "Separate mode channel %d route to IPU%d-DI%d\n",
545                         channel, ipu + 1, di);
546         }
547         writel(reg, ldb->gpr3_reg);
548
549         return 0;
550 }
551
552 static int ldb_disp_init(struct mxc_dispdrv_handle *disp,
553         struct mxc_dispdrv_setting *setting)
554 {
555         int ret = 0, i, lvds_channel = 0;
556         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
557         struct fsl_mxc_ldb_platform_data *plat_data = ldb->pdev->dev.platform_data;
558         struct resource *res;
559         uint32_t reg, setting_idx;
560         uint32_t ch_mask = 0, ch_val = 0;
561         uint32_t ipu_id, disp_id;
562         char di_clk[] = "ipu1_di0_sel";
563         char ldb_clk[] = "ldb_di0";
564         char div_3_5_clk[] = "di0_div_3_5";
565         char div_7_clk[] = "di0_div_7";
566         char div_sel_clk[] = "di0_div_sel";
567
568         /* if input format not valid, make RGB666 as default*/
569         if (!valid_mode(setting->if_fmt)) {
570                 dev_warn(&ldb->pdev->dev, "Input pixel format not valid use default RGB666\n");
571                 setting->if_fmt = IPU_PIX_FMT_RGB666;
572         }
573
574         if (!ldb->inited) {
575                 setting_idx = 0;
576                 res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0);
577                 if (!res) {
578                         dev_err(&ldb->pdev->dev, "get iomem fail.\n");
579                         return -ENOMEM;
580                 }
581
582                 ldb->reg = devm_ioremap(&ldb->pdev->dev, res->start,
583                                         resource_size(res));
584                 ldb->control_reg = ldb->reg + 2;
585                 ldb->gpr3_reg = ldb->reg + 3;
586
587                 /* ipu selected by platform data setting */
588                 setting->dev_id = plat_data->ipu_id;
589
590                 reg = readl(ldb->control_reg);
591
592                 /* reference resistor select */
593                 reg &= ~LDB_BGREF_RMODE_MASK;
594                 if (plat_data->ext_ref)
595                         reg |= LDB_BGREF_RMODE_EXT;
596                 else
597                         reg |= LDB_BGREF_RMODE_INT;
598
599                 /* TODO: now only use SPWG data mapping for both channel */
600                 reg &= ~(LDB_BIT_MAP_CH0_MASK | LDB_BIT_MAP_CH1_MASK);
601                 reg |= LDB_BIT_MAP_CH0_SPWG | LDB_BIT_MAP_CH1_SPWG;
602
603                 /* channel mode setting */
604                 reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
605                 reg &= ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK);
606
607                 if (bits_per_pixel(setting->if_fmt) == 24)
608                         reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24;
609                 else
610                         reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18;
611
612                 if (g_ldb_mode >= LDB_SPL_DI0)
613                         ldb->mode = g_ldb_mode;
614                 else
615                         ldb->mode = plat_data->mode;
616
617                 if ((ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) {
618                         ret = ldb->mode - LDB_SIN0;
619                         if (plat_data->disp_id != ret) {
620                                 dev_warn(&ldb->pdev->dev,
621                                         "change IPU DI%d to IPU DI%d for LDB channel%d.\n",
622                                         plat_data->disp_id, ret, ret);
623                                 plat_data->disp_id = ret;
624                         }
625                 } else if (((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))
626                                 && is_imx6_ldb(plat_data)) {
627                         if (plat_data->ipu_id == plat_data->sec_ipu_id &&
628                                 plat_data->disp_id == plat_data->sec_disp_id) {
629                                 dev_err(&ldb->pdev->dev,
630                                         "For LVDS separate mode, two DIs should be different!\n");
631                                 return -EINVAL;
632                         }
633
634                         if ((!plat_data->disp_id && ldb->mode == LDB_SEP1) ||
635                                 (plat_data->disp_id && ldb->mode == LDB_SEP0)) {
636                                 dev_dbg(&ldb->pdev->dev,
637                                         "LVDS separate mode: swap DI configuration!\n");
638                                 ipu_id = plat_data->ipu_id;
639                                 disp_id = plat_data->disp_id;
640                                 plat_data->ipu_id = plat_data->sec_ipu_id;
641                                 plat_data->disp_id = plat_data->sec_disp_id;
642                                 plat_data->sec_ipu_id = ipu_id;
643                                 plat_data->sec_disp_id = disp_id;
644                         }
645                 }
646
647                 if (ldb->mode == LDB_SPL_DI0) {
648                         reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI0
649                                 | LDB_CH1_MODE_EN_TO_DI0;
650                         setting->disp_id = 0;
651                 } else if (ldb->mode == LDB_SPL_DI1) {
652                         reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI1
653                                 | LDB_CH1_MODE_EN_TO_DI1;
654                         setting->disp_id = 1;
655                 } else if (ldb->mode == LDB_DUL_DI0) {
656                         reg &= ~LDB_SPLIT_MODE_EN;
657                         reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0;
658                         setting->disp_id = 0;
659                 } else if (ldb->mode == LDB_DUL_DI1) {
660                         reg &= ~LDB_SPLIT_MODE_EN;
661                         reg |= LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1;
662                         setting->disp_id = 1;
663                 } else if (ldb->mode == LDB_SIN0) {
664                         reg &= ~LDB_SPLIT_MODE_EN;
665                         setting->disp_id = plat_data->disp_id;
666                         if (setting->disp_id == 0)
667                                 reg |= LDB_CH0_MODE_EN_TO_DI0;
668                         else
669                                 reg |= LDB_CH0_MODE_EN_TO_DI1;
670                         ch_mask = LDB_CH0_MODE_MASK;
671                         ch_val = reg & LDB_CH0_MODE_MASK;
672                 } else if (ldb->mode == LDB_SIN1) {
673                         reg &= ~LDB_SPLIT_MODE_EN;
674                         setting->disp_id = plat_data->disp_id;
675                         if (setting->disp_id == 0)
676                                 reg |= LDB_CH1_MODE_EN_TO_DI0;
677                         else
678                                 reg |= LDB_CH1_MODE_EN_TO_DI1;
679                         ch_mask = LDB_CH1_MODE_MASK;
680                         ch_val = reg & LDB_CH1_MODE_MASK;
681                 } else { /* separate mode */
682                         setting->disp_id = plat_data->disp_id;
683
684                         /* first output is LVDS0 or LVDS1 */
685                         if (ldb->mode == LDB_SEP0)
686                                 lvds_channel = 0;
687                         else
688                                 lvds_channel = 1;
689
690                         reg &= ~LDB_SPLIT_MODE_EN;
691
692                         if ((lvds_channel == 0) && (setting->disp_id == 0))
693                                 reg |= LDB_CH0_MODE_EN_TO_DI0;
694                         else if ((lvds_channel == 0) && (setting->disp_id == 1))
695                                 reg |= LDB_CH0_MODE_EN_TO_DI1;
696                         else if ((lvds_channel == 1) && (setting->disp_id == 0))
697                                 reg |= LDB_CH1_MODE_EN_TO_DI0;
698                         else
699                                 reg |= LDB_CH1_MODE_EN_TO_DI1;
700                         ch_mask = lvds_channel ? LDB_CH1_MODE_MASK :
701                                         LDB_CH0_MODE_MASK;
702                         ch_val = reg & ch_mask;
703
704                         if (bits_per_pixel(setting->if_fmt) == 24) {
705                                 if (lvds_channel == 0)
706                                         reg &= ~LDB_DATA_WIDTH_CH1_24;
707                                 else
708                                         reg &= ~LDB_DATA_WIDTH_CH0_24;
709                         } else {
710                                 if (lvds_channel == 0)
711                                         reg &= ~LDB_DATA_WIDTH_CH1_18;
712                                 else
713                                         reg &= ~LDB_DATA_WIDTH_CH0_18;
714                         }
715                 }
716
717                 writel(reg, ldb->control_reg);
718                 if (ldb->mode <  LDB_SIN0) {
719                         ch_mask = LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK;
720                         ch_val = reg & (LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
721                 }
722         } else { /* second time for separate mode */
723                 if ((ldb->mode == LDB_SPL_DI0) ||
724                         (ldb->mode == LDB_SPL_DI1) ||
725                         (ldb->mode == LDB_DUL_DI0) ||
726                         (ldb->mode == LDB_DUL_DI1) ||
727                         (ldb->mode == LDB_SIN0) ||
728                         (ldb->mode == LDB_SIN1)) {
729                         dev_err(&ldb->pdev->dev, "for second ldb disp ldb mode should be in separate mode\n");
730                         return -EINVAL;
731                 }
732
733                 setting_idx = 1;
734                 if (is_imx6_ldb(plat_data)) {
735                         setting->dev_id = plat_data->sec_ipu_id;
736                         setting->disp_id = plat_data->sec_disp_id;
737                 } else {
738                         setting->dev_id = plat_data->ipu_id;
739                         setting->disp_id = !plat_data->disp_id;
740                 }
741                 if (setting->dev_id == ldb->setting[0].ipu &&
742                         setting->disp_id == ldb->setting[0].di) {
743                         dev_err(&ldb->pdev->dev, "Err: for second ldb disp in separate mode, DI should be different!\n");
744                         return -EINVAL;
745                 }
746
747                 /* second output is LVDS0 or LVDS1 */
748                 if (ldb->mode == LDB_SEP0)
749                         lvds_channel = 1;
750                 else
751                         lvds_channel = 0;
752
753                 reg = readl(ldb->control_reg);
754                 if ((lvds_channel == 0) && (setting->disp_id == 0))
755                         reg |= LDB_CH0_MODE_EN_TO_DI0;
756                 else if ((lvds_channel == 0) && (setting->disp_id == 1))
757                         reg |= LDB_CH0_MODE_EN_TO_DI1;
758                 else if ((lvds_channel == 1) && (setting->disp_id == 0))
759                         reg |= LDB_CH1_MODE_EN_TO_DI0;
760                 else
761                         reg |= LDB_CH1_MODE_EN_TO_DI1;
762                 ch_mask = lvds_channel ?  LDB_CH1_MODE_MASK :
763                                 LDB_CH0_MODE_MASK;
764                 ch_val = reg & ch_mask;
765
766                 if (bits_per_pixel(setting->if_fmt) == 24) {
767                         if (lvds_channel == 0)
768                                 reg |= LDB_DATA_WIDTH_CH0_24;
769                         else
770                                 reg |= LDB_DATA_WIDTH_CH1_24;
771                 } else {
772                         if (lvds_channel == 0)
773                                 reg |= LDB_DATA_WIDTH_CH0_18;
774                         else
775                                 reg |= LDB_DATA_WIDTH_CH1_18;
776                 }
777                 writel(reg, ldb->control_reg);
778         }
779
780         /* get clocks */
781         if (is_imx6_ldb(plat_data) &&
782                 ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))) {
783                 ldb_clk[6] += lvds_channel;
784                 div_3_5_clk[2] += lvds_channel;
785                 div_7_clk[2] += lvds_channel;
786                 div_sel_clk[2] += lvds_channel;
787         } else {
788                 ldb_clk[6] += setting->disp_id;
789                 div_3_5_clk[2] += setting->disp_id;
790                 div_7_clk[2] += setting->disp_id;
791                 div_sel_clk[2] += setting->disp_id;
792         }
793         ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev,
794                                                         ldb_clk);
795         if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) {
796                 dev_err(&ldb->pdev->dev, "Failed to get %s clk: %ld\n",
797                         ldb_clk, PTR_ERR(ldb->setting[setting_idx].ldb_di_clk));
798                 return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk);
799         }
800
801         ldb->setting[setting_idx].div_3_5_clk = clk_get(&ldb->pdev->dev,
802                                                         div_3_5_clk);
803         if (IS_ERR(ldb->setting[setting_idx].div_3_5_clk)) {
804                 dev_err(&ldb->pdev->dev, "Failed to get %s clk: %ld\n",
805                         div_3_5_clk, PTR_ERR(ldb->setting[setting_idx].div_3_5_clk));
806                 return PTR_ERR(ldb->setting[setting_idx].div_3_5_clk);
807         }
808         ldb->setting[setting_idx].div_7_clk = clk_get(&ldb->pdev->dev,
809                                                         div_7_clk);
810         if (IS_ERR(ldb->setting[setting_idx].div_7_clk)) {
811                 dev_err(&ldb->pdev->dev, "Failed to get %s clk: %ld\n",
812                         div_7_clk, PTR_ERR(ldb->setting[setting_idx].div_7_clk));
813                 return PTR_ERR(ldb->setting[setting_idx].div_7_clk);
814         }
815
816         ldb->setting[setting_idx].div_sel_clk = clk_get(&ldb->pdev->dev,
817                                                         div_sel_clk);
818         if (IS_ERR(ldb->setting[setting_idx].div_sel_clk)) {
819                 dev_err(&ldb->pdev->dev, "Failed to get %s clk: %ld\n",
820                         div_sel_clk, PTR_ERR(ldb->setting[setting_idx].div_sel_clk));
821                 return PTR_ERR(ldb->setting[setting_idx].div_sel_clk);
822         }
823
824         di_clk[3] += setting->dev_id;
825         di_clk[7] += setting->disp_id;
826         ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev,
827                                                         di_clk);
828         if (IS_ERR(ldb->setting[setting_idx].di_clk)) {
829                 dev_err(&ldb->pdev->dev, "Failed to get %s clk: %ld\n",
830                         di_clk, PTR_ERR(ldb->setting[setting_idx].di_clk));
831                 return PTR_ERR(ldb->setting[setting_idx].di_clk);
832         }
833
834         ldb->setting[setting_idx].ch_mask = ch_mask;
835         ldb->setting[setting_idx].ch_val = ch_val;
836
837         if (is_imx6_ldb(plat_data))
838                 ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb);
839
840         if (setting->fbmode) {
841                 ldb_modedb[0] = *setting->fbmode;
842                 ldb_modedb_sz = 1;
843         }
844
845         /* must use spec video mode defined by driver */
846         ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str,
847                                 ldb_modedb, ldb_modedb_sz, NULL, setting->default_bpp);
848         if (ret != 1)
849                 fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]);
850
851         INIT_LIST_HEAD(&setting->fbi->modelist);
852         for (i = 0; i < ldb_modedb_sz; i++) {
853                 struct fb_videomode m;
854                 fb_var_to_videomode(&m, &setting->fbi->var);
855                 if (fb_mode_is_equal(&m, &ldb_modedb[i])) {
856                         fb_add_videomode(&ldb_modedb[i],
857                                         &setting->fbi->modelist);
858                         break;
859                 }
860         }
861
862         ldb->setting[setting_idx].ipu = setting->dev_id;
863         ldb->setting[setting_idx].di = setting->disp_id;
864
865         return ret;
866 }
867
868 static int ldb_post_disp_init(struct mxc_dispdrv_handle *disp,
869                                 int ipu_id, int disp_id)
870 {
871         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
872         int setting_idx = ldb->inited ? 1 : 0;
873         int ret = 0;
874
875         if (!ldb->inited) {
876                 ldb->nb.notifier_call = ldb_fb_event;
877                 fb_register_client(&ldb->nb);
878         }
879
880         ret = clk_set_parent(ldb->setting[setting_idx].di_clk,
881                         ldb->setting[setting_idx].ldb_di_clk);
882         if (ret) {
883                 dev_err(&ldb->pdev->dev, "fail to set ldb_di clk as the parent of ipu_di clk\n");
884                 return ret;
885         }
886
887         if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1)) {
888                 ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk,
889                                 ldb->setting[setting_idx].div_3_5_clk);
890                 if (ret) {
891                         dev_err(&ldb->pdev->dev, "fail to set div 3.5 clk as the parent of div sel clk\n");
892                         return ret;
893                 }
894         } else {
895                 ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk,
896                                 ldb->setting[setting_idx].div_7_clk);
897                 if (ret) {
898                         dev_err(&ldb->pdev->dev, "fail to set div 7 clk as the parent of div sel clk\n");
899                         return ret;
900                 }
901         }
902
903         /* save active ldb setting for fb notifier */
904         ldb->setting[setting_idx].active = true;
905
906         ldb->inited = true;
907         return ret;
908 }
909
910 static void ldb_disp_deinit(struct mxc_dispdrv_handle *disp)
911 {
912         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
913         int i;
914
915         writel(0, ldb->control_reg);
916
917         for (i = 0; i < 2; i++) {
918                 clk_disable(ldb->setting[i].ldb_di_clk);
919                 clk_put(ldb->setting[i].ldb_di_clk);
920                 clk_put(ldb->setting[i].div_3_5_clk);
921                 clk_put(ldb->setting[i].div_7_clk);
922                 clk_put(ldb->setting[i].div_sel_clk);
923         }
924
925         fb_unregister_client(&ldb->nb);
926 }
927
928 static struct mxc_dispdrv_driver ldb_drv = {
929         .name   = DISPDRV_LDB,
930         .init   = ldb_disp_init,
931         .post_init = ldb_post_disp_init,
932         .deinit = ldb_disp_deinit,
933         .setup = ldb_disp_setup,
934 };
935
936 static int ldb_suspend(struct platform_device *pdev, pm_message_t state)
937 {
938         struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
939         uint32_t        data;
940
941         if (!ldb->inited)
942                 return 0;
943         data = readl(ldb->control_reg);
944         ldb->control_reg_data = data;
945         data &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
946         writel(data, ldb->control_reg);
947
948         return 0;
949 }
950
951 static int ldb_resume(struct platform_device *pdev)
952 {
953         struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
954
955         if (!ldb->inited)
956                 return 0;
957         writel(ldb->control_reg_data, ldb->control_reg);
958
959         return 0;
960 }
961
962 static struct platform_device_id imx_ldb_devtype[] = {
963         { "ldb-imx6", LDB_IMX6, },
964         { /* sentinel */ }
965 };
966
967 static const struct of_device_id imx_ldb_dt_ids[] = {
968         { .compatible = "fsl,imx6q-ldb", .data = &imx_ldb_devtype[IMX6_LDB],},
969         { /* sentinel */ }
970 };
971
972 /*!
973  * This function is called by the driver framework to initialize the LDB
974  * device.
975  *
976  * @param       dev     The device structure for the LDB passed in by the
977  *                      driver framework.
978  *
979  * @return      Returns 0 on success or negative error code on error
980  */
981 static int ldb_probe(struct platform_device *pdev)
982 {
983         int ret = 0;
984         struct ldb_data *ldb;
985         struct fsl_mxc_ldb_platform_data *plat_data;
986         const struct of_device_id *of_id =
987                         of_match_device(imx_ldb_dt_ids, &pdev->dev);
988
989         dev_dbg(&pdev->dev, "%s enter\n", __func__);
990         ldb = devm_kzalloc(&pdev->dev, sizeof(struct ldb_data), GFP_KERNEL);
991         if (!ldb)
992                 return -ENOMEM;
993
994         plat_data = devm_kzalloc(&pdev->dev,
995                                 sizeof(struct fsl_mxc_ldb_platform_data),
996                                 GFP_KERNEL);
997         if (!plat_data)
998                 return -ENOMEM;
999         pdev->dev.platform_data = plat_data;
1000         if (of_id)
1001                 pdev->id_entry = of_id->data;
1002         plat_data->devtype = pdev->id_entry->driver_data;
1003
1004         ret = ldb_get_of_property(pdev, plat_data);
1005         if (ret < 0) {
1006                 dev_err(&pdev->dev, "get ldb of property fail\n");
1007                 return ret;
1008         }
1009
1010         ldb->pdev = pdev;
1011         ldb->disp_ldb = mxc_dispdrv_register(&ldb_drv);
1012         mxc_dispdrv_setdata(ldb->disp_ldb, ldb);
1013
1014         dev_set_drvdata(&pdev->dev, ldb);
1015
1016         dev_dbg(&pdev->dev, "%s exit\n", __func__);
1017         return ret;
1018 }
1019
1020 static int ldb_remove(struct platform_device *pdev)
1021 {
1022         struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
1023
1024         if (!ldb->inited)
1025                 return 0;
1026         mxc_dispdrv_puthandle(ldb->disp_ldb);
1027         mxc_dispdrv_unregister(ldb->disp_ldb);
1028         return 0;
1029 }
1030
1031 static struct platform_driver mxcldb_driver = {
1032         .driver = {
1033                 .name = "mxc_ldb",
1034                 .of_match_table = imx_ldb_dt_ids,
1035         },
1036         .probe = ldb_probe,
1037         .remove = ldb_remove,
1038         .suspend = ldb_suspend,
1039         .resume = ldb_resume,
1040 };
1041
1042 static int __init ldb_init(void)
1043 {
1044         return platform_driver_register(&mxcldb_driver);
1045 }
1046
1047 static void __exit ldb_uninit(void)
1048 {
1049         platform_driver_unregister(&mxcldb_driver);
1050 }
1051
1052 module_init(ldb_init);
1053 module_exit(ldb_uninit);
1054
1055 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1056 MODULE_DESCRIPTION("MXC LDB driver");
1057 MODULE_LICENSE("GPL");