Kinson Chik | 1ac45ce | 2011-05-29 22:01:34 -0700 | [diff] [blame] | 1 | /* |
| 2 | * * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
| 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions are |
| 6 | * met: |
| 7 | * * Redistributions of source code must retain the above copyright |
| 8 | * notice, this list of conditions and the following disclaimer. |
| 9 | * * Redistributions in binary form must reproduce the above |
| 10 | * copyright notice, this list of conditions and the following |
| 11 | * disclaimer in the documentation and/or other materials provided |
| 12 | * with the distribution. |
| 13 | * * Neither the name of Code Aurora Forum, Inc. nor the names of its |
| 14 | * contributors may be used to endorse or promote products derived |
| 15 | * from this software without specific prior written permission. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | */ |
| 29 | #include <debug.h> |
Kinson Chik | e5c9343 | 2011-06-17 09:10:29 -0700 | [diff] [blame] | 30 | #include <reg.h> |
| 31 | #include <mipi_dsi.h> |
Kinson Chik | fe93103 | 2011-07-21 10:01:34 -0700 | [diff] [blame] | 32 | #include <mdp4.h> |
Kinson Chik | 1ac45ce | 2011-05-29 22:01:34 -0700 | [diff] [blame] | 33 | #include <dev/pm8921.h> |
Kinson Chik | e5c9343 | 2011-06-17 09:10:29 -0700 | [diff] [blame] | 34 | #include <platform/iomap.h> |
| 35 | #include <platform/clock.h> |
| 36 | #include <target/display.h> |
Kinson Chik | 1ac45ce | 2011-05-29 22:01:34 -0700 | [diff] [blame] | 37 | |
Kinson Chik | e5c9343 | 2011-06-17 09:10:29 -0700 | [diff] [blame] | 38 | void panel_backlight_on(void) |
Kinson Chik | 1ac45ce | 2011-05-29 22:01:34 -0700 | [diff] [blame] | 39 | { |
| 40 | struct pm8921_gpio backlight_pwm = { |
| 41 | .direction = PM_GPIO_DIR_OUT, |
| 42 | .output_buffer = 0, |
| 43 | .output_value = 0, |
| 44 | .pull = PM_GPIO_PULL_NO, |
| 45 | .vin_sel = 2, |
| 46 | .out_strength = PM_GPIO_STRENGTH_HIGH, |
| 47 | .function = PM_GPIO_FUNC_1, |
| 48 | .inv_int_pol = 0, |
| 49 | }; |
| 50 | |
| 51 | int rc = pm8921_gpio_config(GPIO_24, &backlight_pwm); |
| 52 | if (rc) { |
Kinson Chik | e5c9343 | 2011-06-17 09:10:29 -0700 | [diff] [blame] | 53 | dprintf(CRITICAL, "FAIL pm8921_gpio_config(): rc=%d.\n", rc); |
Kinson Chik | 1ac45ce | 2011-05-29 22:01:34 -0700 | [diff] [blame] | 54 | } |
| 55 | } |
Kinson Chik | e5c9343 | 2011-06-17 09:10:29 -0700 | [diff] [blame] | 56 | |
| 57 | /* Pull DISP_RST_N high to get panel out of reset */ |
| 58 | void mipi_panel_reset(void){ |
| 59 | |
| 60 | struct pm8921_gpio gpio43_param = { |
| 61 | .direction = PM_GPIO_DIR_OUT, |
| 62 | .output_buffer = 0, |
| 63 | .output_value = 1, |
| 64 | .pull = PM_GPIO_PULL_UP0, |
| 65 | .vin_sel = 2, |
| 66 | .out_strength = PM_GPIO_STRENGTH_HIGH, |
| 67 | .function = PM_GPIO_FUNC_PAIRED, |
| 68 | .inv_int_pol = 0, |
| 69 | .disable_pin = 0, |
| 70 | }; |
| 71 | pm8921_gpio_config(GPIO_43, &gpio43_param); |
| 72 | } |
| 73 | |
| 74 | void mipi_dsi_panel_power_on(void){ |
| 75 | |
| 76 | /* Turn on LDO8 for lcd1 mipi vdd */ |
| 77 | pm8921_ldo_set_voltage(LDO_8, LDO_VOLTAGE_3_0V); |
| 78 | |
| 79 | /* Turn on LDO23 for lcd1 mipi vddio */ |
| 80 | pm8921_ldo_set_voltage(LDO_23, LDO_VOLTAGE_1_8V); |
| 81 | |
| 82 | /* Turn on LDO2 for vdda_mipi_dsi */ |
| 83 | pm8921_ldo_set_voltage(LDO_2, LDO_VOLTAGE_1_2V); |
| 84 | |
| 85 | } |
| 86 | |
| 87 | static void mipi_dsi_calibration(void) |
| 88 | { |
| 89 | int32_t i = 0; |
| 90 | uint32_t term_cnt = 5000; |
| 91 | int32_t cal_busy = readl(MIPI_DSI_BASE + 0x550); |
| 92 | |
| 93 | /* DSI1_DSIPHY_REGULATOR_CAL_PWR_CFG */ |
| 94 | writel(0x01, MIPI_DSI_BASE + 0x0518); |
| 95 | |
| 96 | /* DSI1_DSIPHY_CAL_SW_CFG2 */ |
| 97 | writel(0x0, MIPI_DSI_BASE + 0x0534); |
| 98 | /* DSI1_DSIPHY_CAL_HW_CFG1 */ |
| 99 | writel(0x5a, MIPI_DSI_BASE + 0x053c); |
| 100 | /* DSI1_DSIPHY_CAL_HW_CFG3 */ |
| 101 | writel(0x10, MIPI_DSI_BASE + 0x0544); |
| 102 | /* DSI1_DSIPHY_CAL_HW_CFG4 */ |
| 103 | writel(0x01, MIPI_DSI_BASE + 0x0548); |
| 104 | /* DSI1_DSIPHY_CAL_HW_CFG0 */ |
| 105 | writel(0x01, MIPI_DSI_BASE + 0x0538); |
| 106 | |
| 107 | /* DSI1_DSIPHY_CAL_HW_TRIGGER */ |
| 108 | writel(0x01, MIPI_DSI_BASE + 0x0528); |
Kinson Chik | f91907f | 2011-07-15 10:06:48 -0700 | [diff] [blame] | 109 | |
Kinson Chik | e5c9343 | 2011-06-17 09:10:29 -0700 | [diff] [blame] | 110 | /* DSI1_DSIPHY_CAL_HW_TRIGGER */ |
| 111 | writel(0x00, MIPI_DSI_BASE + 0x0528); |
| 112 | |
| 113 | cal_busy = readl(MIPI_DSI_BASE + 0x550); |
| 114 | while (cal_busy & 0x10) { |
| 115 | i++; |
| 116 | if (i > term_cnt) { |
| 117 | dprintf(CRITICAL, "DSI1 PHY REGULATOR NOT READY," |
| 118 | "exceeded polling TIMEOUT!\n"); |
| 119 | break; |
| 120 | } |
| 121 | cal_busy = readl(MIPI_DSI_BASE + 0x550); |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | int mipi_dsi_phy_init(struct mipi_dsi_panel_config *pinfo){ |
| 126 | struct mipi_dsi_phy_ctrl *pd; |
| 127 | uint32_t i, off = 0; |
| 128 | |
Kinson Chik | f91907f | 2011-07-15 10:06:48 -0700 | [diff] [blame] | 129 | writel(0x0001, MIPI_DSI_BASE + 0x128);/* start phy sw reset */ |
Kinson Chik | e5c9343 | 2011-06-17 09:10:29 -0700 | [diff] [blame] | 130 | writel(0x0000, MIPI_DSI_BASE + 0x128);/* end phy w reset */ |
| 131 | writel(0x0003, MIPI_DSI_BASE + 0x500);/* regulator_ctrl_0 */ |
| 132 | writel(0x0001, MIPI_DSI_BASE + 0x504);/* regulator_ctrl_1 */ |
| 133 | writel(0x0001, MIPI_DSI_BASE + 0x508);/* regulator_ctrl_2 */ |
| 134 | writel(0x0000, MIPI_DSI_BASE + 0x50c);/* regulator_ctrl_3 */ |
| 135 | writel(0x0100, MIPI_DSI_BASE + 0x510);/* regulator_ctrl_4 */ |
| 136 | |
| 137 | pd = (pinfo->dsi_phy_config); |
| 138 | |
| 139 | off = 0x0480; /* strength 0 - 2 */ |
| 140 | for (i = 0; i < 3; i++) { |
| 141 | writel(pd->strength[i], MIPI_DSI_BASE + off); |
| 142 | off += 4; |
| 143 | } |
| 144 | |
| 145 | off = 0x0470; /* ctrl 0 - 3 */ |
| 146 | for (i = 0; i < 4; i++) { |
| 147 | writel(pd->ctrl[i], MIPI_DSI_BASE + off); |
| 148 | off += 4; |
| 149 | } |
| 150 | |
| 151 | off = 0x0500; /* regulator ctrl 0 - 4 */ |
| 152 | for (i = 0; i < 5; i++) { |
| 153 | writel(pd->regulator[i], MIPI_DSI_BASE + off); |
| 154 | off += 4; |
| 155 | } |
| 156 | mipi_dsi_calibration(); |
| 157 | |
| 158 | off = 0x0204; /* pll ctrl 1 - 19, skip 0 */ |
| 159 | for (i = 1; i < 20; i++) { |
| 160 | writel(pd->pll[i], MIPI_DSI_BASE + off); |
| 161 | off += 4; |
| 162 | } |
| 163 | |
| 164 | /* pll ctrl 0 */ |
| 165 | writel(pd->pll[0], MIPI_DSI_BASE + 0x200); |
| 166 | writel((pd->pll[0] | 0x01), MIPI_DSI_BASE + 0x200); |
| 167 | |
| 168 | /* Check that PHY is ready */ |
| 169 | while(!(readl(DSIPHY_PLL_RDY) & 0x01)); |
| 170 | |
| 171 | writel(0x202D, DSI_CLKOUT_TIMING_CTRL); |
| 172 | |
| 173 | off = 0x0440; /* phy timing ctrl 0 - 11 */ |
| 174 | for (i = 0; i < 12; i++) { |
| 175 | writel(pd->timing[i], MIPI_DSI_BASE + off); |
| 176 | off += 4; |
| 177 | } |
| 178 | return 0; |
| 179 | } |
| 180 | |
| 181 | /* Calculations specific for the Toshiba MDT61 Panel */ |
| 182 | void mdp_setup_mdt61_video_dsi_config(void){ |
| 183 | unsigned long hsync_period; |
| 184 | unsigned long vsync_period; |
| 185 | |
| 186 | /* For MDT61 display width is 200 more than image width */ |
| 187 | hsync_period = TSH_MDT61_DISPLAY_WIDTH + MIPI_HSYNC_BACK_PORCH_DCLK |
| 188 | + MIPI_HSYNC_FRONT_PORCH_DCLK + MIPI_HSYNC_PULSE_WIDTH; |
| 189 | |
| 190 | vsync_period = (TSH_MDT61_MIPI_FB_HEIGHT + MIPI_VSYNC_BACK_PORCH_LINES |
| 191 | + MIPI_VSYNC_FRONT_PORCH_LINES + MIPI_VSYNC_PULSE_WIDTH) * hsync_period; |
| 192 | |
| 193 | writel(hsync_period<<16 | MIPI_HSYNC_PULSE_WIDTH<<0, MDP_DSI_VIDEO_HSYNC_CTL); |
| 194 | writel(vsync_period, MDP_DSI_VIDEO_VSYNC_PERIOD); |
| 195 | writel(MIPI_VSYNC_PULSE_WIDTH * hsync_period, MDP_DSI_VIDEO_VSYNC_PULSE_WIDTH); |
| 196 | writel((MIPI_HSYNC_BACK_PORCH_DCLK + MIPI_HSYNC_PULSE_WIDTH + TSH_MDT61_DISPLAY_WIDTH - 1)<<16 | |
| 197 | (MIPI_HSYNC_BACK_PORCH_DCLK + MIPI_HSYNC_PULSE_WIDTH), MDP_DSI_VIDEO_DISPLAY_HCTL); |
| 198 | writel(hsync_period * (MIPI_VSYNC_BACK_PORCH_LINES + MIPI_VSYNC_PULSE_WIDTH), |
| 199 | MDP_DSI_VIDEO_DISPLAY_V_START); |
| 200 | writel(hsync_period * |
| 201 | (MIPI_VSYNC_BACK_PORCH_LINES + MIPI_VSYNC_PULSE_WIDTH + TSH_MDT61_MIPI_FB_HEIGHT) - 1, |
| 202 | MDP_DSI_VIDEO_DISPLAY_V_END); |
| 203 | |
| 204 | /* Special Case for Toshiba 4in Panel */ |
| 205 | writel((1<<31) | |
| 206 | (MIPI_HSYNC_BACK_PORCH_DCLK + MIPI_HSYNC_PULSE_WIDTH + TSH_MDT61_MIPI_FB_WIDTH - 1)<<16 | |
| 207 | MIPI_HSYNC_PULSE_WIDTH + MIPI_HSYNC_BACK_PORCH_DCLK, MDP_DSI_VIDEO_ACTIVE_HCTL); |
| 208 | writel(1<<31 | hsync_period * (MIPI_VSYNC_BACK_PORCH_LINES + MIPI_VSYNC_PULSE_WIDTH), |
| 209 | MDP_DSI_VIDEO_DISPLAY_V_START); |
| 210 | writel((TSH_MDT61_MIPI_FB_HEIGHT + MIPI_VSYNC_BACK_PORCH_LINES + MIPI_VSYNC_PULSE_WIDTH) * |
| 211 | hsync_period - 1, MDP_DSI_VIDEO_DISPLAY_V_END); |
| 212 | |
| 213 | writel(0x00000001, MDP_DSI_VIDEO_EN); // MDP_DSI_EN ENABLE |
| 214 | } |
| 215 | |
| 216 | void config_mdt61_dsi_video_mode(void) |
| 217 | { |
| 218 | |
| 219 | unsigned char dst_format = 3; /* RGB888 */ |
| 220 | unsigned char traffic_mode = 1; /* non burst mode with sync start events */ |
| 221 | unsigned char lane_en = 7; /* 3 Lanes -- Enables Data Lane0, 1, 2 */ |
| 222 | unsigned long low_pwr_stop_mode = 0; |
| 223 | unsigned char eof_bllp_pwr = 0x8; /* Needed or else will have blank line at top of display */ |
| 224 | unsigned char interleav = 0; |
| 225 | |
| 226 | dprintf(SPEW, "DSI_Video_Mode - Dst Format: RGB888\n"); |
| 227 | dprintf(SPEW, "Data Lane: 3 lane\n"); |
| 228 | dprintf(SPEW, "Traffic mode: non burst mode with sync start events\n"); |
| 229 | |
| 230 | writel(0x00000000, MDP_DSI_VIDEO_EN); |
| 231 | |
| 232 | writel(0x00000000, DSI_CLK_CTRL); |
| 233 | writel(0x00000000, DSI_CLK_CTRL); |
| 234 | writel(0x00000000, DSI_CLK_CTRL); |
| 235 | writel(0x00000000, DSI_CLK_CTRL); |
| 236 | writel(0x00000002, DSI_CLK_CTRL); |
| 237 | writel(0x00000006, DSI_CLK_CTRL); |
| 238 | writel(0x0000000e, DSI_CLK_CTRL); |
| 239 | writel(0x0000001e, DSI_CLK_CTRL); |
| 240 | writel(0x0000003e, DSI_CLK_CTRL); |
| 241 | |
| 242 | writel(0, DSI_CTRL); |
| 243 | |
| 244 | writel(0, DSI_ERR_INT_MASK0); |
| 245 | |
| 246 | writel(0x02020202, DSI_INT_CTRL); |
| 247 | |
| 248 | writel((MIPI_HSYNC_PULSE_WIDTH + MIPI_HSYNC_BACK_PORCH_DCLK + TSH_MDT61_DISPLAY_WIDTH)<<16 | |
| 249 | (MIPI_HSYNC_PULSE_WIDTH + MIPI_HSYNC_BACK_PORCH_DCLK), DSI_VIDEO_MODE_ACTIVE_H); |
| 250 | |
| 251 | writel((MIPI_VSYNC_PULSE_WIDTH + MIPI_VSYNC_BACK_PORCH_LINES + TSH_MDT61_MIPI_FB_HEIGHT)<<16 | |
| 252 | (MIPI_VSYNC_PULSE_WIDTH + MIPI_VSYNC_BACK_PORCH_LINES), DSI_VIDEO_MODE_ACTIVE_V); |
| 253 | |
| 254 | writel((MIPI_VSYNC_PULSE_WIDTH + MIPI_VSYNC_BACK_PORCH_LINES + TSH_MDT61_MIPI_FB_HEIGHT + |
| 255 | MIPI_VSYNC_FRONT_PORCH_LINES - 1)<<16 | |
| 256 | (MIPI_HSYNC_PULSE_WIDTH + MIPI_HSYNC_BACK_PORCH_DCLK + TSH_MDT61_DISPLAY_WIDTH + |
| 257 | MIPI_HSYNC_FRONT_PORCH_DCLK - 1), DSI_VIDEO_MODE_TOTAL); |
| 258 | |
| 259 | writel((MIPI_HSYNC_PULSE_WIDTH)<<16 | 0, DSI_VIDEO_MODE_HSYNC); |
| 260 | |
| 261 | writel(0<<16 | 0, DSI_VIDEO_MODE_VSYNC); |
| 262 | |
| 263 | writel(MIPI_VSYNC_PULSE_WIDTH<<16 | 0, DSI_VIDEO_MODE_VSYNC_VPOS); |
| 264 | |
| 265 | writel(1, DSI_EOT_PACKET_CTRL); |
| 266 | |
| 267 | writel(low_pwr_stop_mode << 16 | eof_bllp_pwr << 12 | traffic_mode << 8 |
| 268 | | dst_format << 4 | 0x0, DSI_VIDEO_MODE_CTRL); |
| 269 | |
| 270 | writel(0x00010100, DSI_INT_CTRL); |
| 271 | writel(0x02010202, DSI_INT_CTRL); |
| 272 | writel(0x02030303, DSI_INT_CTRL); |
| 273 | |
| 274 | writel(interleav << 30 | 0 << 24 | 0 << 20 | lane_en << 4 |
| 275 | | 0x103, DSI_CTRL); |
| 276 | } |