2 * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
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.
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.
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.
24 * @brief This file contains the LDB driver device interface and fops
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>
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>
45 #include "mxc_dispdrv.h"
47 #define DISPDRV_LDB "ldb"
49 #define LDB_BGREF_RMODE_MASK 0x00008000
50 #define LDB_BGREF_RMODE_INT 0x00008000
51 #define LDB_BGREF_RMODE_EXT 0x0
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
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
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
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
83 #define LDB_SPLIT_MODE_EN 0x00000010
93 struct fsl_mxc_ldb_platform_data {
108 /*only work for separate mode*/
114 struct platform_device *pdev;
115 struct mxc_dispdrv_handle *disp_ldb;
117 uint32_t *control_reg;
119 uint32_t control_reg_data;
120 struct regulator *lvds_bg_reg;
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;
136 struct notifier_block nb;
139 static int g_ldb_mode;
141 static struct fb_videomode ldb_modedb[] = {
143 "LDB-WXGA", 60, 1280, 800, 14065,
148 FB_VMODE_NONINTERLACED,
152 "LDB-XGA", 60, 1024, 768, 15385,
157 FB_VMODE_NONINTERLACED,
161 "LDB-1080P60", 60, 1920, 1080, 7692,
166 FB_VMODE_NONINTERLACED,
170 "LDB-NL12880BC20", 60, 1280, 800, KHZ2PICOS(71000),
175 FB_VMODE_NONINTERLACED,
179 "LDB-VGA", 60, 640, 480, KHZ2PICOS(25200),
184 FB_VMODE_NONINTERLACED,
188 static int ldb_modedb_sz = ARRAY_SIZE(ldb_modedb);
190 static inline int is_imx6_ldb(struct fsl_mxc_ldb_platform_data *plat_data)
192 return (plat_data->devtype == LDB_IMX6);
195 static int bits_per_pixel(int pixel_fmt)
198 case IPU_PIX_FMT_BGR24:
199 case IPU_PIX_FMT_RGB24:
202 case IPU_PIX_FMT_BGR666:
203 case IPU_PIX_FMT_RGB666:
204 case IPU_PIX_FMT_LVDS666:
213 static int valid_mode(int pixel_fmt)
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));
222 static int parse_ldb_mode(char *mode)
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"))
236 else if (!strcmp(mode, "sin1"))
238 else if (!strcmp(mode, "sep0"))
240 else if (!strcmp(mode, "sep1"))
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
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.
258 * split mode means display data from DI0 or DI1 will be sent to both channels
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
266 static int __init ldb_setup(char *options)
268 g_ldb_mode = parse_ldb_mode(options);
269 return (g_ldb_mode < 0) ? 0 : 1;
271 __setup("ldb=", ldb_setup);
274 static int ldb_get_of_property(struct platform_device *pdev,
275 struct fsl_mxc_ldb_platform_data *plat_data)
277 struct device_node *np = pdev->dev.of_node;
280 u32 sec_ipu_id, sec_disp_id;
284 err = of_property_read_string(np, "mode", (const char **)&mode);
286 dev_err(&pdev->dev, "get of property mode fail\n");
289 err = of_property_read_u32(np, "ext_ref", &ext_ref);
291 dev_err(&pdev->dev, "get of property ext_ref fail\n");
294 err = of_property_read_u32(np, "ipu_id", &ipu_id);
296 dev_err(&pdev->dev, "get of property ipu_id fail\n");
299 err = of_property_read_u32(np, "disp_id", &disp_id);
301 dev_err(&pdev->dev, "get of property disp_id fail\n");
304 err = of_property_read_u32(np, "sec_ipu_id", &sec_ipu_id);
306 dev_err(&pdev->dev, "get of property sec_ipu_id fail\n");
309 err = of_property_read_u32(np, "sec_disp_id", &sec_disp_id);
311 dev_err(&pdev->dev, "get of property sec_disp_id fail\n");
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;
325 static int find_ldb_setting(struct ldb_data *ldb, struct fb_info *fbi)
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))
345 static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi)
348 uint32_t pixel_clk, rounded_pixel_clk;
349 struct clk *ldb_clk_parent;
350 struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
354 setting_idx = find_ldb_setting(ldb, fbi);
358 di = ldb->setting[setting_idx].di;
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));
368 reg = readl(ldb->control_reg);
369 if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) {
371 reg = (reg & ~LDB_DI0_VS_POL_MASK)
372 | LDB_DI0_VS_POL_ACT_HIGH;
374 reg = (reg & ~LDB_DI1_VS_POL_MASK)
375 | LDB_DI1_VS_POL_ACT_HIGH;
378 reg = (reg & ~LDB_DI0_VS_POL_MASK)
379 | LDB_DI0_VS_POL_ACT_LOW;
381 reg = (reg & ~LDB_DI1_VS_POL_MASK)
382 | LDB_DI1_VS_POL_ACT_LOW;
384 writel(reg, ldb->control_reg);
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);
395 if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1))
396 ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7 / 2);
398 ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7);
400 dev_err(&ldb->pdev->dev, "set ldb parent clk fail:%d\n", ret);
403 rounded_pixel_clk = clk_round_rate(ldb->setting[setting_idx].ldb_di_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,
410 dev_err(&ldb->pdev->dev, "set ldb di clk fail:%d\n", ret);
413 ret = clk_prepare_enable(ldb->setting[setting_idx].ldb_di_clk);
415 dev_err(&ldb->pdev->dev, "enable ldb di clk fail:%d\n", ret);
419 if (!ldb->setting[setting_idx].clk_en)
420 ldb->setting[setting_idx].clk_en = true;
425 int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v)
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;
433 index = find_ldb_setting(ldb, fbi);
437 fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var,
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);
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;
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));
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;
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)
500 int mode = ldb->mode;
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",
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);
519 static bool first = true;
522 if (mode == LDB_SEP0) {
523 reg &= ~LVDS0_MUX_CTL_MASK;
526 reg &= ~LVDS1_MUX_CTL_MASK;
531 if (mode == LDB_SEP0) {
532 reg &= ~LVDS1_MUX_CTL_MASK;
535 reg &= ~LVDS0_MUX_CTL_MASK;
540 shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH;
541 reg |= ROUTE_IPU_DI(ipu, di) << shift;
543 dev_dbg(&ldb->pdev->dev,
544 "Separate mode channel %d route to IPU%d-DI%d\n",
545 channel, ipu + 1, di);
547 writel(reg, ldb->gpr3_reg);
552 static int ldb_disp_init(struct mxc_dispdrv_handle *disp,
553 struct mxc_dispdrv_setting *setting)
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";
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;
576 res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0);
578 dev_err(&ldb->pdev->dev, "get iomem fail.\n");
582 ldb->reg = devm_ioremap(&ldb->pdev->dev, res->start,
584 ldb->control_reg = ldb->reg + 2;
585 ldb->gpr3_reg = ldb->reg + 3;
587 /* ipu selected by platform data setting */
588 setting->dev_id = plat_data->ipu_id;
590 reg = readl(ldb->control_reg);
592 /* reference resistor select */
593 reg &= ~LDB_BGREF_RMODE_MASK;
594 if (plat_data->ext_ref)
595 reg |= LDB_BGREF_RMODE_EXT;
597 reg |= LDB_BGREF_RMODE_INT;
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;
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);
607 if (bits_per_pixel(setting->if_fmt) == 24)
608 reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24;
610 reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18;
612 if (g_ldb_mode >= LDB_SPL_DI0)
613 ldb->mode = g_ldb_mode;
615 ldb->mode = plat_data->mode;
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;
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");
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;
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;
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;
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;
684 /* first output is LVDS0 or LVDS1 */
685 if (ldb->mode == LDB_SEP0)
690 reg &= ~LDB_SPLIT_MODE_EN;
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;
699 reg |= LDB_CH1_MODE_EN_TO_DI1;
700 ch_mask = lvds_channel ? LDB_CH1_MODE_MASK :
702 ch_val = reg & ch_mask;
704 if (bits_per_pixel(setting->if_fmt) == 24) {
705 if (lvds_channel == 0)
706 reg &= ~LDB_DATA_WIDTH_CH1_24;
708 reg &= ~LDB_DATA_WIDTH_CH0_24;
710 if (lvds_channel == 0)
711 reg &= ~LDB_DATA_WIDTH_CH1_18;
713 reg &= ~LDB_DATA_WIDTH_CH0_18;
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);
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");
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;
738 setting->dev_id = plat_data->ipu_id;
739 setting->disp_id = !plat_data->disp_id;
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");
747 /* second output is LVDS0 or LVDS1 */
748 if (ldb->mode == LDB_SEP0)
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;
761 reg |= LDB_CH1_MODE_EN_TO_DI1;
762 ch_mask = lvds_channel ? LDB_CH1_MODE_MASK :
764 ch_val = reg & ch_mask;
766 if (bits_per_pixel(setting->if_fmt) == 24) {
767 if (lvds_channel == 0)
768 reg |= LDB_DATA_WIDTH_CH0_24;
770 reg |= LDB_DATA_WIDTH_CH1_24;
772 if (lvds_channel == 0)
773 reg |= LDB_DATA_WIDTH_CH0_18;
775 reg |= LDB_DATA_WIDTH_CH1_18;
777 writel(reg, ldb->control_reg);
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;
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;
793 ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev,
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);
801 ldb->setting[setting_idx].div_3_5_clk = clk_get(&ldb->pdev->dev,
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);
808 ldb->setting[setting_idx].div_7_clk = clk_get(&ldb->pdev->dev,
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);
816 ldb->setting[setting_idx].div_sel_clk = clk_get(&ldb->pdev->dev,
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);
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,
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);
834 ldb->setting[setting_idx].ch_mask = ch_mask;
835 ldb->setting[setting_idx].ch_val = ch_val;
837 if (is_imx6_ldb(plat_data))
838 ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb);
840 if (setting->fbmode) {
841 ldb_modedb[0] = *setting->fbmode;
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);
849 fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]);
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);
862 ldb->setting[setting_idx].ipu = setting->dev_id;
863 ldb->setting[setting_idx].di = setting->disp_id;
868 static int ldb_post_disp_init(struct mxc_dispdrv_handle *disp,
869 int ipu_id, int disp_id)
871 struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
872 int setting_idx = ldb->inited ? 1 : 0;
876 ldb->nb.notifier_call = ldb_fb_event;
877 fb_register_client(&ldb->nb);
880 ret = clk_set_parent(ldb->setting[setting_idx].di_clk,
881 ldb->setting[setting_idx].ldb_di_clk);
883 dev_err(&ldb->pdev->dev, "fail to set ldb_di clk as the parent of ipu_di clk\n");
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);
891 dev_err(&ldb->pdev->dev, "fail to set div 3.5 clk as the parent of div sel clk\n");
895 ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk,
896 ldb->setting[setting_idx].div_7_clk);
898 dev_err(&ldb->pdev->dev, "fail to set div 7 clk as the parent of div sel clk\n");
903 /* save active ldb setting for fb notifier */
904 ldb->setting[setting_idx].active = true;
910 static void ldb_disp_deinit(struct mxc_dispdrv_handle *disp)
912 struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
915 writel(0, ldb->control_reg);
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);
925 fb_unregister_client(&ldb->nb);
928 static struct mxc_dispdrv_driver ldb_drv = {
930 .init = ldb_disp_init,
931 .post_init = ldb_post_disp_init,
932 .deinit = ldb_disp_deinit,
933 .setup = ldb_disp_setup,
936 static int ldb_suspend(struct platform_device *pdev, pm_message_t state)
938 struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
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);
951 static int ldb_resume(struct platform_device *pdev)
953 struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
957 writel(ldb->control_reg_data, ldb->control_reg);
962 static struct platform_device_id imx_ldb_devtype[] = {
963 { "ldb-imx6", LDB_IMX6, },
967 static const struct of_device_id imx_ldb_dt_ids[] = {
968 { .compatible = "fsl,imx6q-ldb", .data = &imx_ldb_devtype[IMX6_LDB],},
973 * This function is called by the driver framework to initialize the LDB
976 * @param dev The device structure for the LDB passed in by the
979 * @return Returns 0 on success or negative error code on error
981 static int ldb_probe(struct platform_device *pdev)
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);
989 dev_dbg(&pdev->dev, "%s enter\n", __func__);
990 ldb = devm_kzalloc(&pdev->dev, sizeof(struct ldb_data), GFP_KERNEL);
994 plat_data = devm_kzalloc(&pdev->dev,
995 sizeof(struct fsl_mxc_ldb_platform_data),
999 pdev->dev.platform_data = plat_data;
1001 pdev->id_entry = of_id->data;
1002 plat_data->devtype = pdev->id_entry->driver_data;
1004 ret = ldb_get_of_property(pdev, plat_data);
1006 dev_err(&pdev->dev, "get ldb of property fail\n");
1011 ldb->disp_ldb = mxc_dispdrv_register(&ldb_drv);
1012 mxc_dispdrv_setdata(ldb->disp_ldb, ldb);
1014 dev_set_drvdata(&pdev->dev, ldb);
1016 dev_dbg(&pdev->dev, "%s exit\n", __func__);
1020 static int ldb_remove(struct platform_device *pdev)
1022 struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
1026 mxc_dispdrv_puthandle(ldb->disp_ldb);
1027 mxc_dispdrv_unregister(ldb->disp_ldb);
1031 static struct platform_driver mxcldb_driver = {
1034 .of_match_table = imx_ldb_dt_ids,
1037 .remove = ldb_remove,
1038 .suspend = ldb_suspend,
1039 .resume = ldb_resume,
1042 static int __init ldb_init(void)
1044 return platform_driver_register(&mxcldb_driver);
1047 static void __exit ldb_uninit(void)
1049 platform_driver_unregister(&mxcldb_driver);
1052 module_init(ldb_init);
1053 module_exit(ldb_uninit);
1055 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1056 MODULE_DESCRIPTION("MXC LDB driver");
1057 MODULE_LICENSE("GPL");