1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <ddk/binding.h> 6#include <ddk/debug.h> 7#include <ddk/protocol/platform-defs.h> 8#include <ddk/protocol/platform-device.h> 9#include <stdlib.h> 10#include <stdio.h> 11#include <string.h> 12#include <unistd.h> 13#include <hw/reg.h> 14#include <ddk/protocol/i2c.h> 15#include <ddk/protocol/gpio.h> 16 17#include "dsi.h" 18#include "adv7533.h" 19 20static zx_status_t dsi_get_display_timing(dsi_t* dsi) { 21 zx_status_t status; 22 uint8_t* edid_buf = adv7533_get_edid_buffer(); 23 uint8_t num_dtd = 0; 24 25 if (edid_buf == 0) { 26 zxlogf(ERROR, "%s: No EDID available\n", __FUNCTION__); 27 return ZX_ERR_NOT_FOUND; 28 } 29 30 dsi->std_raw_dtd = calloc(1, sizeof(detailed_timing_t)); 31 dsi->std_disp_timing = calloc(1, sizeof(disp_timing_t)); 32 if (dsi->std_raw_dtd == 0 || dsi->std_disp_timing == 0) { 33 return ZX_ERR_NO_MEMORY; 34 } 35 36 edid_parse_std_display_timing(edid_buf, dsi->std_raw_dtd, dsi->std_disp_timing); 37 38 if ( (status = edid_get_num_dtd(edid_buf, &num_dtd)) != ZX_OK) { 39 zxlogf(ERROR, "Something went wrong with reading number of DTD\n"); 40 return status; 41 } 42 43 if (num_dtd == 0) { 44 zxlogf(ERROR, "No DTD Founds!!\n"); 45 return ZX_ERR_INTERNAL; 46 } 47 48 zxlogf(INFO, "Number of DTD found was %d\n", num_dtd); 49 dsi->raw_dtd = calloc(num_dtd, sizeof(detailed_timing_t)); 50 dsi->disp_timing = calloc(num_dtd, sizeof(disp_timing_t)); 51 if (dsi->raw_dtd == 0 || dsi->disp_timing == 0) { 52 return ZX_ERR_NO_MEMORY; 53 } 54 55 edid_parse_display_timing(edid_buf, dsi->raw_dtd, dsi->disp_timing, num_dtd); 56 57 return ZX_OK; 58} 59 60/* Unknown DPHY. Use hardcoded values from Android source code for now */ 61static void dsi_dphy_write(dsi_t* dsi, uint32_t reg, uint32_t val) 62{ 63 64 // Select phy register 65 DW_DSI_WRITE32(DW_DSI_PHY_TST_CTRL1, (reg | DW_DSI_PHY_TST_CTRL1_TESTEN)); 66 // pulse 67 DW_DSI_WRITE32(DW_DSI_PHY_TST_CTRL0, DW_DSI_PHY_TST_CTRL0_TSTCLK); 68 DW_DSI_WRITE32(DW_DSI_PHY_TST_CTRL0, DW_DSI_PHY_TST_CTRL0_TSTCLR); 69 70 // write value (for the register selected above) 71 DW_DSI_WRITE32(DW_DSI_PHY_TST_CTRL1, val); 72 73 // pulse 74 DW_DSI_WRITE32(DW_DSI_PHY_TST_CTRL0, DW_DSI_PHY_TST_CTRL0_TSTCLK); 75 DW_DSI_WRITE32(DW_DSI_PHY_TST_CTRL0, DW_DSI_PHY_TST_CTRL0_TSTCLR); 76} 77 78static void dsi_configure_dphy_pll(dsi_t* dsi) { 79 uint32_t i; 80 uint32_t tmp = 0; 81 82 dsi_dphy_write(dsi, 0x14, (0x1 << 4) + (0x0 << 3) + (0x0 << 2) + 0x0); 83 dsi_dphy_write(dsi, 0x15, 0x2d); 84 dsi_dphy_write(dsi, 0x16, (0x1 << 5) + (0x0 << 4) +0x1); 85 dsi_dphy_write(dsi, 0x17, 0x2); 86 dsi_dphy_write(dsi, 0x1D, 0x55); 87 dsi_dphy_write(dsi, 0x1E, (0x3 << 5) + (0x1 << 4) + (0x1 << 3) + (0x0 << 2) + (0x0 << 1) + 0x1); 88 dsi_dphy_write(dsi, 0x1F, 0x5a); 89 dsi_dphy_write(dsi, 0x20, (0x0)); 90 dsi_dphy_write(dsi, 0x21, 0x28); 91 dsi_dphy_write(dsi, 0x22, 0xc); 92 dsi_dphy_write(dsi, 0x23, 0x9); 93 dsi_dphy_write(dsi, 0x24, 0x1a); 94 dsi_dphy_write(dsi, 0x25, 0xa); 95 96 for (i = 0; i < DS_NUM_LANES; i++) { 97 tmp = 0x30 + (i << 4); 98 dsi_dphy_write(dsi, tmp, 0x3c); 99 tmp = 0x31 + (i << 4); 100 dsi_dphy_write(dsi, tmp, 0x0); 101 dsi_dphy_write(dsi, tmp, 0xc); 102 tmp = 0x33 + (i << 4); 103 dsi_dphy_write(dsi, tmp, 0x8); 104 tmp = 0x34 + (i << 4); 105 dsi_dphy_write(dsi, tmp, 0xb); 106 tmp = 0x35 + (i << 4); 107 dsi_dphy_write(dsi, tmp, 0xb); 108 tmp = 0x36 + (i << 4); 109 dsi_dphy_write(dsi, tmp, 0x3); 110 tmp = 0x37 + (i << 4); 111 dsi_dphy_write(dsi, tmp, 0x4); 112 } 113} 114 115static void hdmi_gpio_init(dsi_t* dsi) { 116 gpio_protocol_t* gpios = dsi->hdmi_gpio.gpios; 117 gpio_config_out(&gpios[GPIO_MUX], 0); 118 gpio_config_out(&gpios[GPIO_PD], 0); 119 gpio_config_in(&gpios[GPIO_INT], GPIO_NO_PULL); 120 gpio_write(&gpios[GPIO_MUX], 0); 121} 122 123static void dsi_release(void* ctx) { 124 dsi_t* dsi = ctx; 125 mmio_buffer_release(&dsi->mmio); 126 free(dsi); 127} 128 129static zx_status_t dsi_get_protocol(void* ctx, uint32_t proto_id, void* out) { 130 return ZX_OK; 131} 132 133static zx_protocol_device_t dsi_device_proto = { 134 .version = DEVICE_OPS_VERSION, 135 .get_protocol = dsi_get_protocol, 136 .release = dsi_release, 137}; 138 139static zx_status_t dsi_mipi_test(dsi_t* dsi) { 140 141 // enable video mode 142 DW_DSI_SET_BITS32(DW_DSI_MODE_CFG, 0x0, 1, 0); 143 144 // configure dpi color coding 145 DW_DSI_SET_BITS32(DW_DSI_DPI_COLOR_CODING, 0x5, 4, 0); 146 147 DW_DSI_SET_BITS32(DW_DSI_VID_MODE_CFG, 1, 1, 16); 148 149 return ZX_OK; 150} 151 152static zx_status_t dsi_configure_dphy(dsi_t* dsi) { 153 uint32_t tmp = 0; 154 155 // D-PHY shutdown and reset 156 DW_DSI_WRITE32(DW_DSI_PHY_RSTZ, DW_DSI_PHY_RSTZ_SHUTDOWN); 157 158 // Configure number of lanes 159 DW_DSI_SET_BITS32(DW_DSI_PHY_IF_CFG, (DS_NUM_LANES - 1), 2, 0); 160 161 // Configure TX_EST to frequency lower than 20MHz. Since byte clock is limited to 187.5MHz, 162 // write 0x09 will always generate clock less than 20MHz 163 DW_DSI_SET_BITS32(DW_DSI_CLKMGR_CFG, 0x09, 8, 0); 164 165 // Configure PHY PLL values 166 dsi_configure_dphy_pll(dsi); 167 168 // Enable PHY 169 DW_DSI_WRITE32(DW_DSI_PHY_RSTZ, DW_DSI_PHY_RSTZ_ENABLE); 170 171 // Wait for it to compelete 172 // TODO: Define some sort of timeout 173 tmp = DW_DSI_READ32(DW_DSI_PHY_STATUS); 174 while ((tmp & DW_DSI_PHY_STATUS_PHY_LOCKED) != DW_DSI_PHY_STATUS_PHY_LOCKED) { 175 usleep(1000); 176 tmp = DW_DSI_READ32(DW_DSI_PHY_STATUS); 177 } 178 179 /* Wait for all four lan*/ 180 // TODO: Define some sort of timeout 181 tmp = DW_DSI_READ32(DW_DSI_PHY_STATUS); 182 while ((tmp & DW_DSI_PHY_STATUS_ALLSTOP) != DW_DSI_PHY_STATUS_ALLSTOP) { 183 usleep(1000); 184 tmp = DW_DSI_READ32(DW_DSI_PHY_STATUS); 185 } 186 187 return ZX_OK; 188} 189 190static void dsi_configure_dpi_interface(dsi_t* dsi) { 191 // Configure the virtual channel of the generated packets (0 since single display mode) 192 DW_DSI_SET_BITS32(DW_DSI_DPI_VCID, 0x0, 2, 0); 193 194 // Configure bpp (bits per pixel). Set to 24 bit 195 DW_DSI_SET_BITS32(DW_DSI_DPI_COLOR_CODING, DSI_COLOR_CODE_24BITS, 4, 0); 196 197 // Configure the polarity of dpidataen (active high) 198 DW_DSI_SET_BITS32(DW_DSI_DPI_CFG_POL, DSI_CFG_POL_ACTIVE_HIGH, 1, 199 DW_DSI_DPI_CFG_POL_DATAEN_START); 200 201 // Configure the polarity of vsync (active high) 202 DW_DSI_SET_BITS32(DW_DSI_DPI_CFG_POL, DSI_CFG_POL_ACTIVE_HIGH, 1, 203 DW_DSI_DPI_CFG_POL_VSYNC_START); 204 205 // Configure the polarity of hsync (active high) 206 DW_DSI_SET_BITS32(DW_DSI_DPI_CFG_POL, DSI_CFG_POL_ACTIVE_HIGH, 1, 207 DW_DSI_DPI_CFG_POL_HSYNC_START); 208 209 // Configure the polarity of shutd (active high) 210 DW_DSI_SET_BITS32(DW_DSI_DPI_CFG_POL, DSI_CFG_POL_ACTIVE_HIGH, 1, 211 DW_DSI_DPI_CFG_POL_SHUTD_START); 212 213 // Configure the polarity of colorm (active high) 214 DW_DSI_SET_BITS32(DW_DSI_DPI_CFG_POL, DSI_CFG_POL_ACTIVE_HIGH, 1, 215 DW_DSI_DPI_CFG_POL_COLORM_START); 216 217} 218 219static zx_status_t dsi_mipi_init(dsi_t* dsi) { 220 uint64_t pixel_clk = 0; 221 uint32_t hdisplay; 222 uint32_t vdisplay; 223 uint32_t hsync_start; 224 uint32_t hsync_end; 225 uint32_t htotal; 226 uint32_t vsync_start; 227 uint32_t vsync_end; 228 uint32_t vtotal; 229 uint32_t hfp; 230 uint32_t hbp; 231 uint32_t vfp; 232 uint32_t vbp; 233 uint32_t hpw; 234 uint32_t vpw; 235 uint32_t hsa_time; 236 uint32_t hbp_time; 237 uint32_t hline_time; 238 239 /* Below values are calculatd based on PHY parameters which we don't know */ 240 uint32_t clk_lane_lp2hs_time = 0x3f; 241 uint32_t clk_lane_hs2lp_time = 0x3a; 242 uint32_t data_lane_lp2hs_time = 0x68; 243 uint32_t data_lane_hs2lp_time = 0x13; 244 245 // reset core 246 DW_DSI_WRITE32(DW_DSI_PWR_UP, 0); 247 248 // Configure DPHY 249 dsi_configure_dphy(dsi); 250 251 /* MIPI-DSI Spec Section 3.1.1 */ 252 dsi_configure_dpi_interface(dsi); 253 254 // Configure low-power transitions whenever possible 255 DW_DSI_SET_BITS32(DW_DSI_VID_MODE_CFG, DW_DSI_VID_MODE_CFG_ALL_LP, 256 DW_DSI_VID_MODE_CFG_LP_ALL_BITS, DW_DSI_VID_MODE_CFG_LP_ALL_START); 257 258 // Configure whether controller should request ack msg at end of frame (no need) 259 DW_DSI_SET_BITS32(DW_DSI_VID_MODE_CFG, 0x0, DW_DSI_VID_MODE_CFG_FRAME_ACK_BITS, 260 DW_DSI_VID_MODE_CFG_FRAME_ACK_START); 261 262 // Configure commands to be sent in low power mode only 263 DW_DSI_SET_BITS32(DW_DSI_VID_MODE_CFG, 0x1, DW_DSI_VID_MODE_CFG_LP_CMD_BITS, 264 DW_DSI_VID_MODE_CFG_LP_CMD_START); 265 266 // set mode to Non-burst with sync pulses 267 DW_DSI_SET_BITS32(DW_DSI_VID_MODE_CFG, DSI_NON_BURST_SYNC_PULSES, 268 DW_DSI_VID_MODE_CFG_MODE_BITS, DW_DSI_VID_MODE_CFG_MODE_START); 269 270 // Set number of pixel in a single video packet 271 DW_DSI_SET_BITS32(DW_DSI_VID_PKT_SIZE, dsi->std_disp_timing->HActive, 272 DW_DSI_VID_PKT_SIZE_BITS, DW_DSI_VID_PKT_SIZE_START); 273 274 // Configure number of packets to be transmitted per video line (0 for single transmission) 275 DW_DSI_WRITE32(DW_DSI_VID_NUM_CHUNKS, 0); 276 277 // Disable null packet 278 DW_DSI_WRITE32(DW_DSI_VID_NULL_SIZE, 0); 279 280 /* TODO: fix blank display bug when set backlight*/ 281 DW_DSI_SET_BITS32(DW_DSI_DPI_LP_CMD_TIM, 0x4, 8, 16); 282 283 /* for dsi read, BTA enable*/ 284 DW_DSI_SET_BITS32(DW_DSI_PCKHDL_CFG, 0x1, 1, 2); 285 286 // Define DPI Horizontal and Vertical timing configuration 287 288 289 // TODO: This is a hardcoded value in the Android source. 290 // Supposed to be: pixel_clk = dsi->std_disp_timing->pixel_clk * 10000; 291 pixel_clk = 144000000; 292 hdisplay = dsi->std_disp_timing->HActive; 293 vdisplay = dsi->std_disp_timing->VActive; 294 hsync_start = dsi->std_disp_timing->HActive + dsi->std_disp_timing->HSyncOffset; 295 vsync_start = dsi->std_disp_timing->VActive + dsi->std_disp_timing->VSyncOffset; 296 hsync_end = hsync_start + dsi->std_disp_timing->HSyncPulseWidth; 297 vsync_end = vsync_start + dsi->std_disp_timing->VSyncPulseWidth; 298 htotal = dsi->std_disp_timing->HActive + dsi->std_disp_timing->HBlanking; 299 vtotal = dsi->std_disp_timing->VActive + dsi->std_disp_timing->VBlanking; 300 301 hfp = hsync_start - hdisplay; 302 hbp = htotal - hsync_end; 303 hpw = hsync_end - hsync_start; 304 vfp = vsync_start - vdisplay; 305 vbp = vtotal - vsync_end; 306 vpw = vsync_end - vsync_start; 307 308 hsa_time = (hpw * LANE_BYTE_CLOCK) / pixel_clk; 309 hbp_time = (hbp * LANE_BYTE_CLOCK) / pixel_clk; 310 hline_time = ROUND1((hpw + hbp + hfp + hdisplay) * LANE_BYTE_CLOCK, pixel_clk); 311 312 DW_DSI_SET_BITS32(DW_DSI_VID_HSA_TIME, hsa_time, 12, 0); 313 DW_DSI_SET_BITS32(DW_DSI_VID_HBP_TIME, hbp_time, 12, 0); 314 DW_DSI_SET_BITS32(DW_DSI_VID_HLINE_TIME, hline_time, 15, 0); 315 316 /* Define the Vertical line configuration*/ 317 DW_DSI_SET_BITS32(DW_DSI_VID_VSA_LINES, vpw, 10, 0); 318 DW_DSI_SET_BITS32(DW_DSI_VID_VBP_LINES, vbp, 10, 0); 319 DW_DSI_SET_BITS32(DW_DSI_VID_VFP_LINES, vfp, 10, 0); 320 DW_DSI_SET_BITS32(DW_DSI_VID_VACTIVE_LINES, vdisplay, 14, 0); 321 DW_DSI_SET_BITS32(DW_DSI_TO_CNT_CFG, 0x7FF, 16, 0); 322 323 /* Configure core's phy parameters*/ 324 DW_DSI_SET_BITS32(DW_DSI_PHY_TMR_LPCLK_CFG, clk_lane_lp2hs_time, 10, 0); 325 DW_DSI_SET_BITS32(DW_DSI_PHY_TMR_LPCLK_CFG, clk_lane_hs2lp_time, 10, 16); 326 327 DW_DSI_SET_BITS32(DW_DSI_PHY_TMR_RD_CFG, 0x7FFF, 15, 0); 328 DW_DSI_SET_BITS32(DW_DSI_PHY_TMR_CFG, data_lane_lp2hs_time, 10, 0); 329 DW_DSI_SET_BITS32(DW_DSI_PHY_TMR_CFG, data_lane_hs2lp_time, 10, 16); 330 331 /* Waking up Core*/ 332 DW_DSI_SET_BITS32(DW_DSI_PWR_UP, 0x1, 1, 0); 333 334 /* Make sure we are in video mode */ 335 DW_DSI_SET_BITS32(DW_DSI_MODE_CFG, 0x0, 1, 0); 336 337 /* Enable EoTp Transmission */ 338 DW_DSI_SET_BITS32(DW_DSI_PCKHDL_CFG, 0x1, 1, 0); 339 340 /* Generate High Speed clock, Continuous clock */ 341 DW_DSI_SET_BITS32(DW_DSI_LPCLK_CTRL, 0x1, 2, 0); 342 343 return ZX_OK; 344} 345 346static zx_status_t dsi_bind(void* ctx, zx_device_t* parent) { 347 zxlogf(INFO, "dsi_bind\n"); 348 349 dsi_t* dsi = calloc(1, sizeof(dsi_t)); 350 if (!dsi) { 351 return ZX_ERR_NO_MEMORY; 352 } 353 354 zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_DEV, &dsi->pdev); 355 if (status != ZX_OK) { 356 goto fail; 357 } 358 dsi->parent = parent; 359 360 status = pdev_map_mmio_buffer2(&dsi->pdev, 0, ZX_CACHE_POLICY_UNCACHED_DEVICE, 361 &dsi->mmio); 362 if (status != ZX_OK) { 363 zxlogf(ERROR, "dsi_bind: pdev_map_mmio_buffer failed\n"); 364 goto fail; 365 } 366 367 /* Obtain the I2C devices */ 368 if (pdev_get_protocol(&dsi->pdev, ZX_PROTOCOL_I2C, 0, &dsi->i2c_dev.i2c_main) != ZX_OK) { 369 zxlogf(ERROR, "%s: Could not obtain I2C Protocol\n", __FUNCTION__); 370 goto fail; 371 } 372 if (pdev_get_protocol(&dsi->pdev, ZX_PROTOCOL_I2C, 1, &dsi->i2c_dev.i2c_cec) != ZX_OK) { 373 zxlogf(ERROR, "%s: Could not obtain I2C Protocol\n", __FUNCTION__); 374 goto fail; 375 } 376 if (pdev_get_protocol(&dsi->pdev, ZX_PROTOCOL_I2C, 2, &dsi->i2c_dev.i2c_edid) != ZX_OK) { 377 zxlogf(ERROR, "%s: Could not obtain I2C Protocol\n", __FUNCTION__); 378 goto fail; 379 } 380 381 /* Obtain the GPIO devices */ 382 for (uint32_t i = 0; i < countof(dsi->hdmi_gpio.gpios); i++) { 383 if (pdev_get_protocol(&dsi->pdev, ZX_PROTOCOL_GPIO, i, &dsi->hdmi_gpio.gpios[i]) != ZX_OK) { 384 zxlogf(ERROR, "%s: Could not obtain GPIO Protocol\n", __FUNCTION__); 385 goto fail; 386 } 387 } 388 389 hdmi_gpio_init(dsi); 390 391 if ( (status = adv7533_init(dsi)) != ZX_OK) { 392 zxlogf(ERROR, "%s: Error in ADV7533 Initialization %d\n", __FUNCTION__, status); 393 goto fail; 394 } 395 dsi_get_display_timing(dsi); 396 dsi_mipi_init(dsi); 397 hdmi_init(dsi); 398 dsi_mipi_test(dsi); 399 400 // dsi_mipi_init(dsi); 401 zxlogf(INFO, "MIPI Initialized. Version is 0x%x\n", readl(dsi->mmio.vaddr)); 402 403 device_add_args_t args = { 404 .version = DEVICE_ADD_ARGS_VERSION, 405 .name = "dsi", 406 .ctx = dsi, 407 .ops = &dsi_device_proto, 408 .proto_id = 0, 409 .proto_ops = 0, 410 }; 411 412 status = device_add(parent, &args, &dsi->zxdev); 413 if (status != ZX_OK) { 414 goto fail; 415 } 416 417 return ZX_OK; 418 419fail: 420 zxlogf(ERROR, "dsi3_bind failed %d\n", status); 421 dsi_release(dsi); 422 return status; 423 424} 425 426static zx_driver_ops_t dsi_driver_ops = { 427 .version = DRIVER_OPS_VERSION, 428 .bind = dsi_bind, 429}; 430 431// The formatter does not play nice with these macros. 432// clang-format off 433ZIRCON_DRIVER_BEGIN(dsi, dsi_driver_ops, "zircon", "0.1", 3) 434 BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC), 435 BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC), 436 BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_DSI), 437ZIRCON_DRIVER_END(dsi) 438// clang-format on 439