Загрузка данных


static const struct drm_bridge_funcs adv7511_bridge_funcs = {
	.enable = adv7511_bridge_enable,
	.disable = adv7511_bridge_disable,
	.get_modes = adv7511_bridge_get_modes,
	.mode_set = adv7511_bridge_mode_set,
	.mode_valid = adv7511_bridge_mode_valid,
	.attach = adv7511_bridge_attach,
	.detect = adv7511_bridge_detect,
	.edid_read = adv7511_bridge_edid_read,
	.hpd_notify = adv7511_bridge_hpd_notify,
	.detach = adv7511_bridge_detach,
};

static int adv7511_probe(struct i2c_client *i2c)
{
	struct adv7511_link_config link_config;
	struct adv7511 *adv7511;
	struct device *dev = &i2c->dev;
#if IS_ENABLED(CONFIG_OF_DYNAMIC)
	struct device_node *remote_node = NULL, *endpoint = NULL;
	struct of_changeset ocs;
#endif
	unsigned int main_i2c_addr = i2c->addr << 1;
	unsigned int edid_i2c_addr = main_i2c_addr + 4;
	unsigned int cec_i2c_addr = main_i2c_addr - 2;
	unsigned int pkt_i2c_addr = main_i2c_addr - 0xa;
	unsigned int val;
	int ret;

	if (!dev->of_node)
		return -EINVAL;
	adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
	if (!adv7511)
		return -ENOMEM;
	adv7511->i2c_main = i2c;
	adv7511->powered = false;
	adv7511->status = connector_status_disconnected;
	adv7511->info = i2c_get_match_data(i2c);
	memset(&link_config, 0, sizeof(link_config));
	ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL, &adv7511->next_bridge);
	if (ret && ret != -ENODEV)
		return ret;

	if (adv7511->info->link_config)
		ret = adv7511_parse_dt(dev->of_node, &link_config);
	else
		ret = adv7533_parse_dt(dev->of_node, adv7511);
	if (ret)
		return ret;
	ret = adv7511_init_regulators(adv7511);
	if (ret) {
		dev_err_probe(dev, ret, "failed to init regulators\n");
		goto err_of_node_put;
	}
	if (adv7511->addr_cec != 0)
		cec_i2c_addr = adv7511->addr_cec << 1;
	else
		adv7511->addr_cec = cec_i2c_addr >> 1;
	if (adv7511->addr_edid != 0)
		edid_i2c_addr = adv7511->addr_edid << 1;
	else
		adv7511->addr_edid = edid_i2c_addr >> 1;
	if (adv7511->addr_pkt != 0)
		pkt_i2c_addr = adv7511->addr_pkt << 1;
	else
		adv7511->addr_pkt = pkt_i2c_addr >> 1;
	/*
	 * The power down GPIO is optional. If present, toggle it from active to
	 * inactive to wake up the encoder.
	 */
	adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
	if (IS_ERR(adv7511->gpio_pd)) {
		ret = PTR_ERR(adv7511->gpio_pd);
		goto uninit_regulators;
	}
	if (adv7511->gpio_pd) {
		usleep_range(5000, 6000);
		gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
	}
	adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
	if (IS_ERR(adv7511->regmap)) {
		ret = PTR_ERR(adv7511->regmap);
		goto uninit_regulators;
	}
	ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
	if (ret)
		goto uninit_regulators;
	dev_dbg(dev, "Rev. %d\n", val);
	if (adv7511->info->type == ADV7511)
		ret = regmap_register_patch(adv7511->regmap,adv7511_fixed_registers, ARRAY_SIZE(adv7511_fixed_registers));
	else
		ret = adv7533_patch_registers(adv7511);
	if (ret)
		goto uninit_regulators;
	adv7511_packet_disable(adv7511, 0xffff);
	regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,edid_i2c_addr);
	adv7511->i2c_edid = i2c_new_ancillary_device(i2c, "edid",adv7511->addr_edid);
	if (IS_ERR(adv7511->i2c_edid)) {
		ret = PTR_ERR(adv7511->i2c_edid);
		goto uninit_regulators;
	}
	regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
			pkt_i2c_addr);
	adv7511->i2c_packet = i2c_new_ancillary_device(i2c, "packet",adv7511->addr_pkt);
	if (IS_ERR(adv7511->i2c_packet)) {
		ret = PTR_ERR(adv7511->i2c_packet);
		goto err_i2c_unregister_edid;
	}
	regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR,
			cec_i2c_addr);
	ret = adv7511_init_cec_regmap(adv7511);
	if (ret)
		goto err_i2c_unregister_packet;
	INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work);
	adv7511_power_off(adv7511);
	i2c_set_clientdata(i2c, adv7511);
	if (adv7511->info->link_config)
		adv7511_set_link_config(adv7511, &link_config);
	ret = adv7511_cec_init(dev, adv7511);
	if (ret)
		goto err_unregister_cec;
	adv7511->bridge.funcs = &adv7511_bridge_funcs;
	adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
	if (adv7511->i2c_main->irq)
		adv7511->bridge.ops |= DRM_BRIDGE_OP_HPD;

	adv7511->bridge.of_node = dev->of_node;
	adv7511->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
	drm_bridge_add(&adv7511->bridge);
	adv7511_audio_init(dev, adv7511);
	if (i2c->irq) {
		init_waitqueue_head(&adv7511->wq);
		ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
						adv7511_irq_handler,
						IRQF_ONESHOT | IRQF_SHARED,
						dev_name(dev),
						adv7511);
		if (ret)
			goto err_unregister_cec;
	}
	return 0;
