On 09/11/2020 12:39, Laurent Pinchart wrote: > On Thu, Nov 05, 2020 at 02:03:10PM +0200, Tomi Valkeinen wrote: >> From: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx> >> >> This converts the DSI module to expect common drm_panel display >> drivers instead of dssdev based ones. >> >> Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx> >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@xxxxxx> >> --- >> .../gpu/drm/omapdrm/displays/panel-dsi-cm.c | 204 +++++++----------- >> drivers/gpu/drm/omapdrm/dss/dsi.c | 133 ++++++++++-- >> .../gpu/drm/omapdrm/dss/omapdss-boot-init.c | 1 - >> drivers/gpu/drm/omapdrm/dss/omapdss.h | 8 - >> 4 files changed, 189 insertions(+), 157 deletions(-) >> >> diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c >> index d9b3444b4faf..3668b3f0aff2 100644 >> --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c >> +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c >> @@ -6,8 +6,6 @@ >> * Author: Tomi Valkeinen <tomi.valkeinen@xxxxxx> >> */ >> >> -/* #define DEBUG */ >> - >> #include <linux/backlight.h> >> #include <linux/delay.h> >> #include <linux/gpio/consumer.h> >> @@ -20,11 +18,14 @@ >> #include <linux/regulator/consumer.h> >> >> #include <drm/drm_connector.h> >> +#include <drm/drm_mipi_dsi.h> >> +#include <drm/drm_panel.h> >> +#include <drm/drm_modes.h> > > Alphabetically ordered please. > >> >> +#include <video/display_timing.h> >> #include <video/mipi_display.h> >> #include <video/of_display_timing.h> >> - >> -#include "../dss/omapdss.h" >> +#include <video/videomode.h> >> >> #define DCS_READ_NUM_ERRORS 0x05 >> #define DCS_GET_ID1 0xda >> @@ -35,11 +36,8 @@ >> >> struct panel_drv_data { >> struct mipi_dsi_device *dsi; >> - >> - struct omap_dss_device dssdev; >> - struct omap_dss_device *src; >> - >> - struct videomode vm; >> + struct drm_panel panel; >> + struct drm_display_mode mode; >> >> struct mutex lock; >> >> @@ -71,7 +69,11 @@ struct panel_drv_data { >> bool ulps_enabled; >> }; >> >> -#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) >> + > > A single blank line is enough. > >> +static inline struct panel_drv_data *panel_to_ddata(struct drm_panel *panel) >> +{ >> + return container_of(panel, struct panel_drv_data, panel); >> +} >> >> static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable); >> >> @@ -285,7 +287,6 @@ static void dsicm_hw_reset(struct panel_drv_data *ddata) >> >> static int dsicm_power_on(struct panel_drv_data *ddata) >> { >> - struct omap_dss_device *src = ddata->src; >> u8 id1, id2, id3; >> int r; >> >> @@ -322,10 +323,6 @@ static int dsicm_power_on(struct panel_drv_data *ddata) >> if (r) >> goto err; >> >> - r = src->ops->dsi.enable_video_output(src, ddata->dsi->channel); >> - if (r) >> - goto err; >> - >> ddata->enabled = true; >> >> if (!ddata->intro_printed) { >> @@ -345,15 +342,12 @@ static int dsicm_power_on(struct panel_drv_data *ddata) >> return r; >> } >> >> -static void dsicm_power_off(struct panel_drv_data *ddata) >> +static int dsicm_power_off(struct panel_drv_data *ddata) >> { >> - struct omap_dss_device *src = ddata->src; >> int r; >> >> ddata->enabled = false; >> >> - src->ops->dsi.disable_video_output(src, ddata->dsi->channel); >> - >> r = mipi_dsi_dcs_set_display_off(ddata->dsi); >> if (!r) >> r = dsicm_sleep_in(ddata); >> @@ -363,51 +357,25 @@ static void dsicm_power_off(struct panel_drv_data *ddata) >> "error disabling panel, issuing HW reset\n"); >> dsicm_hw_reset(ddata); >> } >> -} >> - >> -static int dsicm_connect(struct omap_dss_device *src, >> - struct omap_dss_device *dst) >> -{ >> - struct panel_drv_data *ddata = to_panel_data(dst); >> - >> - ddata->src = src; >> - return 0; >> -} >> - >> -static void dsicm_disconnect(struct omap_dss_device *src, >> - struct omap_dss_device *dst) >> -{ >> - struct panel_drv_data *ddata = to_panel_data(dst); >> >> - ddata->src = NULL; >> + return r; >> } >> >> -static void dsicm_pre_enable(struct omap_dss_device *dssdev) >> +static int dsicm_prepare(struct drm_panel *panel) >> { >> - struct panel_drv_data *ddata = to_panel_data(dssdev); >> - struct omap_dss_device *src = ddata->src; >> + struct panel_drv_data *ddata = panel_to_ddata(panel); >> int r; >> - struct omap_dss_dsi_config dsi_config = { >> - .vm = &ddata->vm, >> - .hs_clk_min = 150000000, >> - .hs_clk_max = 300000000, >> - .lp_clk_min = 7000000, >> - .lp_clk_max = 10000000, >> - }; >> >> r = regulator_bulk_enable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies); >> if (r) >> dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r); >> >> - r = src->ops->dsi.set_config(src, &dsi_config); >> - if (r) { >> - dev_err(&ddata->dsi->dev, "failed to configure DSI\n"); >> - } >> + return r; >> } >> >> -static void dsicm_enable(struct omap_dss_device *dssdev) >> +static int dsicm_enable(struct drm_panel *panel) >> { >> - struct panel_drv_data *ddata = to_panel_data(dssdev); >> + struct panel_drv_data *ddata = panel_to_ddata(panel); >> int r; >> >> mutex_lock(&ddata->lock); >> @@ -420,33 +388,39 @@ static void dsicm_enable(struct omap_dss_device *dssdev) >> >> dsicm_bl_power(ddata, true); >> >> - return; >> + return 0; >> err: >> - dev_dbg(&ddata->dsi->dev, "enable failed (%d)\n", r); >> + dev_err(&ddata->dsi->dev, "enable failed (%d)\n", r); >> mutex_unlock(&ddata->lock); >> + return r; >> +} >> + >> +static int dsicm_unprepare(struct drm_panel *panel) >> +{ >> + struct panel_drv_data *ddata = panel_to_ddata(panel); >> + int r; >> + >> + r = regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies); >> + if (r) >> + dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r); >> + >> + return r; >> } >> >> -static void dsicm_disable(struct omap_dss_device *dssdev) >> +static int dsicm_disable(struct drm_panel *panel) >> { >> - struct panel_drv_data *ddata = to_panel_data(dssdev); >> + struct panel_drv_data *ddata = panel_to_ddata(panel); >> + int r; >> >> dsicm_bl_power(ddata, false); >> >> mutex_lock(&ddata->lock); >> >> - dsicm_power_off(ddata); >> + r = dsicm_power_off(ddata); >> >> mutex_unlock(&ddata->lock); >> -} >> - >> -static void dsicm_post_disable(struct omap_dss_device *dssdev) >> -{ >> - struct panel_drv_data *ddata = to_panel_data(dssdev); >> - int r; >> >> - r = regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies); >> - if (r) >> - dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r); >> + return r; >> } >> >> static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable) >> @@ -465,50 +439,37 @@ static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable) >> return r; >> } >> >> -static int dsicm_get_modes(struct omap_dss_device *dssdev, >> +static int dsicm_get_modes(struct drm_panel *panel, >> struct drm_connector *connector) >> { >> - struct panel_drv_data *ddata = to_panel_data(dssdev); >> + struct panel_drv_data *ddata = panel_to_ddata(panel); >> + struct drm_display_mode *mode; >> + >> + mode = drm_mode_duplicate(connector->dev, &ddata->mode); >> + if (!mode) { >> + dev_err(&ddata->dsi->dev, "failed to add mode %ux%ux@%u kHz\n", >> + ddata->mode.hdisplay, ddata->mode.vdisplay, >> + ddata->mode.clock); >> + return -ENOMEM; >> + } >> + >> + drm_mode_set_name(mode); >> + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; >> >> connector->display_info.width_mm = ddata->width_mm; >> connector->display_info.height_mm = ddata->height_mm; >> >> - return omapdss_display_get_modes(connector, &ddata->vm); >> -} >> - >> -static int dsicm_check_timings(struct omap_dss_device *dssdev, >> - struct drm_display_mode *mode) >> -{ >> - struct panel_drv_data *ddata = to_panel_data(dssdev); >> - int ret = 0; >> - >> - if (mode->hdisplay != ddata->vm.hactive) >> - ret = -EINVAL; >> - >> - if (mode->vdisplay != ddata->vm.vactive) >> - ret = -EINVAL; >> + drm_mode_probed_add(connector, mode); >> >> - if (ret) { >> - dev_warn(dssdev->dev, "wrong resolution: %d x %d", >> - mode->hdisplay, mode->vdisplay); >> - dev_warn(dssdev->dev, "panel resolution: %d x %d", >> - ddata->vm.hactive, ddata->vm.vactive); >> - } >> - >> - return ret; >> + return 1; >> } >> >> -static const struct omap_dss_device_ops dsicm_ops = { >> - .connect = dsicm_connect, >> - .disconnect = dsicm_disconnect, >> - >> - .pre_enable = dsicm_pre_enable, >> - .enable = dsicm_enable, >> - .disable = dsicm_disable, >> - .post_disable = dsicm_post_disable, >> - >> - .get_modes = dsicm_get_modes, >> - .check_timings = dsicm_check_timings, >> +static const struct drm_panel_funcs dsicm_panel_funcs = { >> + .unprepare = dsicm_unprepare, >> + .disable = dsicm_disable, >> + .prepare = dsicm_prepare, >> + .enable = dsicm_enable, >> + .get_modes = dsicm_get_modes, >> }; >> >> static int dsicm_probe_of(struct mipi_dsi_device *dsi) >> @@ -517,8 +478,12 @@ static int dsicm_probe_of(struct mipi_dsi_device *dsi) >> struct backlight_device *backlight; >> struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi); >> struct display_timing timing; >> + struct videomode vm = { 0 }; > > How about > > struct videomode vm = { > .hactive = 864, > .vactive = 480, > }; > >> int err; >> >> + vm.hactive = 864; >> + vm.vactive = 480; >> + >> ddata->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW); >> if (IS_ERR(ddata->reset_gpio)) { >> err = PTR_ERR(ddata->reset_gpio); >> @@ -528,15 +493,16 @@ static int dsicm_probe_of(struct mipi_dsi_device *dsi) >> >> err = of_get_display_timing(node, "panel-timing", &timing); >> if (!err) { >> - videomode_from_timing(&timing, &ddata->vm); >> - if (!ddata->vm.pixelclock) >> - ddata->vm.pixelclock = >> - ddata->vm.hactive * ddata->vm.vactive * 60; >> + videomode_from_timing(&timing, &vm); >> } else { >> dev_warn(&dsi->dev, >> "failed to get video timing, using defaults\n"); >> } >> >> + if (!vm.pixelclock) >> + vm.pixelclock = vm.hactive * vm.vactive * 60; >> + drm_display_mode_from_videomode(&vm, &ddata->mode); >> + >> ddata->width_mm = 0; >> of_property_read_u32(node, "width-mm", &ddata->width_mm); >> >> @@ -570,7 +536,6 @@ static int dsicm_probe(struct mipi_dsi_device *dsi) >> struct panel_drv_data *ddata; >> struct backlight_device *bldev = NULL; >> struct device *dev = &dsi->dev; >> - struct omap_dss_device *dssdev; >> int r; >> >> dev_dbg(dev, "probe\n"); >> @@ -582,30 +547,17 @@ static int dsicm_probe(struct mipi_dsi_device *dsi) >> mipi_dsi_set_drvdata(dsi, ddata); >> ddata->dsi = dsi; >> >> - ddata->vm.hactive = 864; >> - ddata->vm.vactive = 480; >> - ddata->vm.pixelclock = 864 * 480 * 60; >> - >> r = dsicm_probe_of(dsi); >> if (r) >> return r; >> >> - dssdev = &ddata->dssdev; >> - dssdev->dev = dev; >> - dssdev->ops = &dsicm_ops; >> - dssdev->type = OMAP_DISPLAY_TYPE_DSI; >> - dssdev->display = true; >> - dssdev->owner = THIS_MODULE; >> - dssdev->of_port = 0; >> - dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES; >> - >> - omapdss_display_init(dssdev); >> - omapdss_device_register(dssdev); >> - >> mutex_init(&ddata->lock); >> >> dsicm_hw_reset(ddata); >> >> + drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs, >> + DRM_MODE_CONNECTOR_DSI); >> + >> if (ddata->use_dsi_backlight) { >> struct backlight_properties props = { 0 }; >> props.max_brightness = 255; >> @@ -637,6 +589,8 @@ static int dsicm_probe(struct mipi_dsi_device *dsi) >> if (ddata->ulps_enabled) >> dsi->mode_flags |= MIPI_DSI_MODE_ULPS_IDLE; >> >> + drm_panel_add(&ddata->panel); >> + >> r = mipi_dsi_attach(dsi); >> if (r < 0) >> goto err_dsi_attach; >> @@ -644,6 +598,7 @@ static int dsicm_probe(struct mipi_dsi_device *dsi) >> return 0; >> >> err_dsi_attach: >> + drm_panel_remove(&ddata->panel); >> sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group); >> err_bl: >> if (ddata->extbldev) >> @@ -655,15 +610,12 @@ static int dsicm_probe(struct mipi_dsi_device *dsi) >> static int __exit dsicm_remove(struct mipi_dsi_device *dsi) >> { >> struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi); >> - struct omap_dss_device *dssdev = &ddata->dssdev; >> >> dev_dbg(&dsi->dev, "remove\n"); >> >> mipi_dsi_detach(dsi); >> >> - omapdss_device_unregister(dssdev); >> - >> - omapdss_device_disconnect(ddata->src, dssdev); >> + drm_panel_remove(&ddata->panel); >> >> sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group); >> >> @@ -677,7 +629,7 @@ static int __exit dsicm_remove(struct mipi_dsi_device *dsi) >> } >> >> static const struct of_device_id dsicm_of_match[] = { >> - { .compatible = "omapdss,panel-dsi-cm", }, >> + { .compatible = "panel-dsi-cm", }, >> {}, >> }; >> >> diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c >> index 620cef8bb1f2..a1a867a7d91d 100644 >> --- a/drivers/gpu/drm/omapdrm/dss/dsi.c >> +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c >> @@ -36,6 +36,7 @@ >> #include <linux/sys_soc.h> >> >> #include <drm/drm_mipi_dsi.h> >> +#include <drm/drm_panel.h> >> #include <video/mipi_display.h> >> >> #include "omapdss.h" >> @@ -217,6 +218,8 @@ static int dsi_vc_send_null(struct dsi_data *dsi, int channel); >> static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi, >> const struct mipi_dsi_msg *msg); >> >> +static void dsi_display_disable(struct omap_dss_device *dssdev); >> + > > Could you reorder functions to avoid forward-declarations ? This can be > done on top if it generates annoying conflicts. > >> /* DSI PLL HSDIV indices */ >> #define HSDIV_DISPC 0 >> #define HSDIV_DSI 1 >> @@ -383,6 +386,7 @@ struct dsi_data { >> bool te_enabled; >> bool ulps_enabled; >> bool ulps_auto_idle; >> + bool video_enabled; >> >> struct delayed_work ulps_work; >> >> @@ -423,6 +427,8 @@ struct dsi_data { >> >> unsigned int scp_clk_refcount; >> >> + struct omap_dss_dsi_config config; >> + >> struct dss_lcd_mgr_config mgr_config; >> struct videomode vm; >> enum mipi_dsi_pixel_format pix_fmt; >> @@ -3622,7 +3628,7 @@ static int dsi_configure_pins(struct omap_dss_device *dssdev, >> return 0; >> } >> >> -static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) >> +static void dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) >> { >> struct dsi_data *dsi = to_dsi_data(dssdev); >> int bpp = mipi_dsi_pixel_format_to_bpp(dsi->pix_fmt); >> @@ -3631,8 +3637,10 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) >> int r; >> >> r = dsi_display_init_dispc(dsi); >> - if (r) >> - return r; >> + if (r) { >> + dev_err(dsi->dev, "failed to init dispc!\n"); >> + return; >> + } >> >> if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { >> switch (dsi->pix_fmt) { >> @@ -3672,7 +3680,7 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) >> if (r) >> goto err_mgr_enable; >> >> - return 0; >> + return; >> >> err_mgr_enable: >> if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { >> @@ -3681,7 +3689,8 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) >> } >> err_pix_fmt: >> dsi_display_uninit_dispc(dsi); >> - return r; >> + dev_err(dsi->dev, "failed to enable DSI encoder!\n"); >> + return; >> } >> >> static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) >> @@ -3704,6 +3713,25 @@ static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel >> dsi_display_uninit_dispc(dsi); >> } >> >> +static void dsi_disable_video_outputs(struct omap_dss_device *dssdev) >> +{ >> + struct dsi_data *dsi = to_dsi_data(dssdev); >> + int i; >> + >> + dsi_bus_lock(dsi); >> + dsi->video_enabled = false; >> + >> + for (i = 0; i < 3; i++) { >> + if (!dsi->vc[i].dest) >> + continue; >> + dsi_disable_video_output(dssdev, i); >> + } >> + >> + dsi_display_disable(dssdev); >> + >> + dsi_bus_unlock(dsi); >> +} >> + >> static void dsi_update_screen_dispc(struct dsi_data *dsi) >> { >> unsigned int bytespp; >> @@ -3897,6 +3925,11 @@ static int dsi_update_channel(struct omap_dss_device *dssdev, int channel) >> >> dsi_bus_lock(dsi); >> >> + if (!dsi->video_enabled) { >> + r = -EIO; >> + goto err; >> + } >> + >> if (!dsi->vc[channel].dest) { >> r = -ENODEV; >> goto err; >> @@ -3942,7 +3975,7 @@ static int dsi_update_all(struct omap_dss_device *dssdev) >> >> for (i = 0; i < 4; i++) { >> r = dsi_update_channel(dssdev, i); >> - if (r != -ENODEV) >> + if (r && r != -ENODEV) > > Does this belong to this patch ? I haven't flagged it when reviwing the > patch that introduced this code, assuming that you meant to exit from > the loop once a channel with a client is found, given that we don't > support multiple clients. In any case this should be coordinated with > dsi_enable_video_outputs() and dsi_disable_video_outputs(), all should > stop on the first client, or loop over all clients. Yes, it should be in an earlier patch. I think this code needs more work, but in any case this change belongs to the patch that added dsi_update_all. >> @@ -5057,6 +5138,10 @@ static int omap_dsi_host_attach(struct mipi_dsi_host *host, >> >> dsi_bus_lock(dsi); >> >> + panel = of_drm_find_panel(client->dev.of_node); >> + if (IS_ERR(panel)) >> + return PTR_ERR(panel); > > Is it intended that the panel isn't used ? I think it's left over code. I'll drop. Tomi -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel