From b93109d7dc9e15649e1cf18281f02d8b4a102584 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Feb 2018 15:58:13 +0200 Subject: drm/omap: dss: Move common device operations to common structure The various types of omapdss_*_ops structures define multiple operations that are not specific to a bus type. To simplify the code and remove dependencies on specific bus types move those operations to a common structure. Operations that are specific to a bus type are kept in the specialized ops structures. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 50 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 74467b308721..3cc91e973f01 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -5000,43 +5000,45 @@ static void dsi_disconnect(struct omap_dss_device *dssdev, dss_mgr_disconnect(&dsi->output, dssdev); } -static const struct omapdss_dsi_ops dsi_ops = { +static const struct omap_dss_device_ops dsi_ops = { .connect = dsi_connect, .disconnect = dsi_disconnect, + .enable = dsi_display_enable, - .bus_lock = dsi_bus_lock, - .bus_unlock = dsi_bus_unlock, + .dsi = { + .bus_lock = dsi_bus_lock, + .bus_unlock = dsi_bus_unlock, - .enable = dsi_display_enable, - .disable = dsi_display_disable, + .disable = dsi_display_disable, - .enable_hs = dsi_vc_enable_hs, + .enable_hs = dsi_vc_enable_hs, - .configure_pins = dsi_configure_pins, - .set_config = dsi_set_config, + .configure_pins = dsi_configure_pins, + .set_config = dsi_set_config, - .enable_video_output = dsi_enable_video_output, - .disable_video_output = dsi_disable_video_output, + .enable_video_output = dsi_enable_video_output, + .disable_video_output = dsi_disable_video_output, - .update = dsi_update, + .update = dsi_update, - .enable_te = dsi_enable_te, + .enable_te = dsi_enable_te, - .request_vc = dsi_request_vc, - .set_vc_id = dsi_set_vc_id, - .release_vc = dsi_release_vc, + .request_vc = dsi_request_vc, + .set_vc_id = dsi_set_vc_id, + .release_vc = dsi_release_vc, - .dcs_write = dsi_vc_dcs_write, - .dcs_write_nosync = dsi_vc_dcs_write_nosync, - .dcs_read = dsi_vc_dcs_read, + .dcs_write = dsi_vc_dcs_write, + .dcs_write_nosync = dsi_vc_dcs_write_nosync, + .dcs_read = dsi_vc_dcs_read, - .gen_write = dsi_vc_generic_write, - .gen_write_nosync = dsi_vc_generic_write_nosync, - .gen_read = dsi_vc_generic_read, + .gen_write = dsi_vc_generic_write, + .gen_write_nosync = dsi_vc_generic_write_nosync, + .gen_read = dsi_vc_generic_read, - .bta_sync = dsi_vc_send_bta_sync, + .bta_sync = dsi_vc_send_bta_sync, - .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size, + .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size, + }, }; static void dsi_init_output(struct dsi_data *dsi) @@ -5050,7 +5052,7 @@ static void dsi_init_output(struct dsi_data *dsi) 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 = &dsi_ops; + out->ops = &dsi_ops; out->owner = THIS_MODULE; omapdss_register_output(out); -- cgit v1.2.3 From fb5571717c24c264518aaaf1ab4ec4df73e4cebd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Feb 2018 17:30:30 +0200 Subject: drm/omap: dss: Move src and dst check and set to connection handlers The encoders duplicate the same omap_dss_device src and dst fields set and checks in their connect and disconnect handlers. Move the code to the connect and disconnect wrappers. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 3cc91e973f01..8e3dce1ddfb0 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4990,11 +4990,6 @@ static void dsi_disconnect(struct omap_dss_device *dssdev, { struct dsi_data *dsi = to_dsi_data(dssdev); - WARN_ON(dst != dssdev->dst); - - if (dst != dssdev->dst) - return; - omapdss_output_unset_device(dssdev); dss_mgr_disconnect(&dsi->output, dssdev); -- cgit v1.2.3 From f3ed97f9ae7df6a36025b94e1943492e73691f7c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 2 Mar 2018 00:40:04 +0200 Subject: drm/omap: dsi: Simplify debugfs implementation The DSI debugfs regs and irqs show handlers received a pointer to the DSI private data. There's no need to look it up from the list of DSS outputs. Use the pointer directly, this allows simplifying the implementation of the handlers. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 63 +++++++++------------------------------ 1 file changed, 14 insertions(+), 49 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 8e3dce1ddfb0..6b16eec0b2b2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -1518,8 +1518,9 @@ void dsi_dump_clocks(struct seq_file *s) } #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS -static void dsi_dump_dsi_irqs(struct dsi_data *dsi, struct seq_file *s) +static int dsi_dump_dsi_irqs(struct seq_file *s, void *p) { + struct dsi_data *dsi = p; unsigned long flags; struct dsi_irq_stats stats; @@ -1603,33 +1604,20 @@ static void dsi_dump_dsi_irqs(struct dsi_data *dsi, struct seq_file *s) PIS(ULPSACTIVENOT_ALL0); PIS(ULPSACTIVENOT_ALL1); #undef PIS -} - -static int dsi1_dump_irqs(struct seq_file *s, void *p) -{ - struct dsi_data *dsi = dsi_get_dsi_from_id(0); - dsi_dump_dsi_irqs(dsi, s); - return 0; -} - -static int dsi2_dump_irqs(struct seq_file *s, void *p) -{ - struct dsi_data *dsi = dsi_get_dsi_from_id(1); - - dsi_dump_dsi_irqs(dsi, s); return 0; } #endif -static void dsi_dump_dsi_regs(struct dsi_data *dsi, struct seq_file *s) +static int dsi_dump_dsi_regs(struct seq_file *s, void *p) { -#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r)) + struct dsi_data *dsi = p; if (dsi_runtime_get(dsi)) - return; + return 0; dsi_enable_scp_clk(dsi); +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r)) DUMPREG(DSI_REVISION); DUMPREG(DSI_SYSCONFIG); DUMPREG(DSI_SYSSTATUS); @@ -1699,25 +1687,11 @@ static void dsi_dump_dsi_regs(struct dsi_data *dsi, struct seq_file *s) DUMPREG(DSI_PLL_GO); DUMPREG(DSI_PLL_CONFIGURATION1); DUMPREG(DSI_PLL_CONFIGURATION2); +#undef DUMPREG dsi_disable_scp_clk(dsi); dsi_runtime_put(dsi); -#undef DUMPREG -} - -static int dsi1_dump_regs(struct seq_file *s, void *p) -{ - struct dsi_data *dsi = dsi_get_dsi_from_id(0); - dsi_dump_dsi_regs(dsi, s); - return 0; -} - -static int dsi2_dump_regs(struct seq_file *s, void *p) -{ - struct dsi_data *dsi = dsi_get_dsi_from_id(1); - - dsi_dump_dsi_regs(dsi, s); return 0; } @@ -5305,6 +5279,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) struct dsi_data *dsi; struct resource *dsi_mem; struct resource *res; + char name[10]; dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); if (!dsi) @@ -5443,23 +5418,13 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) dsi_runtime_put(dsi); - if (dsi->module_id == 0) - dsi->debugfs.regs = dss_debugfs_create_file(dss, "dsi1_regs", - dsi1_dump_regs, - &dsi); - else - dsi->debugfs.regs = dss_debugfs_create_file(dss, "dsi2_regs", - dsi2_dump_regs, - &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 - if (dsi->module_id == 0) - dsi->debugfs.irqs = dss_debugfs_create_file(dss, "dsi1_irqs", - dsi1_dump_irqs, - &dsi); - else - dsi->debugfs.irqs = dss_debugfs_create_file(dss, "dsi2_irqs", - dsi2_dump_irqs, - &dsi); + 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 return 0; -- cgit v1.2.3 From 3ce75d67e44c11c9f84ea0355fe6431a43ce6e94 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 2 Mar 2018 00:40:04 +0200 Subject: drm/omap: Move DSI debugfs clocks dump to dsi%u_clks files The DSI clocks are dumped in the DSS-level debugfs clocks file. This complicates the implementation as the DSI private data has to be looked up through the outputs list. Simplify it by creating two debugfs files, dsi1_clks and dsi2_clks, to dump the DSI clocks. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 43 ++++++++------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 6b16eec0b2b2..ac6ec1f20d31 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -403,6 +403,7 @@ struct dsi_data { struct { struct dss_debugfs_entry *irqs; struct dss_debugfs_entry *regs; + struct dss_debugfs_entry *clks; } debugfs; #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -442,27 +443,6 @@ static inline struct dsi_data *to_dsi_data(struct omap_dss_device *dssdev) return dev_get_drvdata(dssdev->dev); } -static struct dsi_data *dsi_get_dsi_from_id(int module) -{ - struct omap_dss_device *out; - enum omap_dss_output_id id; - - switch (module) { - case 0: - id = OMAP_DSS_OUTPUT_DSI1; - break; - case 1: - id = OMAP_DSS_OUTPUT_DSI2; - break; - default: - return NULL; - } - - out = omap_dss_get_output(id); - - return out ? to_dsi_data(out) : NULL; -} - static inline void dsi_write_reg(struct dsi_data *dsi, const struct dsi_reg idx, u32 val) { @@ -1448,8 +1428,9 @@ static void dsi_pll_disable(struct dss_pll *pll) dsi_pll_uninit(dsi, true); } -static void dsi_dump_dsi_clocks(struct dsi_data *dsi, struct seq_file *s) +static int dsi_dump_dsi_clocks(struct seq_file *s, void *p) { + struct dsi_data *dsi = p; struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo; enum dss_clk_source dispc_clk_src, dsi_clk_src; int dsi_module = dsi->module_id; @@ -1459,7 +1440,7 @@ static void dsi_dump_dsi_clocks(struct dsi_data *dsi, struct seq_file *s) dsi_clk_src = dss_get_dsi_clk_source(dsi->dss, dsi_module); if (dsi_runtime_get(dsi)) - return; + return 0; seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); @@ -1503,18 +1484,8 @@ static void dsi_dump_dsi_clocks(struct dsi_data *dsi, struct seq_file *s) seq_printf(s, "LP_CLK\t\t%lu\n", dsi->current_lp_cinfo.lp_clk); dsi_runtime_put(dsi); -} - -void dsi_dump_clocks(struct seq_file *s) -{ - struct dsi_data *dsi; - int i; - for (i = 0; i < MAX_NUM_DSI; i++) { - dsi = dsi_get_dsi_from_id(i); - if (dsi) - dsi_dump_dsi_clocks(dsi, s); - } + return 0; } #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -5426,6 +5397,9 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) 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; @@ -5442,6 +5416,7 @@ 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); -- cgit v1.2.3 From de57e9dbc1454704a54190cb3b544b841c34301a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 2 Mar 2018 01:25:32 +0200 Subject: drm/omap: dss: Remove output devices list The output devices list isn't used anymore, all output devices are accessed through the global devices list. Remove it. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index ac6ec1f20d31..e061816e5381 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4995,14 +4995,14 @@ static void dsi_init_output(struct dsi_data *dsi) out->ops = &dsi_ops; out->owner = THIS_MODULE; - omapdss_register_output(out); + omapdss_device_register(out); } static void dsi_uninit_output(struct dsi_data *dsi) { struct omap_dss_device *out = &dsi->output; - omapdss_unregister_output(out); + omapdss_device_unregister(out); } static int dsi_probe_of(struct dsi_data *dsi) -- cgit v1.2.3 From 4e20bda68e01f723d7fcc4e7d55a4afc78223fb7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 4 Mar 2018 21:49:28 +0200 Subject: drm/omap: dss: Replace omap_dss_device port number with bitmask The omap_dss_device port_num field stores the DT port number associated with the device. The field is used in different ways depending on the device type: - For DPI outputs, the port number is used as an identifier of the DPI instance - For sources, the port number is used to look up the omap_dss_device by DT port node As omap_dss_device instances are only looked up as sources by sinks, setting the field to the number of the source port works for both use cases. However, to enable looking up sinks, we need to record all the ports associated with an omap_dss_device. Do so by turning the port_num field into an of_ports bitmask. For DPI outputs the port number is additionally stored in the dpi_data structure as the output ID. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index e061816e5381..ee260353b9ca 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4994,6 +4994,7 @@ static void dsi_init_output(struct dsi_data *dsi) out->dispc_channel = dsi_get_channel(dsi); out->ops = &dsi_ops; out->owner = THIS_MODULE; + out->of_ports = BIT(0); omapdss_device_register(out); } -- cgit v1.2.3 From 66aacfe22d53137eab511b3f4d674ddd40a7b1ac Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 2 Mar 2018 21:38:21 +0200 Subject: drm/omap: dss: Cleanup error paths in output init functions Rename the jump labels according to the cleanup they perform, not the location they're accessed from, and move functions from error checks to cleanup paths, and move reference handling to simplify cleanup. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index ee260353b9ca..173c05a54550 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -5360,7 +5360,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) r = dsi_runtime_get(dsi); if (r) - goto err_runtime_get; + goto err_pm_disable; rev = dsi_read_reg(dsi, DSI_REVISION); dev_dbg(dev, "OMAP DSI rev %d.%d\n", @@ -5381,7 +5381,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) r = dsi_probe_of(dsi); if (r) { DSSERR("Invalid DSI DT data\n"); - goto err_probe_of; + goto err_uninit_output; } r = of_platform_populate(dev->of_node, NULL, NULL, dev); @@ -5404,11 +5404,10 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) return 0; -err_probe_of: +err_uninit_output: dsi_uninit_output(dsi); dsi_runtime_put(dsi); - -err_runtime_get: +err_pm_disable: pm_runtime_disable(dev); return r; } -- cgit v1.2.3 From edb715dffdee71bb8216ee4d71c0714d932e9acf Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 3 Mar 2018 18:52:59 +0200 Subject: 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 Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 301 ++++++++++++++++++++------------------ 1 file changed, 161 insertions(+), 140 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 173c05a54550..ab0426fab22e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -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; } -- cgit v1.2.3 From 27d624527d99265c2df999af3615ff71c29d06f4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 2 Mar 2018 22:13:06 +0200 Subject: drm/omap: dss: Acquire next dssdev at probe time Look up the next dssdev at probe time based on device tree links for all DSS outputs and encoders. This will be used to reverse the order of the dssdev connect and disconnect call chains. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index ab0426fab22e..631bf5805649 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -5165,7 +5165,7 @@ static const struct component_ops dsi_component_ops = { * Probe & Remove, Suspend & Resume */ -static void dsi_init_output(struct dsi_data *dsi) +static int dsi_init_output(struct dsi_data *dsi) { struct omap_dss_device *out = &dsi->output; @@ -5180,13 +5180,24 @@ static void dsi_init_output(struct dsi_data *dsi) out->owner = THIS_MODULE; out->of_ports = BIT(0); + out->next = omapdss_of_find_connected_device(out->dev->of_node, 0); + if (IS_ERR(out->next)) { + if (PTR_ERR(out->next) != -EPROBE_DEFER) + dev_err(out->dev, "failed to find video sink\n"); + return PTR_ERR(out->next); + } + omapdss_device_register(out); + + return 0; } static void dsi_uninit_output(struct dsi_data *dsi) { struct omap_dss_device *out = &dsi->output; + if (out->next) + omapdss_device_put(out->next); omapdss_device_unregister(out); } @@ -5431,7 +5442,9 @@ static int dsi_probe(struct platform_device *pdev) else dsi->num_lanes_supported = 3; - dsi_init_output(dsi); + r = dsi_init_output(dsi); + if (r) + goto err_pm_disable; r = dsi_probe_of(dsi); if (r) { @@ -5451,6 +5464,7 @@ static int dsi_probe(struct platform_device *pdev) err_uninit_output: dsi_uninit_output(dsi); +err_pm_disable: pm_runtime_disable(dev); return r; } -- cgit v1.2.3 From a48bc6ac2c6cd85bc079fc859ab14ea844e812cd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 4 Mar 2018 23:55:56 +0200 Subject: drm/omap: dss: Remove duplicated parameter to dss_mgr_(dis)connect() The dss_mgr_connect() and dss_mgr_disconnect() functions take two omap_dss_device pointers as parameters, which are always set to the same value by all callers. Remove the duplicated pointer. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 631bf5805649..d5ae01529901 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4915,7 +4915,7 @@ static int dsi_connect(struct omap_dss_device *dssdev, if (r) return r; - r = dss_mgr_connect(&dsi->output, dssdev); + r = dss_mgr_connect(dssdev); if (r) return r; @@ -4923,7 +4923,7 @@ static int dsi_connect(struct omap_dss_device *dssdev, if (r) { DSSERR("failed to connect output to new device: %s\n", dssdev->name); - dss_mgr_disconnect(&dsi->output, dssdev); + dss_mgr_disconnect(dssdev); return r; } @@ -4933,11 +4933,9 @@ static int dsi_connect(struct omap_dss_device *dssdev, static void dsi_disconnect(struct omap_dss_device *dssdev, struct omap_dss_device *dst) { - struct dsi_data *dsi = to_dsi_data(dssdev); - omapdss_output_unset_device(dssdev); - dss_mgr_disconnect(&dsi->output, dssdev); + dss_mgr_disconnect(dssdev); } static const struct omap_dss_device_ops dsi_ops = { -- cgit v1.2.3 From 8a36357ae3b2d1b4647d20bc806d524c21132572 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 5 Mar 2018 00:10:55 +0200 Subject: drm/omap: dss: Get regulators at probe time Regulators for the DPI, DSI, HDMI, SDI and VENC outputs are all looked up when connecting the output omap_dss_device. There's no need to delay regulator handling to that time, get the regulators at probe time. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index d5ae01529901..41a98021d5bf 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -1137,26 +1137,6 @@ static void dsi_runtime_put(struct dsi_data *dsi) WARN_ON(r < 0 && r != -ENOSYS); } -static int dsi_regulator_init(struct dsi_data *dsi) -{ - struct regulator *vdds_dsi; - - if (dsi->vdds_dsi_reg != NULL) - return 0; - - vdds_dsi = devm_regulator_get(dsi->dev, "vdd"); - - if (IS_ERR(vdds_dsi)) { - if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER) - DSSERR("can't get DSI VDD regulator\n"); - return PTR_ERR(vdds_dsi); - } - - dsi->vdds_dsi_reg = vdds_dsi; - - return 0; -} - static void _dsi_print_reset_status(struct dsi_data *dsi) { u32 l; @@ -1353,10 +1333,6 @@ static int dsi_pll_enable(struct dss_pll *pll) DSSDBG("PLL init\n"); - r = dsi_regulator_init(dsi); - if (r) - return r; - r = dsi_runtime_get(dsi); if (r) return r; @@ -4908,13 +4884,8 @@ static int dsi_get_clocks(struct dsi_data *dsi) static int dsi_connect(struct omap_dss_device *dssdev, struct omap_dss_device *dst) { - struct dsi_data *dsi = to_dsi_data(dssdev); int r; - r = dsi_regulator_init(dsi); - if (r) - return r; - r = dss_mgr_connect(dssdev); if (r) return r; @@ -5384,6 +5355,13 @@ static int dsi_probe(struct platform_device *pdev) return r; } + dsi->vdds_dsi_reg = devm_regulator_get(dev, "vdd"); + if (IS_ERR(dsi->vdds_dsi_reg)) { + if (PTR_ERR(dsi->vdds_dsi_reg) != -EPROBE_DEFER) + DSSERR("can't get DSI VDD regulator\n"); + return PTR_ERR(dsi->vdds_dsi_reg); + } + soc = soc_device_match(dsi_soc_devices); if (soc) dsi->data = soc->data; -- cgit v1.2.3 From 511afb44d72aa7b6b871fa71f829afaaa27e84f0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 4 Mar 2018 23:42:36 +0200 Subject: drm/omap: Reverse direction of DSS device (dis)connect operations The omapdrm and omapdss drivers are architectured based on display pipelines made of multiple components handled from sink (display) to source (DSS output). This is incompatible with the DRM bridge and panel APIs that handle components from source to sink. To reconcile the omapdrm and omapdss drivers with the DRM bridge and panel model, we need to reverse the direction of the DSS device operations. Start with the connect and disconnect operations. Signed-off-by: Laurent Pinchart Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 41a98021d5bf..0e88ae1178f7 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4881,32 +4881,42 @@ static int dsi_get_clocks(struct dsi_data *dsi) return 0; } -static int dsi_connect(struct omap_dss_device *dssdev, - struct omap_dss_device *dst) +static int dsi_connect(struct omap_dss_device *src, + struct omap_dss_device *dst) { int r; - r = dss_mgr_connect(dssdev); + r = dss_mgr_connect(dst); if (r) return r; - r = omapdss_output_set_device(dssdev, dst); + r = omapdss_output_set_device(dst, dst->next); if (r) { DSSERR("failed to connect output to new device: %s\n", - dssdev->name); - dss_mgr_disconnect(dssdev); - return r; + dst->name); + goto err_mgr_disconnect; } + r = omapdss_device_connect(dst->dss, dst, dst->next); + if (r) + goto err_output_unset; + return 0; + +err_output_unset: + omapdss_output_unset_device(dst); +err_mgr_disconnect: + dss_mgr_disconnect(dst); + return r; } -static void dsi_disconnect(struct omap_dss_device *dssdev, - struct omap_dss_device *dst) +static void dsi_disconnect(struct omap_dss_device *src, + struct omap_dss_device *dst) { - omapdss_output_unset_device(dssdev); + omapdss_device_disconnect(dst, dst->next); + omapdss_output_unset_device(dst); - dss_mgr_disconnect(dssdev); + dss_mgr_disconnect(dst); } static const struct omap_dss_device_ops dsi_ops = { -- cgit v1.2.3 From 713165561b7e372cd21f34bfeb82188361569f74 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 6 Mar 2018 01:25:13 +0200 Subject: drm/omap: dss: Move display type validation to initialization time The display type is validated when the display is connected to the DSS output. We already have all the information we need for validation when initializing the outputs. Move validation to output initialization to simplify pipeline connection handling. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 0e88ae1178f7..9c617e35efd1 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4890,24 +4890,13 @@ static int dsi_connect(struct omap_dss_device *src, if (r) return r; - r = omapdss_output_set_device(dst, dst->next); + r = omapdss_device_connect(dst->dss, dst, dst->next); if (r) { - DSSERR("failed to connect output to new device: %s\n", - dst->name); - goto err_mgr_disconnect; + dss_mgr_disconnect(dst); + return r; } - r = omapdss_device_connect(dst->dss, dst, dst->next); - if (r) - goto err_output_unset; - return 0; - -err_output_unset: - omapdss_output_unset_device(dst); -err_mgr_disconnect: - dss_mgr_disconnect(dst); - return r; } static void dsi_disconnect(struct omap_dss_device *src, @@ -5147,6 +5136,7 @@ static const struct component_ops dsi_component_ops = { static int dsi_init_output(struct dsi_data *dsi) { struct omap_dss_device *out = &dsi->output; + int r; out->dev = dsi->dev; out->id = dsi->module_id == 0 ? @@ -5166,6 +5156,13 @@ static int dsi_init_output(struct dsi_data *dsi) return PTR_ERR(out->next); } + r = omapdss_output_validate(out); + if (r) { + omapdss_device_put(out->next); + out->next = NULL; + return r; + } + omapdss_device_register(out); return 0; -- cgit v1.2.3 From 3be0f15bd6e94aa17a571020704bde413342e8eb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 6 Mar 2018 01:51:31 +0200 Subject: drm/omap: dss: Merge two disconnection helpers To simplify the pipeline disconnection handling merge the omapdss_device_disconnect() and omapdss_output_unset_device() functions. The device state check is now called for every device in the pipeline, extending this sanity check coverage. There is no need to return an error from omapdss_device_disconnect() when the check fails, as omapdss_output_unset_device() used to do, given that we can't prevent disconnection due to device unbinding (the return value of omapdss_output_unset_device() is never checked in the current code for that reason). Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 9c617e35efd1..948e3b873523 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4903,7 +4903,6 @@ static void dsi_disconnect(struct omap_dss_device *src, struct omap_dss_device *dst) { omapdss_device_disconnect(dst, dst->next); - omapdss_output_unset_device(dst); dss_mgr_disconnect(dst); } -- cgit v1.2.3 From 0f37938c7c432c7737d85940475bcbd3c362447e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 7 Mar 2018 00:28:18 +0200 Subject: drm/omap: Set dispc_channel_connect from DSS output connect handlers The omap_dss_device.dispc_channel_connect field is used by DSS outputs to fail the .enable() operation if they're not connected. Set the field directly from the (dis)connect handlers of the DSS outputs instead of going through the CRTC dss_mgr operations. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 948e3b873523..921e794aec0d 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4896,12 +4896,15 @@ static int dsi_connect(struct omap_dss_device *src, return r; } + dst->dispc_channel_connected = true; return 0; } static void dsi_disconnect(struct omap_dss_device *src, struct omap_dss_device *dst) { + dst->dispc_channel_connected = false; + omapdss_device_disconnect(dst, dst->next); dss_mgr_disconnect(dst); -- cgit v1.2.3 From 43f7078f6b6f8fed8edfbbdeff83e276306e5e6e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 6 Mar 2018 23:34:53 +0200 Subject: drm/omap: dss: Remove the dss_mgr_(dis)connect() operations The dss_mgr .connect() and .disconnect() are implemented as no-op in omapdrm. The operations are unneeded, remove them. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 921e794aec0d..0afefac4bf65 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4886,15 +4886,9 @@ static int dsi_connect(struct omap_dss_device *src, { int r; - r = dss_mgr_connect(dst); - if (r) - return r; - r = omapdss_device_connect(dst->dss, dst, dst->next); - if (r) { - dss_mgr_disconnect(dst); + if (r) return r; - } dst->dispc_channel_connected = true; return 0; @@ -4906,8 +4900,6 @@ static void dsi_disconnect(struct omap_dss_device *src, dst->dispc_channel_connected = false; omapdss_device_disconnect(dst, dst->next); - - dss_mgr_disconnect(dst); } static const struct omap_dss_device_ops dsi_ops = { -- cgit v1.2.3 From b4935e3a3cfa456b356e9714e75513be672c227e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 6 Jun 2018 15:20:01 +0300 Subject: drm/omap: Store bus flags in the omap_dss_device structure Source components in the display pipeline need to configure their output signals polarities and clock driving edge based on the requirements of the sink component. Those requirements are currently shared across the whole pipeline in the flags of a videomode structure, instead of being local to each bus. This both prevents multiple buses from having different configurations (when the hardware supports it), and makes it difficult to move from videomode to drm_display_mode as the latter doesn't contain bus polarities and clock edge flags. Add a bus_flags field to the omap_dss_device structure and move the DISPLAY_FLAGS_DE_(LOW|HIGH), DISPLAY_FLAGS_PIXDATA_(POS|NEG)EDGE and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE videomode flags to bus_flags in all external encoders, connectors and panels. The videomode flags are still used internally for internal encoders, this will be addressed in a second step. The related videomode flags in the default mode of the DVI connector can simply be dropped, as they are always overridden by the TFP410 driver. Note that this results in both the DISPLAY_FLAGS_SYNC_POSEDGE and DISPLAY_FLAGS_SYNC_NEGEDGE flags being set, which is invalid, but only the former is tested for when programming the DISPC, so the DVI connector flags are effectively overridden by the TFP410 flags. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 0afefac4bf65..280f63081224 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4053,12 +4053,6 @@ static int dsi_display_init_dispc(struct dsi_data *dsi) dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; - dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; - dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; - dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW; - dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH; - dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; - dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; dss_mgr_set_timings(&dsi->output, &dsi->vm); @@ -5142,6 +5136,9 @@ static int dsi_init_output(struct dsi_data *dsi) out->ops = &dsi_ops; out->owner = THIS_MODULE; out->of_ports = BIT(0); + out->bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE + | DRM_BUS_FLAG_DE_HIGH + | DRM_BUS_FLAG_SYNC_NEGEDGE; out->next = omapdss_of_find_connected_device(out->dev->of_node, 0); if (IS_ERR(out->next)) { -- cgit v1.2.3 From 7d39e59be51bddbd5cd487274d48969a39a3bcd1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 8 Jun 2018 15:59:31 +0300 Subject: drm/omap: dsi: Fixup video mode in .set_config() operation The DSI encoder modifies the passed videomode to take the requirements of the internal DISPC-DSI bus into account in the .enable_video_output() operation. This should be performed in the .check_timings() operation instead. There is however no .check_timings() operation as the DSI encoder uses a custom API, so move it to the closest match which is the .set_config() operation. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 280f63081224..d1734ea2534a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -3265,7 +3265,7 @@ static void dsi_config_vp_num_line_buffers(struct dsi_data *dsi) if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { int bpp = dsi_get_pixel_size(dsi->pix_fmt); - struct videomode *vm = &dsi->vm; + const struct videomode *vm = &dsi->vm; /* * Don't use line buffers if width is greater than the video * port's line buffer size @@ -3394,7 +3394,7 @@ static void dsi_config_cmd_mode_interleaving(struct dsi_data *dsi) int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; int tclk_trail, ths_exit, exiths_clk; bool ddr_alwon; - struct videomode *vm = &dsi->vm; + const struct videomode *vm = &dsi->vm; int bpp = dsi_get_pixel_size(dsi->pix_fmt); int ndl = dsi->num_lanes_used - 1; int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1; @@ -3644,7 +3644,7 @@ static void dsi_proto_timings(struct dsi_data *dsi) int vbp = dsi->vm_timings.vbp; int window_sync = dsi->vm_timings.window_sync; bool hsync_end; - struct videomode *vm = &dsi->vm; + const struct videomode *vm = &dsi->vm; int bpp = dsi_get_pixel_size(dsi->pix_fmt); int tl, t_he, width_bytes; @@ -4044,16 +4044,6 @@ static int dsi_display_init_dispc(struct dsi_data *dsi) dsi->mgr_config.fifohandcheck = false; } - /* - * override interlace, logic level and edge related parameters in - * videomode with default values - */ - dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED; - dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; - dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; - dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; - dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; - dss_mgr_set_timings(&dsi->output, &dsi->vm); r = dsi_configure_dispc_clocks(dsi); @@ -4755,6 +4745,17 @@ static int dsi_set_config(struct omap_dss_device *dssdev, dsi->user_dispc_cinfo = ctx.dispc_cinfo; dsi->vm = ctx.vm; + + /* + * override interlace, logic level and edge related parameters in + * videomode with default values + */ + dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED; + dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; + dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; + dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; + dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; + dsi->vm_timings = ctx.dsi_vm; mutex_unlock(&dsi->lock); -- cgit v1.2.3 From d8dbe79143764b86bd04c63c044431565582a22d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 8 Jun 2018 16:53:37 +0300 Subject: drm/omap: Store CRTC timings in .set_timings() operation The video timings are stored in the CRTC structure by the omap_crtc_dss_set_timings() function, called by dss_mgr_set_timings() from the .enable() operation of the internal encoders. This instead belongs to the .set_timings() code paths. Move the omap_crtc_dss_set_timings() calls accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dsi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c') diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index d1734ea2534a..394c129cfb3b 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -3901,8 +3901,6 @@ static void dsi_update_screen_dispc(struct dsi_data *dsi) msecs_to_jiffies(250)); BUG_ON(r == 0); - dss_mgr_set_timings(&dsi->output, &dsi->vm); - dss_mgr_start_update(&dsi->output); if (dsi->te_enabled) { @@ -4044,8 +4042,6 @@ static int dsi_display_init_dispc(struct dsi_data *dsi) dsi->mgr_config.fifohandcheck = false; } - dss_mgr_set_timings(&dsi->output, &dsi->vm); - r = dsi_configure_dispc_clocks(dsi); if (r) goto err1; @@ -4756,6 +4752,8 @@ static int dsi_set_config(struct omap_dss_device *dssdev, dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; + dss_mgr_set_timings(&dsi->output, &dsi->vm); + dsi->vm_timings = ctx.dsi_vm; mutex_unlock(&dsi->lock); -- cgit v1.2.3