err_unregister_cec:
	cec_unregister_adapter(adv7511->cec_adap);
	i2c_unregister_device(adv7511->i2c_cec);
	clk_disable_unprepare(adv7511->cec_clk);
err_i2c_unregister_packet:
	i2c_unregister_device(adv7511->i2c_packet);
err_i2c_unregister_edid:
	i2c_unregister_device(adv7511->i2c_edid);
uninit_regulators:
	adv7511_uninit_regulators(adv7511);
err_of_node_put:
	of_node_put(adv7511->host_node);
#if IS_ENABLED(CONFIG_OF_DYNAMIC)
	if (ret == -EPROBE_DEFER)
		return ret;
	endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
	if (endpoint) {
		remote_node = of_graph_get_remote_port_parent(endpoint);
		of_node_put(endpoint);
	}
	if (!remote_node)
		return ret;
	/* Find remote's endpoint connected to us and detach it */
	endpoint = NULL;
	while ((endpoint = of_graph_get_next_endpoint(remote_node,endpoint))) {
		struct device_node *us;
		us = of_graph_get_remote_port_parent(endpoint);
		if (us == dev->of_node)
			break;
	}
	of_node_put(remote_node);
	if (!endpoint)
		return ret;
	of_changeset_init(&ocs);
	of_changeset_detach_node(&ocs, endpoint);
	ret = of_changeset_apply(&ocs);
	if (!ret)
		dev_warn(dev,
			 "Probe failed. Remote port '%s' disabled\n",
			 remote_node->full_name);
#endif
	return ret;
}

static void adv7511_remove(struct i2c_client *i2c)
{
	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);

	of_node_put(adv7511->host_node);
	adv7511_uninit_regulators(adv7511);
	drm_bridge_remove(&adv7511->bridge);
	adv7511_audio_exit(adv7511);
	cec_unregister_adapter(adv7511->cec_adap);
	i2c_unregister_device(adv7511->i2c_cec);
	clk_disable_unprepare(adv7511->cec_clk);
	i2c_unregister_device(adv7511->i2c_packet);
	i2c_unregister_device(adv7511->i2c_edid);
}

static const struct adv7511_chip_info adv7511_chip_info = {
	.type = ADV7511,
	.supply_names = adv7511_supply_names,
	.num_supplies = ARRAY_SIZE(adv7511_supply_names),
	.link_config = true,
};

static const struct adv7511_chip_info adv7533_chip_info = {
	.type = ADV7533,
	.max_mode_clock_khz = 80000,
	.max_lane_freq_khz = 800000,
	.supply_names = adv7533_supply_names,
	.num_supplies = ARRAY_SIZE(adv7533_supply_names),
	.reg_cec_offset = ADV7533_REG_CEC_OFFSET,
	.has_dsi = true,
};

static const struct adv7511_chip_info adv7535_chip_info = {
	.type = ADV7535,
	.max_mode_clock_khz = 148500,
	.max_lane_freq_khz = 891000,
	.supply_names = adv7533_supply_names,
	.num_supplies = ARRAY_SIZE(adv7533_supply_names),
	.reg_cec_offset = ADV7533_REG_CEC_OFFSET,
	.has_dsi = true,
	.hpd_override_enable = true,
};

static const struct i2c_device_id adv7511_i2c_ids[] = {
	{ "adv7511", (kernel_ulong_t)&adv7511_chip_info },
	{ "adv7511w", (kernel_ulong_t)&adv7511_chip_info },
	{ "adv7513", (kernel_ulong_t)&adv7511_chip_info },
	{ "adv7533", (kernel_ulong_t)&adv7533_chip_info },
	{ "adv7535", (kernel_ulong_t)&adv7535_chip_info },
	{ }
};
MODULE_DEVICE_TABLE(i2c, adv7511_i2c_ids);

static const struct of_device_id adv7511_of_ids[] = {
	{ .compatible = "adi,adv7511", .data = &adv7511_chip_info },
	{ .compatible = "adi,adv7511w", .data = &adv7511_chip_info },
	{ .compatible = "adi,adv7513", .data = &adv7511_chip_info },
	{ .compatible = "adi,adv7533", .data = &adv7533_chip_info },
	{ .compatible = "adi,adv7535", .data = &adv7535_chip_info },
	{ }
};
MODULE_DEVICE_TABLE(of, adv7511_of_ids);

static struct mipi_dsi_driver adv7533_dsi_driver = {
	.driver.name = "adv7533",
};

static struct i2c_driver adv7511_driver = {
	.driver = {
		.name = "adv7511",
		.of_match_table = adv7511_of_ids,
	},
	.id_table = adv7511_i2c_ids,
	.probe = adv7511_probe,
	.remove = adv7511_remove,
};

static int __init adv7511_init(void)
{
	int ret;
	if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
		ret = mipi_dsi_driver_register(&adv7533_dsi_driver);
		if (ret)
			return ret;
	}
	ret = i2c_add_driver(&adv7511_driver);
	if (ret) {
		if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
			mipi_dsi_driver_unregister(&adv7533_dsi_driver);
	}
	return ret;
}
module_init(adv7511_init);
static void __exit adv7511_exit(void)
{
	i2c_del_driver(&adv7511_driver);
	if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
		mipi_dsi_driver_unregister(&adv7533_dsi_driver);
}
module_exit(adv7511_exit);

весь код не выслылаю, он большой, только то, что необходимо. Если нужны реализации конкретных функций, напиши