/* ----------------------------------------------------------------------------- * HDMI registers are separated into three banks: * 1) HDMI register common bank: 0x00 ~ 0x2f
*/
/* IT6263 data sheet Rev0.8: LVDS RX supports input clock rate up to 150MHz. */ #define MAX_PIXEL_CLOCK_KHZ 150000
/* IT6263 programming guide Ver0.90: PCLK_HIGH for TMDS clock over 80MHz. */ #define HIGH_PIXEL_CLOCK_KHZ 80000
/* * IT6263 data sheet Rev0.8: HDMI TX supports link speeds of up to 2.25Gbps * (link clock rate of 225MHz).
*/ #define MAX_HDMI_TMDS_CHAR_RATE_HZ 225000000
staticbool it6263_hdmi_writeable_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case HDMI_REG_SW_RST: case HDMI_REG_BANK_CTRL: case HDMI_REG_DDC_MASTER_CTRL: case HDMI_REG_DDC_HEADER: case HDMI_REG_DDC_REQOFF: case HDMI_REG_DDC_REQCOUNT: case HDMI_REG_DDC_EDIDSEG: case HDMI_REG_DDC_CMD: case HDMI_REG_LVDS_PORT: case HDMI_REG_LVDS_PORT_EN: case HDMI_REG_AFE_DRV_CTRL: case HDMI_REG_AFE_XP_CTRL: case HDMI_REG_AFE_ISW_CTRL: case HDMI_REG_AFE_IP_CTRL: case HDMI_REG_INPUT_MODE: case HDMI_REG_HDMI_MODE: case HDMI_REG_GCP: case HDMI_REG_PKT_GENERAL_CTRL: case HDMI_REG_AVI_INFOFRM_CTRL: case HDMI_REG_AVI_DB1: case HDMI_REG_AVI_DB2: case HDMI_REG_AVI_DB3: case HDMI_REG_AVI_DB4: case HDMI_REG_AVI_DB5: case HDMI_REG_AVI_CSUM: case HDMI_REG_AVI_DB6: case HDMI_REG_AVI_DB7: case HDMI_REG_AVI_DB8: case HDMI_REG_AVI_DB9: case HDMI_REG_AVI_DB10: case HDMI_REG_AVI_DB11: case HDMI_REG_AVI_DB12: case HDMI_REG_AVI_DB13: returntrue; default: returnfalse;
}
}
staticbool it6263_lvds_writeable_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case LVDS_REG_05: case LVDS_REG_0B: case LVDS_REG_2C: case LVDS_REG_3C: case LVDS_REG_3F: case LVDS_REG_47: case LVDS_REG_48: case LVDS_REG_4F: case LVDS_REG_52: returntrue; default: returnfalse;
}
}
it->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0); if (IS_ERR(it->next_bridge)) return dev_err_probe(dev, PTR_ERR(it->next_bridge), "failed to get next bridge\n");
port0 = of_graph_get_port_by_id(dev->of_node, 0);
port1 = of_graph_get_port_by_id(dev->of_node, 1); if (port0 && port1) { int order;
it->lvds_dual_link = true;
order = drm_of_lvds_get_dual_link_pixel_order_sink(port0, port1); if (order < 0) {
dev_err(dev, "failed to get dual link pixel order: %d\n",
order);
ret = order;
} elseif (order == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
it->lvds_link12_swap = true;
}
} elseif (port1) {
ret = -EINVAL;
dev_err(dev, "single input LVDS port1 is not supported\n");
} elseif (!port0) {
ret = -EINVAL;
dev_err(dev, "no input LVDS port\n");
}
of_node_put(port0);
of_node_put(port1);
return ret;
}
staticinlinevoid it6263_hw_reset(struct gpio_desc *reset_gpio)
{ if (!reset_gpio) return;
gpiod_set_value_cansleep(reset_gpio, 0);
fsleep(1000);
gpiod_set_value_cansleep(reset_gpio, 1); /* The chip maker says the low pulse should be at least 40ms. */
fsleep(40000);
gpiod_set_value_cansleep(reset_gpio, 0); /* addtional time to wait the high voltage to be stable */
fsleep(5000);
}
staticinlineint it6263_lvds_set_i2c_addr(struct it6263 *it)
{ int ret;
ret = regmap_write(it->hdmi_regmap, HDMI_REG_LVDS_PORT,
LVDS_INPUT_CTRL_I2C_ADDR << 1); if (ret) return ret;
/* reconfigure LVDS and retry several times in case video is instable */ for (i = 0; i < 3; i++) {
ret = regmap_read_poll_timeout(regmap, HDMI_REG_SYS_STATUS, val,
val & TXVIDSTABLE,
20000, 500000); if (!ret) {
is_stable = true; break;
}
it6263_lvds_config(it);
}
if (!is_stable)
dev_warn(it->dev, "failed to wait for video stable\n");
/* HDMI AFE reset release and power up */
regmap_write(regmap, HDMI_REG_AFE_DRV_CTRL, 0);
/* write the first AVI infoframe data byte chunk(DB1-DB5) */
regmap_bulk_write(regmap, HDMI_REG_AVI_DB1,
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
HDMI_AVI_DB_CHUNK1_SIZE);
/* write the second AVI infoframe data byte chunk(DB6-DB13) */
regmap_bulk_write(regmap, HDMI_REG_AVI_DB6,
&buffer[HDMI_INFOFRAME_HEADER_SIZE +
HDMI_AVI_DB_CHUNK1_SIZE],
HDMI_AVI_DB_CHUNK2_SIZE);
it = devm_drm_bridge_alloc(dev, struct it6263, bridge,
&it6263_bridge_funcs); if (IS_ERR(it)) return PTR_ERR(it);
it->dev = dev;
it->hdmi_i2c = client;
it->hdmi_regmap = devm_regmap_init_i2c(client,
&it6263_hdmi_regmap_config); if (IS_ERR(it->hdmi_regmap)) return dev_err_probe(dev, PTR_ERR(it->hdmi_regmap), "failed to init I2C regmap for HDMI\n");
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(reset_gpio)) return dev_err_probe(dev, PTR_ERR(reset_gpio), "failed to get reset gpio\n");
ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(it6263_supplies),
it6263_supplies); if (ret) return dev_err_probe(dev, ret, "failed to get power supplies\n");
ret = it6263_parse_dt(it); if (ret) return ret;
it6263_hw_reset(reset_gpio);
ret = it6263_lvds_set_i2c_addr(it); if (ret) return dev_err_probe(dev, ret, "failed to set I2C addr\n");
it->lvds_i2c = devm_i2c_new_dummy_device(dev, client->adapter,
LVDS_INPUT_CTRL_I2C_ADDR); if (IS_ERR(it->lvds_i2c)) return dev_err_probe(it->dev, PTR_ERR(it->lvds_i2c), "failed to allocate I2C device for LVDS\n");
it->lvds_regmap = devm_regmap_init_i2c(it->lvds_i2c,
&it6263_lvds_regmap_config); if (IS_ERR(it->lvds_regmap)) return dev_err_probe(dev, PTR_ERR(it->lvds_regmap), "failed to init I2C regmap for LVDS\n");
MODULE_DESCRIPTION("ITE Tech. Inc. IT6263 LVDS/HDMI bridge");
MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");
MODULE_LICENSE("GPL");
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.17Bemerkung:
(vorverarbeitet am 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.