1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2022 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <i2c.h> 10 #include <max96745.h> 11 #include <video_bridge.h> 12 #include <linux/iopoll.h> 13 14 #include "rockchip_bridge.h" 15 #include "rockchip_display.h" 16 #include "rockchip_panel.h" 17 18 static bool max96745_bridge_link_locked(struct udevice *dev) 19 { 20 int ret; 21 22 ret = dm_i2c_reg_read(dev->parent, 0x002a); 23 if (ret < 0) 24 return false; 25 26 if (!FIELD_GET(LINK_LOCKED, ret)) 27 return false; 28 29 return true; 30 } 31 32 static bool max96745_bridge_detect(struct rockchip_bridge *bridge) 33 { 34 return max96745_bridge_link_locked(bridge->dev); 35 } 36 37 static void max96745_bridge_enable(struct rockchip_bridge *bridge) 38 { 39 struct udevice *dev = bridge->dev; 40 struct drm_display_mode *mode = &bridge->state->conn_state.mode; 41 u8 cxtp, tx_rate; 42 int ret; 43 44 ret = dm_i2c_reg_read(dev->parent, 0x0011); 45 if (ret < 0) 46 return; 47 48 cxtp = FIELD_GET(CXTP_A, ret); 49 50 ret = dm_i2c_reg_read(dev->parent, 0x0028); 51 if (ret < 0) 52 return; 53 54 tx_rate = FIELD_GET(TX_RATE, ret); 55 56 if (!cxtp && mode->clock > 95000 && tx_rate == 1) { 57 ret = dm_i2c_reg_clrset(dev->parent, 0x0028, TX_RATE, 58 FIELD_PREP(TX_RATE, 2)); 59 if (ret < 0) 60 return; 61 62 ret = dm_i2c_reg_clrset(dev->parent, 0x0029, RESET_ONESHOT, 63 FIELD_PREP(RESET_ONESHOT, 1)); 64 if (ret < 0) 65 return; 66 67 if (readx_poll_timeout(max96745_bridge_link_locked, dev, ret, 68 ret, 200000)) 69 dev_err(dev, "%s: GMSL link not locked\n", __func__); 70 } 71 } 72 73 static void max96745_bridge_post_disable(struct rockchip_bridge *bridge) 74 { 75 struct udevice *dev = bridge->dev; 76 u8 cxtp, tx_rate; 77 int ret; 78 79 ret = dm_i2c_reg_read(dev->parent, 0x0011); 80 if (ret < 0) 81 return; 82 83 cxtp = FIELD_GET(CXTP_A, ret); 84 85 ret = dm_i2c_reg_read(dev->parent, 0x0028); 86 if (ret < 0) 87 return; 88 89 tx_rate = FIELD_GET(TX_RATE, ret); 90 91 if (!cxtp && tx_rate == 2) { 92 ret = dm_i2c_reg_clrset(dev->parent, 0x0028, TX_RATE, 93 FIELD_PREP(TX_RATE, 1)); 94 if (ret < 0) 95 return; 96 97 ret = dm_i2c_reg_clrset(dev->parent, 0x0029, RESET_ONESHOT, 98 FIELD_PREP(RESET_ONESHOT, 1)); 99 if (ret < 0) 100 return; 101 102 if (readx_poll_timeout(max96745_bridge_link_locked, dev, ret, 103 ret, 200000)) 104 dev_err(dev, "%s: GMSL link not locked\n", __func__); 105 } 106 } 107 108 static const struct rockchip_bridge_funcs max96745_bridge_funcs = { 109 .detect = max96745_bridge_detect, 110 .enable = max96745_bridge_enable, 111 .post_disable = max96745_bridge_post_disable, 112 }; 113 114 static int max96745_bridge_probe(struct udevice *dev) 115 { 116 struct rockchip_bridge *bridge; 117 118 bridge = calloc(1, sizeof(*bridge)); 119 if (!bridge) 120 return -ENOMEM; 121 122 dev->driver_data = (ulong)bridge; 123 bridge->dev = dev; 124 bridge->funcs = &max96745_bridge_funcs; 125 126 return 0; 127 } 128 129 static const struct udevice_id max96745_bridge_of_match[] = { 130 { .compatible = "maxim,max96745-bridge", }, 131 { } 132 }; 133 134 U_BOOT_DRIVER(max96745_bridge) = { 135 .name = "max96745_bridge", 136 .id = UCLASS_VIDEO_BRIDGE, 137 .of_match = max96745_bridge_of_match, 138 .probe = max96745_bridge_probe, 139 }; 140