blob: 0a16c348097fccbb6b5ad89ed745f25864f7b634 [file] [log] [blame]
Duy Truongf3ac7b32013-02-13 01:07:28 -08001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
Shashank Mittal4bfb2e32012-04-16 10:56:27 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
Duy Truongf3ac7b32013-02-13 01:07:28 -080012 * * Neither the name of The Linux Foundation nor the names of its
Shashank Mittal4bfb2e32012-04-16 10:56:27 -070013 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#include <stdint.h>
31#include <reg.h>
32#include <err.h>
33#include <bits.h>
Channagoud Kadabi6d6223c2013-08-05 15:27:55 -070034#include <arch/defines.h>
Shashank Mittal4bfb2e32012-04-16 10:56:27 -070035#include <platform/iomap.h>
36#include <platform/clock.h>
37#include <dev/fbcon.h>
38#include <dev/lcdc.h>
39
40#include <msm_panel.h>
41#define MDP_OUTP(addr, val) writel(val, addr);
42
43void lvds_init(struct msm_panel_info *pinfo)
44{
45 unsigned int lvds_intf, lvds_phy_cfg0;
46 MDP_OUTP(MDP_BASE + 0xc2034, 0x33);
47 udelay(1000);
48
49 /*1. Configure LVDS PHY PLL through MDP_LVDSPHY_PLL_CTRL_* registers*/
50 /* LVDS PHY PLL configuration */
51 MDP_OUTP(MDP_BASE + 0xc3000, 0x08);
52 MDP_OUTP(MDP_BASE + 0xc3004, 0x87);
53 MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
54 MDP_OUTP(MDP_BASE + 0xc300c, 0x06);
55 MDP_OUTP(MDP_BASE + 0xc3014, 0x20);
56 MDP_OUTP(MDP_BASE + 0xc3018, 0x0F);
57 MDP_OUTP(MDP_BASE + 0xc301c, 0x01);
58 MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
59 MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
60 MDP_OUTP(MDP_BASE + 0xc3028, 0x07);
61 MDP_OUTP(MDP_BASE + 0xc302c, 0x00);
62 MDP_OUTP(MDP_BASE + 0xc3030, 0x1c);
63 MDP_OUTP(MDP_BASE + 0xc3034, 0x01);
64 MDP_OUTP(MDP_BASE + 0xc3038, 0x00);
65 MDP_OUTP(MDP_BASE + 0xc3040, 0xC0);
66 MDP_OUTP(MDP_BASE + 0xc3044, 0x00);
67 MDP_OUTP(MDP_BASE + 0xc3048, 0x30);
68 MDP_OUTP(MDP_BASE + 0xc304c, 0x00);
69
70 MDP_OUTP(MDP_BASE + 0xc3000, 0x11);
71 MDP_OUTP(MDP_BASE + 0xc3064, 0x05);
72 MDP_OUTP(MDP_BASE + 0xc3050, 0x20);
73
74 /*2. Enable LVDS PHY PLL in MDP_LVDSPHY_PLL_CTRL_0*/
75 MDP_OUTP(MDP_BASE + 0xc3000, 0x01);
76
77 /*3. Poll the MDP_LVDSPHY_PLL_RDY register until it is 1*/
78 /* Wait until LVDS PLL is locked and ready */
79 while (!readl(MDP_BASE + 0xc3080))
80 udelay(1);
81
82 /*4. Enable dsi2_pixel domain clocks*/
83 writel(0x00, REG_MM(0x0264));
84 writel(0x00, REG_MM(0x0094));
85
86 writel(0x02, REG_MM(0x00E4));
87
88 writel((0x80 | readl(REG_MM(0x00E4))),
89 REG_MM(0x00E4));
90 udelay(1000);
91 writel((~0x80 & readl(REG_MM(0x00E4))),
92 REG_MM(0x00E4));
93
94 writel(0x05, REG_MM(0x0094));
95 writel(0x02, REG_MM(0x0264));
96 /* Wait until LVDS pixel clock output is enabled */
97 dsb();
98 if (pinfo->bpp == 24) {
99 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
100 MDP_OUTP(MDP_BASE + 0xc2014, 0x03040508);
101 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
102 MDP_OUTP(MDP_BASE + 0xc2018, 0x00000102);
103 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
104 MDP_OUTP(MDP_BASE + 0xc201c, 0x0c0d1011);
105 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
106 MDP_OUTP(MDP_BASE + 0xc2020, 0x00090a0b);
107 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
108 MDP_OUTP(MDP_BASE + 0xc2024, 0x151a191a);
109 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
110 MDP_OUTP(MDP_BASE + 0xc2028, 0x00121314);
111 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
112 MDP_OUTP(MDP_BASE + 0xc202c, 0x1706071b);
113 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
114 MDP_OUTP(MDP_BASE + 0xc2030, 0x000e0f16);
115
116 if (pinfo->lvds.channel_mode ==
117 LVDS_DUAL_CHANNEL_MODE) {
118 lvds_intf = 0x0001ff80;
119 lvds_phy_cfg0 = BIT(6) | BIT(7);
120 if (pinfo->lvds.channel_swap)
121 lvds_intf |= BIT(4);
122 } else {
123 lvds_intf = 0x00010f84;
124 lvds_phy_cfg0 = BIT(6);
125 }
126 } else if (pinfo->bpp == 18) {
127 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
128 MDP_OUTP(MDP_BASE + 0xc2014, 0x03040508);
129 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
130 MDP_OUTP(MDP_BASE + 0xc2018, 0x00000102);
131 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
132 MDP_OUTP(MDP_BASE + 0xc201c, 0x0c0d1011);
133 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
134 MDP_OUTP(MDP_BASE + 0xc2020, 0x00090a0b);
135 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
136 MDP_OUTP(MDP_BASE + 0xc2024, 0x1518191a);
137 /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
138 MDP_OUTP(MDP_BASE + 0xc2028, 0x00121314);
139
140 if (pinfo->lvds.channel_mode ==
141 LVDS_DUAL_CHANNEL_MODE) {
142 lvds_intf = 0x00017788;
143 lvds_phy_cfg0 = BIT(6) | BIT(7);
144 if (pinfo->lvds.channel_swap)
145 lvds_intf |= BIT(4);
146 } else {
147 lvds_intf = 0x0001078c;
148 lvds_phy_cfg0 = BIT(6);
149 }
150 }
151
152 /* MDP_LVDSPHY_CFG0 */
153 MDP_OUTP(MDP_BASE + 0xc3100, lvds_phy_cfg0);
154 /* MDP_LCDC_LVDS_INTF_CTL */
155 MDP_OUTP(MDP_BASE + 0xc2000, lvds_intf);
156 MDP_OUTP(MDP_BASE + 0xc3108, 0x30);
157 lvds_phy_cfg0 |= BIT(4);
158
159 /* Wait until LVDS PHY registers are configured */
160 dsb();
161 udelay(1);
162 /* MDP_LVDSPHY_CFG0, enable serialization */
163 MDP_OUTP(MDP_BASE + 0xc3100, lvds_phy_cfg0);
164}
165
166int lvds_on(struct msm_fb_panel_data *pdata)
167{
168 int ret = 0;
169 if (pdata == NULL) {
170 ret = ERR_INVALID_ARGS;
171 goto out;
172 }
173
174 lvds_init(&(pdata->panel_info));
175out:
176 return ret;
177}
178