drm/omap: dss: dsi: Move initialization code from bind to probe

There's no reason to delay initialization of most of the driver (such as
mapping memory I/O or enabling runtime PM) to the component bind
handler. Perform as much of the initialization as possible at probe
time, initializing at bind time only the parts that depends on the DSS.
The cleanup code is moved from unbind to remove in a similar way.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
This commit is contained in:
Laurent Pinchart 2018-03-03 18:52:59 +02:00 коммит произвёл Tomi Valkeinen
Родитель 66aacfe22d
Коммит edb715dffd
1 изменённых файлов: 161 добавлений и 140 удалений

Просмотреть файл

@ -4981,85 +4981,9 @@ static const struct omap_dss_device_ops dsi_ops = {
},
};
static void dsi_init_output(struct dsi_data *dsi)
{
struct omap_dss_device *out = &dsi->output;
out->dev = dsi->dev;
out->id = dsi->module_id == 0 ?
OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
out->output_type = OMAP_DISPLAY_TYPE_DSI;
out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
out->dispc_channel = dsi_get_channel(dsi);
out->ops = &dsi_ops;
out->owner = THIS_MODULE;
out->of_ports = BIT(0);
omapdss_device_register(out);
}
static void dsi_uninit_output(struct dsi_data *dsi)
{
struct omap_dss_device *out = &dsi->output;
omapdss_device_unregister(out);
}
static int dsi_probe_of(struct dsi_data *dsi)
{
struct device_node *node = dsi->dev->of_node;
struct property *prop;
u32 lane_arr[10];
int len, num_pins;
int r, i;
struct device_node *ep;
struct omap_dsi_pin_config pin_cfg;
ep = of_graph_get_endpoint_by_regs(node, 0, 0);
if (!ep)
return 0;
prop = of_find_property(ep, "lanes", &len);
if (prop == NULL) {
dev_err(dsi->dev, "failed to find lane data\n");
r = -EINVAL;
goto err;
}
num_pins = len / sizeof(u32);
if (num_pins < 4 || num_pins % 2 != 0 ||
num_pins > dsi->num_lanes_supported * 2) {
dev_err(dsi->dev, "bad number of lanes\n");
r = -EINVAL;
goto err;
}
r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins);
if (r) {
dev_err(dsi->dev, "failed to read lane data\n");
goto err;
}
pin_cfg.num_pins = num_pins;
for (i = 0; i < num_pins; ++i)
pin_cfg.pins[i] = (int)lane_arr[i];
r = dsi_configure_pins(&dsi->output, &pin_cfg);
if (r) {
dev_err(dsi->dev, "failed to configure pins");
goto err;
}
of_node_put(ep);
return 0;
err:
of_node_put(ep);
return r;
}
/* -----------------------------------------------------------------------------
* PLL
*/
static const struct dss_pll_ops dsi_pll_ops = {
.enable = dsi_pll_enable,
@ -5174,7 +5098,153 @@ static int dsi_init_pll_data(struct dss_device *dss, struct dsi_data *dsi)
return 0;
}
/* DSI1 HW IP initialisation */
/* -----------------------------------------------------------------------------
* Component Bind & Unbind
*/
static int dsi_bind(struct device *dev, struct device *master, void *data)
{
struct dss_device *dss = dss_get_device(master);
struct dsi_data *dsi = dev_get_drvdata(dev);
char name[10];
u32 rev;
int r;
dsi->dss = dss;
dsi_init_pll_data(dss, dsi);
r = dsi_runtime_get(dsi);
if (r)
return r;
rev = dsi_read_reg(dsi, DSI_REVISION);
dev_dbg(dev, "OMAP DSI rev %d.%d\n",
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
dsi->line_buffer_size = dsi_get_line_buf_size(dsi);
dsi_runtime_put(dsi);
snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);
dsi->debugfs.regs = dss_debugfs_create_file(dss, name,
dsi_dump_dsi_regs, &dsi);
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);
dsi->debugfs.irqs = dss_debugfs_create_file(dss, name,
dsi_dump_dsi_irqs, &dsi);
#endif
snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);
dsi->debugfs.clks = dss_debugfs_create_file(dss, name,
dsi_dump_dsi_clocks, &dsi);
return 0;
}
static void dsi_unbind(struct device *dev, struct device *master, void *data)
{
struct dsi_data *dsi = dev_get_drvdata(dev);
dss_debugfs_remove_file(dsi->debugfs.clks);
dss_debugfs_remove_file(dsi->debugfs.irqs);
dss_debugfs_remove_file(dsi->debugfs.regs);
of_platform_depopulate(dev);
WARN_ON(dsi->scp_clk_refcount > 0);
dss_pll_unregister(&dsi->pll);
}
static const struct component_ops dsi_component_ops = {
.bind = dsi_bind,
.unbind = dsi_unbind,
};
/* -----------------------------------------------------------------------------
* Probe & Remove, Suspend & Resume
*/
static void dsi_init_output(struct dsi_data *dsi)
{
struct omap_dss_device *out = &dsi->output;
out->dev = dsi->dev;
out->id = dsi->module_id == 0 ?
OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
out->output_type = OMAP_DISPLAY_TYPE_DSI;
out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
out->dispc_channel = dsi_get_channel(dsi);
out->ops = &dsi_ops;
out->owner = THIS_MODULE;
out->of_ports = BIT(0);
omapdss_device_register(out);
}
static void dsi_uninit_output(struct dsi_data *dsi)
{
struct omap_dss_device *out = &dsi->output;
omapdss_device_unregister(out);
}
static int dsi_probe_of(struct dsi_data *dsi)
{
struct device_node *node = dsi->dev->of_node;
struct property *prop;
u32 lane_arr[10];
int len, num_pins;
int r, i;
struct device_node *ep;
struct omap_dsi_pin_config pin_cfg;
ep = of_graph_get_endpoint_by_regs(node, 0, 0);
if (!ep)
return 0;
prop = of_find_property(ep, "lanes", &len);
if (prop == NULL) {
dev_err(dsi->dev, "failed to find lane data\n");
r = -EINVAL;
goto err;
}
num_pins = len / sizeof(u32);
if (num_pins < 4 || num_pins % 2 != 0 ||
num_pins > dsi->num_lanes_supported * 2) {
dev_err(dsi->dev, "bad number of lanes\n");
r = -EINVAL;
goto err;
}
r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins);
if (r) {
dev_err(dsi->dev, "failed to read lane data\n");
goto err;
}
pin_cfg.num_pins = num_pins;
for (i = 0; i < num_pins; ++i)
pin_cfg.pins[i] = (int)lane_arr[i];
r = dsi_configure_pins(&dsi->output, &pin_cfg);
if (r) {
dev_err(dsi->dev, "failed to configure pins");
goto err;
}
of_node_put(ep);
return 0;
err:
of_node_put(ep);
return r;
}
static const struct dsi_of_data dsi_of_data_omap34xx = {
.model = DSI_MODEL_OMAP3,
.pll_hw = &dss_omap3_dsi_pll_hw,
@ -5240,24 +5310,21 @@ static const struct soc_device_attribute dsi_soc_devices[] = {
{ /* sentinel */ }
};
static int dsi_bind(struct device *dev, struct device *master, void *data)
static int dsi_probe(struct platform_device *pdev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dss_device *dss = dss_get_device(master);
const struct soc_device_attribute *soc;
const struct dsi_module_id_data *d;
u32 rev;
int r, i;
struct device *dev = &pdev->dev;
struct dsi_data *dsi;
struct resource *dsi_mem;
struct resource *res;
char name[10];
unsigned int i;
int r;
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
if (!dsi)
return -ENOMEM;
dsi->dss = dss;
dsi->dev = dev;
dev_set_drvdata(dev, dsi);
@ -5354,18 +5421,8 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
if (r)
return r;
dsi_init_pll_data(dss, dsi);
pm_runtime_enable(dev);
r = dsi_runtime_get(dsi);
if (r)
goto err_pm_disable;
rev = dsi_read_reg(dsi, DSI_REVISION);
dev_dbg(dev, "OMAP DSI rev %d.%d\n",
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
* of data to 3 by default */
if (dsi->data->quirks & DSI_QUIRK_GNQ)
@ -5374,8 +5431,6 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
else
dsi->num_lanes_supported = 3;
dsi->line_buffer_size = dsi_get_line_buf_size(dsi);
dsi_init_output(dsi);
r = dsi_probe_of(dsi);
@ -5388,67 +5443,33 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
if (r)
DSSERR("Failed to populate DSI child devices: %d\n", r);
dsi_runtime_put(dsi);
snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);
dsi->debugfs.regs = dss_debugfs_create_file(dss, name,
dsi_dump_dsi_regs, &dsi);
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);
dsi->debugfs.irqs = dss_debugfs_create_file(dss, name,
dsi_dump_dsi_irqs, &dsi);
#endif
snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);
dsi->debugfs.clks = dss_debugfs_create_file(dss, name,
dsi_dump_dsi_clocks, &dsi);
r = component_add(&pdev->dev, &dsi_component_ops);
if (r)
goto err_uninit_output;
return 0;
err_uninit_output:
dsi_uninit_output(dsi);
dsi_runtime_put(dsi);
err_pm_disable:
pm_runtime_disable(dev);
return r;
}
static void dsi_unbind(struct device *dev, struct device *master, void *data)
static int dsi_remove(struct platform_device *pdev)
{
struct dsi_data *dsi = dev_get_drvdata(dev);
struct dsi_data *dsi = platform_get_drvdata(pdev);
dss_debugfs_remove_file(dsi->debugfs.clks);
dss_debugfs_remove_file(dsi->debugfs.irqs);
dss_debugfs_remove_file(dsi->debugfs.regs);
of_platform_depopulate(dev);
WARN_ON(dsi->scp_clk_refcount > 0);
dss_pll_unregister(&dsi->pll);
component_del(&pdev->dev, &dsi_component_ops);
dsi_uninit_output(dsi);
pm_runtime_disable(dev);
pm_runtime_disable(&pdev->dev);
if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
regulator_disable(dsi->vdds_dsi_reg);
dsi->vdds_dsi_enabled = false;
}
}
static const struct component_ops dsi_component_ops = {
.bind = dsi_bind,
.unbind = dsi_unbind,
};
static int dsi_probe(struct platform_device *pdev)
{
return component_add(&pdev->dev, &dsi_component_ops);
}
static int dsi_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &dsi_component_ops);
return 0;
}