]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/video/mxc/ldb.c
video: mxc: print error messages with dev_err() rather than dev_dbg()
[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 "mxc_dispdrv.h"
42
43 #define DISPDRV_LDB     "ldb"
44
45 #define LDB_BGREF_RMODE_MASK            0x00008000
46 #define LDB_BGREF_RMODE_INT             0x00008000
47 #define LDB_BGREF_RMODE_EXT             0x0
48
49 #define LDB_DI1_VS_POL_MASK             0x00000400
50 #define LDB_DI1_VS_POL_ACT_LOW          0x00000400
51 #define LDB_DI1_VS_POL_ACT_HIGH         0x0
52 #define LDB_DI0_VS_POL_MASK             0x00000200
53 #define LDB_DI0_VS_POL_ACT_LOW          0x00000200
54 #define LDB_DI0_VS_POL_ACT_HIGH         0x0
55
56 #define LDB_BIT_MAP_CH1_MASK            0x00000100
57 #define LDB_BIT_MAP_CH1_JEIDA           0x00000100
58 #define LDB_BIT_MAP_CH1_SPWG            0x0
59 #define LDB_BIT_MAP_CH0_MASK            0x00000040
60 #define LDB_BIT_MAP_CH0_JEIDA           0x00000040
61 #define LDB_BIT_MAP_CH0_SPWG            0x0
62
63 #define LDB_DATA_WIDTH_CH1_MASK         0x00000080
64 #define LDB_DATA_WIDTH_CH1_24           0x00000080
65 #define LDB_DATA_WIDTH_CH1_18           0x0
66 #define LDB_DATA_WIDTH_CH0_MASK         0x00000020
67 #define LDB_DATA_WIDTH_CH0_24           0x00000020
68 #define LDB_DATA_WIDTH_CH0_18           0x0
69
70 #define LDB_CH1_MODE_MASK               0x0000000C
71 #define LDB_CH1_MODE_EN_TO_DI1          0x0000000C
72 #define LDB_CH1_MODE_EN_TO_DI0          0x00000004
73 #define LDB_CH1_MODE_DISABLE            0x0
74 #define LDB_CH0_MODE_MASK               0x00000003
75 #define LDB_CH0_MODE_EN_TO_DI1          0x00000003
76 #define LDB_CH0_MODE_EN_TO_DI0          0x00000001
77 #define LDB_CH0_MODE_DISABLE            0x0
78
79 #define LDB_SPLIT_MODE_EN               0x00000010
80
81 enum {
82         IMX6_LDB,
83 };
84
85 enum {
86         LDB_IMX6 = 1,
87 };
88
89 struct fsl_mxc_ldb_platform_data {
90         int devtype;
91         u32 ext_ref;
92 #define LDB_SPL_DI0     1
93 #define LDB_SPL_DI1     2
94 #define LDB_DUL_DI0     3
95 #define LDB_DUL_DI1     4
96 #define LDB_SIN0        5
97 #define LDB_SIN1        6
98 #define LDB_SEP0        7
99 #define LDB_SEP1        8
100         int mode;
101         int ipu_id;
102         int disp_id;
103
104         /*only work for separate mode*/
105         int sec_ipu_id;
106         int sec_disp_id;
107 };
108
109 struct ldb_data {
110         struct platform_device *pdev;
111         struct mxc_dispdrv_handle *disp_ldb;
112         uint32_t *reg;
113         uint32_t *control_reg;
114         uint32_t *gpr3_reg;
115         uint32_t control_reg_data;
116         struct regulator *lvds_bg_reg;
117         int mode;
118         bool inited;
119         struct ldb_setting {
120                 struct clk *di_clk;
121                 struct clk *ldb_di_clk;
122                 struct clk *div_3_5_clk;
123                 struct clk *div_7_clk;
124                 struct clk *div_sel_clk;
125                 bool active;
126                 bool clk_en;
127                 int ipu;
128                 int di;
129                 uint32_t ch_mask;
130                 uint32_t ch_val;
131         } setting[2];
132         struct notifier_block nb;
133 };
134
135 static int g_ldb_mode;
136
137 static struct fb_videomode ldb_modedb[] = {
138         {
139          "LDB-WXGA", 60, 1280, 800, 14065,
140          40, 40,
141          10, 3,
142          80, 10,
143          0,
144          FB_VMODE_NONINTERLACED,
145          FB_MODE_IS_DETAILED,},
146         {
147          "LDB-XGA", 60, 1024, 768, 15385,
148          220, 40,
149          21, 7,
150          60, 10,
151          0,
152          FB_VMODE_NONINTERLACED,
153          FB_MODE_IS_DETAILED,},
154         {
155          "LDB-1080P60", 60, 1920, 1080, 7692,
156          100, 40,
157          30, 3,
158          10, 2,
159          0,
160          FB_VMODE_NONINTERLACED,
161          FB_MODE_IS_DETAILED,},
162 };
163 static int ldb_modedb_sz = ARRAY_SIZE(ldb_modedb);
164
165 static inline int is_imx6_ldb(struct fsl_mxc_ldb_platform_data *plat_data)
166 {
167         return (plat_data->devtype == LDB_IMX6);
168 }
169
170 static int bits_per_pixel(int pixel_fmt)
171 {
172         switch (pixel_fmt) {
173         case IPU_PIX_FMT_BGR24:
174         case IPU_PIX_FMT_RGB24:
175                 return 24;
176                 break;
177         case IPU_PIX_FMT_BGR666:
178         case IPU_PIX_FMT_RGB666:
179         case IPU_PIX_FMT_LVDS666:
180                 return 18;
181                 break;
182         default:
183                 break;
184         }
185         return 0;
186 }
187
188 static int valid_mode(int pixel_fmt)
189 {
190         return ((pixel_fmt == IPU_PIX_FMT_RGB24) ||
191                 (pixel_fmt == IPU_PIX_FMT_BGR24) ||
192                 (pixel_fmt == IPU_PIX_FMT_LVDS666) ||
193                 (pixel_fmt == IPU_PIX_FMT_RGB666) ||
194                 (pixel_fmt == IPU_PIX_FMT_BGR666));
195 }
196
197 static int parse_ldb_mode(char *mode)
198 {
199         int ldb_mode;
200
201         if (!strcmp(mode, "spl0"))
202                 ldb_mode = LDB_SPL_DI0;
203         else if (!strcmp(mode, "spl1"))
204                 ldb_mode = LDB_SPL_DI1;
205         else if (!strcmp(mode, "dul0"))
206                 ldb_mode = LDB_DUL_DI0;
207         else if (!strcmp(mode, "dul1"))
208                 ldb_mode = LDB_DUL_DI1;
209         else if (!strcmp(mode, "sin0"))
210                 ldb_mode = LDB_SIN0;
211         else if (!strcmp(mode, "sin1"))
212                 ldb_mode = LDB_SIN1;
213         else if (!strcmp(mode, "sep0"))
214                 ldb_mode = LDB_SEP0;
215         else if (!strcmp(mode, "sep1"))
216                 ldb_mode = LDB_SEP1;
217         else
218                 ldb_mode = -EINVAL;
219
220         return ldb_mode;
221 }
222
223 #ifndef MODULE
224 /*
225  *    "ldb=spl0/1"       --      split mode on DI0/1
226  *    "ldb=dul0/1"       --      dual mode on DI0/1
227  *    "ldb=sin0/1"       --      single mode on LVDS0/1
228  *    "ldb=sep0/1"       --      separate mode begin from LVDS0/1
229  *
230  *    there are two LVDS channels(LVDS0 and LVDS1) which can transfer video
231  *    datas, there two channels can be used as split/dual/single/separate mode.
232  *
233  *    split mode means display data from DI0 or DI1 will send to both channels
234  *    LVDS0+LVDS1.
235  *    dual mode means display data from DI0 or DI1 will be duplicated on LVDS0
236  *    and LVDS1, it said, LVDS0 and LVDS1 has the same content.
237  *    single mode means only work for DI0/DI1->LVDS0 or DI0/DI1->LVDS1.
238  *    separate mode means you can make DI0/DI1->LVDS0 and DI0/DI1->LVDS1 work
239  *    at the same time.
240  */
241 static int __init ldb_setup(char *options)
242 {
243         g_ldb_mode = parse_ldb_mode(options);
244         return (g_ldb_mode < 0) ? 0 : 1;
245 }
246 __setup("ldb=", ldb_setup);
247 #endif
248
249 static int ldb_get_of_property(struct platform_device *pdev,
250                                 struct fsl_mxc_ldb_platform_data *plat_data)
251 {
252         struct device_node *np = pdev->dev.of_node;
253         int err;
254         u32 ipu_id, disp_id;
255         u32 sec_ipu_id, sec_disp_id;
256         char *mode;
257         u32 ext_ref;
258
259         err = of_property_read_string(np, "mode", (const char **)&mode);
260         if (err) {
261                 dev_err(&pdev->dev, "get of property mode fail\n");
262                 return err;
263         }
264         err = of_property_read_u32(np, "ext_ref", &ext_ref);
265         if (err) {
266                 dev_err(&pdev->dev, "get of property ext_ref fail\n");
267                 return err;
268         }
269         err = of_property_read_u32(np, "ipu_id", &ipu_id);
270         if (err) {
271                 dev_err(&pdev->dev, "get of property ipu_id fail\n");
272                 return err;
273         }
274         err = of_property_read_u32(np, "disp_id", &disp_id);
275         if (err) {
276                 dev_err(&pdev->dev, "get of property disp_id fail\n");
277                 return err;
278         }
279         err = of_property_read_u32(np, "sec_ipu_id", &sec_ipu_id);
280         if (err) {
281                 dev_err(&pdev->dev, "get of property sec_ipu_id fail\n");
282                 return err;
283         }
284         err = of_property_read_u32(np, "sec_disp_id", &sec_disp_id);
285         if (err) {
286                 dev_err(&pdev->dev, "get of property sec_disp_id fail\n");
287                 return err;
288         }
289
290         plat_data->mode = parse_ldb_mode(mode);
291         plat_data->ext_ref = ext_ref;
292         plat_data->ipu_id = ipu_id;
293         plat_data->disp_id = disp_id;
294         plat_data->sec_ipu_id = sec_ipu_id;
295         plat_data->sec_disp_id = sec_disp_id;
296
297         return err;
298 }
299
300 static int find_ldb_setting(struct ldb_data *ldb, struct fb_info *fbi)
301 {
302         char *id_di[] = {
303                  "DISP3 BG",
304                  "DISP3 BG - DI1",
305                 };
306         char id[16];
307         int i;
308
309         for (i = 0; i < 2; i++) {
310                 if (ldb->setting[i].active) {
311                         memset(id, 0, 16);
312                         memcpy(id, id_di[ldb->setting[i].di],
313                                 strlen(id_di[ldb->setting[i].di]));
314                         id[4] += ldb->setting[i].ipu;
315                         if (!strcmp(id, fbi->fix.id))
316                                 return i;
317                 }
318         }
319         return -EINVAL;
320 }
321
322 static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi)
323 {
324         uint32_t reg, val;
325         uint32_t pixel_clk, rounded_pixel_clk;
326         struct clk *ldb_clk_parent;
327         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
328         int setting_idx, di;
329         int ret;
330
331         setting_idx = find_ldb_setting(ldb, fbi);
332         if (setting_idx < 0)
333                 return setting_idx;
334
335         di = ldb->setting[setting_idx].di;
336
337         /* restore channel mode setting */
338         val = readl(ldb->control_reg);
339         val |= ldb->setting[setting_idx].ch_val;
340         writel(val, ldb->control_reg);
341         dev_dbg(&ldb->pdev->dev, "LDB setup, control reg:0x%x\n",
342                         readl(ldb->control_reg));
343
344         /* vsync setup */
345         reg = readl(ldb->control_reg);
346         if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) {
347                 if (di == 0)
348                         reg = (reg & ~LDB_DI0_VS_POL_MASK)
349                                 | LDB_DI0_VS_POL_ACT_HIGH;
350                 else
351                         reg = (reg & ~LDB_DI1_VS_POL_MASK)
352                                 | LDB_DI1_VS_POL_ACT_HIGH;
353         } else {
354                 if (di == 0)
355                         reg = (reg & ~LDB_DI0_VS_POL_MASK)
356                                 | LDB_DI0_VS_POL_ACT_LOW;
357                 else
358                         reg = (reg & ~LDB_DI1_VS_POL_MASK)
359                                 | LDB_DI1_VS_POL_ACT_LOW;
360         }
361         writel(reg, ldb->control_reg);
362
363         /* clk setup */
364         if (ldb->setting[setting_idx].clk_en)
365                  clk_disable_unprepare(ldb->setting[setting_idx].ldb_di_clk);
366         pixel_clk = (PICOS2KHZ(fbi->var.pixclock)) * 1000UL;
367         ldb_clk_parent = clk_get_parent(ldb->setting[setting_idx].ldb_di_clk);
368         if (IS_ERR(ldb_clk_parent)) {
369                 dev_err(&ldb->pdev->dev, "get ldb di parent clk fail\n");
370                 return PTR_ERR(ldb_clk_parent);
371         }
372         if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1))
373                 ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7 / 2);
374         else
375                 ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7);
376         if (ret < 0) {
377                 dev_err(&ldb->pdev->dev, "set ldb parent clk fail:%d\n", ret);
378                 return ret;
379         }
380         rounded_pixel_clk = clk_round_rate(ldb->setting[setting_idx].ldb_di_clk,
381                                                 pixel_clk);
382         dev_dbg(&ldb->pdev->dev, "pixel_clk:%d, rounded_pixel_clk:%d\n",
383                         pixel_clk, rounded_pixel_clk);
384         ret = clk_set_rate(ldb->setting[setting_idx].ldb_di_clk,
385                                 rounded_pixel_clk);
386         if (ret < 0) {
387                 dev_err(&ldb->pdev->dev, "set ldb di clk fail:%d\n", ret);
388                 return ret;
389         }
390         ret = clk_prepare_enable(ldb->setting[setting_idx].ldb_di_clk);
391         if (ret < 0) {
392                 dev_err(&ldb->pdev->dev, "enable ldb di clk fail:%d\n", ret);
393                 return ret;
394         }
395
396         if (!ldb->setting[setting_idx].clk_en)
397                 ldb->setting[setting_idx].clk_en = true;
398
399         return 0;
400 }
401
402 int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v)
403 {
404         struct ldb_data *ldb = container_of(nb, struct ldb_data, nb);
405         struct fb_event *event = v;
406         struct fb_info *fbi = event->info;
407         int index;
408         uint32_t data;
409
410         index = find_ldb_setting(ldb, fbi);
411         if (index < 0)
412                 return 0;
413
414         fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var,
415                         &fbi->modelist);
416
417         if (!fbi->mode) {
418                 dev_warn(&ldb->pdev->dev,
419                                 "LDB: can not find mode for xres=%d, yres=%d\n",
420                                 fbi->var.xres, fbi->var.yres);
421                 if (ldb->setting[index].clk_en) {
422                         clk_disable(ldb->setting[index].ldb_di_clk);
423                         ldb->setting[index].clk_en = false;
424                         data = readl(ldb->control_reg);
425                         data &= ~ldb->setting[index].ch_mask;
426                         writel(data, ldb->control_reg);
427                 }
428                 return 0;
429         }
430
431         switch (val) {
432         case FB_EVENT_BLANK:
433         {
434                 if (*((int *)event->data) == FB_BLANK_UNBLANK) {
435                         if (!ldb->setting[index].clk_en) {
436                                 clk_enable(ldb->setting[index].ldb_di_clk);
437                                 ldb->setting[index].clk_en = true;
438                         }
439                 } else {
440                         if (ldb->setting[index].clk_en) {
441                                 clk_disable(ldb->setting[index].ldb_di_clk);
442                                 ldb->setting[index].clk_en = false;
443                                 data = readl(ldb->control_reg);
444                                 data &= ~ldb->setting[index].ch_mask;
445                                 writel(data, ldb->control_reg);
446                                 dev_dbg(&ldb->pdev->dev,
447                                         "LDB blank, control reg:0x%x\n",
448                                                 readl(ldb->control_reg));
449                         }
450                 }
451                 break;
452         }
453         case FB_EVENT_SUSPEND:
454                 if (ldb->setting[index].clk_en) {
455                         clk_disable(ldb->setting[index].ldb_di_clk);
456                         ldb->setting[index].clk_en = false;
457                 }
458                 break;
459         default:
460                 break;
461         }
462         return 0;
463 }
464
465 #define LVDS_MUX_CTL_WIDTH      2
466 #define LVDS_MUX_CTL_MASK       3
467 #define LVDS0_MUX_CTL_OFFS      6
468 #define LVDS1_MUX_CTL_OFFS      8
469 #define LVDS0_MUX_CTL_MASK      (LVDS_MUX_CTL_MASK << 6)
470 #define LVDS1_MUX_CTL_MASK      (LVDS_MUX_CTL_MASK << 8)
471 #define ROUTE_IPU_DI(ipu, di)   (((ipu << 1) | di) & LVDS_MUX_CTL_MASK)
472 static int ldb_ipu_ldb_route(int ipu, int di, struct ldb_data *ldb)
473 {
474         uint32_t reg;
475         int channel;
476         int shift;
477         int mode = ldb->mode;
478
479         reg = readl(ldb->gpr3_reg);
480         if (mode < LDB_SIN0) {
481                 reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
482                 reg |= (ROUTE_IPU_DI(ipu, di) << LVDS0_MUX_CTL_OFFS) |
483                         (ROUTE_IPU_DI(ipu, di) << LVDS1_MUX_CTL_OFFS);
484                 dev_dbg(&ldb->pdev->dev,
485                         "Dual/Split mode both channels route to IPU%d-DI%d\n",
486                         ipu, di);
487         } else if ((mode == LDB_SIN0) || (mode == LDB_SIN1)) {
488                 reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
489                 channel = mode - LDB_SIN0;
490                 shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH;
491                 reg |= ROUTE_IPU_DI(ipu, di) << shift;
492                 dev_dbg(&ldb->pdev->dev,
493                         "Single mode channel %d route to IPU%d-DI%d\n",
494                                 channel, ipu, di);
495         } else {
496                 static bool first = true;
497
498                 if (first) {
499                         if (mode == LDB_SEP0) {
500                                 reg &= ~LVDS0_MUX_CTL_MASK;
501                                 channel = 0;
502                         } else {
503                                 reg &= ~LVDS1_MUX_CTL_MASK;
504                                 channel = 1;
505                         }
506                         first = false;
507                 } else {
508                         if (mode == LDB_SEP0) {
509                                 reg &= ~LVDS1_MUX_CTL_MASK;
510                                 channel = 1;
511                         } else {
512                                 reg &= ~LVDS0_MUX_CTL_MASK;
513                                 channel = 0;
514                         }
515                 }
516
517                 shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH;
518                 reg |= ROUTE_IPU_DI(ipu, di) << shift;
519
520                 dev_dbg(&ldb->pdev->dev,
521                         "Separate mode channel %d route to IPU%d-DI%d\n",
522                         channel, ipu, di);
523         }
524         writel(reg, ldb->gpr3_reg);
525
526         return 0;
527 }
528
529 static int ldb_disp_init(struct mxc_dispdrv_handle *disp,
530         struct mxc_dispdrv_setting *setting)
531 {
532         int ret = 0, i, lvds_channel = 0;
533         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
534         struct fsl_mxc_ldb_platform_data *plat_data = ldb->pdev->dev.platform_data;
535         struct resource *res;
536         uint32_t reg, setting_idx;
537         uint32_t ch_mask = 0, ch_val = 0;
538         uint32_t ipu_id, disp_id;
539         char di_clk[] = "ipu1_di0_sel";
540         char ldb_clk[] = "ldb_di0";
541         char div_3_5_clk[] = "di0_div_3_5";
542         char div_7_clk[] = "di0_div_7";
543         char div_sel_clk[] = "di0_div_sel";
544
545         /* if input format not valid, make RGB666 as default*/
546         if (!valid_mode(setting->if_fmt)) {
547                 dev_warn(&ldb->pdev->dev, "Input pixel format not valid"
548                                         " use default RGB666\n");
549                 setting->if_fmt = IPU_PIX_FMT_RGB666;
550         }
551
552         if (!ldb->inited) {
553                 setting_idx = 0;
554                 res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0);
555                 if (!res) {
556                         dev_err(&ldb->pdev->dev, "get iomem fail.\n");
557                         return -ENOMEM;
558                 }
559
560                 ldb->reg = devm_ioremap(&ldb->pdev->dev, res->start,
561                                         resource_size(res));
562                 ldb->control_reg = ldb->reg + 2;
563                 ldb->gpr3_reg = ldb->reg + 3;
564
565                 /* ipu selected by platform data setting */
566                 setting->dev_id = plat_data->ipu_id;
567
568                 reg = readl(ldb->control_reg);
569
570                 /* refrence resistor select */
571                 reg &= ~LDB_BGREF_RMODE_MASK;
572                 if (plat_data->ext_ref)
573                         reg |= LDB_BGREF_RMODE_EXT;
574                 else
575                         reg |= LDB_BGREF_RMODE_INT;
576
577                 /* TODO: now only use SPWG data mapping for both channel */
578                 reg &= ~(LDB_BIT_MAP_CH0_MASK | LDB_BIT_MAP_CH1_MASK);
579                 reg |= LDB_BIT_MAP_CH0_SPWG | LDB_BIT_MAP_CH1_SPWG;
580
581                 /* channel mode setting */
582                 reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
583                 reg &= ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK);
584
585                 if (bits_per_pixel(setting->if_fmt) == 24)
586                         reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24;
587                 else
588                         reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18;
589
590                 if (g_ldb_mode >= LDB_SPL_DI0)
591                         ldb->mode = g_ldb_mode;
592                 else
593                         ldb->mode = plat_data->mode;
594
595                 if ((ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) {
596                         ret = ldb->mode - LDB_SIN0;
597                         if (plat_data->disp_id != ret) {
598                                 dev_warn(&ldb->pdev->dev,
599                                         "change IPU DI%d to IPU DI%d for LDB "
600                                         "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->disp_id == plat_data->sec_disp_id) {
607                                 dev_err(&ldb->pdev->dev,
608                                         "For LVDS separate mode,"
609                                         "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) &&
615                                         (ldb->mode == LDB_SEP0))) {
616                                 dev_dbg(&ldb->pdev->dev,
617                                         "LVDS separate mode:"
618                                         "swap DI configuration!\n");
619                                 ipu_id = plat_data->ipu_id;
620                                 disp_id = plat_data->disp_id;
621                                 plat_data->ipu_id = plat_data->sec_ipu_id;
622                                 plat_data->disp_id = plat_data->sec_disp_id;
623                                 plat_data->sec_ipu_id = ipu_id;
624                                 plat_data->sec_disp_id = disp_id;
625                         }
626                 }
627
628                 if (ldb->mode == LDB_SPL_DI0) {
629                         reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI0
630                                 | LDB_CH1_MODE_EN_TO_DI0;
631                         setting->disp_id = 0;
632                 } else if (ldb->mode == LDB_SPL_DI1) {
633                         reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI1
634                                 | LDB_CH1_MODE_EN_TO_DI1;
635                         setting->disp_id = 1;
636                 } else if (ldb->mode == LDB_DUL_DI0) {
637                         reg &= ~LDB_SPLIT_MODE_EN;
638                         reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0;
639                         setting->disp_id = 0;
640                 } else if (ldb->mode == LDB_DUL_DI1) {
641                         reg &= ~LDB_SPLIT_MODE_EN;
642                         reg |= LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1;
643                         setting->disp_id = 1;
644                 } else if (ldb->mode == LDB_SIN0) {
645                         reg &= ~LDB_SPLIT_MODE_EN;
646                         setting->disp_id = plat_data->disp_id;
647                         if (setting->disp_id == 0)
648                                 reg |= LDB_CH0_MODE_EN_TO_DI0;
649                         else
650                                 reg |= LDB_CH0_MODE_EN_TO_DI1;
651                         ch_mask = LDB_CH0_MODE_MASK;
652                         ch_val = reg & LDB_CH0_MODE_MASK;
653                 } else if (ldb->mode == LDB_SIN1) {
654                         reg &= ~LDB_SPLIT_MODE_EN;
655                         setting->disp_id = plat_data->disp_id;
656                         if (setting->disp_id == 0)
657                                 reg |= LDB_CH1_MODE_EN_TO_DI0;
658                         else
659                                 reg |= LDB_CH1_MODE_EN_TO_DI1;
660                         ch_mask = LDB_CH1_MODE_MASK;
661                         ch_val = reg & LDB_CH1_MODE_MASK;
662                 } else { /* separate mode*/
663                         setting->disp_id = plat_data->disp_id;
664
665                         /* first output is LVDS0 or LVDS1 */
666                         if (ldb->mode == LDB_SEP0)
667                                 lvds_channel = 0;
668                         else
669                                 lvds_channel = 1;
670
671                         reg &= ~LDB_SPLIT_MODE_EN;
672
673                         if ((lvds_channel == 0) && (setting->disp_id == 0))
674                                 reg |= LDB_CH0_MODE_EN_TO_DI0;
675                         else if ((lvds_channel == 0) && (setting->disp_id == 1))
676                                 reg |= LDB_CH0_MODE_EN_TO_DI1;
677                         else if ((lvds_channel == 1) && (setting->disp_id == 0))
678                                 reg |= LDB_CH1_MODE_EN_TO_DI0;
679                         else
680                                 reg |= LDB_CH1_MODE_EN_TO_DI1;
681                         ch_mask = lvds_channel ? LDB_CH1_MODE_MASK :
682                                         LDB_CH0_MODE_MASK;
683                         ch_val = reg & ch_mask;
684
685                         if (bits_per_pixel(setting->if_fmt) == 24) {
686                                 if (lvds_channel == 0)
687                                         reg &= ~LDB_DATA_WIDTH_CH1_24;
688                                 else
689                                         reg &= ~LDB_DATA_WIDTH_CH0_24;
690                         } else {
691                                 if (lvds_channel == 0)
692                                         reg &= ~LDB_DATA_WIDTH_CH1_18;
693                                 else
694                                         reg &= ~LDB_DATA_WIDTH_CH0_18;
695                         }
696                 }
697
698                 writel(reg, ldb->control_reg);
699                 if (ldb->mode <  LDB_SIN0) {
700                         ch_mask = LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK;
701                         ch_val = reg & (LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
702                 }
703         } else { /* second time for separate mode */
704                 if ((ldb->mode == LDB_SPL_DI0) ||
705                         (ldb->mode == LDB_SPL_DI1) ||
706                         (ldb->mode == LDB_DUL_DI0) ||
707                         (ldb->mode == LDB_DUL_DI1) ||
708                         (ldb->mode == LDB_SIN0) ||
709                         (ldb->mode == LDB_SIN1)) {
710                         dev_err(&ldb->pdev->dev, "for second ldb disp"
711                                         "ldb mode should in separate mode\n");
712                         return -EINVAL;
713                 }
714
715                 setting_idx = 1;
716                 if (is_imx6_ldb(plat_data)) {
717                         setting->dev_id = plat_data->sec_ipu_id;
718                         setting->disp_id = plat_data->sec_disp_id;
719                 } else {
720                         setting->dev_id = plat_data->ipu_id;
721                         setting->disp_id = !plat_data->disp_id;
722                 }
723                 if (setting->disp_id == ldb->setting[0].di) {
724                         dev_err(&ldb->pdev->dev, "Err: for second ldb disp in"
725                                 "separate mode, DI should be different!\n");
726                         return -EINVAL;
727                 }
728
729                 /* second output is LVDS0 or LVDS1 */
730                 if (ldb->mode == LDB_SEP0)
731                         lvds_channel = 1;
732                 else
733                         lvds_channel = 0;
734
735                 reg = readl(ldb->control_reg);
736                 if ((lvds_channel == 0) && (setting->disp_id == 0))
737                         reg |= LDB_CH0_MODE_EN_TO_DI0;
738                 else if ((lvds_channel == 0) && (setting->disp_id == 1))
739                         reg |= LDB_CH0_MODE_EN_TO_DI1;
740                 else if ((lvds_channel == 1) && (setting->disp_id == 0))
741                         reg |= LDB_CH1_MODE_EN_TO_DI0;
742                 else
743                         reg |= LDB_CH1_MODE_EN_TO_DI1;
744                 ch_mask = lvds_channel ?  LDB_CH1_MODE_MASK :
745                                 LDB_CH0_MODE_MASK;
746                 ch_val = reg & ch_mask;
747
748                 if (bits_per_pixel(setting->if_fmt) == 24) {
749                         if (lvds_channel == 0)
750                                 reg |= LDB_DATA_WIDTH_CH0_24;
751                         else
752                                 reg |= LDB_DATA_WIDTH_CH1_24;
753                 } else {
754                         if (lvds_channel == 0)
755                                 reg |= LDB_DATA_WIDTH_CH0_18;
756                         else
757                                 reg |= LDB_DATA_WIDTH_CH1_18;
758                 }
759                 writel(reg, ldb->control_reg);
760         }
761
762         /* get clocks */
763         if (is_imx6_ldb(plat_data) &&
764                 ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))) {
765                 ldb_clk[6] += lvds_channel;
766                 div_3_5_clk[2] += lvds_channel;
767                 div_7_clk[2] += lvds_channel;
768                 div_sel_clk[2] += lvds_channel;
769         } else {
770                 ldb_clk[6] += setting->disp_id;
771                 div_3_5_clk[2] += setting->disp_id;
772                 div_7_clk[2] += setting->disp_id;
773                 div_sel_clk[2] += setting->disp_id;
774         }
775         ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev,
776                                                         ldb_clk);
777         if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) {
778                 dev_err(&ldb->pdev->dev, "get ldb clk failed\n");
779                 return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk);
780         }
781
782         ldb->setting[setting_idx].div_3_5_clk = clk_get(&ldb->pdev->dev,
783                                                         div_3_5_clk);
784         if (IS_ERR(ldb->setting[setting_idx].div_3_5_clk)) {
785                 dev_err(&ldb->pdev->dev, "get div 3.5 clk failed\n");
786                 return PTR_ERR(ldb->setting[setting_idx].div_3_5_clk);
787         }
788         ldb->setting[setting_idx].div_7_clk = clk_get(&ldb->pdev->dev,
789                                                         div_7_clk);
790         if (IS_ERR(ldb->setting[setting_idx].div_7_clk)) {
791                 dev_err(&ldb->pdev->dev, "get div 7 clk failed\n");
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, "get div sel clk failed\n");
799                 return PTR_ERR(ldb->setting[setting_idx].div_sel_clk);
800         }
801
802         di_clk[3] += setting->dev_id;
803         di_clk[7] += setting->disp_id;
804         ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev,
805                                                         di_clk);
806         if (IS_ERR(ldb->setting[setting_idx].di_clk)) {
807                 dev_err(&ldb->pdev->dev, "get di clk failed\n");
808                 return PTR_ERR(ldb->setting[setting_idx].di_clk);
809         }
810
811         ldb->setting[setting_idx].ch_mask = ch_mask;
812         ldb->setting[setting_idx].ch_val = ch_val;
813
814         if (is_imx6_ldb(plat_data))
815                 ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb);
816
817         /* must use spec video mode defined by driver */
818         ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str,
819                                 ldb_modedb, ldb_modedb_sz, NULL, setting->default_bpp);
820         if (ret != 1)
821                 fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]);
822
823         INIT_LIST_HEAD(&setting->fbi->modelist);
824         for (i = 0; i < ldb_modedb_sz; i++) {
825                 struct fb_videomode m;
826                 fb_var_to_videomode(&m, &setting->fbi->var);
827                 if (fb_mode_is_equal(&m, &ldb_modedb[i])) {
828                         fb_add_videomode(&ldb_modedb[i],
829                                         &setting->fbi->modelist);
830                         break;
831                 }
832         }
833
834         ldb->setting[setting_idx].ipu = setting->dev_id;
835         ldb->setting[setting_idx].di = setting->disp_id;
836
837         return ret;
838 }
839
840 static int ldb_post_disp_init(struct mxc_dispdrv_handle *disp,
841                                 int ipu_id, int disp_id)
842 {
843         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
844         int setting_idx = ldb->inited ? 1 : 0;
845         int ret = 0;
846
847         if (!ldb->inited) {
848                 ldb->nb.notifier_call = ldb_fb_event;
849                 fb_register_client(&ldb->nb);
850         }
851
852         ret = clk_set_parent(ldb->setting[setting_idx].di_clk,
853                         ldb->setting[setting_idx].ldb_di_clk);
854         if (ret) {
855                 dev_err(&ldb->pdev->dev, "fail to set ldb_di clk as"
856                         "the parent of ipu_di clk\n");
857                 return ret;
858         }
859
860         if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1)) {
861                 ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk,
862                                 ldb->setting[setting_idx].div_3_5_clk);
863                 if (ret) {
864                         dev_err(&ldb->pdev->dev, "fail to set div 3.5 clk as"
865                                 "the parent of div sel clk\n");
866                         return ret;
867                 }
868         } else {
869                 ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk,
870                                 ldb->setting[setting_idx].div_7_clk);
871                 if (ret) {
872                         dev_err(&ldb->pdev->dev, "fail to set div 7 clk as"
873                                 "the parent of div sel clk\n");
874                         return ret;
875                 }
876         }
877
878         /* save active ldb setting for fb notifier */
879         ldb->setting[setting_idx].active = true;
880
881         ldb->inited = true;
882         return ret;
883 }
884
885 static void ldb_disp_deinit(struct mxc_dispdrv_handle *disp)
886 {
887         struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
888         int i;
889
890         writel(0, ldb->control_reg);
891
892         for (i = 0; i < 2; i++) {
893                 clk_disable(ldb->setting[i].ldb_di_clk);
894                 clk_put(ldb->setting[i].ldb_di_clk);
895                 clk_put(ldb->setting[i].div_3_5_clk);
896                 clk_put(ldb->setting[i].div_7_clk);
897                 clk_put(ldb->setting[i].div_sel_clk);
898         }
899
900         fb_unregister_client(&ldb->nb);
901 }
902
903 static struct mxc_dispdrv_driver ldb_drv = {
904         .name   = DISPDRV_LDB,
905         .init   = ldb_disp_init,
906         .post_init = ldb_post_disp_init,
907         .deinit = ldb_disp_deinit,
908         .setup = ldb_disp_setup,
909 };
910
911 static int ldb_suspend(struct platform_device *pdev, pm_message_t state)
912 {
913         struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
914         uint32_t        data;
915
916         if (!ldb->inited)
917                 return 0;
918         data = readl(ldb->control_reg);
919         ldb->control_reg_data = data;
920         data &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
921         writel(data, ldb->control_reg);
922
923         return 0;
924 }
925
926 static int ldb_resume(struct platform_device *pdev)
927 {
928         struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
929
930         if (!ldb->inited)
931                 return 0;
932         writel(ldb->control_reg_data, ldb->control_reg);
933
934         return 0;
935 }
936
937 static struct platform_device_id imx_ldb_devtype[] = {
938         {
939                 .name = "ldb-imx6",
940                 .driver_data = LDB_IMX6,
941         }, {
942                 /* sentinel */
943         }
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");