18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright © 2010 Intel Corporation 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 218c2ecf20Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Authors: 248c2ecf20Sopenharmony_ci * jim liu <jim.liu@intel.com> 258c2ecf20Sopenharmony_ci * Jackie Li<yaodong.li@intel.com> 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <linux/delay.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <drm/drm_simple_kms_helper.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "mdfld_dsi_dpi.h" 338c2ecf20Sopenharmony_ci#include "mdfld_dsi_pkg_sender.h" 348c2ecf20Sopenharmony_ci#include "mdfld_output.h" 358c2ecf20Sopenharmony_ci#include "psb_drv.h" 368c2ecf20Sopenharmony_ci#include "tc35876x-dsi-lvds.h" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, 398c2ecf20Sopenharmony_ci int pipe); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); 448c2ecf20Sopenharmony_ci int timeout = 0; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci udelay(500); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* This will time out after approximately 2+ seconds */ 498c2ecf20Sopenharmony_ci while ((timeout < 20000) && 508c2ecf20Sopenharmony_ci (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) { 518c2ecf20Sopenharmony_ci udelay(100); 528c2ecf20Sopenharmony_ci timeout++; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (timeout == 20000) 568c2ecf20Sopenharmony_ci DRM_INFO("MIPI: HS Data FIFO was never cleared!\n"); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); 628c2ecf20Sopenharmony_ci int timeout = 0; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci udelay(500); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* This will time out after approximately 2+ seconds */ 678c2ecf20Sopenharmony_ci while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) 688c2ecf20Sopenharmony_ci & DSI_FIFO_GEN_HS_CTRL_FULL)) { 698c2ecf20Sopenharmony_ci udelay(100); 708c2ecf20Sopenharmony_ci timeout++; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci if (timeout == 20000) 738c2ecf20Sopenharmony_ci DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n"); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); 798c2ecf20Sopenharmony_ci int timeout = 0; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci udelay(500); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* This will time out after approximately 2+ seconds */ 848c2ecf20Sopenharmony_ci while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & 858c2ecf20Sopenharmony_ci DPI_FIFO_EMPTY) != DPI_FIFO_EMPTY)) { 868c2ecf20Sopenharmony_ci udelay(100); 878c2ecf20Sopenharmony_ci timeout++; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (timeout == 20000) 918c2ecf20Sopenharmony_ci DRM_ERROR("MIPI: DPI FIFO was never cleared\n"); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe); 978c2ecf20Sopenharmony_ci int timeout = 0; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci udelay(500); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* This will time out after approximately 2+ seconds */ 1028c2ecf20Sopenharmony_ci while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) 1038c2ecf20Sopenharmony_ci & DSI_INTR_STATE_SPL_PKG_SENT))) { 1048c2ecf20Sopenharmony_ci udelay(100); 1058c2ecf20Sopenharmony_ci timeout++; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (timeout == 20000) 1098c2ecf20Sopenharmony_ci DRM_ERROR("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n"); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* For TC35876X */ 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic void dsi_set_device_ready_state(struct drm_device *dev, int state, 1158c2ecf20Sopenharmony_ci int pipe) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), !!state, 0, 0); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic void dsi_set_pipe_plane_enable_state(struct drm_device *dev, 1218c2ecf20Sopenharmony_ci int state, int pipe) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 1248c2ecf20Sopenharmony_ci u32 pipeconf_reg = PIPEACONF; 1258c2ecf20Sopenharmony_ci u32 dspcntr_reg = DSPACNTR; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci u32 dspcntr = dev_priv->dspcntr[pipe]; 1288c2ecf20Sopenharmony_ci u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (pipe) { 1318c2ecf20Sopenharmony_ci pipeconf_reg = PIPECCONF; 1328c2ecf20Sopenharmony_ci dspcntr_reg = DSPCCNTR; 1338c2ecf20Sopenharmony_ci } else 1348c2ecf20Sopenharmony_ci mipi &= (~0x03); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (state) { 1378c2ecf20Sopenharmony_ci /*Set up pipe */ 1388c2ecf20Sopenharmony_ci REG_WRITE(pipeconf_reg, BIT(31)); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (REG_BIT_WAIT(pipeconf_reg, 1, 30)) 1418c2ecf20Sopenharmony_ci dev_err(&dev->pdev->dev, "%s: Pipe enable timeout\n", 1428c2ecf20Sopenharmony_ci __func__); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /*Set up display plane */ 1458c2ecf20Sopenharmony_ci REG_WRITE(dspcntr_reg, dspcntr); 1468c2ecf20Sopenharmony_ci } else { 1478c2ecf20Sopenharmony_ci u32 dspbase_reg = pipe ? MDFLD_DSPCBASE : MRST_DSPABASE; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* Put DSI lanes to ULPS to disable pipe */ 1508c2ecf20Sopenharmony_ci REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 2, 2, 1); 1518c2ecf20Sopenharmony_ci REG_READ(MIPI_DEVICE_READY_REG(pipe)); /* posted write? */ 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* LP Hold */ 1548c2ecf20Sopenharmony_ci REG_FLD_MOD(MIPI_PORT_CONTROL(pipe), 0, 16, 16); 1558c2ecf20Sopenharmony_ci REG_READ(MIPI_PORT_CONTROL(pipe)); /* posted write? */ 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Disable display plane */ 1588c2ecf20Sopenharmony_ci REG_FLD_MOD(dspcntr_reg, 0, 31, 31); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Flush the plane changes ??? posted write? */ 1618c2ecf20Sopenharmony_ci REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); 1628c2ecf20Sopenharmony_ci REG_READ(dspbase_reg); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* Disable PIPE */ 1658c2ecf20Sopenharmony_ci REG_FLD_MOD(pipeconf_reg, 0, 31, 31); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci if (REG_BIT_WAIT(pipeconf_reg, 0, 30)) 1688c2ecf20Sopenharmony_ci dev_err(&dev->pdev->dev, "%s: Pipe disable timeout\n", 1698c2ecf20Sopenharmony_ci __func__); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci if (REG_BIT_WAIT(MIPI_GEN_FIFO_STAT_REG(pipe), 1, 28)) 1728c2ecf20Sopenharmony_ci dev_err(&dev->pdev->dev, "%s: FIFO not empty\n", 1738c2ecf20Sopenharmony_ci __func__); 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void mdfld_dsi_configure_down(struct mdfld_dsi_encoder *dsi_encoder, 1788c2ecf20Sopenharmony_ci int pipe) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_output *dpi_output = 1818c2ecf20Sopenharmony_ci MDFLD_DSI_DPI_OUTPUT(dsi_encoder); 1828c2ecf20Sopenharmony_ci struct mdfld_dsi_config *dsi_config = 1838c2ecf20Sopenharmony_ci mdfld_dsi_encoder_get_config(dsi_encoder); 1848c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 1858c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (!dev_priv->dpi_panel_on[pipe]) { 1888c2ecf20Sopenharmony_ci dev_err(dev->dev, "DPI panel is already off\n"); 1898c2ecf20Sopenharmony_ci return; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci tc35876x_toshiba_bridge_panel_off(dev); 1928c2ecf20Sopenharmony_ci tc35876x_set_bridge_reset_state(dev, 1); 1938c2ecf20Sopenharmony_ci dsi_set_pipe_plane_enable_state(dev, 0, pipe); 1948c2ecf20Sopenharmony_ci mdfld_dsi_dpi_shut_down(dpi_output, pipe); 1958c2ecf20Sopenharmony_ci dsi_set_device_ready_state(dev, 0, pipe); 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic void mdfld_dsi_configure_up(struct mdfld_dsi_encoder *dsi_encoder, 1998c2ecf20Sopenharmony_ci int pipe) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_output *dpi_output = 2028c2ecf20Sopenharmony_ci MDFLD_DSI_DPI_OUTPUT(dsi_encoder); 2038c2ecf20Sopenharmony_ci struct mdfld_dsi_config *dsi_config = 2048c2ecf20Sopenharmony_ci mdfld_dsi_encoder_get_config(dsi_encoder); 2058c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 2068c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (dev_priv->dpi_panel_on[pipe]) { 2098c2ecf20Sopenharmony_ci dev_err(dev->dev, "DPI panel is already on\n"); 2108c2ecf20Sopenharmony_ci return; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* For resume path sequence */ 2148c2ecf20Sopenharmony_ci mdfld_dsi_dpi_shut_down(dpi_output, pipe); 2158c2ecf20Sopenharmony_ci dsi_set_device_ready_state(dev, 0, pipe); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci dsi_set_device_ready_state(dev, 1, pipe); 2188c2ecf20Sopenharmony_ci tc35876x_set_bridge_reset_state(dev, 0); 2198c2ecf20Sopenharmony_ci tc35876x_configure_lvds_bridge(dev); 2208c2ecf20Sopenharmony_ci mdfld_dsi_dpi_turn_on(dpi_output, pipe); /* Send turn on command */ 2218c2ecf20Sopenharmony_ci dsi_set_pipe_plane_enable_state(dev, 1, pipe); 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci/* End for TC35876X */ 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* ************************************************************************* *\ 2268c2ecf20Sopenharmony_ci * FUNCTION: mdfld_dsi_tpo_ic_init 2278c2ecf20Sopenharmony_ci * 2288c2ecf20Sopenharmony_ci * DESCRIPTION: This function is called only by mrst_dsi_mode_set and 2298c2ecf20Sopenharmony_ci * restore_display_registers. since this function does not 2308c2ecf20Sopenharmony_ci * acquire the mutex, it is important that the calling function 2318c2ecf20Sopenharmony_ci * does! 2328c2ecf20Sopenharmony_ci\* ************************************************************************* */ 2338c2ecf20Sopenharmony_cistatic void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 2368c2ecf20Sopenharmony_ci u32 dcsChannelNumber = dsi_config->channel_num; 2378c2ecf20Sopenharmony_ci u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe); 2388c2ecf20Sopenharmony_ci u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe); 2398c2ecf20Sopenharmony_ci u32 gen_ctrl_val = GEN_LONG_WRITE; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci DRM_INFO("Enter mrst init TPO MIPI display.\n"); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci /* Flip page order */ 2468c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2478c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x00008036); 2488c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 2498c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* 0xF0 */ 2528c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2538c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x005a5af0); 2548c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 2558c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* Write protection key */ 2588c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2598c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x005a5af1); 2608c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 2618c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* 0xFC */ 2648c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2658c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x005a5afc); 2668c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 2678c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* 0xB7 */ 2708c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2718c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x770000b7); 2728c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2738c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x00000044); 2748c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 2758c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS)); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* 0xB6 */ 2788c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2798c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x000a0ab6); 2808c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 2818c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* 0xF2 */ 2848c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2858c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x081010f2); 2868c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2878c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x4a070708); 2888c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2898c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x000000c5); 2908c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 2918c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* 0xF8 */ 2948c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2958c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x024003f8); 2968c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2978c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x01030a04); 2988c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 2998c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x0e020220); 3008c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3018c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x00000004); 3028c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 3038c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS)); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* 0xE2 */ 3068c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3078c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x398fc3e2); 3088c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3098c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x0000916f); 3108c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 3118c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS)); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* 0xB0 */ 3148c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3158c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x000000b0); 3168c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 3178c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* 0xF4 */ 3208c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3218c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x240242f4); 3228c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3238c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x78ee2002); 3248c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3258c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x2a071050); 3268c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3278c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x507fee10); 3288c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3298c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x10300710); 3308c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 3318c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS)); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* 0xBA */ 3348c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3358c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x19fe07ba); 3368c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3378c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x101c0a31); 3388c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3398c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x00000010); 3408c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 3418c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* 0xBB */ 3448c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3458c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x28ff07bb); 3468c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3478c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x24280a31); 3488c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3498c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x00000034); 3508c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 3518c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci /* 0xFB */ 3548c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3558c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x535d05fb); 3568c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3578c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x1b1a2130); 3588c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3598c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x221e180e); 3608c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3618c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x131d2120); 3628c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3638c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x535d0508); 3648c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3658c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x1c1a2131); 3668c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3678c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x231f160d); 3688c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3698c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x111b2220); 3708c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3718c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x535c2008); 3728c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3738c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x1f1d2433); 3748c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3758c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x2c251a10); 3768c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3778c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x2c34372d); 3788c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3798c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x00000023); 3808c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 3818c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* 0xFA */ 3848c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3858c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x525c0bfa); 3868c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3878c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x1c1c232f); 3888c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3898c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x2623190e); 3908c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3918c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x18212625); 3928c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3938c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x545d0d0e); 3948c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3958c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x1e1d2333); 3968c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3978c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x26231a10); 3988c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 3998c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x1a222725); 4008c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 4018c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x545d280f); 4028c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 4038c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x21202635); 4048c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 4058c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x31292013); 4068c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 4078c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x31393d33); 4088c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 4098c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x00000029); 4108c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 4118c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci /* Set DM */ 4148c2ecf20Sopenharmony_ci mdfld_wait_for_HS_DATA_FIFO(dev, pipe); 4158c2ecf20Sopenharmony_ci REG_WRITE(gen_data_reg, 0x000100f7); 4168c2ecf20Sopenharmony_ci mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); 4178c2ecf20Sopenharmony_ci REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, 4218c2ecf20Sopenharmony_ci int num_lane, int bpp) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci/* 4278c2ecf20Sopenharmony_ci * Calculate the dpi time basing on a given drm mode @mode 4288c2ecf20Sopenharmony_ci * return 0 on success. 4298c2ecf20Sopenharmony_ci * FIXME: I was using proposed mode value for calculation, may need to 4308c2ecf20Sopenharmony_ci * use crtc mode values later 4318c2ecf20Sopenharmony_ci */ 4328c2ecf20Sopenharmony_ciint mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, 4338c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_timing *dpi_timing, 4348c2ecf20Sopenharmony_ci int num_lane, int bpp) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive; 4378c2ecf20Sopenharmony_ci int pclk_vsync, pclk_vfp, pclk_vbp; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci pclk_hactive = mode->hdisplay; 4408c2ecf20Sopenharmony_ci pclk_hfp = mode->hsync_start - mode->hdisplay; 4418c2ecf20Sopenharmony_ci pclk_hsync = mode->hsync_end - mode->hsync_start; 4428c2ecf20Sopenharmony_ci pclk_hbp = mode->htotal - mode->hsync_end; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci pclk_vfp = mode->vsync_start - mode->vdisplay; 4458c2ecf20Sopenharmony_ci pclk_vsync = mode->vsync_end - mode->vsync_start; 4468c2ecf20Sopenharmony_ci pclk_vbp = mode->vtotal - mode->vsync_end; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci /* 4498c2ecf20Sopenharmony_ci * byte clock counts were calculated by following formula 4508c2ecf20Sopenharmony_ci * bclock_count = pclk_count * bpp / num_lane / 8 4518c2ecf20Sopenharmony_ci */ 4528c2ecf20Sopenharmony_ci dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count( 4538c2ecf20Sopenharmony_ci pclk_hsync, num_lane, bpp); 4548c2ecf20Sopenharmony_ci dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count( 4558c2ecf20Sopenharmony_ci pclk_hbp, num_lane, bpp); 4568c2ecf20Sopenharmony_ci dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count( 4578c2ecf20Sopenharmony_ci pclk_hfp, num_lane, bpp); 4588c2ecf20Sopenharmony_ci dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count( 4598c2ecf20Sopenharmony_ci pclk_hactive, num_lane, bpp); 4608c2ecf20Sopenharmony_ci dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count( 4618c2ecf20Sopenharmony_ci pclk_vsync, num_lane, bpp); 4628c2ecf20Sopenharmony_ci dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count( 4638c2ecf20Sopenharmony_ci pclk_vbp, num_lane, bpp); 4648c2ecf20Sopenharmony_ci dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count( 4658c2ecf20Sopenharmony_ci pclk_vfp, num_lane, bpp); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci return 0; 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_civoid mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, 4718c2ecf20Sopenharmony_ci int pipe) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 4748c2ecf20Sopenharmony_ci int lane_count = dsi_config->lane_count; 4758c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_timing dpi_timing; 4768c2ecf20Sopenharmony_ci struct drm_display_mode *mode = dsi_config->mode; 4778c2ecf20Sopenharmony_ci u32 val; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci /*un-ready device*/ 4808c2ecf20Sopenharmony_ci REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /*init dsi adapter before kicking off*/ 4838c2ecf20Sopenharmony_ci REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /*enable all interrupts*/ 4868c2ecf20Sopenharmony_ci REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci /*set up func_prg*/ 4898c2ecf20Sopenharmony_ci val = lane_count; 4908c2ecf20Sopenharmony_ci val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci switch (dsi_config->bpp) { 4938c2ecf20Sopenharmony_ci case 16: 4948c2ecf20Sopenharmony_ci val |= DSI_DPI_COLOR_FORMAT_RGB565; 4958c2ecf20Sopenharmony_ci break; 4968c2ecf20Sopenharmony_ci case 18: 4978c2ecf20Sopenharmony_ci val |= DSI_DPI_COLOR_FORMAT_RGB666; 4988c2ecf20Sopenharmony_ci break; 4998c2ecf20Sopenharmony_ci case 24: 5008c2ecf20Sopenharmony_ci val |= DSI_DPI_COLOR_FORMAT_RGB888; 5018c2ecf20Sopenharmony_ci break; 5028c2ecf20Sopenharmony_ci default: 5038c2ecf20Sopenharmony_ci DRM_ERROR("unsupported color format, bpp = %d\n", 5048c2ecf20Sopenharmony_ci dsi_config->bpp); 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 5098c2ecf20Sopenharmony_ci (mode->vtotal * mode->htotal * dsi_config->bpp / 5108c2ecf20Sopenharmony_ci (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); 5118c2ecf20Sopenharmony_ci REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 5128c2ecf20Sopenharmony_ci 0xffff & DSI_LP_RX_TIMEOUT_MASK); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci /*max value: 20 clock cycles of txclkesc*/ 5158c2ecf20Sopenharmony_ci REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 5168c2ecf20Sopenharmony_ci 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci /*min 21 txclkesc, max: ffffh*/ 5198c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 5208c2ecf20Sopenharmony_ci 0xffff & DSI_RESET_TIMER_MASK); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), 5238c2ecf20Sopenharmony_ci mode->vdisplay << 16 | mode->hdisplay); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci /*set DPI timing registers*/ 5268c2ecf20Sopenharmony_ci mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, 5278c2ecf20Sopenharmony_ci dsi_config->lane_count, dsi_config->bpp); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), 5308c2ecf20Sopenharmony_ci dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); 5318c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HBP_COUNT_REG(pipe), 5328c2ecf20Sopenharmony_ci dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); 5338c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HFP_COUNT_REG(pipe), 5348c2ecf20Sopenharmony_ci dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); 5358c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), 5368c2ecf20Sopenharmony_ci dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); 5378c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), 5388c2ecf20Sopenharmony_ci dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); 5398c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VBP_COUNT_REG(pipe), 5408c2ecf20Sopenharmony_ci dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); 5418c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VFP_COUNT_REG(pipe), 5428c2ecf20Sopenharmony_ci dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci /*min: 7d0 max: 4e20*/ 5478c2ecf20Sopenharmony_ci REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci /*set up video mode*/ 5508c2ecf20Sopenharmony_ci val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; 5518c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci /*TODO: figure out how to setup these registers*/ 5588c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TC35876X) 5598c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); 5608c2ecf20Sopenharmony_ci else 5618c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TC35876X) 5668c2ecf20Sopenharmony_ci tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci /*set device ready*/ 5698c2ecf20Sopenharmony_ci REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_civoid mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci struct drm_device *dev = output->dev; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci /* clear special packet sent bit */ 5778c2ecf20Sopenharmony_ci if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) 5788c2ecf20Sopenharmony_ci REG_WRITE(MIPI_INTR_STAT_REG(pipe), 5798c2ecf20Sopenharmony_ci DSI_INTR_STATE_SPL_PKG_SENT); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci /*send turn on package*/ 5828c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci /*wait for SPL_PKG_SENT interrupt*/ 5858c2ecf20Sopenharmony_ci mdfld_wait_for_SPL_PKG_SENT(dev, pipe); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) 5888c2ecf20Sopenharmony_ci REG_WRITE(MIPI_INTR_STAT_REG(pipe), 5898c2ecf20Sopenharmony_ci DSI_INTR_STATE_SPL_PKG_SENT); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci output->panel_on = 1; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci /* FIXME the following is disabled to WA the X slow start issue 5948c2ecf20Sopenharmony_ci for TMD panel 5958c2ecf20Sopenharmony_ci if (pipe == 2) 5968c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on2 = true; 5978c2ecf20Sopenharmony_ci else if (pipe == 0) 5988c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on = true; */ 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cistatic void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, 6028c2ecf20Sopenharmony_ci int pipe) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci struct drm_device *dev = output->dev; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci /*if output is on, or mode setting didn't happen, ignore this*/ 6078c2ecf20Sopenharmony_ci if ((!output->panel_on) || output->first_boot) { 6088c2ecf20Sopenharmony_ci output->first_boot = 0; 6098c2ecf20Sopenharmony_ci return; 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* Wait for dpi fifo to empty */ 6138c2ecf20Sopenharmony_ci mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* Clear the special packet interrupt bit if set */ 6168c2ecf20Sopenharmony_ci if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) 6178c2ecf20Sopenharmony_ci REG_WRITE(MIPI_INTR_STAT_REG(pipe), 6188c2ecf20Sopenharmony_ci DSI_INTR_STATE_SPL_PKG_SENT); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN) 6218c2ecf20Sopenharmony_ci goto shutdown_out; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN); 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cishutdown_out: 6268c2ecf20Sopenharmony_ci output->panel_on = 0; 6278c2ecf20Sopenharmony_ci output->first_boot = 0; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* FIXME the following is disabled to WA the X slow start issue 6308c2ecf20Sopenharmony_ci for TMD panel 6318c2ecf20Sopenharmony_ci if (pipe == 2) 6328c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on2 = false; 6338c2ecf20Sopenharmony_ci else if (pipe == 0) 6348c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on = false; */ 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); 6408c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_output *dpi_output = 6418c2ecf20Sopenharmony_ci MDFLD_DSI_DPI_OUTPUT(dsi_encoder); 6428c2ecf20Sopenharmony_ci struct mdfld_dsi_config *dsi_config = 6438c2ecf20Sopenharmony_ci mdfld_dsi_encoder_get_config(dsi_encoder); 6448c2ecf20Sopenharmony_ci int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); 6458c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 6468c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci /*start up display island if it was shutdown*/ 6498c2ecf20Sopenharmony_ci if (!gma_power_begin(dev, true)) 6508c2ecf20Sopenharmony_ci return; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (on) { 6538c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TMD_VID) 6548c2ecf20Sopenharmony_ci mdfld_dsi_dpi_turn_on(dpi_output, pipe); 6558c2ecf20Sopenharmony_ci else if (mdfld_get_panel_type(dev, pipe) == TC35876X) 6568c2ecf20Sopenharmony_ci mdfld_dsi_configure_up(dsi_encoder, pipe); 6578c2ecf20Sopenharmony_ci else { 6588c2ecf20Sopenharmony_ci /*enable mipi port*/ 6598c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(pipe), 6608c2ecf20Sopenharmony_ci REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31)); 6618c2ecf20Sopenharmony_ci REG_READ(MIPI_PORT_CONTROL(pipe)); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci mdfld_dsi_dpi_turn_on(dpi_output, pipe); 6648c2ecf20Sopenharmony_ci mdfld_dsi_tpo_ic_init(dsi_config, pipe); 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on[pipe] = true; 6678c2ecf20Sopenharmony_ci } else { 6688c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TMD_VID) 6698c2ecf20Sopenharmony_ci mdfld_dsi_dpi_shut_down(dpi_output, pipe); 6708c2ecf20Sopenharmony_ci else if (mdfld_get_panel_type(dev, pipe) == TC35876X) 6718c2ecf20Sopenharmony_ci mdfld_dsi_configure_down(dsi_encoder, pipe); 6728c2ecf20Sopenharmony_ci else { 6738c2ecf20Sopenharmony_ci mdfld_dsi_dpi_shut_down(dpi_output, pipe); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci /*disable mipi port*/ 6768c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(pipe), 6778c2ecf20Sopenharmony_ci REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31)); 6788c2ecf20Sopenharmony_ci REG_READ(MIPI_PORT_CONTROL(pipe)); 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on[pipe] = false; 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci gma_power_end(dev); 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_civoid mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci mdfld_dsi_dpi_set_power(encoder, mode == DRM_MODE_DPMS_ON); 6888c2ecf20Sopenharmony_ci} 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_cibool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, 6918c2ecf20Sopenharmony_ci const struct drm_display_mode *mode, 6928c2ecf20Sopenharmony_ci struct drm_display_mode *adjusted_mode) 6938c2ecf20Sopenharmony_ci{ 6948c2ecf20Sopenharmony_ci struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); 6958c2ecf20Sopenharmony_ci struct mdfld_dsi_config *dsi_config = 6968c2ecf20Sopenharmony_ci mdfld_dsi_encoder_get_config(dsi_encoder); 6978c2ecf20Sopenharmony_ci struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci if (fixed_mode) { 7008c2ecf20Sopenharmony_ci adjusted_mode->hdisplay = fixed_mode->hdisplay; 7018c2ecf20Sopenharmony_ci adjusted_mode->hsync_start = fixed_mode->hsync_start; 7028c2ecf20Sopenharmony_ci adjusted_mode->hsync_end = fixed_mode->hsync_end; 7038c2ecf20Sopenharmony_ci adjusted_mode->htotal = fixed_mode->htotal; 7048c2ecf20Sopenharmony_ci adjusted_mode->vdisplay = fixed_mode->vdisplay; 7058c2ecf20Sopenharmony_ci adjusted_mode->vsync_start = fixed_mode->vsync_start; 7068c2ecf20Sopenharmony_ci adjusted_mode->vsync_end = fixed_mode->vsync_end; 7078c2ecf20Sopenharmony_ci adjusted_mode->vtotal = fixed_mode->vtotal; 7088c2ecf20Sopenharmony_ci adjusted_mode->clock = fixed_mode->clock; 7098c2ecf20Sopenharmony_ci drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci return true; 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_civoid mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci mdfld_dsi_dpi_set_power(encoder, false); 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_civoid mdfld_dsi_dpi_commit(struct drm_encoder *encoder) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci mdfld_dsi_dpi_set_power(encoder, true); 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci/* For TC35876X */ 7258c2ecf20Sopenharmony_ci/* This functionality was implemented in FW in iCDK */ 7268c2ecf20Sopenharmony_ci/* But removed in DV0 and later. So need to add here. */ 7278c2ecf20Sopenharmony_cistatic void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); 7328c2ecf20Sopenharmony_ci REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); 7338c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff); 7348c2ecf20Sopenharmony_ci REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff); 7358c2ecf20Sopenharmony_ci REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14); 7368c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff); 7378c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25); 7388c2ecf20Sopenharmony_ci REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0); 7398c2ecf20Sopenharmony_ci REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); 7408c2ecf20Sopenharmony_ci REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); 7418c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820); 7428c2ecf20Sopenharmony_ci REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config, 7468c2ecf20Sopenharmony_ci int pipe) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 7498c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_timing dpi_timing; 7508c2ecf20Sopenharmony_ci struct drm_display_mode *mode = dsi_config->mode; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, 7538c2ecf20Sopenharmony_ci dsi_config->lane_count, 7548c2ecf20Sopenharmony_ci dsi_config->bpp); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), 7578c2ecf20Sopenharmony_ci mode->vdisplay << 16 | mode->hdisplay); 7588c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), 7598c2ecf20Sopenharmony_ci dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); 7608c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HBP_COUNT_REG(pipe), 7618c2ecf20Sopenharmony_ci dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); 7628c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HFP_COUNT_REG(pipe), 7638c2ecf20Sopenharmony_ci dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); 7648c2ecf20Sopenharmony_ci REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), 7658c2ecf20Sopenharmony_ci dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); 7668c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), 7678c2ecf20Sopenharmony_ci dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); 7688c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VBP_COUNT_REG(pipe), 7698c2ecf20Sopenharmony_ci dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); 7708c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VFP_COUNT_REG(pipe), 7718c2ecf20Sopenharmony_ci dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_cistatic void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe) 7758c2ecf20Sopenharmony_ci{ 7768c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 7778c2ecf20Sopenharmony_ci int lane_count = dsi_config->lane_count; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci if (pipe) { 7808c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002); 7818c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000); 7828c2ecf20Sopenharmony_ci } else { 7838c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000); 7848c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(2), 0x00); 7858c2ecf20Sopenharmony_ci } 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F); 7888c2ecf20Sopenharmony_ci REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci /* lane_count = 3 */ 7918c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci mdfld_mipi_set_video_timing(dsi_config, pipe); 7948c2ecf20Sopenharmony_ci} 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_cistatic void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 7998c2ecf20Sopenharmony_ci struct drm_display_mode *mode = dsi_config->mode; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1)); 8028c2ecf20Sopenharmony_ci REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1)); 8038c2ecf20Sopenharmony_ci REG_WRITE(HSYNC_A, 8048c2ecf20Sopenharmony_ci ((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1)); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1)); 8078c2ecf20Sopenharmony_ci REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1)); 8088c2ecf20Sopenharmony_ci REG_WRITE(VSYNC_A, 8098c2ecf20Sopenharmony_ci ((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1)); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci REG_WRITE(PIPEASRC, 8128c2ecf20Sopenharmony_ci ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); 8138c2ecf20Sopenharmony_ci} 8148c2ecf20Sopenharmony_ci/* End for TC35876X */ 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_civoid mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, 8178c2ecf20Sopenharmony_ci struct drm_display_mode *mode, 8188c2ecf20Sopenharmony_ci struct drm_display_mode *adjusted_mode) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); 8218c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_output *dpi_output = 8228c2ecf20Sopenharmony_ci MDFLD_DSI_DPI_OUTPUT(dsi_encoder); 8238c2ecf20Sopenharmony_ci struct mdfld_dsi_config *dsi_config = 8248c2ecf20Sopenharmony_ci mdfld_dsi_encoder_get_config(dsi_encoder); 8258c2ecf20Sopenharmony_ci struct drm_device *dev = dsi_config->dev; 8268c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 8278c2ecf20Sopenharmony_ci int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); 8288c2ecf20Sopenharmony_ci u32 pipeconf_reg = PIPEACONF; 8298c2ecf20Sopenharmony_ci u32 dspcntr_reg = DSPACNTR; 8308c2ecf20Sopenharmony_ci u32 pipeconf, dspcntr; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci if (WARN_ON(pipe < 0)) 8358c2ecf20Sopenharmony_ci return; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci pipeconf = dev_priv->pipeconf[pipe]; 8388c2ecf20Sopenharmony_ci dspcntr = dev_priv->dspcntr[pipe]; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (pipe) { 8418c2ecf20Sopenharmony_ci pipeconf_reg = PIPECCONF; 8428c2ecf20Sopenharmony_ci dspcntr_reg = DSPCCNTR; 8438c2ecf20Sopenharmony_ci } else { 8448c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TC35876X) 8458c2ecf20Sopenharmony_ci mipi &= (~0x03); /* Use all four lanes */ 8468c2ecf20Sopenharmony_ci else 8478c2ecf20Sopenharmony_ci mipi |= 2; 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci /*start up display island if it was shutdown*/ 8518c2ecf20Sopenharmony_ci if (!gma_power_begin(dev, true)) 8528c2ecf20Sopenharmony_ci return; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TC35876X) { 8558c2ecf20Sopenharmony_ci /* 8568c2ecf20Sopenharmony_ci * The following logic is required to reset the bridge and 8578c2ecf20Sopenharmony_ci * configure. This also starts the DSI clock at 200MHz. 8588c2ecf20Sopenharmony_ci */ 8598c2ecf20Sopenharmony_ci tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ 8608c2ecf20Sopenharmony_ci tc35876x_toshiba_bridge_panel_on(dev); 8618c2ecf20Sopenharmony_ci udelay(100); 8628c2ecf20Sopenharmony_ci /* Now start the DSI clock */ 8638c2ecf20Sopenharmony_ci REG_WRITE(MRST_DPLL_A, 0x00); 8648c2ecf20Sopenharmony_ci REG_WRITE(MRST_FPA0, 0xC1); 8658c2ecf20Sopenharmony_ci REG_WRITE(MRST_DPLL_A, 0x00800000); 8668c2ecf20Sopenharmony_ci udelay(500); 8678c2ecf20Sopenharmony_ci REG_WRITE(MRST_DPLL_A, 0x80800000); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci if (REG_BIT_WAIT(pipeconf_reg, 1, 29)) 8708c2ecf20Sopenharmony_ci dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n", 8718c2ecf20Sopenharmony_ci __func__); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci mipi_set_properties(dsi_config, pipe); 8768c2ecf20Sopenharmony_ci mdfld_mipi_config(dsi_config, pipe); 8778c2ecf20Sopenharmony_ci mdfld_set_pipe_timing(dsi_config, pipe); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci REG_WRITE(DSPABASE, 0x00); 8808c2ecf20Sopenharmony_ci REG_WRITE(DSPASIZE, 8818c2ecf20Sopenharmony_ci ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci REG_WRITE(DSPACNTR, 0x98000000); 8848c2ecf20Sopenharmony_ci REG_WRITE(DSPASURF, 0x00); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci REG_WRITE(VGACNTRL, 0x80000000); 8878c2ecf20Sopenharmony_ci REG_WRITE(DEVICE_READY_REG, 0x00000001); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000); 8908c2ecf20Sopenharmony_ci } else { 8918c2ecf20Sopenharmony_ci /*set up mipi port FIXME: do at init time */ 8928c2ecf20Sopenharmony_ci REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi); 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci REG_READ(MIPI_PORT_CONTROL(pipe)); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { 8978c2ecf20Sopenharmony_ci /* NOP */ 8988c2ecf20Sopenharmony_ci } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { 8998c2ecf20Sopenharmony_ci /* set up DSI controller DPI interface */ 9008c2ecf20Sopenharmony_ci mdfld_dsi_dpi_controller_init(dsi_config, pipe); 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci /* Configure MIPI Bridge and Panel */ 9038c2ecf20Sopenharmony_ci tc35876x_configure_lvds_bridge(dev); 9048c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on[pipe] = true; 9058c2ecf20Sopenharmony_ci } else { 9068c2ecf20Sopenharmony_ci /*turn on DPI interface*/ 9078c2ecf20Sopenharmony_ci mdfld_dsi_dpi_turn_on(dpi_output, pipe); 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci /*set up pipe*/ 9118c2ecf20Sopenharmony_ci REG_WRITE(pipeconf_reg, pipeconf); 9128c2ecf20Sopenharmony_ci REG_READ(pipeconf_reg); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci /*set up display plane*/ 9158c2ecf20Sopenharmony_ci REG_WRITE(dspcntr_reg, dspcntr); 9168c2ecf20Sopenharmony_ci REG_READ(dspcntr_reg); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci msleep(20); /* FIXME: this should wait for vblank */ 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { 9218c2ecf20Sopenharmony_ci /* NOP */ 9228c2ecf20Sopenharmony_ci } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { 9238c2ecf20Sopenharmony_ci mdfld_dsi_dpi_turn_on(dpi_output, pipe); 9248c2ecf20Sopenharmony_ci } else { 9258c2ecf20Sopenharmony_ci /* init driver ic */ 9268c2ecf20Sopenharmony_ci mdfld_dsi_tpo_ic_init(dsi_config, pipe); 9278c2ecf20Sopenharmony_ci /*init backlight*/ 9288c2ecf20Sopenharmony_ci mdfld_dsi_brightness_init(dsi_config, pipe); 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci gma_power_end(dev); 9328c2ecf20Sopenharmony_ci} 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci/* 9358c2ecf20Sopenharmony_ci * Init DSI DPI encoder. 9368c2ecf20Sopenharmony_ci * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector 9378c2ecf20Sopenharmony_ci * return pointer of newly allocated DPI encoder, NULL on error 9388c2ecf20Sopenharmony_ci */ 9398c2ecf20Sopenharmony_cistruct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, 9408c2ecf20Sopenharmony_ci struct mdfld_dsi_connector *dsi_connector, 9418c2ecf20Sopenharmony_ci const struct panel_funcs *p_funcs) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci struct mdfld_dsi_dpi_output *dpi_output = NULL; 9448c2ecf20Sopenharmony_ci struct mdfld_dsi_config *dsi_config; 9458c2ecf20Sopenharmony_ci struct drm_connector *connector = NULL; 9468c2ecf20Sopenharmony_ci struct drm_encoder *encoder = NULL; 9478c2ecf20Sopenharmony_ci int pipe; 9488c2ecf20Sopenharmony_ci u32 data; 9498c2ecf20Sopenharmony_ci int ret; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci pipe = dsi_connector->pipe; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) != TC35876X) { 9548c2ecf20Sopenharmony_ci dsi_config = mdfld_dsi_get_config(dsi_connector); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci /* panel hard-reset */ 9578c2ecf20Sopenharmony_ci if (p_funcs->reset) { 9588c2ecf20Sopenharmony_ci ret = p_funcs->reset(dev, pipe); 9598c2ecf20Sopenharmony_ci if (ret) { 9608c2ecf20Sopenharmony_ci DRM_ERROR("Panel %d hard-reset failed\n", pipe); 9618c2ecf20Sopenharmony_ci return NULL; 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci /* panel drvIC init */ 9668c2ecf20Sopenharmony_ci if (p_funcs->drv_ic_init) 9678c2ecf20Sopenharmony_ci p_funcs->drv_ic_init(dsi_config, pipe); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* panel power mode detect */ 9708c2ecf20Sopenharmony_ci ret = mdfld_dsi_get_power_mode(dsi_config, &data, false); 9718c2ecf20Sopenharmony_ci if (ret) { 9728c2ecf20Sopenharmony_ci DRM_ERROR("Panel %d get power mode failed\n", pipe); 9738c2ecf20Sopenharmony_ci dsi_connector->status = connector_status_disconnected; 9748c2ecf20Sopenharmony_ci } else { 9758c2ecf20Sopenharmony_ci DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); 9768c2ecf20Sopenharmony_ci dsi_connector->status = connector_status_connected; 9778c2ecf20Sopenharmony_ci } 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); 9818c2ecf20Sopenharmony_ci if (!dpi_output) { 9828c2ecf20Sopenharmony_ci DRM_ERROR("No memory\n"); 9838c2ecf20Sopenharmony_ci return NULL; 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci dpi_output->panel_on = 0; 9878c2ecf20Sopenharmony_ci dpi_output->dev = dev; 9888c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, pipe) != TC35876X) 9898c2ecf20Sopenharmony_ci dpi_output->p_funcs = p_funcs; 9908c2ecf20Sopenharmony_ci dpi_output->first_boot = 1; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci /*get fixed mode*/ 9938c2ecf20Sopenharmony_ci dsi_config = mdfld_dsi_get_config(dsi_connector); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci /*create drm encoder object*/ 9968c2ecf20Sopenharmony_ci connector = &dsi_connector->base.base; 9978c2ecf20Sopenharmony_ci encoder = &dpi_output->base.base.base; 9988c2ecf20Sopenharmony_ci drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS); 9998c2ecf20Sopenharmony_ci drm_encoder_helper_add(encoder, 10008c2ecf20Sopenharmony_ci p_funcs->encoder_helper_funcs); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci /*attach to given connector*/ 10038c2ecf20Sopenharmony_ci drm_connector_attach_encoder(connector, encoder); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci /*set possible crtcs and clones*/ 10068c2ecf20Sopenharmony_ci if (dsi_connector->pipe) { 10078c2ecf20Sopenharmony_ci encoder->possible_crtcs = (1 << 2); 10088c2ecf20Sopenharmony_ci encoder->possible_clones = 0; 10098c2ecf20Sopenharmony_ci } else { 10108c2ecf20Sopenharmony_ci encoder->possible_crtcs = (1 << 0); 10118c2ecf20Sopenharmony_ci encoder->possible_clones = 0; 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci dsi_connector->base.encoder = &dpi_output->base.base; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci return &dpi_output->base; 10178c2ecf20Sopenharmony_ci} 1018