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


static int lt9611_bridge_attach(struct drm_bridge *bridge,
				enum drm_bridge_attach_flags flags)
{
	struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
        if(lt9611->next_bridge) {
	    return drm_bridge_attach(bridge->encoder, lt9611->next_bridge, bridge, flags);
        }
        return 0;
}

static const struct drm_bridge_funcs lt9611_bridge_funcs = {
	.attach = lt9611_bridge_attach,
	.mode_valid = lt9611_bridge_mode_valid,
	.detect = lt9611_bridge_detect,
	.edid_read = lt9611_bridge_edid_read,
	.hpd_enable = lt9611_bridge_hpd_enable,

	.atomic_pre_enable = lt9611_bridge_atomic_pre_enable,
	.atomic_enable = lt9611_bridge_atomic_enable,
	.atomic_disable = lt9611_bridge_atomic_disable,
	.atomic_post_disable = lt9611_bridge_atomic_post_disable,
	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
	.atomic_reset = drm_atomic_helper_bridge_reset,
	.atomic_get_input_bus_fmts = lt9611_atomic_get_input_bus_fmts,
};

static int lt9611_parse_dt(struct device *dev, struct lt9611 *lt9611)
{
	int ret = 0;
	lt9611->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1);
	if (!lt9611->dsi0_node) {
		dev_err(lt9611->dev, "failed to get remote node for primary dsi\n");
		return -ENODEV;
	}
	lt9611->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1);
	lt9611->ac_mode = of_property_read_bool(dev->of_node, "lt,ac-mode");
	ret = drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, &lt9611->next_bridge);
        if(ret == -ENODEV) {
            lt9611->next_bridge = NULL;
            return 0;
        }
        return ret;
}

static int lt9611_probe(struct i2c_client *client)
{
	struct lt9611 *lt9611;
	struct device *dev = &client->dev;
	int ret;
	bool is_i2s = true;

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		dev_err(dev, "device doesn't support I2C\n");
		return -ENODEV;
	}
	lt9611 = devm_kzalloc(dev, sizeof(*lt9611), GFP_KERNEL);
	if (!lt9611)
		return -ENOMEM;
	lt9611->dev = dev;
	lt9611->client = client;
	lt9611->sleep = false;
	lt9611->regmap = devm_regmap_init_i2c(client, &lt9611_regmap_config);
	if (IS_ERR(lt9611->regmap)) {
		dev_err(lt9611->dev, "regmap i2c init failed\n");
		return PTR_ERR(lt9611->regmap);
	}
	ret = lt9611_parse_dt(dev, lt9611);
	if (ret) {
		dev_err(dev, "failed to parse device tree\n");
		return ret;
	}
	if (of_property_read_bool(dev->of_node, "fsl,audio-spdif")) {
		is_i2s = false;
	}
	ret = lt9611_gpio_init(lt9611);
	if (ret < 0)
		goto err_of_put;
	ret = lt9611_regulator_init(lt9611);
	if (ret < 0)
		goto err_of_put;
	lt9611_assert_5v(lt9611);
	ret = lt9611_regulator_enable(lt9611);
	if (ret)
		goto err_of_put;
	lt9611_reset(lt9611);
	ret = lt9611_read_device_rev(lt9611);
	if (ret) {
		dev_err(dev, "failed to read chip rev\n");
		goto err_disable_regulators;
	}
	ret = devm_request_threaded_irq(dev, client->irq, NULL,lt9611_irq_thread_handler,IRQF_ONESHOT, "lt9611", lt9611);
	if (ret) {
		dev_err(dev, "failed to request irq\n");
		goto err_disable_regulators;
	}
	i2c_set_clientdata(client, lt9611);
	lt9611->bridge.funcs = &lt9611_bridge_funcs;
	lt9611->bridge.of_node = client->dev.of_node;
	lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
			     DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES;
	lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
	drm_bridge_add(&lt9611->bridge);
#ifdef MY_CODE
	/* Attach primary DSI */
	lt9611->dsi0 = lt9611_attach_dsi(lt9611, lt9611->dsi0_node);
	if (IS_ERR(lt9611->dsi0)) {
		ret = PTR_ERR(lt9611->dsi0);
		goto err_remove_bridge;
	}
#endif
	lt9611_enable_hpd_interrupts(lt9611);
//CEC
	mutex_init(&lt9611->cec_ioctl_mutex);
	init_completion(&lt9611->rx_ok);
	pdata_global = lt9611;
	ret = cec_sysfs_init();
	if (ret) {
		printk("Error cec sysfs init");
	}
	else
	{
		ret = register_chrdev(0, CEC_DEV_NAME, &hdmitx_cec_fops);
		if (ret < 0)
			printk("%s alloc chrdev CEC failed\n",__FUNCTION__);
		else
		{
			lt9611->cec_dev_no = ret;
			cec_sysfs_dev_new(lt9611);
		}
	}
	ret = lt9611_audio_init(dev, lt9611, is_i2s);
	if (ret)
		goto err_remove_bridge;
	return 0;
err_remove_bridge:
	drm_bridge_remove(&lt9611->bridge);
err_disable_regulators:
	regulator_bulk_disable(ARRAY_SIZE(lt9611->supplies), lt9611->supplies);
err_of_put:
	of_node_put(lt9611->dsi1_node);
	of_node_put(lt9611->dsi0_node);
	return ret;
}

static struct i2c_driver lt9611_driver = {
	.driver = {
		.name = "lt9611",
		.of_match_table = lt9611_match_table,
	},
	.probe = lt9611_probe,
	.remove = lt9611_remove,
	.id_table = lt9611_id,
};
module_i2c_driver(lt9611_driver);