.. | .. |
---|
11 | 11 | |
---|
12 | 12 | #include "maxim4c_api.h" |
---|
13 | 13 | |
---|
| 14 | +static int maxim4c_txphy_init_timing(maxim4c_t *maxim4c) |
---|
| 15 | +{ |
---|
| 16 | + struct i2c_client *client = maxim4c->client; |
---|
| 17 | + int ret = 0; |
---|
| 18 | + u16 reg_addr = 0; |
---|
| 19 | + u8 reg_mask; |
---|
| 20 | + u8 timing; |
---|
| 21 | + u8 phy_idx = 0; |
---|
| 22 | + |
---|
| 23 | + if (!maxim4c->mipi_txphy.timing_override_en) |
---|
| 24 | + return 0; |
---|
| 25 | + |
---|
| 26 | + timing = ((maxim4c->mipi_txphy.timing.t_hs_przero & 0x3) << 6 | |
---|
| 27 | + (maxim4c->mipi_txphy.timing.t_hs_prep & 0x3) << 4 | |
---|
| 28 | + (maxim4c->mipi_txphy.timing.t_clk_trail & 0x3) << 2 | |
---|
| 29 | + (maxim4c->mipi_txphy.timing.t_clk_przero & 0x3) << 0); |
---|
| 30 | + |
---|
| 31 | + ret |= maxim4c_i2c_write_byte(client, 0x08A1, |
---|
| 32 | + MAXIM4C_I2C_REG_ADDR_16BITS, timing); |
---|
| 33 | + |
---|
| 34 | + reg_mask = 0x0F; |
---|
| 35 | + timing = ((maxim4c->mipi_txphy.timing.t_lpx & 0x3) << 2 | |
---|
| 36 | + (maxim4c->mipi_txphy.timing.t_hs_trail & 0x3) << 0); |
---|
| 37 | + |
---|
| 38 | + ret |= maxim4c_i2c_update_byte( |
---|
| 39 | + client, 0x08A2, MAXIM4C_I2C_REG_ADDR_16BITS, reg_mask, timing); |
---|
| 40 | + |
---|
| 41 | + reg_mask = (0x3 << 6); |
---|
| 42 | + timing = (maxim4c->mipi_txphy.timing.t_lpxesc & 0x3) << 6; |
---|
| 43 | + ret |= maxim4c_i2c_update_byte( |
---|
| 44 | + client, 0x08A5, MAXIM4C_I2C_REG_ADDR_16BITS, reg_mask, timing); |
---|
| 45 | + |
---|
| 46 | + reg_mask = (0x7 << 5); |
---|
| 47 | + timing = (maxim4c->mipi_txphy.timing.t_lpxesc & 0x7) << 5; |
---|
| 48 | + ret |= maxim4c_i2c_update_byte( |
---|
| 49 | + client, 0x08A8, MAXIM4C_I2C_REG_ADDR_16BITS, reg_mask, timing); |
---|
| 50 | + |
---|
| 51 | + for (phy_idx = 0; phy_idx < MAXIM4C_TXPHY_ID_MAX; phy_idx++) { |
---|
| 52 | + reg_mask = 0xFF; |
---|
| 53 | + reg_addr = 0x0905 + 0x40 * phy_idx; |
---|
| 54 | + timing = maxim4c->mipi_txphy.timing.csi2_t_pre; |
---|
| 55 | + ret |= maxim4c_i2c_update_byte(client, reg_addr, |
---|
| 56 | + MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
| 57 | + reg_mask, timing); |
---|
| 58 | + |
---|
| 59 | + reg_addr = 0x0906 + 0x40 * phy_idx; |
---|
| 60 | + timing = maxim4c->mipi_txphy.timing.csi2_t_post; |
---|
| 61 | + ret |= maxim4c_i2c_update_byte(client, reg_addr, |
---|
| 62 | + MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
| 63 | + reg_mask, timing); |
---|
| 64 | + |
---|
| 65 | + reg_addr = 0x0907 + 0x40 * phy_idx; |
---|
| 66 | + timing = maxim4c->mipi_txphy.timing.csi2_tx_gap; |
---|
| 67 | + ret |= maxim4c_i2c_update_byte(client, reg_addr, |
---|
| 68 | + MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
| 69 | + reg_mask, timing); |
---|
| 70 | + |
---|
| 71 | + reg_addr = 0x0908 + 0x40 * phy_idx; |
---|
| 72 | + timing = maxim4c->mipi_txphy.timing.csi2_twakeup & 0xFF; |
---|
| 73 | + ret |= maxim4c_i2c_update_byte(client, reg_addr, |
---|
| 74 | + MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
| 75 | + reg_mask, timing); |
---|
| 76 | + timing = (maxim4c->mipi_txphy.timing.csi2_twakeup >> 8) & 0xFF; |
---|
| 77 | + ret |= maxim4c_i2c_update_byte(client, reg_addr + 1, |
---|
| 78 | + MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
| 79 | + reg_mask, timing); |
---|
| 80 | + reg_mask = 0x7; |
---|
| 81 | + timing = (maxim4c->mipi_txphy.timing.csi2_twakeup >> 16) & 0x7; |
---|
| 82 | + ret |= maxim4c_i2c_update_byte(client, reg_addr + 2, |
---|
| 83 | + MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
| 84 | + reg_mask, timing); |
---|
| 85 | + } |
---|
| 86 | + |
---|
| 87 | + return ret; |
---|
| 88 | +} |
---|
| 89 | + |
---|
14 | 90 | static int maxim4c_txphy_auto_init_deskew(maxim4c_t *maxim4c) |
---|
15 | 91 | { |
---|
16 | 92 | struct i2c_client *client = maxim4c->client; |
---|
.. | .. |
---|
182 | 258 | reg_addr, MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
183 | 259 | 0xf4); |
---|
184 | 260 | |
---|
| 261 | + reg_addr = 0x1C03 + 0x100 * phy_idx; |
---|
| 262 | + ret |= maxim4c_i2c_update_byte(client, reg_addr, |
---|
| 263 | + MAXIM4C_I2C_REG_ADDR_16BITS, |
---|
| 264 | + 0x07, phy_cfg->ssc_ratio); |
---|
| 265 | + |
---|
185 | 266 | // Set dpll data rate |
---|
186 | 267 | reg_addr = 0x0415 + 0x03 * phy_idx; |
---|
187 | 268 | ret |= maxim4c_i2c_update_byte(client, |
---|
.. | .. |
---|
349 | 430 | phy_cfg->clock_mode = value; |
---|
350 | 431 | } |
---|
351 | 432 | |
---|
| 433 | + ret = of_property_read_u32(node, "ssc-ratio", &value); |
---|
| 434 | + if (ret == 0) { |
---|
| 435 | + dev_info(dev, "ssc-ratio property: %d", value); |
---|
| 436 | + phy_cfg->ssc_ratio = value; |
---|
| 437 | + } |
---|
| 438 | + |
---|
352 | 439 | sub_idx++; |
---|
353 | 440 | } |
---|
354 | 441 | } |
---|
.. | .. |
---|
510 | 597 | // mipi txphy auto init deskew |
---|
511 | 598 | ret |= maxim4c_txphy_auto_init_deskew(maxim4c); |
---|
512 | 599 | |
---|
| 600 | + // mipi txphy timing init |
---|
| 601 | + ret |= maxim4c_txphy_init_timing(maxim4c); |
---|
| 602 | + |
---|
513 | 603 | if (ret) { |
---|
514 | 604 | dev_err(dev, "%s: txphy hw init error\n", __func__); |
---|
515 | 605 | return ret; |
---|
.. | .. |
---|
529 | 619 | mipi_txphy->force_clock_out_en = 1; |
---|
530 | 620 | mipi_txphy->force_clk0_en = 0; |
---|
531 | 621 | mipi_txphy->force_clk3_en = 0; |
---|
| 622 | + mipi_txphy->timing.t_lpx = 1; |
---|
| 623 | + mipi_txphy->timing.csi2_t_pre = 0x71; |
---|
| 624 | + mipi_txphy->timing.csi2_t_post = 0x19; |
---|
| 625 | + mipi_txphy->timing.csi2_tx_gap = 0x1C; |
---|
| 626 | + mipi_txphy->timing.csi2_twakeup = 0x100; |
---|
532 | 627 | |
---|
533 | 628 | for (i = 0; i < MAXIM4C_TXPHY_ID_MAX; i++) { |
---|
534 | 629 | phy_cfg = &mipi_txphy->phy_cfg[i]; |
---|
.. | .. |
---|
541 | 636 | phy_cfg->vc_ext_en = 0; |
---|
542 | 637 | phy_cfg->clock_master = 0; |
---|
543 | 638 | phy_cfg->clock_mode = MAXIM4C_TXPHY_DPLL_PREDEF; |
---|
| 639 | + phy_cfg->ssc_ratio = 0; |
---|
544 | 640 | } |
---|
545 | 641 | } |
---|
546 | 642 | EXPORT_SYMBOL(maxim4c_mipi_txphy_data_init); |
---|