| /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| #include <debug.h> |
| #include <msm_panel.h> |
| #include <dev/pm8921.h> |
| #include <board.h> |
| #include <mdp4.h> |
| #include <target/display.h> |
| #include <target/board.h> |
| |
| static struct msm_fb_panel_data panel; |
| static uint8_t display_enable; |
| |
| extern int msm_display_init(struct msm_fb_panel_data *pdata); |
| extern int msm_display_off(); |
| |
| static int apq8064_lvds_panel_power(int enable) |
| { |
| if (enable) { |
| /* Enable LVS7 */ |
| pm8921_low_voltage_switch_enable(lvs_7); |
| /* Set and enabale LDO2 1.2V for VDDA_LVDS_PLL*/ |
| pm8921_ldo_set_voltage(LDO_2, LDO_VOLTAGE_1_2V); |
| |
| /* Enable Ext 3.3V - MSM GPIO 77*/ |
| /* TODO: IS this really needed? This wasn't even implemented correctly. |
| * GPIO enable was not happening. |
| */ |
| apq8064_ext_3p3V_enable(); |
| |
| apq8064_display_gpio_init(); |
| |
| /* Configure PMM MPP 3*/ |
| pm8921_mpp_set_digital_output(mpp_3); |
| } |
| |
| return 0; |
| } |
| |
| static int apq8064_lvds_clock(int enable) |
| { |
| if (enable) |
| mdp_clock_init(); |
| |
| return 0; |
| } |
| |
| static int fusion3_mtp_panel_power(int enable) |
| { |
| if (enable) { |
| /* Enable LVS7 */ |
| pm8921_low_voltage_switch_enable(7); |
| |
| /* Set and enabale LDO2 1.2V for VDDA_MIPI_DSI0/1_PLL */ |
| pm8921_ldo_set_voltage(LDO_2, LDO_VOLTAGE_1_2V); |
| |
| /* Set and enabale LDO11 3.0V for LCD1_MIPI_AVDD */ |
| pm8921_ldo_set_voltage(LDO_11, LDO_VOLTAGE_3_0V); |
| |
| apq8064_display_gpio_init(); |
| } |
| |
| return 0; |
| } |
| |
| static int fusion3_mtp_clock(int enable) |
| { |
| if (enable) { |
| mdp_clock_init(); |
| mmss_clock_init(); |
| } else if(!target_cont_splash_screen()) { |
| mmss_clock_disable(); |
| } |
| |
| return 0; |
| } |
| |
| static void msm8960_backlight_on(void) |
| { |
| struct pm8921_gpio backlight_pwm = { |
| .direction = PM_GPIO_DIR_OUT, |
| .output_buffer = 0, |
| .output_value = 0, |
| .pull = PM_GPIO_PULL_NO, |
| .vin_sel = 2, |
| .out_strength = PM_GPIO_STRENGTH_HIGH, |
| .function = PM_GPIO_FUNC_1, |
| .inv_int_pol = 0, |
| }; |
| |
| int rc = pm8921_gpio_config(PM_GPIO(24), &backlight_pwm); |
| if (rc) |
| dprintf(CRITICAL, "FAIL pm8921_gpio_config(): rc=%d.\n", rc); |
| } |
| |
| /* Pull DISP_RST_N high to get panel out of reset */ |
| static void msm8960_mipi_panel_reset(void) |
| { |
| struct pm8921_gpio gpio43_param = { |
| .direction = PM_GPIO_DIR_OUT, |
| .output_buffer = 0, |
| .output_value = 1, |
| .pull = PM_GPIO_PULL_UP_30, |
| .vin_sel = 2, |
| .out_strength = PM_GPIO_STRENGTH_HIGH, |
| .function = PM_GPIO_FUNC_PAIRED, |
| .inv_int_pol = 0, |
| .disable_pin = 0, |
| }; |
| pm8921_gpio_config(PM_GPIO(43), &gpio43_param); |
| } |
| |
| static int msm8960_mipi_panel_clock(int enable) |
| { |
| if (enable) { |
| mdp_clock_init(); |
| mmss_clock_init(); |
| } else if(!target_cont_splash_screen()) { |
| mmss_clock_disable(); |
| } |
| |
| return 0; |
| } |
| |
| static int mpq8064_hdmi_panel_clock(int enable) |
| { |
| if (enable) |
| mdp_clock_init(); |
| |
| hdmi_app_clk_init(enable); |
| |
| return 0; |
| } |
| |
| static int mpq8064_hdmi_panel_power(int enable) |
| { |
| if (enable) |
| hdmi_power_init(); |
| |
| return 0; |
| } |
| |
| static int msm8960_liquid_mipi_panel_clock(int enable) |
| { |
| if (enable) { |
| mdp_clock_init(); |
| liquid_mmss_clock_init(); /* 240 MHZ MIPI-DSI clk */ |
| } else if(!target_cont_splash_screen()) { |
| mmss_clock_disable(); |
| } |
| |
| return 0; |
| } |
| |
| static int msm8960_mipi_panel_power(int enable) |
| { |
| if (enable) { |
| msm8960_backlight_on(); |
| |
| /* Turn on LDO8 for lcd1 mipi vdd */ |
| pm8921_ldo_set_voltage(LDO_8, LDO_VOLTAGE_3_0V); |
| |
| /* Turn on LDO23 for lcd1 mipi vddio */ |
| pm8921_ldo_set_voltage(LDO_23, LDO_VOLTAGE_1_8V); |
| |
| /* Turn on LDO2 for vdda_mipi_dsi */ |
| pm8921_ldo_set_voltage(LDO_2, LDO_VOLTAGE_1_2V); |
| |
| msm8960_mipi_panel_reset(); |
| } |
| |
| return 0; |
| } |
| |
| #define PM_GPIO_VIN_VPH 0 /* 3v ~ 4.4v */ |
| #define PM_GPIO_VIN_BB 1 /* ~3.3v */ |
| #define PM_GPIO_VIN_S4 2 /* 1.8v */ |
| #define PM_GPIO_VIN_L15 3 |
| |
| static int msm8960_liquid_mipi_panel_power(int enable) |
| { |
| if (enable) { |
| static int gpio17, gpio21, gpio43 ; |
| int rc; |
| |
| struct pm8921_gpio gpio_config = { |
| .direction = PM_GPIO_DIR_OUT, |
| .output_buffer = 0, |
| .output_value = 1, |
| .pull = PM_GPIO_PULL_NO, |
| .vin_sel = PM_GPIO_VIN_S4, |
| .out_strength = PM_GPIO_STRENGTH_HIGH, |
| .function = PM_GPIO_FUNC_NORMAL, |
| .inv_int_pol = 0, |
| .disable_pin = 0, |
| }; |
| |
| /* Note: PWM is controlled by PM-GPIO#24 */ |
| gpio17 = PM_GPIO(17); /* ext_3p3v */ |
| gpio21 = PM_GPIO(21); /* disp power enable_n , vin=VPH-PWR */ |
| gpio43 = PM_GPIO(43); /* Displays Enable (rst_n) */ |
| |
| gpio_config.output_value = 1; |
| rc = pm8921_gpio_config(gpio17, &gpio_config); |
| mdelay(100); |
| gpio_config.output_value = 0; |
| /* disp disable (resx=0) */ |
| rc = pm8921_gpio_config(gpio43, &gpio_config); |
| mdelay(100); |
| gpio_config.output_value = 0; |
| gpio_config.vin_sel = PM_GPIO_VIN_VPH; /* VPH_PWR */ |
| /* disp power enable_n */ |
| rc = pm8921_gpio_config(gpio21, &gpio_config); |
| mdelay(100); |
| gpio_config.output_value = 1; |
| gpio_config.vin_sel = PM_GPIO_VIN_S4; |
| /* disp enable */ |
| rc = pm8921_gpio_config(gpio43, &gpio_config); |
| mdelay(100); |
| |
| pm8921_low_voltage_switch_enable(lvs_4); /* S4 1.8 V */ |
| |
| /* Turn on LDO2 for vdda_mipi_dsi */ |
| pm8921_ldo_set_voltage(LDO_2, LDO_VOLTAGE_1_2V); |
| |
| msm8960_backlight_on(); |
| } |
| |
| return 0; |
| } |
| |
| void target_display_init(const char *panel_name) |
| { |
| int target_id = board_target_id(); |
| |
| dprintf(INFO, "display_init(),target_id=%d.\n", target_id); |
| |
| switch (target_id) { |
| case LINUX_MACHTYPE_8960_LIQUID: |
| mipi_chimei_video_wxga_init(&(panel.panel_info)); |
| /* |
| * mipi_chimei_wxga panel not supported yet in LK. |
| * However, MIPI clocks and power should be set in LK. |
| */ |
| panel.clk_func = msm8960_liquid_mipi_panel_clock; |
| panel.power_func = msm8960_liquid_mipi_panel_power; |
| panel.fb.base = MIPI_FB_ADDR; |
| panel.fb.width = panel.panel_info.xres; |
| panel.fb.height = panel.panel_info.yres; |
| panel.fb.stride = panel.panel_info.xres; |
| panel.fb.bpp = panel.panel_info.bpp; |
| panel.fb.format = FB_FORMAT_RGB888; |
| panel.mdp_rev = MDP_REV_44; |
| break; |
| case LINUX_MACHTYPE_8064_CDP: |
| lvds_chimei_wxga_init(&(panel.panel_info)); |
| panel.clk_func = apq8064_lvds_clock; |
| panel.power_func = apq8064_lvds_panel_power; |
| panel.fb.base = 0x80B00000; |
| panel.fb.width = panel.panel_info.xres; |
| panel.fb.height = panel.panel_info.yres; |
| panel.fb.stride = panel.panel_info.xres; |
| panel.fb.bpp = panel.panel_info.bpp; |
| panel.fb.format = FB_FORMAT_RGB888; |
| panel.mdp_rev = MDP_REV_44; |
| break; |
| case LINUX_MACHTYPE_8064_MTP: |
| mipi_toshiba_video_wsvga_init(&(panel.panel_info)); |
| panel.clk_func = fusion3_mtp_clock; |
| panel.power_func = fusion3_mtp_panel_power; |
| panel.fb.base = 0x89000000; |
| panel.fb.width = panel.panel_info.xres; |
| panel.fb.height = panel.panel_info.yres; |
| panel.fb.stride = panel.panel_info.xres; |
| panel.fb.bpp = panel.panel_info.bpp; |
| panel.fb.format = FB_FORMAT_RGB888; |
| panel.mdp_rev = MDP_REV_44; |
| break; |
| case LINUX_MACHTYPE_8960_CDP: |
| case LINUX_MACHTYPE_8960_MTP: |
| case LINUX_MACHTYPE_8960_FLUID: |
| mipi_toshiba_video_wsvga_init(&(panel.panel_info)); |
| panel.clk_func = msm8960_mipi_panel_clock; |
| panel.power_func = msm8960_mipi_panel_power; |
| panel.fb.base = 0x89000000; |
| panel.fb.width = panel.panel_info.xres; |
| panel.fb.height = panel.panel_info.yres; |
| panel.fb.stride = panel.panel_info.xres; |
| panel.fb.bpp = panel.panel_info.bpp; |
| panel.fb.format = FB_FORMAT_RGB888; |
| panel.mdp_rev = MDP_REV_42; |
| break; |
| case LINUX_MACHTYPE_8064_MPQ_CDP: |
| case LINUX_MACHTYPE_8064_MPQ_HRD: |
| case LINUX_MACHTYPE_8064_MPQ_DTV: |
| hdmi_msm_panel_init(&panel.panel_info); |
| |
| panel.clk_func = mpq8064_hdmi_panel_clock; |
| panel.power_func = mpq8064_hdmi_panel_power; |
| panel.fb.base = 0x89000000; |
| panel.fb.width = panel.panel_info.xres; |
| panel.fb.height = panel.panel_info.yres; |
| panel.fb.stride = panel.panel_info.xres; |
| panel.fb.bpp = panel.panel_info.bpp; |
| panel.fb.format = FB_FORMAT_RGB565; |
| panel.mdp_rev = MDP_REV_44; |
| |
| hdmi_set_fb_addr(panel.fb.base); |
| break; |
| default: |
| return; |
| }; |
| |
| if (msm_display_init(&panel)) { |
| dprintf(CRITICAL, "Display init failed!\n"); |
| return; |
| } |
| |
| display_enable = 1; |
| } |
| |
| void target_display_shutdown(void) |
| { |
| if (display_enable) { |
| msm_display_off(); |
| } |
| } |
| |