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