Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * CrOS EC ANX7688 HDMI->DP bridge driver
0004  *
0005  * Copyright 2020 Google LLC
0006  */
0007 
0008 #include <drm/drm_bridge.h>
0009 #include <drm/drm_print.h>
0010 #include <linux/i2c.h>
0011 #include <linux/module.h>
0012 #include <linux/regmap.h>
0013 #include <linux/types.h>
0014 
0015 /* Register addresses */
0016 #define ANX7688_VENDOR_ID_REG       0x00
0017 #define ANX7688_DEVICE_ID_REG       0x02
0018 
0019 #define ANX7688_FW_VERSION_REG      0x80
0020 
0021 #define ANX7688_DP_BANDWIDTH_REG    0x85
0022 #define ANX7688_DP_LANE_COUNT_REG   0x86
0023 
0024 #define ANX7688_VENDOR_ID       0x1f29
0025 #define ANX7688_DEVICE_ID       0x7688
0026 
0027 /* First supported firmware version (0.85) */
0028 #define ANX7688_MINIMUM_FW_VERSION  0x0085
0029 
0030 static const struct regmap_config cros_ec_anx7688_regmap_config = {
0031     .reg_bits = 8,
0032     .val_bits = 8,
0033 };
0034 
0035 struct cros_ec_anx7688 {
0036     struct i2c_client *client;
0037     struct regmap *regmap;
0038     struct drm_bridge bridge;
0039     bool filter;
0040 };
0041 
0042 static inline struct cros_ec_anx7688 *
0043 bridge_to_cros_ec_anx7688(struct drm_bridge *bridge)
0044 {
0045     return container_of(bridge, struct cros_ec_anx7688, bridge);
0046 }
0047 
0048 static bool cros_ec_anx7688_bridge_mode_fixup(struct drm_bridge *bridge,
0049                           const struct drm_display_mode *mode,
0050                           struct drm_display_mode *adjusted_mode)
0051 {
0052     struct cros_ec_anx7688 *anx = bridge_to_cros_ec_anx7688(bridge);
0053     int totalbw, requiredbw;
0054     u8 dpbw, lanecount;
0055     u8 regs[2];
0056     int ret;
0057 
0058     if (!anx->filter)
0059         return true;
0060 
0061     /* Read both regs 0x85 (bandwidth) and 0x86 (lane count). */
0062     ret = regmap_bulk_read(anx->regmap, ANX7688_DP_BANDWIDTH_REG, regs, 2);
0063     if (ret < 0) {
0064         DRM_ERROR("Failed to read bandwidth/lane count\n");
0065         return false;
0066     }
0067     dpbw = regs[0];
0068     lanecount = regs[1];
0069 
0070     /* Maximum 0x19 bandwidth (6.75 Gbps Turbo mode), 2 lanes */
0071     if (dpbw > 0x19 || lanecount > 2) {
0072         DRM_ERROR("Invalid bandwidth/lane count (%02x/%d)\n", dpbw,
0073               lanecount);
0074         return false;
0075     }
0076 
0077     /* Compute available bandwidth (kHz) */
0078     totalbw = dpbw * lanecount * 270000 * 8 / 10;
0079 
0080     /* Required bandwidth (8 bpc, kHz) */
0081     requiredbw = mode->clock * 8 * 3;
0082 
0083     DRM_DEBUG_KMS("DP bandwidth: %d kHz (%02x/%d); mode requires %d Khz\n",
0084               totalbw, dpbw, lanecount, requiredbw);
0085 
0086     if (totalbw == 0) {
0087         DRM_ERROR("Bandwidth/lane count are 0, not rejecting modes\n");
0088         return true;
0089     }
0090 
0091     return totalbw >= requiredbw;
0092 }
0093 
0094 static const struct drm_bridge_funcs cros_ec_anx7688_bridge_funcs = {
0095     .mode_fixup = cros_ec_anx7688_bridge_mode_fixup,
0096 };
0097 
0098 static int cros_ec_anx7688_bridge_probe(struct i2c_client *client)
0099 {
0100     struct device *dev = &client->dev;
0101     struct cros_ec_anx7688 *anx7688;
0102     u16 vendor, device, fw_version;
0103     u8 buffer[4];
0104     int ret;
0105 
0106     anx7688 = devm_kzalloc(dev, sizeof(*anx7688), GFP_KERNEL);
0107     if (!anx7688)
0108         return -ENOMEM;
0109 
0110     anx7688->client = client;
0111     i2c_set_clientdata(client, anx7688);
0112 
0113     anx7688->regmap = devm_regmap_init_i2c(client, &cros_ec_anx7688_regmap_config);
0114     if (IS_ERR(anx7688->regmap)) {
0115         ret = PTR_ERR(anx7688->regmap);
0116         dev_err(dev, "regmap i2c init failed: %d\n", ret);
0117         return ret;
0118     }
0119 
0120     /* Read both vendor and device id (4 bytes). */
0121     ret = regmap_bulk_read(anx7688->regmap, ANX7688_VENDOR_ID_REG,
0122                    buffer, 4);
0123     if (ret) {
0124         dev_err(dev, "Failed to read chip vendor/device id\n");
0125         return ret;
0126     }
0127 
0128     vendor = (u16)buffer[1] << 8 | buffer[0];
0129     device = (u16)buffer[3] << 8 | buffer[2];
0130     if (vendor != ANX7688_VENDOR_ID || device != ANX7688_DEVICE_ID) {
0131         dev_err(dev, "Invalid vendor/device id %04x/%04x\n",
0132             vendor, device);
0133         return -ENODEV;
0134     }
0135 
0136     ret = regmap_bulk_read(anx7688->regmap, ANX7688_FW_VERSION_REG,
0137                    buffer, 2);
0138     if (ret) {
0139         dev_err(dev, "Failed to read firmware version\n");
0140         return ret;
0141     }
0142 
0143     fw_version = (u16)buffer[0] << 8 | buffer[1];
0144     dev_info(dev, "ANX7688 firmware version 0x%04x\n", fw_version);
0145 
0146     anx7688->bridge.of_node = dev->of_node;
0147 
0148     /* FW version >= 0.85 supports bandwidth/lane count registers */
0149     if (fw_version >= ANX7688_MINIMUM_FW_VERSION)
0150         anx7688->filter = true;
0151     else
0152         /* Warn, but not fail, for backwards compatibility */
0153         DRM_WARN("Old ANX7688 FW version (0x%04x), not filtering\n",
0154              fw_version);
0155 
0156     anx7688->bridge.funcs = &cros_ec_anx7688_bridge_funcs;
0157     drm_bridge_add(&anx7688->bridge);
0158 
0159     return 0;
0160 }
0161 
0162 static int cros_ec_anx7688_bridge_remove(struct i2c_client *client)
0163 {
0164     struct cros_ec_anx7688 *anx7688 = i2c_get_clientdata(client);
0165 
0166     drm_bridge_remove(&anx7688->bridge);
0167 
0168     return 0;
0169 }
0170 
0171 static const struct of_device_id cros_ec_anx7688_bridge_match_table[] = {
0172     { .compatible = "google,cros-ec-anx7688" },
0173     { }
0174 };
0175 MODULE_DEVICE_TABLE(of, cros_ec_anx7688_bridge_match_table);
0176 
0177 static struct i2c_driver cros_ec_anx7688_bridge_driver = {
0178     .probe_new = cros_ec_anx7688_bridge_probe,
0179     .remove = cros_ec_anx7688_bridge_remove,
0180     .driver = {
0181         .name = "cros-ec-anx7688-bridge",
0182         .of_match_table = cros_ec_anx7688_bridge_match_table,
0183     },
0184 };
0185 
0186 module_i2c_driver(cros_ec_anx7688_bridge_driver);
0187 
0188 MODULE_DESCRIPTION("ChromeOS EC ANX7688 HDMI->DP bridge driver");
0189 MODULE_AUTHOR("Nicolas Boichat <drinkcat@chromium.org>");
0190 MODULE_AUTHOR("Enric Balletbo i Serra <enric.balletbo@collabora.com>");
0191 MODULE_LICENSE("GPL");