Re: [PATCH] drm/omap: tiler: add hibernation callback
On Wed, Feb 25, 2015 at 1:08 PM, grygorii.stras...@linaro.org wrote: From: Grygorii Strashko grygorii.stras...@linaro.org Setting a dev_pm_ops resume callback but not a set of hibernation handler means that pm function will not be called upon hibernation. Fix this by using SIMPLE_DEV_PM_OPS, which appropriately assigns the suspend and hibernation handlers and move omap_dmm_resume under CONFIG_PM_SLEEP to avoid build warnings. Signed-off-by: Grygorii Strashko grygorii.stras...@linaro.org Reviewed-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 10 +++--- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index 56c6055..afb8cfc 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -941,7 +941,7 @@ error: } #endif -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int omap_dmm_resume(struct device *dev) { struct tcm_area area; @@ -965,12 +965,10 @@ static int omap_dmm_resume(struct device *dev) return 0; } - -static const struct dev_pm_ops omap_dmm_pm_ops = { - .resume = omap_dmm_resume, -}; #endif +SIMPLE_DEV_PM_OPS(omap_dmm_pm_ops, NULL, omap_dmm_resume); + #if defined(CONFIG_OF) static const struct of_device_id dmm_of_match[] = { { .compatible = ti,omap4-dmm, }, @@ -986,9 +984,7 @@ struct platform_driver omap_dmm_driver = { .owner = THIS_MODULE, .name = DMM_DRIVER_NAME, .of_match_table = of_match_ptr(dmm_of_match), -#ifdef CONFIG_PM .pm = omap_dmm_pm_ops, -#endif }, }; -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH/RESEND 0/9] drm: tilcdc driver fixes
On Fri, Jun 27, 2014 at 6:08 PM, Darren Etheridge detheri...@ti.com wrote: Guido, On 06/17/2014 09:17 AM, Guido Martínez wrote: The tilcdc driver could be compiled as a module, but was severely broken and could not be used as such. This patchset attempts to fix the issues preventing a proper load/unload of the module. Issues included dangling sysfs nodes, dangling devices, memory leaks and a double kfree. It now seems to be working ok. We have tested this by loading and unloading the driver repeteadly, with both panel and slave connectors and found no flaws. There is still one warning left on tilcdc_crtc_destroy, caused by destroying the connector while still in an ON status. We don't know why this happens or why it's an issue, so we did not fix it. Yes I see what you mean, it triggers the WARN_ON in tilcdc_crtc_destroy because DRM_MODE_DPMS_ON is still set. This WARN_ON does make some sense because DPMS_OFF would have the effect of turning off clocks and putting the monitor to sleep which seems logical considering we have torn down the display. Adding a tilcdc_crtc_dpms(DPMS_OFF) right before the WARN_ON confirms this, but it seems strange that this hasn't happened automatically (+ Russell doesn't need to do it in his Armada driver) - so I suspect there is a better way. tbh, I'm not entirely sure offhand why drm_mode_config_cleanup() doesn't remove the fb's first (which should have the effect of shutting down any lit crtc/encoder/connector).. that would seem like the sensible way to shut down.. BR, -R Otherwise I think this is a good and useful patch series. Darren The first 7 patches are bug fixes which and should probably be applied in the stable trees. The last two are clean-ups. Resending this since I got no replies. Guido Martínez (9): drm/i2c: tda998x: move drm_i2c_encoder_destroy call drm/tilcdc: panel: fix dangling sysfs connector node drm/tilcdc: slave: fix dangling sysfs connector node drm/tilcdc: tfp410: fix dangling sysfs connector node drm/tilcdc: panel: fix leak when unloading the module drm/tilcdc: fix release order on exit drm/tilcdc: fix double kfree drm/tilcdc: remove submodule destroy calls drm/tilcdc: replace late_initcall with module_init drivers/gpu/drm/i2c/tda998x_drv.c | 2 +- drivers/gpu/drm/tilcdc/Module.symvers | 0 drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 + drivers/gpu/drm/tilcdc/tilcdc_drv.h| 1 - drivers/gpu/drm/tilcdc/tilcdc_panel.c | 39 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 27 +-- drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 35 +++--- 7 files changed, 59 insertions(+), 60 deletions(-) create mode 100644 drivers/gpu/drm/tilcdc/Module.symvers ___ dri-devel mailing list dri-de...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm/tilcdc: Defer probe if no encoders/connectors found
On Wed, Dec 18, 2013 at 8:56 AM, Markus Pargmann m...@pengutronix.de wrote: At the moment this driver fails to load if no encoders/connectors were found. In case other drivers that register encoders/connectors (tilcdc_panel) are defered it would be better to check for encoders/connectors later again. This patch replaces the returncode -ENXIO with -EPROBE_DEFER to get a working setup even if tilcdc_panel probes after tilcdc. yeah, that is probably better than relying on late_initcall() hacks.. Signed-off-by: Rob Clark robdcl...@gmail.com Signed-off-by: Markus Pargmann m...@pengutronix.de --- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 116da19..217303c 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -84,7 +84,7 @@ static int modeset_init(struct drm_device *dev) if ((priv-num_encoders == 0) || (priv-num_connectors == 0)) { /* oh nos! */ dev_err(dev-dev, no encoders/connectors found\n); - return -ENXIO; + return -EPROBE_DEFER; } dev-mode_config.min_width = 0; -- 1.8.5.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] drm: omap: Enable DT support for DMM
On Mon, Sep 16, 2013 at 2:28 AM, Archit Taneja arc...@ti.com wrote: On Friday 13 September 2013 07:44 PM, Rob Clark wrote: On Fri, Sep 13, 2013 at 5:14 AM, Archit Taneja arc...@ti.com wrote: Enable use of DT for DMM/Tiler. Originally worked on by Andy Gross. looks good.. but do we want to get information about # of LUT's, etc, from DT? Or did we decide that we can reliably get this from the hw? I lost track of that discussion (I guess Andy would remember).. I am not aware of the discussion either. But looks like we get the LUT info from the HW registers in omap_dmm_probe: right.. I'm possibly mis-remembering, but I thought I remember Andy worried that this was not reliable for some reason or another, but I can't really remember the details. The issue may have only been related to a pre-Si simulation environment, so it could be nothing. I suppose if it becomes an issue in the future we could always add DT bindings to override what we would read from the hw, so I guess if this works on all the current devices, maybe it isn't worth worrying about right now. BR, -R hwinfo = readl(omap_dmm-base + DMM_PAT_HWINFO); omap_dmm-num_engines = (hwinfo 24) 0x1F; omap_dmm-num_lut = (hwinfo 16) 0x1F; omap_dmm-container_width = 256; omap_dmm-container_height = 128; atomic_set(omap_dmm-engine_counter, omap_dmm-num_engines); /* read out actual LUT width and height */ pat_geom = readl(omap_dmm-base + DMM_PAT_GEOMETRY); omap_dmm-lut_width = ((pat_geom 16) 0xF) 5; omap_dmm-lut_height = ((pat_geom 24) 0xF) 5; /* increment LUT by one if on OMAP5 */ /* LUT has twice the height, and is split into a separate container */ if (omap_dmm-lut_height != omap_dmm-container_height) omap_dmm-num_lut++; Archit -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] drm: omap: Enable DT support for DMM
On Fri, Sep 13, 2013 at 5:14 AM, Archit Taneja arc...@ti.com wrote: Enable use of DT for DMM/Tiler. Originally worked on by Andy Gross. looks good.. but do we want to get information about # of LUT's, etc, from DT? Or did we decide that we can reliably get this from the hw? I lost track of that discussion (I guess Andy would remember).. BR, -R Cc: Andy Gross andy...@gmail.com Cc: DRI Development dri-de...@lists.freedesktop.org Signed-off-by: Archit Taneja arc...@ti.com --- drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index acf6678..59f17de 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -968,12 +968,23 @@ static const struct dev_pm_ops omap_dmm_pm_ops = { }; #endif +#if defined(CONFIG_OF) +static const struct of_device_id dmm_of_match[] = { + { .compatible = ti,omap4-dmm, }, + { .compatible = ti,omap5-dmm, }, + {}, +}; +#else +#define dmm_of_match NULL +#endif + struct platform_driver omap_dmm_driver = { .probe = omap_dmm_probe, .remove = omap_dmm_remove, .driver = { .owner = THIS_MODULE, .name = DMM_DRIVER_NAME, + .of_match_table = dmm_of_match, #ifdef CONFIG_PM .pm = omap_dmm_pm_ops, #endif -- 1.8.1.2 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Latest randconfig build errors
On Mon, Mar 4, 2013 at 1:46 PM, Tony Lindgren t...@atomide.com wrote: drivers/gpu/drm/tilcdc/tilcdc_slave.o:(.data+0x54): multiple definition of `__mod_of_device_table' drivers/gpu/drm/tilcdc/tilcdc_tfp410.o:(.data+0x54): first defined here drivers/gpu/drm/tilcdc/tilcdc_panel.o:(.data+0x54): multiple definition of `__mod_of_device_table' drivers/gpu/drm/tilcdc/tilcdc_tfp410.o:(.data+0x54): first defined here drivers/gpu/drm/tilcdc/tilcdc_drv.o:(.data+0x184): multiple definition of `__mod_of_device_table' drivers/gpu/drm/tilcdc/tilcdc_tfp410.o:(.data+0x54): first defined here Rob, I assume you'll do a patch for this one? oh, I apologize for the late reply, I didn't see this email... There is a patch that we can merge to make tilcdc bool instead of tristate[1], which I suppose is ok for a temporary fix. Although I'm all-ears if someone has a better idea about how to fix this. The problem is that we have multiple sub-devices for different possible panel drivers, so that depending on DT tables, the correct ones get loaded for the hw. But they are all built into a single module. Splitting them into multiple modules will be problematic, as panel drivers which are present really need to get probed before the toplevel drm device.. I suppose in theory it is possible to make drm cope better with dynamically loaded outputs, but I'm not sure that there is any way to do this without breaking userspace which expects that all of the connectors/encoders are present once the drm device is loaded. BR, -R [1] https://patchwork.kernel.org/patch/2376061/ -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Latest randconfig build errors
On Sat, Apr 13, 2013 at 5:45 PM, Thierry Reding thierry.red...@avionic-design.de wrote: On Sat, Apr 13, 2013 at 08:54:22AM -0400, Rob Clark wrote: On Mon, Mar 4, 2013 at 1:46 PM, Tony Lindgren t...@atomide.com wrote: drivers/gpu/drm/tilcdc/tilcdc_slave.o:(.data+0x54): multiple definition of `__mod_of_device_table' drivers/gpu/drm/tilcdc/tilcdc_tfp410.o:(.data+0x54): first defined here drivers/gpu/drm/tilcdc/tilcdc_panel.o:(.data+0x54): multiple definition of `__mod_of_device_table' drivers/gpu/drm/tilcdc/tilcdc_tfp410.o:(.data+0x54): first defined here drivers/gpu/drm/tilcdc/tilcdc_drv.o:(.data+0x184): multiple definition of `__mod_of_device_table' drivers/gpu/drm/tilcdc/tilcdc_tfp410.o:(.data+0x54): first defined here Rob, I assume you'll do a patch for this one? oh, I apologize for the late reply, I didn't see this email... There is a patch that we can merge to make tilcdc bool instead of tristate[1], which I suppose is ok for a temporary fix. Although I'm all-ears if someone has a better idea about how to fix this. The problem is that we have multiple sub-devices for different possible panel drivers, so that depending on DT tables, the correct ones get loaded for the hw. But they are all built into a single module. Splitting them into multiple modules will be problematic, as panel drivers which are present really need to get probed before the toplevel drm device.. You could look at the Tegra driver. I had to solve a similar problem there. What I did is basically parse the DT in the host1x driver and add all device nodes which are required by DRM to a list. Later when the individual devices are probed they are removed from that list, so that when the list becomes empty we are sure that all required devices are there and only then call the drm_platform_init() function. thx, ok, I'll have a look at this This fits very well with how Tegra hardware is designed because host1x is the parent for all DRM subdevices (DC, RGB/LVDS, HDMI, ...). So it is probed before any of its children and it can easily parse the DT upfront and initialize the list of required devices. I suppose in theory it is possible to make drm cope better with dynamically loaded outputs, but I'm not sure that there is any way to do this without breaking userspace which expects that all of the connectors/encoders are present once the drm device is loaded. I had been thinking about this on and off for a while, but I haven't come up with anything concrete. Ideally we could just have some kind of event that userspace would listen for, so that new outputs can be dynamically added and userspace informed about them. Last time I checked most of the helpers assumed that the complete output configuration is known when the DRM device is registered, so some major rework will be required to efficiently make use of such dynamicity. I'm less worried about the kernel re-work.. more worried about the fact that we have no way to know whether userspace knows to listen for this new event. So anything down this path could, I think, be considered as breaking userspace. I think in the end, we need some way to have sort of dummy connectors for output drivers which might or might not be probed, so that from userspace perspective, non-present panels appear as displays that are not plugged in. BR, -R Thierry -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm/omap: Take a fb reference in omap_plane_update()
On Tue, Apr 9, 2013 at 8:26 AM, Archit Taneja arc...@ti.com wrote: When userspace calls SET_PLANE ioctl, drm core takes a reference of the fb and passes control to the update_plane op defined by the drm driver. In omapdrm, we have a worker thread which queues framebuffers objects received from update_plane and displays them at the appropriate time. It is possible that the framebuffer is destoryed by userspace between the time of calling the ioctl and apply-worker being scheduled. If this happens, the apply-worker holds a pointer to a framebuffer which is already destroyed. Take an extra refernece/unreference of the fb in omap_plane_update() to prevent this from happening. A reference is taken of the fb passed to update_plane(), the previous framebuffer (held by plane-fb) is unreferenced. This will prevent drm from destroying the framebuffer till the time it's unreferenced by the apply-worker. This is in addition to the exisitng reference/unreference in update_pin(), which is taken for the scanout of the plane's current framebuffer, and an unreference the previous framebuffer. Signed-off-by: Archit Taneja arc...@ti.com Cc: Rob Clark robdcl...@gmail.com Good catch Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/omapdrm/omap_plane.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 2882cda..8d225d7 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -247,6 +247,12 @@ static int omap_plane_update(struct drm_plane *plane, { struct omap_plane *omap_plane = to_omap_plane(plane); omap_plane-enabled = true; + + if (plane-fb) + drm_framebuffer_unreference(plane-fb); + + drm_framebuffer_reference(fb); + return omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h, -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm/omap: Take a fb reference in omap_plane_update()
On Tue, Apr 9, 2013 at 8:53 AM, Daniel Vetter dan...@ffwll.ch wrote: On Tue, Apr 09, 2013 at 05:56:02PM +0530, Archit Taneja wrote: When userspace calls SET_PLANE ioctl, drm core takes a reference of the fb and passes control to the update_plane op defined by the drm driver. In omapdrm, we have a worker thread which queues framebuffers objects received from update_plane and displays them at the appropriate time. It is possible that the framebuffer is destoryed by userspace between the time of calling the ioctl and apply-worker being scheduled. If this happens, the apply-worker holds a pointer to a framebuffer which is already destroyed. Take an extra refernece/unreference of the fb in omap_plane_update() to prevent this from happening. A reference is taken of the fb passed to update_plane(), the previous framebuffer (held by plane-fb) is unreferenced. This will prevent drm from destroying the framebuffer till the time it's unreferenced by the apply-worker. This is in addition to the exisitng reference/unreference in update_pin(), which is taken for the scanout of the plane's current framebuffer, and an unreference the previous framebuffer. Signed-off-by: Archit Taneja arc...@ti.com Cc: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/omapdrm/omap_plane.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 2882cda..8d225d7 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -247,6 +247,12 @@ static int omap_plane_update(struct drm_plane *plane, { struct omap_plane *omap_plane = to_omap_plane(plane); omap_plane-enabled = true; + + if (plane-fb) + drm_framebuffer_unreference(plane-fb); Shouldn't the unref only happen once the flip has completed? Otherwise we might free the memory which is still being scanned out and put some other crap there. yup, there is a 2nd ref grabbed when we start scanout and dropped when we finish scanout.. so that part was already covered. What wasn't covered before was the time between the ioctl and the worker thread (which was grabbing/dropping the scanout ref) BR, -R Note that I've been too lazy to read the code, but I expected the unref of the old one to happen after the ref-taking for the new one, with a vblank wait/delay in between ... Might be that I'm completely off ;-) -Daniel + + drm_framebuffer_reference(fb); + return omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h, -- 1.7.10.4 ___ dri-devel mailing list dri-de...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] drm/omap: Don't return from modeset_init if a panel doesn't satisfy omapdrm requirements
On Tue, Mar 5, 2013 at 9:17 AM, Archit Taneja arc...@ti.com wrote: modeset_init iterates through all the registered omapdss devices and has some initial checks to see if the panel has a driver and the required driver ops for it to be usable by omapdrm. The function bails out from modeset_init if a panel doesn't meet the requirements, and stops the registration of the future panels and encoders which come after it, that isn't the correct thing to do, we should go through the rest of the panels. Replace the 'return's with 'continue's. Signed-off-by: Archit Taneja arc...@ti.com Reviewed-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/omapdrm/omap_drv.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 079c54c..77b7225 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -121,7 +121,7 @@ static int omap_modeset_init(struct drm_device *dev) if (!dssdev-driver) { dev_warn(dev-dev, %s has no driver.. skipping it\n, dssdev-name); - return 0; + continue; } if (!(dssdev-driver-get_timings || @@ -129,7 +129,7 @@ static int omap_modeset_init(struct drm_device *dev) dev_warn(dev-dev, %s driver does not support get_timings or read_edid.. skipping it!\n, dssdev-name); - return 0; + continue; } encoder = omap_encoder_init(dev, dssdev); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] drm/omap: Make fixed resolution panels work
On Tue, Mar 5, 2013 at 9:17 AM, Archit Taneja arc...@ti.com wrote: The omapdrm driver requires omapdss panel drivers to expose ops like detect, set_timings and check_timings. These can be NULL for fixed panel DPI, DBI, DSI and SDI drivers. At some places, there are no checks to see if the panel driver has these ops or not, and that leads to a crash. The following things are done to make fixed panels work: - The omap_connector's detect function is modified such that it considers panel types which are generally fixed panels as always connected(provided the panel driver doesn't have a detect op). Hence, the connector corresponding to these panels is always in a 'connected' state. - If a panel driver doesn't have a check_timings op, assume that it supports the mode passed to omap_connector_mode_valid(the 'mode_valid' drm helper function) - The function omap_encoder_update shouldn't really do anything for fixed resolution panels, make sure that it calls set_timings only if the panel driver has one. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/gpu/drm/omapdrm/omap_connector.c | 10 -- drivers/gpu/drm/omapdrm/omap_encoder.c |6 -- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index c451c41..c952324 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -110,6 +110,11 @@ static enum drm_connector_status omap_connector_detect( ret = connector_status_connected; else ret = connector_status_disconnected; + } else if (dssdev-type == OMAP_DISPLAY_TYPE_DPI || + dssdev-type == OMAP_DISPLAY_TYPE_DBI || + dssdev-type == OMAP_DISPLAY_TYPE_SDI || + dssdev-type == OMAP_DISPLAY_TYPE_DSI) { + ret = connector_status_connected; } else { ret = connector_status_unknown; } @@ -189,12 +194,13 @@ static int omap_connector_mode_valid(struct drm_connector *connector, struct omap_video_timings timings = {0}; struct drm_device *dev = connector-dev; struct drm_display_mode *new_mode; - int ret = MODE_BAD; + int r, ret = MODE_BAD; copy_timings_drm_to_omap(timings, mode); mode-vrefresh = drm_mode_vrefresh(mode); - if (!dssdrv-check_timings(dssdev, timings)) { + r = dssdrv-check_timings ? dssdrv-check_timings(dssdev, timings) : 0; + if (!r) { /* check if vrefresh is still valid */ new_mode = drm_mode_duplicate(dev, mode); new_mode-clock = timings.pixel_clock; diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index d48df71..9aed178 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c @@ -135,13 +135,15 @@ int omap_encoder_update(struct drm_encoder *encoder, dssdev-output-manager = mgr; - ret = dssdrv-check_timings(dssdev, timings); + ret = dssdrv-check_timings ? + dssdrv-check_timings(dssdev, timings) : 0; if (ret) { dev_err(dev-dev, could not set timings: %d\n, ret); return ret; } - dssdrv-set_timings(dssdev, timings); + if (dssdrv-set_timings) + dssdrv-set_timings(dssdev, timings); maybe either here or _mode_valid(), for panels that don't have set_timings(), we should double check that the new timings match what we get from the panel's get_timings(). Other than that, it looks fine. BR, -R return 0; } -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] omapdrm: Make fixed resolution panels work
On Thu, Feb 14, 2013 at 6:52 AM, Archit Taneja arc...@ti.com wrote: The omapdrm driver requires omapdss panel drivers to expose ops like detect, set_timings and check_timings. These can be NULL for fixed panel DPI, DBI, DSI and SDI drivers. At some places, there are no checks to see if the panel driver has these ops or not, and that leads to a crash. The following things are done to make fixed panels work: - The omap_connector's detect function is modified such that it considers panel types which are generally fixed panels as always connected(provided the panel driver doesn't have a detect op). Hence, the connector corresponding to these panels is always in a 'connected' state. - If a panel driver doesn't have a check_timings op, assume that it supports the mode passed to omap_connector_mode_valid(the 'mode_valid' drm helper function) - The function omap_encoder_update shouldn't really do anything for fixed resolution panels, make sure that it calls set_timings only if the panel driver has one. I tested this with picodlp on a OMAP4 sdp board. I couldn't get any other working boards with fixed DPI panels. I could try the DSI video mode panel on an OMAP5 sevm, but that will require me to patch a lot of things to get omap5 dss work with DT. I can try if needed. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/staging/omapdrm/omap_connector.c | 10 -- drivers/staging/omapdrm/omap_encoder.c |6 -- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 4cc9ee7..839c6e4 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -110,6 +110,11 @@ static enum drm_connector_status omap_connector_detect( ret = connector_status_connected; else ret = connector_status_disconnected; + } else if (dssdev-type == OMAP_DISPLAY_TYPE_DPI || + dssdev-type == OMAP_DISPLAY_TYPE_DBI || + dssdev-type == OMAP_DISPLAY_TYPE_SDI || + dssdev-type == OMAP_DISPLAY_TYPE_DSI) { + ret = connector_status_connected; hmm, why not just have a default detect fxn for panel drivers which always returns true? Seems a bit cleaner.. otherwise, I guess we could just change omap_connector so that if dssdev-detect is null, assume always connected. Seems maybe a slightly better way since currently omap_connector doesn't really know too much about different sorts of panels. But I'm not too picky if that is a big pain because we probably end up changing all this as CFP starts coming into existence. Same goes for check_timings/set_timings.. it seems a bit cleaner just to have default fxns in the panel drivers that do-the-right-thing, although I suppose it might be a bit more convenient for out-of-tree panel drivers to just assume fixed panel if these fxns are null. BR, -R } else { ret = connector_status_unknown; } @@ -189,12 +194,13 @@ static int omap_connector_mode_valid(struct drm_connector *connector, struct omap_video_timings timings = {0}; struct drm_device *dev = connector-dev; struct drm_display_mode *new_mode; - int ret = MODE_BAD; + int r, ret = MODE_BAD; copy_timings_drm_to_omap(timings, mode); mode-vrefresh = drm_mode_vrefresh(mode); - if (!dssdrv-check_timings(dssdev, timings)) { + r = dssdrv-check_timings ? dssdrv-check_timings(dssdev, timings) : 0; + if (!r) { /* check if vrefresh is still valid */ new_mode = drm_mode_duplicate(dev, mode); new_mode-clock = timings.pixel_clock; diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c index e053160..871af12e 100644 --- a/drivers/staging/omapdrm/omap_encoder.c +++ b/drivers/staging/omapdrm/omap_encoder.c @@ -128,13 +128,15 @@ int omap_encoder_update(struct drm_encoder *encoder, dssdev-output-manager = mgr; - ret = dssdrv-check_timings(dssdev, timings); + ret = dssdrv-check_timings ? + dssdrv-check_timings(dssdev, timings) : 0; if (ret) { dev_err(dev-dev, could not set timings: %d\n, ret); return ret; } - dssdrv-set_timings(dssdev, timings); + if (dssdrv-set_timings) + dssdrv-set_timings(dssdev, timings); return 0; } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] drm/i2c: nxp-tda998x (v3)
On Wed, Jan 30, 2013 at 8:23 PM, Sebastian Hesselbarth sebastian.hesselba...@gmail.com wrote: On 01/29/2013 06:23 PM, Rob Clark wrote: Driver for the NXP TDA998X i2c hdmi encoder slave. Rob, good to see a driver for TDA998x comming! I'd love to test it on CuBox (mach-dove) but there is no gpu driver I can hook up, yet. Anyway, I will make some comments how I think the driver should be improved. diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig index 1611836..4d341db 100644 --- a/drivers/gpu/drm/i2c/Kconfig +++ b/drivers/gpu/drm/i2c/Kconfig @@ -19,4 +19,10 @@ config DRM_I2C_SIL164 when used in pairs) TMDS transmitters, used in some nVidia video cards. +config DRM_I2C_NXP_TDA998X + tristate NXP Semiconductors TDA998X HDMI encoder + default m if DRM_TILCDC + help + Support for NXP Semiconductors TDA998X HDMI encoders. Maybe nit-picking but later down you actually support TDA9989, TDA19988, and TDA19989. The latter ones don't fit in TDA998x, so at least the Kconfig entry should reflect TDA9989/TDA1998x. yeah, it is a bit weird naming scheme, but I'm just copying NXP in referring to the whole family as TDA998x [...] diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c new file mode 100644 index 000..e68b58a --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -0,0 +1,906 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clarkrobdcl...@gmail.com + * + [...] + +/* The TDA9988 series of devices use a paged register scheme.. to simplify + * things we encode the page # in upper bits of the register #. To read/ + * write a given register, we need to make sure CURPAGE register is set + * appropriately. Which implies reads/writes are not atomic. Fun! + */ Please have a look at regmap-i2c, it also supports paged i2c registers and will save you _a lot_ of the i2c handling. Yeah, I have looked at it, and will eventually convert over to using it. The problems at the moment are that I don't really have enough documentation about the chip at the register level to properly use the caching modes, and from my digging through the regmap code it looked like paged regmap + non-caching will result in writes to the page register for every transaction. That, and a bit of docs or few more examples of using the paging support in regmap would be nice. For now, I am punting on regmap conversion. [...] + +/* Device versions: */ +#define TDA9989N2 0x0101 +#define TDA19989 0x0201 +#define TDA19989N20x0202 +#define TDA19988 0x0301 Maybe split this into device_version/revision? What does N2 stand for or is this the name NXP uses for that device? The register names are based on the names used in the NXP out-of-tree driver (the 50kloc monstrosity, if you've seen it).. that was pretty much all the register level documentation I had. [...] +static void +cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val) +{ + struct i2c_client *client = to_tda998x_priv(encoder)-cec; + uint8_t buf[] = {addr, val}; + int ret; + + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); + if (ret 0) + dev_err(client-dev, Error %d writing to cec:0x%x\n, ret, addr); +} Has there been any decision on how to split/integrate cec from drm? Or is there display stuff located in cec i2c slave (I see HPD in ..._detect below)? not sure, but at least in this case it can't really be decoupled. I need to use the CEC interface for HPD (as you noticed) and also to power up the HDMI bits.. [...] +static void +tda998x_encoder_save(struct drm_encoder *encoder) +{ + DBG(); +} + +static void +tda998x_encoder_restore(struct drm_encoder *encoder) +{ + DBG(); +} Hmmm, these DBG() shouldn't be in upstream kernel code? yeah, I suppose these traces don't add too much value, I can remove them +static bool +tda998x_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static int +tda998x_encoder_mode_valid(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + return MODE_OK; +} At least a note would be helpful to see what callbacks are not yet done. I guess there will be some kind of mode check someday? Well, some of these drm will assume the fxn ptrs are not null, so we need something even if it is empty. I suppose there are must be some upper bounds on pixel clock supported, which could perhaps be added some day in _mode_valid(). On the device I am working on, the limiting factor is the crtc (upstream of the encoder), so I haven't really needed this yet. I expect that as people start using this on some other
Re: [PATCH 2/4] drm/i2c: nxp-tda998x (v3)
On Thu, Jan 31, 2013 at 2:14 PM, Sebastian Hesselbarth sebastian.hesselba...@gmail.com wrote: On 01/31/2013 03:23 PM, Rob Clark wrote: On Wed, Jan 30, 2013 at 8:23 PM, Sebastian Hesselbarth sebastian.hesselba...@gmail.com wrote: On 01/29/2013 06:23 PM, Rob Clark wrote: [...] + +/* The TDA9988 series of devices use a paged register scheme.. to simplify + * things we encode the page # in upper bits of the register #. To read/ + * write a given register, we need to make sure CURPAGE register is set + * appropriately. Which implies reads/writes are not atomic. Fun! + */ Please have a look at regmap-i2c, it also supports paged i2c registers and will save you _a lot_ of the i2c handling. Yeah, I have looked at it, and will eventually convert over to using it. The problems at the moment are that I don't really have enough documentation about the chip at the register level to properly use the caching modes, and from my digging through the regmap code it looked like paged regmap + non-caching will result in writes to the page register for every transaction. That, and a bit of docs or few more examples of using the paging support in regmap would be nice. For now, I am punting on regmap conversion. Hmm, flipping through the public tda998x sources *sigh* I found a quite complete register list that also states if registers are RO or RW. Even if you are not using all registers you can still prevent regmap from reading/writing to them. But yes, documentation lacks some examples ;) [...] + +/* Device versions: */ +#define TDA9989N2 0x0101 +#define TDA19989 0x0201 +#define TDA19989N20x0202 +#define TDA19988 0x0301 Maybe split this into device_version/revision? What does N2 stand for or is this the name NXP uses for that device? The register names are based on the names used in the NXP out-of-tree driver (the 50kloc monstrosity, if you've seen it).. that was pretty much all the register level documentation I had. Yeah, but there is a comment about N2, that says the last bit is not a register bit, but is derived by the driver from the new N5 registers... I guess you will not see that many i2c devices returning you N2 version registers.. hmm, maybe you are looking at a different (newer?) version of the nxp code? I did not see this. Perhaps the n2 stuff isn't too critical, but I figured it would be nice to see if someone is trying to bring up a device with one of these parts and I ask them to send me a boot log with drm traces enabled [...] +static void +cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val) +{ + struct i2c_client *client = to_tda998x_priv(encoder)-cec; + uint8_t buf[] = {addr, val}; + int ret; + + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); + if (ret 0) + dev_err(client-dev, Error %d writing to cec:0x%x\n, ret, addr); +} Has there been any decision on how to split/integrate cec from drm? Or is there display stuff located in cec i2c slave (I see HPD in ..._detect below)? not sure, but at least in this case it can't really be decoupled. I need to use the CEC interface for HPD (as you noticed) and also to power up the HDMI bits.. Just to make things clearer here, TDA998x ususally has two i2c slaves at power-up, 0x70 (hdmi slave) and 0x34 (cec slave). Are you actually accessing the cec slave? yes, as I mentioned, it is not possible to access the hdmi slave without first accessing the cec slave to enable the hdmi slave [...] +static bool +tda998x_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static int +tda998x_encoder_mode_valid(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + return MODE_OK; +} At least a note would be helpful to see what callbacks are not yet done. I guess there will be some kind of mode check someday? Well, some of these drm will assume the fxn ptrs are not null, so we need something even if it is empty. I suppose there are must be some upper bounds on pixel clock supported, which could perhaps be added some day in _mode_valid(). On Depends what drm expects on mode_valid or mode_fixup, I haven't dug into drm encoders, yet. But usually for HDMI/DVI you will only choose between modes supplied by monitor EDID and not choose something close. Anyway, I just think a note about stuff that is not yet working is helpful. I would put a note if there was something that was not working about it ;-) Currently there is no need to validate or fixup the mode, which is why these functions are empty. DRM has hooks for the drivers at many point. Not always are all of them needed, in this case they are not needed. the device I
[PATCH 0/4] TI LCDC DRM driver
One more iteration.. now with more cowbell! The first patch adds the basic driver and TFP410 DVI output. The second patch adds support for NXP TDA998x family of i2c connected HDMI encoders. It is split out into an i2c encoder-slave in case someone else has hw with the same HDMI encoder. The final patch adds support for LCD panels, with timings and panel info coming from device-tree. The patch set has dependencies on the following patches that I have sent earlier (which have not changed since then so I am not resending): * drm/cma: add debugfs helpers - https://patchwork.kernel.org/patch/1876721/ * drm: i2c encoder helper wrappers - https://patchwork.kernel.org/patch/1950971/ * drm/i2c: give i2c it's own Kconfig - https://patchwork.kernel.org/patch/2037181/ In addition, the LCD panel patch also depends on Steffen Trumtrar's OF display helper series. I've moved this patch to last so it can be merged later if needed. Although I really see no reason not to merge the OF display helper series for 3.9. These patches and their dependencies can also be found here: git://people.freedesktop.org/~robclark/linux tilcdc-next http://cgit.freedesktop.org/~robclark/linux/log/?h=tilcdc-next Rob Clark (4): drm/tilcdc: add TI LCD Controller DRM driver (v4) drm/i2c: nxp-tda998x (v3) drm/tilcdc: add encoder slave (v2) drm/tilcdc: add support for LCD panels (v5) .../devicetree/bindings/drm/tilcdc/panel.txt | 59 ++ .../devicetree/bindings/drm/tilcdc/slave.txt | 19 + .../devicetree/bindings/drm/tilcdc/tfp410.txt | 21 + .../devicetree/bindings/drm/tilcdc/tilcdc.txt | 21 + drivers/gpu/drm/Kconfig| 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/i2c/Kconfig| 6 + drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/tda998x_drv.c | 906 + drivers/gpu/drm/tilcdc/Kconfig | 13 + drivers/gpu/drm/tilcdc/Makefile| 10 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 602 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.c| 611 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.h| 150 drivers/gpu/drm/tilcdc/tilcdc_panel.c | 436 ++ drivers/gpu/drm/tilcdc/tilcdc_panel.h | 26 + drivers/gpu/drm/tilcdc/tilcdc_regs.h | 154 drivers/gpu/drm/tilcdc/tilcdc_slave.c | 376 + drivers/gpu/drm/tilcdc/tilcdc_slave.h | 26 + drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 419 ++ drivers/gpu/drm/tilcdc/tilcdc_tfp410.h | 26 + 21 files changed, 3887 insertions(+) create mode 100644 Documentation/devicetree/bindings/drm/tilcdc/panel.txt create mode 100644 Documentation/devicetree/bindings/drm/tilcdc/slave.txt create mode 100644 Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt create mode 100644 Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c create mode 100644 drivers/gpu/drm/tilcdc/Kconfig create mode 100644 drivers/gpu/drm/tilcdc/Makefile create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_crtc.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_regs.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.h -- 1.8.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] drm/tilcdc: add encoder slave (v2)
Add output panel driver for i2c encoder slaves. v1: original v2: add DT bindings docs, and minor updates for review comments Signed-off-by: Rob Clark robdcl...@gmail.com Reviewed-by: Daniel Vetter daniel.vet...@ffwll.ch Tested-by: Koen Kooi k...@dominion.thruhere.net --- .../devicetree/bindings/drm/tilcdc/slave.txt | 19 ++ drivers/gpu/drm/tilcdc/Makefile| 1 + drivers/gpu/drm/tilcdc/tilcdc_drv.c| 5 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 376 + drivers/gpu/drm/tilcdc/tilcdc_slave.h | 26 ++ 5 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/drm/tilcdc/slave.txt create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.h diff --git a/Documentation/devicetree/bindings/drm/tilcdc/slave.txt b/Documentation/devicetree/bindings/drm/tilcdc/slave.txt new file mode 100644 index 000..ba51337 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/tilcdc/slave.txt @@ -0,0 +1,19 @@ +Device-Tree bindings for tilcdc DRM encoder slave output driver + +Required properties: + - compatible: value should be tilcdc,slave. + - i2c: the phandle for the i2c device the encoder slave is connected to + +Recommended properties: + - pinctrl-names, pinctrl-0: the pincontrol settings to configure + muxing properly for pins that connect to TFP410 device + +Example: + + hdmi { + compatible = tilcdc,slave; + i2c = i2c0; + pinctrl-names = default; + pinctrl-0 = nxp_hdmi_bonelt_pins; + }; + \ No newline at end of file diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile index 1359cc2..aa9097e 100644 --- a/drivers/gpu/drm/tilcdc/Makefile +++ b/drivers/gpu/drm/tilcdc/Makefile @@ -3,6 +3,7 @@ ccflags-y := -Iinclude/drm -Werror tilcdc-y := \ tilcdc_crtc.o \ tilcdc_tfp410.o \ + tilcdc_slave.o \ tilcdc_drv.o obj-$(CONFIG_DRM_TILCDC) += tilcdc.o diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index f6defbf..25f3add 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -20,6 +20,7 @@ #include tilcdc_drv.h #include tilcdc_regs.h #include tilcdc_tfp410.h +#include tilcdc_slave.h #include drm_fb_helper.h @@ -587,6 +588,7 @@ static int __init tilcdc_drm_init(void) { DBG(init); tilcdc_tfp410_init(); + tilcdc_slave_init(); return platform_driver_register(tilcdc_platform_driver); } @@ -594,10 +596,11 @@ static void __exit tilcdc_drm_fini(void) { DBG(fini); tilcdc_tfp410_fini(); + tilcdc_slave_fini(); platform_driver_unregister(tilcdc_platform_driver); } -module_init(tilcdc_drm_init); +late_initcall(tilcdc_drm_init); module_exit(tilcdc_drm_fini); MODULE_AUTHOR(Rob Clark robdcl...@gmail.com); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c new file mode 100644 index 000..7d05c3d --- /dev/null +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + +#include linux/i2c.h +#include linux/of_i2c.h +#include linux/pinctrl/pinmux.h +#include linux/pinctrl/consumer.h +#include drm/drm_encoder_slave.h + +#include tilcdc_drv.h + +struct slave_module { + struct tilcdc_module base; + struct i2c_adapter *i2c; +}; +#define to_slave_module(x) container_of(x, struct slave_module, base) + +static const struct tilcdc_panel_info slave_info = { + .bpp= 16, + .ac_bias= 255, + .ac_bias_intrpt = 0, + .dma_burst_sz = 16, + .fdd= 0x80, + .tft_alt_mode = 0, + .sync_edge = 0, + .sync_ctrl = 1, + .raster_order = 0, +}; + + +/* + * Encoder: + */ + +struct slave_encoder { + struct drm_encoder_slave base; + struct slave_module *mod; +}; +#define to_slave_encoder(x) container_of(to_encoder_slave(x), struct slave_encoder, base) + +static inline struct drm_encoder_slave_funcs
[PATCH 4/4] drm/tilcdc: add support for LCD panels (v5)
Add an output panel driver for LCD panels. Tested with LCD3 cape on beaglebone. v1: original v2: s/of_find_node_by_name()/of_get_child_by_name()/ from Pantelis Antoniou v3: add backlight support v4: rebase to latest of video timing helpers v5: remove some unneeded fields from panel-info struct, add DT bindings docs Signed-off-by: Rob Clark robdcl...@gmail.com Tested-by: Koen Kooi k...@dominion.thruhere.net --- .../devicetree/bindings/drm/tilcdc/panel.txt | 59 +++ drivers/gpu/drm/tilcdc/Kconfig | 3 + drivers/gpu/drm/tilcdc/Makefile| 1 + drivers/gpu/drm/tilcdc/tilcdc_drv.c| 3 + drivers/gpu/drm/tilcdc/tilcdc_panel.c | 436 + drivers/gpu/drm/tilcdc/tilcdc_panel.h | 26 ++ 6 files changed, 528 insertions(+) create mode 100644 Documentation/devicetree/bindings/drm/tilcdc/panel.txt create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.h diff --git a/Documentation/devicetree/bindings/drm/tilcdc/panel.txt b/Documentation/devicetree/bindings/drm/tilcdc/panel.txt new file mode 100644 index 000..5ff1e61 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/tilcdc/panel.txt @@ -0,0 +1,59 @@ +Device-Tree bindings for tilcdc DRM generic panel output driver + +Required properties: + - compatible: value should be tilcdc,panel. + - panel-info: configuration info to configure LCDC correctly for the panel + - ac-bias: AC Bias Pin Frequency + - ac-bias-intrpt: AC Bias Pin Transitions per Interrupt + - dma-burst-sz: DMA burst size + - bpp: Bits per pixel + - fdd: FIFO DMA Request Delay + - sync-edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling + - sync-ctrl: Horizontal and Vertical Sync: Control: 0=ignore + - raster-order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most + - fifo-th: DMA FIFO threshold + - display-timings: typical videomode of lcd panel. Multiple video modes + can be listed if the panel supports multiple timings, but the 'native-mode' + should be the preferred/default resolution. Refer to + Documentation/devicetree/bindings/video/display-timing.txt for display + timing binding details. + +Recommended properties: + - pinctrl-names, pinctrl-0: the pincontrol settings to configure + muxing properly for pins that connect to TFP410 device + +Example: + + /* Settings for CDTech_S035Q01 / LCD3 cape: */ + lcd3 { + compatible = tilcdc,panel; + pinctrl-names = default; + pinctrl-0 = bone_lcd3_cape_lcd_pins; + panel-info { + ac-bias = 255; + ac-bias-intrpt= 0; + dma-burst-sz = 16; + bpp = 16; + fdd = 0x80; + sync-edge = 0; + sync-ctrl = 1; + raster-order = 0; + fifo-th = 0; + }; + display-timings { + native-mode = timing0; + timing0: 320x240 { + hactive = 320; + vactive = 240; + hback-porch = 21; + hfront-porch= 58; + hsync-len = 47; + vback-porch = 11; + vfront-porch= 23; + vsync-len = 2; + clock-frequency = 800; + hsync-active= 0; + vsync-active= 0; + }; + }; + }; diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index ee9b592..ae14fd6 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -4,6 +4,9 @@ config DRM_TILCDC select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER + select OF_VIDEOMODE + select OF_DISPLAY_TIMING + select BACKLIGHT_CLASS_DEVICE help Choose this option if you have an TI SoC with LCDC display controller, for example AM33xx in beagle-bone, DA8xx, or diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile index aa9097e..deda656 100644 --- a/drivers/gpu/drm/tilcdc/Makefile +++ b/drivers/gpu/drm/tilcdc/Makefile @@ -4,6 +4,7 @@ tilcdc-y := \ tilcdc_crtc.o \ tilcdc_tfp410.o \ tilcdc_slave.o \ + tilcdc_panel.o \ tilcdc_drv.o obj-$(CONFIG_DRM_TILCDC) += tilcdc.o diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 25f3add..c5b592d 100644 --- a/drivers/gpu/drm/tilcdc
[PATCH 2/4] drm/i2c: nxp-tda998x (v3)
Driver for the NXP TDA998X i2c hdmi encoder slave. v1: original v2: fix npix/nline programming v3: add Kconfig, fix dup'd MODULE_DESCRIPTION Signed-off-by: Rob Clark robdcl...@gmail.com Reviewed-by: Daniel Vetter daniel.vet...@ffwll.ch Tested-by: Koen Kooi k...@dominion.thruhere.net --- drivers/gpu/drm/i2c/Kconfig | 6 + drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/tda998x_drv.c | 906 ++ 3 files changed, 915 insertions(+) create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig index 1611836..4d341db 100644 --- a/drivers/gpu/drm/i2c/Kconfig +++ b/drivers/gpu/drm/i2c/Kconfig @@ -19,4 +19,10 @@ config DRM_I2C_SIL164 when used in pairs) TMDS transmitters, used in some nVidia video cards. +config DRM_I2C_NXP_TDA998X + tristate NXP Semiconductors TDA998X HDMI encoder + default m if DRM_TILCDC + help + Support for NXP Semiconductors TDA998X HDMI encoders. + endmenu diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 9286256..43aa33b 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o + +tda998x-y := tda998x_drv.o +obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c new file mode 100644 index 000..e68b58a --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -0,0 +1,906 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + + + +#include linux/module.h + +#include drm/drmP.h +#include drm/drm_crtc_helper.h +#include drm/drm_encoder_slave.h +#include drm/drm_edid.h + + +#define DBG(fmt, ...) DRM_DEBUG(fmt\n, ##__VA_ARGS__) + +struct tda998x_priv { + struct i2c_client *cec; + uint16_t rev; + uint8_t current_page; + int dpms; +}; + +#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)-slave_priv) + +/* The TDA9988 series of devices use a paged register scheme.. to simplify + * things we encode the page # in upper bits of the register #. To read/ + * write a given register, we need to make sure CURPAGE register is set + * appropriately. Which implies reads/writes are not atomic. Fun! + */ + +#define REG(page, addr) (((page) 8) | (addr)) +#define REG2ADDR(reg) ((reg) 0xff) +#define REG2PAGE(reg) (((reg) 8) 0xff) + +#define REG_CURPAGE 0xff/* write */ + + +/* Page 00h: General Control */ +#define REG_VERSION_LSB REG(0x00, 0x00) /* read */ +#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */ +# define MAIN_CNTRL0_SR (1 0) +# define MAIN_CNTRL0_DECS (1 1) +# define MAIN_CNTRL0_DEHS (1 2) +# define MAIN_CNTRL0_CECS (1 3) +# define MAIN_CNTRL0_CEHS (1 4) +# define MAIN_CNTRL0_SCALER (1 7) +#define REG_VERSION_MSB REG(0x00, 0x02) /* read */ +#define REG_SOFTRESET REG(0x00, 0x0a) /* write */ +# define SOFTRESET_AUDIO (1 0) +# define SOFTRESET_I2C_MASTER (1 1) +#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */ +#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */ +#define REG_I2C_MASTERREG(0x00, 0x0d) /* read/write */ +# define I2C_MASTER_DIS_MM(1 0) +# define I2C_MASTER_DIS_FILT (1 1) +# define I2C_MASTER_APP_STRT_LAT (1 2) +#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ +#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ +#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ +# define INT_FLAGS_2_EDID_BLK_RD (1 1) +#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ +#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ +#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ +#define REG_ENA_APREG(0x00, 0x1e) /* read/write */ +#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */ +# define VIP_CNTRL_0_MIRR_A (1 7) +# define VIP_CNTRL_0_SWAP_A(x)(((x) 7) 4) +# define VIP_CNTRL_0_MIRR_B (1 3) +# define
Re: [PATCH 1/4] drm/tilcdc: add TI LCD Controller DRM driver (v3)
On Mon, Jan 28, 2013 at 3:56 AM, Mohammed, Afzal af...@ti.com wrote: Hi Rob, On Fri, Jan 25, 2013 at 20:22:55, Rob Clark wrote: On Fri, Jan 25, 2013 at 8:15 AM, Mohammed, Afzal af...@ti.com wrote: It's not about being simple, but not doing the wrong way, here you are relying on a platform specific clock in a driver, think about the case where same IP is used on another platform. Either way it is not a good thing to handle platform specific details (about disp_clk) in driver. Right, but I was trying to understand what was the benefit that the added complexity is. I didn't realize on davinci that you are limited Here I am referring to usage of disp_clk, Driver is not supposed to do platform hacks - here you are trying to configure something (PLL) in your driver which is not part of LCDC IP. And LCDC IP is not aware of PLL which is a platform specific matter (existent only in AM335x), it is only aware of functional clock. You can set the rate on fck (functional clock) in AM335x using my patch, ARM: AM33XX: clock: SET_RATE_PARENT in lcd path, and there would not be any need for driver to be aware of platform specific PLL. right, but I think it would be better to just make another patch that changes tilcdc to just set rate on fck after that patch is merged. I mean, I'd rather have the driver at least usable on AM33xx until then, rather than broken for everyone. BR, -R + priv-clk = clk_get(dev-dev, fck); + priv-disp_clk = clk_get(dev-dev, dpll_disp_ck); at the moment all this discussion is a bit moot. I'd propose leaving the driver as it is for now, because that at least makes it useful on am33xx. And when CCF and davinci have the needed support in place, Let's forget about leveraging CCF in driver, but sane solution w.r.t PLL configuration would be to do as mentioned above. Regards Afzal -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] drm/tilcdc: add TI LCD Controller DRM driver (v3)
On Fri, Jan 25, 2013 at 7:19 AM, Mohammed, Afzal af...@ti.com wrote: Hi Rob, On Wed, Jan 23, 2013 at 04:06:22, Rob Clark wrote: A simple DRM/KMS driver for the TI LCD Controller found in various smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the +void tilcdc_crtc_update_clk(struct drm_crtc *crtc) + /* in raster mode, minimum divisor is 2: */ + ret = clk_set_rate(priv-disp_clk, crtc-mode.clock * 1000 * 2); These things can better be handled with divider clock having a minimum value (being discussed with Mike on how exactly it should be) and instead of setting rate over a platform specific clock, you can set rate over lcd clock using SET_RATE_PARENT at platform level, more below, I looked at that patch you were proposing for da8xx-fb.. to be honest, it did not seem simpler to me, so I was sort of failing to see the benefit.. + /* Configure the LCD clock divisor. */ + tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) | + LCDC_RASTER_MODE); + + if (priv-rev == 2) + tilcdc_set(dev, LCDC_CLK_ENABLE_REG, + LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | + LCDC_V2_CORE_CLK_EN); Mike was suggesting to model the above using gate/divider/composite clocks of CCF in the FB driver. + priv-clk = clk_get(dev-dev, fck); + if (IS_ERR(priv-clk)) { + dev_err(dev-dev, failed to get functional clock\n); + ret = -ENODEV; + goto fail; + } + + priv-disp_clk = clk_get(dev-dev, dpll_disp_ck); + if (IS_ERR(priv-clk)) { + dev_err(dev-dev, failed to get display clock\n); + ret = -ENODEV; + goto fail; + } dpll_disp_ck is a platform specific matter, driver should not be handling platform specifics. And this won't work on DaVinci, you can probably make use of meaning the clock has a different name on davinci, or? Presumably there must be some clock generating the pixel clock for the display, but I confess to not being too familiar with the details on davinci.. BR, -R my series [PATCH v2 0/4] ARM: AM335x: LCDC platform support or something similar to overcome this. Regards Afzal -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] drm/tilcdc: add TI LCD Controller DRM driver (v3)
On Fri, Jan 25, 2013 at 8:15 AM, Mohammed, Afzal af...@ti.com wrote: Hi Rob, On Fri, Jan 25, 2013 at 19:29:40, Rob Clark wrote: On Fri, Jan 25, 2013 at 7:19 AM, Mohammed, Afzal af...@ti.com wrote: On Wed, Jan 23, 2013 at 04:06:22, Rob Clark wrote: A simple DRM/KMS driver for the TI LCD Controller found in various smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the +void tilcdc_crtc_update_clk(struct drm_crtc *crtc) + /* in raster mode, minimum divisor is 2: */ + ret = clk_set_rate(priv-disp_clk, crtc-mode.clock * 1000 * 2); These things can better be handled with divider clock having a minimum value (being discussed with Mike on how exactly it should be) and instead of setting rate over a platform specific clock, you can set rate over lcd clock using SET_RATE_PARENT at platform level, more below, I looked at that patch you were proposing for da8xx-fb.. to be honest, it did not seem simpler to me, so I was sort of failing to see the benefit.. It's not about being simple, but not doing the wrong way, here you are relying on a platform specific clock in a driver, think about the case where same IP is used on another platform. Either way it is not a good thing to handle platform specific details (about disp_clk) in driver. Right, but I was trying to understand what was the benefit that the added complexity is. I didn't realize on davinci that you are limited to just setting divider values (which is going to drastically limit the timings you can generate, although maybe not an issue if all you support is a fixed lcd panel). And Mike mentioned that one of design goals of CCF is to model these kinds of clocks in IP's. + /* Configure the LCD clock divisor. */ + tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) | + LCDC_RASTER_MODE); + + if (priv-rev == 2) + tilcdc_set(dev, LCDC_CLK_ENABLE_REG, + LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | + LCDC_V2_CORE_CLK_EN); Mike was suggesting to model the above using gate/divider/composite clocks of CCF in the FB driver. + priv-clk = clk_get(dev-dev, fck); + if (IS_ERR(priv-clk)) { + dev_err(dev-dev, failed to get functional clock\n); + ret = -ENODEV; + goto fail; + } + + priv-disp_clk = clk_get(dev-dev, dpll_disp_ck); + if (IS_ERR(priv-clk)) { + dev_err(dev-dev, failed to get display clock\n); + ret = -ENODEV; + goto fail; + } dpll_disp_ck is a platform specific matter, driver should not be handling platform specifics. And this won't work on DaVinci, you can probably make use of meaning the clock has a different name on davinci, or? Presumably there must be some clock generating the pixel clock for the display, but I confess to not being too familiar with the details on davinci.. The only option for the driver in DaVinci is to configure clock rate using the divider of LCDC IP, it has fck, which gives a rate decided by its ancestors. Well, from looking at the other patch series it seems CCF doesn't support minimum divider yet. And davinci doesn't support CCF yet. So at the moment all this discussion is a bit moot. I'd propose leaving the driver as it is for now, because that at least makes it useful on am33xx. And when CCF and davinci have the needed support in place, then send a patch to change the clock handling in tilcdc. I don't actually have any davinci hw to test on, but I can easily test on am33xx. BR, -R Regards Afzal -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] drm/i2c: nxp-tda998x (v2)
On Thu, Jan 24, 2013 at 5:57 AM, Daniel Vetter dan...@ffwll.ch wrote: On Tue, Jan 22, 2013 at 04:36:23PM -0600, Rob Clark wrote: Driver for the NXP TDA998X i2c hdmi encoder slave. v1: original v2: fix npix/nline programming Signed-off-by: Rob Clark robdcl...@gmail.com Just one bikeshed, otherwise Reviewed-by: Daniel Vetter daniel.vet...@ffwll.ch [cut] +static void +reg_set(struct drm_encoder *encoder, uint16_t reg, uint8_t val) +{ + reg_write(encoder, reg, reg_read(encoder, reg) | val); +} + +static void +reg_clear(struct drm_encoder *encoder, uint16_t reg, uint8_t val) +{ + reg_write(encoder, reg, reg_read(encoder, reg) ~val); +} What about drivers/base/regmap? I haven't looked to closely yet and never used it in code, but there's a presentation [1] and it sounds like it provides some nice (and more important standardized) helper stuff for debug, tracing, ... Since encoder slave drivers tend to be utterly boring register bashing and we expect tons of time, I think high levels of standardization would be really useful. Care to look into this a bit? I did look at regmap.. what convinced me against using it was that if you don't use cached mode, it ends up writing the page selector register for every read/write. And I don't have enough actual documentation about this nxp part to know the reset values of all the registers in order to use caching. BR, -R Cheers, Daniel 1: http://free-electrons.com/blog/fosdem2012-videos/ -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] drm/tilcdc: add encoder slave
On Thu, Jan 24, 2013 at 6:43 AM, Daniel Vetter dan...@ffwll.ch wrote: On Tue, Jan 22, 2013 at 04:36:24PM -0600, Rob Clark wrote: Add output panel driver for i2c encoder slaves. Signed-off-by: Rob Clark robdcl...@gmail.com A few questions below, otherwise Reviewed-by: Daniel Vetter daniel.vet...@ffwll.ch --- [snip] diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index ee9b592..99beca2 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -8,3 +8,15 @@ config DRM_TILCDC Choose this option if you have an TI SoC with LCDC display controller, for example AM33xx in beagle-bone, DA8xx, or OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver. + +menu I2C encoder or helper chips + depends on DRM DRM_KMS_HELPER I2C + +config DRM_I2C_NXP_TDA998X + tristate NXP Semiconductors TDA998X HDMI encoder + default m if DRM_TILCDC + help + Support for NXP Semiconductors TDA998X HDMI encoders. + +endmenu + Shouldn't that hunk be in patch 2? yeah, probably.. I just copied how it was done in nouveau, but I think probably the Kconfig for the i2c encoder slaves should be moved into drivers/gpu/drm/i2c [snip] +/* + * Encoder: + */ + +struct slave_encoder { + struct drm_encoder_slave base; + struct slave_module *mod; +}; +#define to_slave_encoder(x) container_of(to_encoder_slave(x), struct slave_encoder, base) Since you have a 1:1:1 relationship between module/drm_encoder, the drm_encoder_slave and the connector I'd just smash this all into one struct. Pure bikeshed though ;-) yeah, but drm_encoder_slave is coming from drm core [snip] +static struct drm_encoder *slave_encoder_create(struct drm_device *dev, + struct slave_module *mod) +{ + struct slave_encoder *slave_encoder; + struct drm_encoder *encoder; + int ret; + + slave_encoder = kzalloc(sizeof(*slave_encoder), GFP_KERNEL); + if (!slave_encoder) { + dev_err(dev-dev, allocation failed\n); + return NULL; + } + + slave_encoder-mod = mod; + + encoder = slave_encoder-base.base; + encoder-possible_crtcs = 1; + + ret = drm_encoder_init(dev, encoder, slave_encoder_funcs, + DRM_MODE_ENCODER_LVDS); DRM_MODE_ENCODER_TMDS? Although I guess adding a new kind of multi-function encoder type would make more sense and also useful in other places. E.g. i915-sdvo/dvo just set meaningless types for multi-function encoders (i.e. more than one connector on the same output), namely the type which matches the connector last initalized. I suppose TDMS makes more sense.. perhaps getting both this and connector type from the encoder-slave would make the most sense, but I can change it to TDMS for now [snip] +static struct drm_connector *slave_connector_create(struct drm_device *dev, + struct slave_module *mod, struct drm_encoder *encoder) +{ + struct slave_connector *slave_connector; + struct drm_connector *connector; + int ret; + + slave_connector = kzalloc(sizeof(*slave_connector), GFP_KERNEL); + if (!slave_connector) { + dev_err(dev-dev, allocation failed\n); + return NULL; + } + + slave_connector-encoder = encoder; + slave_connector-mod = mod; + + connector = slave_connector-base; + + drm_connector_init(dev, connector, slave_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA); Shouldn't we get the connector type from the drm_encoder_slave somehow? Works here for now, so just food for thought for future encoder slave refactorings and infrastructure work. yeah, getting it from the encoder slave makes the most sense [snip] +static struct of_device_id slave_of_match[] = { + { .compatible = tilcdc,slave, }, + { }, +}; +MODULE_DEVICE_TABLE(of, slave_of_match); + +struct platform_driver slave_driver = { + .probe = slave_probe, + .remove = slave_remove, + .driver = { + .owner = THIS_MODULE, + .name = slave, + .of_match_table = slave_of_match, + }, +}; No idea how this devicetree matching stuff is supposed to work, but I guess this needs to be updated in the devictree docs like the base match. yeah, I didn't realize previously about the DT bindings docs, so I need to look into that BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] drm/tilcdc: add encoder slave
On Thu, Jan 24, 2013 at 7:01 AM, Daniel Vetter dan...@ffwll.ch wrote: On Tue, Jan 22, 2013 at 04:36:24PM -0600, Rob Clark wrote: Add output panel driver for i2c encoder slaves. Signed-off-by: Rob Clark robdcl...@gmail.com Found some more stuff ... [cut] +static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { + .dpms = drm_i2c_encoder_dpms, + .mode_fixup = drm_i2c_encoder_mode_fixup, + .prepare= slave_encoder_prepare, + .commit = drm_i2c_encoder_commit, + .mode_set = drm_i2c_encoder_mode_set, + .save = drm_i2c_encoder_save, + .restore= drm_i2c_encoder_restore, +}; I couldn't find these wrappers anywhere ... this is in one of the dependent patches (also on my tilcdc-next branch): https://patchwork.kernel.org/patch/1950971/ I also cleaned up nouveau to use 'em: https://patchwork.kernel.org/patch/1951051/ + +static const struct i2c_board_info info = { + I2C_BOARD_INFO(tda998x, 0x70) +}; Shouldn't there be some of/devicetree thing to tell us which one to load? There are limited options for the i2c addresses, and all the boards I've seen which have this part are at 0x70 and 0x34 for CEC. Probably the CEC address needs to come from a config struct or maybe the i2c encoder just gets passed a 'struct device_node *'. I'm not really sure the best way to handle that to share the encoder between DT and non-DT platforms, and since I didn't really need the configurability yet, I just left that for now and decided we could figure out how to handle that as the need arose. BR, -R -Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/4] drm/tilcdc: add support for LCD panels (v4)
On Thu, Jan 24, 2013 at 7:08 AM, Daniel Vetter dan...@ffwll.ch wrote: On Tue, Jan 22, 2013 at 04:36:25PM -0600, Rob Clark wrote: Add an output panel driver for LCD panels. Tested with LCD3 cape on beaglebone. v1: original v2: s/of_find_node_by_name()/of_get_child_by_name()/ from Pantelis Antoniou v3: add backlight support v4: rebase to latest of video timing helpers Signed-off-by: Rob Clark robdcl...@gmail.com So given that I'm utterly lacking clue about all things of (which seems to be where all the magic in this patch lies) I'm just gonna ask a few funny questions. [cut] +static int panel_connector_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector-dev; + struct panel_connector *panel_connector = to_panel_connector(connector); + struct display_timings *timings = panel_connector-mod-timings; + int i; + + for (i = 0; i timings-num_timings; i++) { + struct drm_display_mode *mode = drm_mode_create(dev); + struct videomode vm; + + if (videomode_from_timing(timings, vm, i)) + break; + + drm_display_mode_from_videomode(vm, mode); Why do we need to jump through the intermediate videomode thing here? Is that a deficiency of the of/videomode stuff? there is a helper that cut through the intermediate videomode structure, although it assumed you are doing that at the point where you still have the 'struct device_node *' (in the probe code) which didn't really fit well for how I had structured things. So I just skipped it. I guess I could have gone straight to array of drm_display_mode in the probe call, and then copied them here in get_modes() but this just seemed a bit easier. [cut] + ret |= of_property_read_u32(info_np, ac-bias, info-ac_bias); + ret |= of_property_read_u32(info_np, ac-bias-intrpt, info-ac_bias_intrpt); + ret |= of_property_read_u32(info_np, dma-burst-sz, info-dma_burst_sz); + ret |= of_property_read_u32(info_np, bpp, info-bpp); + ret |= of_property_read_u32(info_np, fdd, info-fdd); + ret |= of_property_read_u32(info_np, sync-edge, info-sync_edge); + ret |= of_property_read_u32(info_np, sync-ctrl, info-sync_ctrl); + ret |= of_property_read_u32(info_np, raster-order, info-raster_order); + ret |= of_property_read_u32(info_np, fifo-th, info-fifo_th); Shouldn't these values all be documented somewhere in the devictree docs? Or are they somewhat standardized? Yeah, I guess I need to add DT docs.. I didn't realize this earlier. BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] drm/tilcdc: add TI LCD Controller DRM driver (v3)
On Wed, Jan 23, 2013 at 3:42 AM, Jean-Francois Moine moin...@free.fr wrote: Hi Rob, As I wanted to re-use your nxp-tda998x driver for the Marvell Dove SoC, I had a look at your IT LCD driver. Comments below. Just fyi, you can re-use the nxp-tda998x part independently of tilcdc (just in case that wasn't clear). It may be that we need to add some configuration info struct, if for example there are some differences in video signal mux on the dove board, but that shouldn't be a big deal. I figure we can see what is needed as others start to use it and add as needed. On Tue, 22 Jan 2013 16:36:22 -0600 Rob Clark robdcl...@gmail.com wrote: A simple DRM/KMS driver for the TI LCD Controller found in various smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the CMA helpers. Currently only the TFP410 DVI encoder is supported (tested with beaglebone + DVI cape). There are also various LCD displays, for which support can be added (as I get hw to test on), and an external i2c HDMI encoder found on some boards. The display controller supports a single CRTC. And the encoder+ connector are split out into sub-devices. Depending on which LCD or external encoder is actually present, the appropriate output module(s) will be loaded. v1: original v2: fix fb refcnting and few other cleanups v3: get +/- vsync/hsync from timings rather than panel-info, add option DT max-bandwidth field so driver doesn't attempt to pick a display mode with too high memory bandwidth, and other small cleanups Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/Kconfig| 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/tilcdc/Kconfig | 10 + drivers/gpu/drm/tilcdc/Makefile| 8 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 597 drivers/gpu/drm/tilcdc/tilcdc_drv.c| 605 + drivers/gpu/drm/tilcdc/tilcdc_drv.h| 159 + drivers/gpu/drm/tilcdc/tilcdc_regs.h | 154 + drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 423 +++ drivers/gpu/drm/tilcdc/tilcdc_tfp410.h | 26 ++ 10 files changed, 1985 insertions(+) create mode 100644 drivers/gpu/drm/tilcdc/Kconfig create mode 100644 drivers/gpu/drm/tilcdc/Makefile create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_crtc.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_regs.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.h [snip] diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig new file mode 100644 index 000..ee9b592 --- /dev/null +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -0,0 +1,10 @@ +config DRM_TILCDC + tristate DRM Support for TI LCDC Display Controller + depends on DRM OF + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER + help + Choose this option if you have an TI SoC with LCDC display + controller, for example AM33xx in beagle-bone, DA8xx, or + OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver. diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile new file mode 100644 index 000..1359cc2 --- /dev/null +++ b/drivers/gpu/drm/tilcdc/Makefile @@ -0,0 +1,8 @@ +ccflags-y := -Iinclude/drm -Werror + +tilcdc-y := \ + tilcdc_crtc.o \ + tilcdc_tfp410.o \ + tilcdc_drv.o As I understand, this means that the 3 objects will go into the resident kernel. I though that the device tree was created for Linux distributors who might generate generic ARM kernels, the choice of the drivers being done according the local device tree. From this point of vue, it would be nicer to have 2 separate modules: tilcdc and tfp410, tilcdc_crtc being included in one of these ones (I did not look deep enough at the code to know which). drv and crtc are the core driver... arguably the tfp410 part could be optional. I'd prefer *not* as a separate module, as this implies some independence of module lifetime, which is not true. I generally prefer to start simple and add complexity later if someone really thinks they need it, which is why I avoided adding a bunch of kconfig options to start with. [snip] diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c new file mode 100644 index 000..cf1fddc --- /dev/null +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -0,0 +1,605 @@ [snip] +static struct drm_driver tilcdc_driver = { + .driver_features= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET, + .load = tilcdc_load, + .unload = tilcdc_unload, + .preclose = tilcdc_preclose, + .lastclose
Re: [PATCH 2/4] drm/i2c: nxp-tda998x (v2)
On Wed, Jan 23, 2013 at 3:42 AM, Jean-Francois Moine moin...@free.fr wrote: On Tue, 22 Jan 2013 16:36:23 -0600 Rob Clark robdcl...@gmail.com wrote: Driver for the NXP TDA998X i2c hdmi encoder slave. v1: original v2: fix npix/nline programming Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/tda998x_drv.c | 908 ++ 2 files changed, 911 insertions(+) create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c [snip] diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c new file mode 100644 index 000..02054e8 --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -0,0 +1,908 @@ [snip] +static void __exit +tda998x_exit(void) +{ + DBG(); + drm_i2c_encoder_unregister(tda998x_driver); +} + +MODULE_DESCRIPTION(NXP Semiconductors TDA998X TMDS transmitter driver); + +MODULE_AUTHOR(Rob Clark robdcl...@gmail.com); +MODULE_DESCRIPTION(NXP Semiconductors TDA998X HDMI Encoder); +MODULE_LICENSE(GPL); + +module_init(tda998x_init); +module_exit(tda998x_exit); There are 2 MODULE_DESCRIPTION(). oh, whoops.. I'll fix that BR, -R -- Ken ar c'hentañ | ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/ -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] drm/tilcdc: add TI LCD Controller DRM driver (v3)
On Wed, Jan 23, 2013 at 7:36 AM, Russell King - ARM Linux li...@arm.linux.org.uk wrote: On Wed, Jan 23, 2013 at 07:24:33AM -0600, Rob Clark wrote: On Wed, Jan 23, 2013 at 3:42 AM, Jean-Francois Moine moin...@free.fr wrote: Hi Rob, As I wanted to re-use your nxp-tda998x driver for the Marvell Dove SoC, I had a look at your IT LCD driver. Comments below. Just fyi, you can re-use the nxp-tda998x part independently of tilcdc (just in case that wasn't clear). Great, this chip is also used on the cubox too. cool, it would be great if other platforms could benefit from this as well.. the out-of-tree nxp driver is just horrid ;-) The one thing I wonder is how you deal with the VSYNC/HSYNC polarities that are provided to the TDA9988x chip. On the cubox, I have to adjust the mode parameters such that the polarities are fixed up thusly: adjusted-flags = ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_PCSYNC | DRM_MODE_FLAG_NCSYNC); /* The TDA19988 always requires negative VSYNC? */ adjusted-flags |= DRM_MODE_FLAG_NVSYNC; /* The TDA19988 requires positive HSYNC on 1080p or 720p */ if ((adjusted-hdisplay == 1920 adjusted-vdisplay == 1080) || (adjusted-hdisplay == 1280 adjusted-vdisplay == 720)) adjusted-flags |= DRM_MODE_FLAG_PHSYNC; else adjusted-flags |= DRM_MODE_FLAG_NHSYNC; return true; for these resolutions to be displayed correctly. hmm, I didn't come across this. Although 1080p seems to be a bit more than what the little board I'm working on can drive. I didn't have to do any special fixup for 720p.. I wonder if you are having to do that with the nxp out of tree driver? Maybe it is related to how that driver it is configuring the hw? It would be interesting if you hit the same issue w/ the i2c encoder slave version. At any rate, if it turns out to be needed, we can add this in tda998x_encoder_mode_fixup(). Also, when the only output is the HDMI device, reporting the display disconnected and without any modes seems to cause problems - I have to report unknown status when there's nothing connected, and also provide a default (720p) mode when no EDID is received. hmm, also did not run into any issues here on my end. What sort of problems did you hit? BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 00/12] video: da8xx-fb: am335x DT support
On Wed, Jan 23, 2013 at 6:27 AM, Mohammed, Afzal af...@ti.com wrote: Hi, On Wed, Jan 23, 2013 at 00:15:09, Rob Clark wrote: Wouldn't it be better to delete da8xx-fb.* and switch to Rob Clarks DRM based driver for this IP block? we probably can't delete da8xx-fb, but I think it would be ok to only use it for legacy platforms not yet ported to DT. We can't remove da8xx-fb as DA830 is a non-DT one and DA850 is only gaining DT support. And Rob, I am not familiar with drm setup, would all the user space frame buffer based applications work as is with drm driver? drm does provide a legacy fbdev interface (needed for fbcon, for example). I don't think da8xx-fb has any custom ioctls, so probably what drm provides should be enough. BR, -R Regards Afzal -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] drm/tilcdc: add TI LCD Controller DRM driver (v3)
On Wed, Jan 23, 2013 at 8:13 AM, Rob Clark robdcl...@gmail.com wrote: On Wed, Jan 23, 2013 at 7:36 AM, Russell King - ARM Linux li...@arm.linux.org.uk wrote: On Wed, Jan 23, 2013 at 07:24:33AM -0600, Rob Clark wrote: On Wed, Jan 23, 2013 at 3:42 AM, Jean-Francois Moine moin...@free.fr wrote: Hi Rob, As I wanted to re-use your nxp-tda998x driver for the Marvell Dove SoC, I had a look at your IT LCD driver. Comments below. Just fyi, you can re-use the nxp-tda998x part independently of tilcdc (just in case that wasn't clear). Great, this chip is also used on the cubox too. cool, it would be great if other platforms could benefit from this as well.. the out-of-tree nxp driver is just horrid ;-) The one thing I wonder is how you deal with the VSYNC/HSYNC polarities that are provided to the TDA9988x chip. On the cubox, I have to adjust the mode parameters such that the polarities are fixed up thusly: adjusted-flags = ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_PCSYNC | DRM_MODE_FLAG_NCSYNC); /* The TDA19988 always requires negative VSYNC? */ adjusted-flags |= DRM_MODE_FLAG_NVSYNC; /* The TDA19988 requires positive HSYNC on 1080p or 720p */ if ((adjusted-hdisplay == 1920 adjusted-vdisplay == 1080) || (adjusted-hdisplay == 1280 adjusted-vdisplay == 720)) adjusted-flags |= DRM_MODE_FLAG_PHSYNC; else adjusted-flags |= DRM_MODE_FLAG_NHSYNC; return true; for these resolutions to be displayed correctly. hmm, I didn't come across this. Although 1080p seems to be a bit more than what the little board I'm working on can drive. I didn't have to do any special fixup for 720p.. one thought.. I haven't enabled any hdmi features like audio yet.. which could be a reason that I didn't hit some of these issues. I'm not really much of an audio/asoc expert so I'm not really sure how this should hook in for audio stuff, but if someone out there with some hw with a similar nxp encoder chip does have some better audio experience, I'd be interested to work together on that. BR, -R I wonder if you are having to do that with the nxp out of tree driver? Maybe it is related to how that driver it is configuring the hw? It would be interesting if you hit the same issue w/ the i2c encoder slave version. At any rate, if it turns out to be needed, we can add this in tda998x_encoder_mode_fixup(). Also, when the only output is the HDMI device, reporting the display disconnected and without any modes seems to cause problems - I have to report unknown status when there's nothing connected, and also provide a default (720p) mode when no EDID is received. hmm, also did not run into any issues here on my end. What sort of problems did you hit? BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 00/12] video: da8xx-fb: am335x DT support
On Tue, Jan 22, 2013 at 11:03 AM, Koen Kooi k...@dominion.thruhere.net wrote: Op 22 jan. 2013, om 17:51 heeft Afzal Mohammed af...@ti.com het volgende geschreven: Hi, This series adds DT support to da8xx-fb driver (device found on DaVinci and AM335x SoC's). It does certain cleanup's in the process. This series as compared to previous version handles configuration of the LCDC clock rate by modelling as a clock divider of CCF. This would take effect only if CCF is selected, if not, no change to existing method. This makes use of Steffen Trumtrar's v16 of display timing DT support. Wouldn't it be better to delete da8xx-fb.* and switch to Rob Clarks DRM based driver for this IP block? we probably can't delete da8xx-fb, but I think it would be ok to only use it for legacy platforms not yet ported to DT. BR, -R regards, Koen-- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] TI LCDC DRM driver
I think this driver is ready to go, so I've removed the 'RFC' tag. Prove me wrong by reviewing the patches and sending comments ;-) The first patch adds the basic driver and TFP410 DVI output. The second patch adds support for NXP TDA998x family of i2c connected HDMI encoders. It is split out into an i2c encoder-slave in case someone else has hw with the same HDMI encoder. The final patch adds support for LCD panels, with timings and panel info coming from device-tree. The patch set has dependencies on the following patches that I have sent earlier (which have not changed since then so I am not resending): * drm/cma: add debugfs helpers * drm: i2c encoder helper wrappers In addition, the LCD panel patch also depends on Steffen Trumtrar's OF display helper series. I've moved this patch to last so it can be merged later if needed. Although I really see no reason not to merge the OF display helper series for 3.9. These patches and their dependencies can also be found here: git://people.freedesktop.org/~robclark/linux tilcdc-next http://cgit.freedesktop.org/~robclark/linux/log/?h=tilcdc-next Rob Clark (4): drm/tilcdc: add TI LCD Controller DRM driver (v3) drm/i2c: nxp-tda998x (v2) drm/tilcdc: add encoder slave drm/tilcdc: add support for LCD panels (v4) drivers/gpu/drm/Kconfig| 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/tda998x_drv.c | 908 + drivers/gpu/drm/tilcdc/Kconfig | 25 + drivers/gpu/drm/tilcdc/Makefile| 10 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 597 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.c| 611 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.h| 159 ++ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 443 drivers/gpu/drm/tilcdc/tilcdc_panel.h | 26 + drivers/gpu/drm/tilcdc/tilcdc_regs.h | 154 ++ drivers/gpu/drm/tilcdc/tilcdc_slave.c | 380 ++ drivers/gpu/drm/tilcdc/tilcdc_slave.h | 26 + drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 423 +++ drivers/gpu/drm/tilcdc/tilcdc_tfp410.h | 26 + 16 files changed, 3794 insertions(+) create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c create mode 100644 drivers/gpu/drm/tilcdc/Kconfig create mode 100644 drivers/gpu/drm/tilcdc/Makefile create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_crtc.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_regs.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.h create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.h -- 1.8.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] drm/i2c: nxp-tda998x (v2)
Driver for the NXP TDA998X i2c hdmi encoder slave. v1: original v2: fix npix/nline programming Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/tda998x_drv.c | 908 ++ 2 files changed, 911 insertions(+) create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 9286256..43aa33b 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o + +tda998x-y := tda998x_drv.o +obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c new file mode 100644 index 000..02054e8 --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -0,0 +1,908 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + + + +#include linux/module.h + +#include drm/drmP.h +#include drm/drm_crtc_helper.h +#include drm/drm_encoder_slave.h +#include drm/drm_edid.h + + +#define DBG(fmt, ...) DRM_DEBUG(fmt\n, ##__VA_ARGS__) + +struct tda998x_priv { + struct i2c_client *cec; + uint16_t rev; + uint8_t current_page; + int dpms; +}; + +#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)-slave_priv) + +/* The TDA9988 series of devices use a paged register scheme.. to simplify + * things we encode the page # in upper bits of the register #. To read/ + * write a given register, we need to make sure CURPAGE register is set + * appropriately. Which implies reads/writes are not atomic. Fun! + */ + +#define REG(page, addr) (((page) 8) | (addr)) +#define REG2ADDR(reg) ((reg) 0xff) +#define REG2PAGE(reg) (((reg) 8) 0xff) + +#define REG_CURPAGE 0xff/* write */ + + +/* Page 00h: General Control */ +#define REG_VERSION_LSB REG(0x00, 0x00) /* read */ +#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */ +# define MAIN_CNTRL0_SR (1 0) +# define MAIN_CNTRL0_DECS (1 1) +# define MAIN_CNTRL0_DEHS (1 2) +# define MAIN_CNTRL0_CECS (1 3) +# define MAIN_CNTRL0_CEHS (1 4) +# define MAIN_CNTRL0_SCALER (1 7) +#define REG_VERSION_MSB REG(0x00, 0x02) /* read */ +#define REG_SOFTRESET REG(0x00, 0x0a) /* write */ +# define SOFTRESET_AUDIO (1 0) +# define SOFTRESET_I2C_MASTER (1 1) +#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */ +#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */ +#define REG_I2C_MASTERREG(0x00, 0x0d) /* read/write */ +# define I2C_MASTER_DIS_MM(1 0) +# define I2C_MASTER_DIS_FILT (1 1) +# define I2C_MASTER_APP_STRT_LAT (1 2) +#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ +#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ +#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ +# define INT_FLAGS_2_EDID_BLK_RD (1 1) +#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ +#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ +#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ +#define REG_ENA_APREG(0x00, 0x1e) /* read/write */ +#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */ +# define VIP_CNTRL_0_MIRR_A (1 7) +# define VIP_CNTRL_0_SWAP_A(x)(((x) 7) 4) +# define VIP_CNTRL_0_MIRR_B (1 3) +# define VIP_CNTRL_0_SWAP_B(x)(((x) 7) 0) +#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */ +# define VIP_CNTRL_1_MIRR_C (1 7) +# define VIP_CNTRL_1_SWAP_C(x)(((x) 7) 4) +# define VIP_CNTRL_1_MIRR_D (1 3) +# define VIP_CNTRL_1_SWAP_D(x)(((x) 7) 0) +#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */ +# define VIP_CNTRL_2_MIRR_E (1 7) +# define VIP_CNTRL_2_SWAP_E(x)(((x) 7) 4) +# define VIP_CNTRL_2_MIRR_F (1 3) +# define VIP_CNTRL_2_SWAP_F(x)(((x) 7) 0) +#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */ +# define VIP_CNTRL_3_X_TGL(1 0) +# define VIP_CNTRL_3_H_TGL(1 1) +# define
[PATCH 3/4] drm/tilcdc: add encoder slave
Add output panel driver for i2c encoder slaves. Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/tilcdc/Kconfig| 12 ++ drivers/gpu/drm/tilcdc/Makefile | 1 + drivers/gpu/drm/tilcdc/tilcdc_drv.c | 5 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 380 ++ drivers/gpu/drm/tilcdc/tilcdc_slave.h | 26 +++ 5 files changed, 423 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.h diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index ee9b592..99beca2 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -8,3 +8,15 @@ config DRM_TILCDC Choose this option if you have an TI SoC with LCDC display controller, for example AM33xx in beagle-bone, DA8xx, or OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver. + +menu I2C encoder or helper chips + depends on DRM DRM_KMS_HELPER I2C + +config DRM_I2C_NXP_TDA998X + tristate NXP Semiconductors TDA998X HDMI encoder + default m if DRM_TILCDC + help + Support for NXP Semiconductors TDA998X HDMI encoders. + +endmenu + diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile index 1359cc2..aa9097e 100644 --- a/drivers/gpu/drm/tilcdc/Makefile +++ b/drivers/gpu/drm/tilcdc/Makefile @@ -3,6 +3,7 @@ ccflags-y := -Iinclude/drm -Werror tilcdc-y := \ tilcdc_crtc.o \ tilcdc_tfp410.o \ + tilcdc_slave.o \ tilcdc_drv.o obj-$(CONFIG_DRM_TILCDC) += tilcdc.o diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index cf1fddc..ca76dbe 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -20,6 +20,7 @@ #include tilcdc_drv.h #include tilcdc_regs.h #include tilcdc_tfp410.h +#include tilcdc_slave.h #include drm_fb_helper.h @@ -587,6 +588,7 @@ static int __init tilcdc_drm_init(void) { DBG(init); tilcdc_tfp410_init(); + tilcdc_slave_init(); return platform_driver_register(tilcdc_platform_driver); } @@ -594,10 +596,11 @@ static void __exit tilcdc_drm_fini(void) { DBG(fini); tilcdc_tfp410_fini(); + tilcdc_slave_fini(); platform_driver_unregister(tilcdc_platform_driver); } -module_init(tilcdc_drm_init); +late_initcall(tilcdc_drm_init); module_exit(tilcdc_drm_fini); MODULE_AUTHOR(Rob Clark robdcl...@gmail.com); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c new file mode 100644 index 000..b6f3e63 --- /dev/null +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + +#include linux/i2c.h +#include linux/of_i2c.h +#include linux/pinctrl/pinmux.h +#include linux/pinctrl/consumer.h +#include drm/drm_encoder_slave.h + +#include tilcdc_drv.h + +struct slave_module { + struct tilcdc_module base; + struct i2c_adapter *i2c; +}; +#define to_slave_module(x) container_of(x, struct slave_module, base) + +static const struct tilcdc_panel_info slave_info = { + .min_bpp= 16, + .max_bpp= 16, + .bpp= 16, + .ac_bias= 255, + .ac_bias_intrpt = 0, + .dma_burst_sz = 16, + .fdd= 0x80, + .tft_alt_mode = 0, + .stn_565_mode = 0, + .mono_8bit_mode = 0, + .sync_edge = 0, + .sync_ctrl = 1, + .raster_order = 0, +}; + + +/* + * Encoder: + */ + +struct slave_encoder { + struct drm_encoder_slave base; + struct slave_module *mod; +}; +#define to_slave_encoder(x) container_of(to_encoder_slave(x), struct slave_encoder, base) + +static inline struct drm_encoder_slave_funcs * +get_slave_funcs(struct drm_encoder *enc) +{ + return to_encoder_slave(enc)-slave_funcs; +} + +static void slave_encoder_destroy(struct drm_encoder *encoder) +{ + struct slave_encoder *slave_encoder = to_slave_encoder(encoder); + if (get_slave_funcs(encoder
[PATCH 4/4] drm/tilcdc: add support for LCD panels (v4)
Add an output panel driver for LCD panels. Tested with LCD3 cape on beaglebone. v1: original v2: s/of_find_node_by_name()/of_get_child_by_name()/ from Pantelis Antoniou v3: add backlight support v4: rebase to latest of video timing helpers Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/tilcdc/Kconfig| 3 + drivers/gpu/drm/tilcdc/Makefile | 1 + drivers/gpu/drm/tilcdc/tilcdc_drv.c | 3 + drivers/gpu/drm/tilcdc/tilcdc_panel.c | 443 ++ drivers/gpu/drm/tilcdc/tilcdc_panel.h | 26 ++ 5 files changed, 476 insertions(+) create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.c create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.h diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index 99beca2..f468b2b 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -4,6 +4,9 @@ config DRM_TILCDC select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER + select OF_VIDEOMODE + select OF_DISPLAY_TIMING + select BACKLIGHT_CLASS_DEVICE help Choose this option if you have an TI SoC with LCDC display controller, for example AM33xx in beagle-bone, DA8xx, or diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile index aa9097e..deda656 100644 --- a/drivers/gpu/drm/tilcdc/Makefile +++ b/drivers/gpu/drm/tilcdc/Makefile @@ -4,6 +4,7 @@ tilcdc-y := \ tilcdc_crtc.o \ tilcdc_tfp410.o \ tilcdc_slave.o \ + tilcdc_panel.o \ tilcdc_drv.o obj-$(CONFIG_DRM_TILCDC) += tilcdc.o diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index ca76dbe..d10858c 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -21,6 +21,7 @@ #include tilcdc_regs.h #include tilcdc_tfp410.h #include tilcdc_slave.h +#include tilcdc_panel.h #include drm_fb_helper.h @@ -589,6 +590,7 @@ static int __init tilcdc_drm_init(void) DBG(init); tilcdc_tfp410_init(); tilcdc_slave_init(); + tilcdc_panel_init(); return platform_driver_register(tilcdc_platform_driver); } @@ -597,6 +599,7 @@ static void __exit tilcdc_drm_fini(void) DBG(fini); tilcdc_tfp410_fini(); tilcdc_slave_fini(); + tilcdc_panel_fini(); platform_driver_unregister(tilcdc_platform_driver); } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c new file mode 100644 index 000..a3c7fe93 --- /dev/null +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + +#include linux/pinctrl/pinmux.h +#include linux/pinctrl/consumer.h +#include linux/backlight.h +#include video/display_timing.h +#include video/of_display_timing.h +#include video/videomode.h + +#include tilcdc_drv.h + +struct panel_module { + struct tilcdc_module base; + struct tilcdc_panel_info *info; + struct display_timings *timings; + struct backlight_device *backlight; +}; +#define to_panel_module(x) container_of(x, struct panel_module, base) + + +/* + * Encoder: + */ + +struct panel_encoder { + struct drm_encoder base; + struct panel_module *mod; +}; +#define to_panel_encoder(x) container_of(x, struct panel_encoder, base) + + +static void panel_encoder_destroy(struct drm_encoder *encoder) +{ + struct panel_encoder *panel_encoder = to_panel_encoder(encoder); + drm_encoder_cleanup(encoder); + kfree(panel_encoder); +} + +static void panel_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct panel_encoder *panel_encoder = to_panel_encoder(encoder); + struct backlight_device *backlight = panel_encoder-mod-backlight; + + if (!backlight) + return; + + backlight-props.power = mode == DRM_MODE_DPMS_ON +? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; + backlight_update_status(backlight); +} + +static bool panel_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* nothing needed */ + return true; +} + +static void panel_encoder_prepare
[PATCH] ARM: OMAP2+: fix build break for omapdrm
Fixes compile break with 3.8-rc4. Signed-off-by: Rob Clark robdcl...@gmail.com --- arch/arm/mach-omap2/drm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c index 4c7566c..2a2cfa8 100644 --- a/arch/arm/mach-omap2/drm.c +++ b/arch/arm/mach-omap2/drm.c @@ -25,6 +25,7 @@ #include linux/dma-mapping.h #include linux/platform_data/omap_drm.h +#include soc.h #include omap_device.h #include omap_hwmod.h @@ -56,7 +57,7 @@ static int __init omap_init_drm(void) oh-name); } - platform_data.omaprev = GET_OMAP_REVISION(); + platform_data.omaprev = GET_OMAP_TYPE; return platform_device_register(omap_drm_device); -- 1.8.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 0/4] TI LCDC DRM driver
On Thu, Jan 10, 2013 at 6:05 PM, Laurent Pinchart laurent.pinch...@ideasonboard.com wrote: On Thursday 10 January 2013 10:16:10 Dave Airlie wrote: On Wed, Jan 9, 2013 at 2:11 PM, Rob Clark robdcl...@gmail.com wrote: Updated version of DRM driver for TI LCD Controller. Since the initial version of the patch, which only supported TFP410 DVI output, I've added an output driver for LCD panels (for example, LCD3 or LCD7 cape for the beagle-bone), and initial support for HDMI output via NXP TDA19988 HDMI encoder (via i2c encoder-slave output driver). At this point, I think the basic lcdc drm driver plus TFP410 DVI output (first patch) is in reasonable shape (barring potential rename, if lcdc is too generic of a name... but I was not feeling creative enough yet to pick a new name). I'd like at least tilcdc :-) So do I :-) The Renesas LCD controller is also called LCDC, and they called the fbdev driver sh_mobile_lcdcfb. tilcdc isn't *that* long in comparison :-) next version will be 'tilcdc' :-) I would appreciate some thoughts about more generic devicetree lcd panel parameters for the (ti)lcdc_panel patch.. from a functional standpoint, I think the lcd panel support part is also pretty much ready to go (I've added backlight support since the last version I sent), but I'm not really happy with the DT bindings for that because they seem to me a bit too hw specific, but I'm not really sure how they should look. Fwiw, on the CDF - KMS end of things, I'm sort of thinking the i2c encoder slave is not too far off.. just needs to be a bit decoupled from i2c. BR, -R -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 0/4] TI LCDC DRM driver
Updated version of DRM driver for TI LCD Controller. Since the initial version of the patch, which only supported TFP410 DVI output, I've added an output driver for LCD panels (for example, LCD3 or LCD7 cape for the beagle-bone), and initial support for HDMI output via NXP TDA19988 HDMI encoder (via i2c encoder-slave output driver). At this point, I think the basic lcdc drm driver plus TFP410 DVI output (first patch) is in reasonable shape (barring potential rename, if lcdc is too generic of a name... but I was not feeling creative enough yet to pick a new name). The second patch, adding LCD panel support, still needs backlight support. And the DT bindings for panel parameters should probably be made more generic. But I guess someone should have some opinions on that so I figured it would be good to send as an RFC in it's current form and hear other's opinions. The remaining two patches, adding support for HDMI output via NXP TDA998x i2c encoder are fairly preliminary, but basically working (for some definitions of working). At this point, there is only basic DVI output support. Audio, HDCP, etc, can come later. Rob Clark (4): RFC: drm/lcdc: add TI LCD Controller DRM driver (v2) RFC: drm/lcdc: add support for LCD panels (v2) RFC: drm/i2c: nxp-tda998x RFC: drm/lcdc: add encoder slave drivers/gpu/drm/Kconfig| 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/tda998x_drv.c | 907 + drivers/gpu/drm/lcdc/Kconfig | 24 + drivers/gpu/drm/lcdc/Makefile | 10 + drivers/gpu/drm/lcdc/lcdc_crtc.c | 598 drivers/gpu/drm/lcdc/lcdc_drv.c| 608 + drivers/gpu/drm/lcdc/lcdc_drv.h| 164 +++ drivers/gpu/drm/lcdc/lcdc_panel.c | 458 +++ drivers/gpu/drm/lcdc/lcdc_panel.h | 26 ++ drivers/gpu/drm/lcdc/lcdc_regs.h | 154 +++ drivers/gpu/drm/lcdc/lcdc_slave.c | 384 drivers/gpu/drm/lcdc/lcdc_slave.h | 26 ++ drivers/gpu/drm/lcdc/lcdc_tfp410.c | 425 + drivers/gpu/drm/lcdc/lcdc_tfp410.h | 26 ++ 16 files changed, 3816 insertions(+) create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c create mode 100644 drivers/gpu/drm/lcdc/Kconfig create mode 100644 drivers/gpu/drm/lcdc/Makefile create mode 100644 drivers/gpu/drm/lcdc/lcdc_crtc.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_drv.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_drv.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_panel.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_panel.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_regs.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_slave.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_slave.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_tfp410.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_tfp410.h -- 1.8.0.2 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] RFC: drm/lcdc: add support for LCD panels (v2)
Add an output panel driver for LCD panels. Tested with LCD3 cape on beaglebone. TODO: need some way to control the appropriate backlight device TODO: probably want to make the DT bindings more generic for panel-info v1: original v2: s/of_find_node_by_name()/of_get_child_by_name()/ from Pantelis Antoniou Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/lcdc/Kconfig | 2 + drivers/gpu/drm/lcdc/Makefile | 1 + drivers/gpu/drm/lcdc/lcdc_drv.c | 3 + drivers/gpu/drm/lcdc/lcdc_panel.c | 458 ++ drivers/gpu/drm/lcdc/lcdc_panel.h | 26 +++ 5 files changed, 490 insertions(+) create mode 100644 drivers/gpu/drm/lcdc/lcdc_panel.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_panel.h diff --git a/drivers/gpu/drm/lcdc/Kconfig b/drivers/gpu/drm/lcdc/Kconfig index 58806d4..7806184 100644 --- a/drivers/gpu/drm/lcdc/Kconfig +++ b/drivers/gpu/drm/lcdc/Kconfig @@ -4,6 +4,8 @@ config DRM_LCDC select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER + select DISPLAY_TIMING + select OF_DISPLAY_TIMINGS help Choose this option if you have an TI SoC with LCDC display controller, for example AM33xx in beagle-bone, DA8xx, or diff --git a/drivers/gpu/drm/lcdc/Makefile b/drivers/gpu/drm/lcdc/Makefile index db32161..27d19ce 100644 --- a/drivers/gpu/drm/lcdc/Makefile +++ b/drivers/gpu/drm/lcdc/Makefile @@ -3,6 +3,7 @@ ccflags-y := -Iinclude/drm -Werror lcdc-y := \ lcdc_crtc.o \ lcdc_tfp410.o \ + lcdc_panel.o \ lcdc_drv.o obj-$(CONFIG_DRM_LCDC) += lcdc.o diff --git a/drivers/gpu/drm/lcdc/lcdc_drv.c b/drivers/gpu/drm/lcdc/lcdc_drv.c index 5e6d218..ee892cb 100644 --- a/drivers/gpu/drm/lcdc/lcdc_drv.c +++ b/drivers/gpu/drm/lcdc/lcdc_drv.c @@ -20,6 +20,7 @@ #include lcdc_drv.h #include lcdc_regs.h #include lcdc_tfp410.h +#include lcdc_panel.h #include drm_fb_helper.h @@ -584,6 +585,7 @@ static int __init lcdc_drm_init(void) { DBG(init); lcdc_tfp410_init(); + lcdc_panel_init(); return platform_driver_register(lcdc_platform_driver); } @@ -591,6 +593,7 @@ static void __exit lcdc_drm_fini(void) { DBG(fini); lcdc_tfp410_fini(); + lcdc_panel_fini(); platform_driver_unregister(lcdc_platform_driver); } diff --git a/drivers/gpu/drm/lcdc/lcdc_panel.c b/drivers/gpu/drm/lcdc/lcdc_panel.c new file mode 100644 index 000..037e2d2 --- /dev/null +++ b/drivers/gpu/drm/lcdc/lcdc_panel.c @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + +#include linux/pinctrl/pinmux.h +#include linux/pinctrl/consumer.h +#include linux/of_display_timings.h + +#include lcdc_drv.h + +struct panel_module { + struct lcdc_module base; + struct lcdc_panel_info *info; + struct display_timings *timings; +}; +#define to_panel_module(x) container_of(x, struct panel_module, base) + + +/* + * Encoder: + */ + +struct panel_encoder { + struct drm_encoder base; + struct panel_module *mod; +}; +#define to_panel_encoder(x) container_of(x, struct panel_encoder, base) + + +static void panel_encoder_destroy(struct drm_encoder *encoder) +{ + struct panel_encoder *panel_encoder = to_panel_encoder(encoder); + drm_encoder_cleanup(encoder); + kfree(panel_encoder); +} + +static void panel_encoder_dpms(struct drm_encoder *encoder, int mode) +{ +} + +static bool panel_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* nothing needed */ + return true; +} + +static void panel_encoder_prepare(struct drm_encoder *encoder) +{ + struct panel_encoder *panel_encoder = to_panel_encoder(encoder); + panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + lcdc_crtc_set_panel_info(encoder-crtc, panel_encoder-mod-info); +} + +static void panel_encoder_commit(struct drm_encoder *encoder) +{ + panel_encoder_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void panel_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* nothing needed */ +} + +static const struct drm_encoder_funcs panel_encoder_funcs
[PATCH 3/4] RFC: drm/i2c: nxp-tda998x
Driver for the NXP TDA998X i2c hdmi encoder slave. Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/tda998x_drv.c | 907 ++ 2 files changed, 910 insertions(+) create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 9286256..43aa33b 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o + +tda998x-y := tda998x_drv.o +obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c new file mode 100644 index 000..47f8fd2 --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -0,0 +1,907 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + + + +#include linux/module.h + +#include drm/drmP.h +#include drm/drm_crtc_helper.h +#include drm/drm_encoder_slave.h +#include drm/drm_edid.h + + +#define DBG(fmt, ...) DRM_DEBUG(fmt\n, ##__VA_ARGS__) + +struct tda998x_priv { + struct i2c_client *cec; + uint16_t rev; + uint8_t current_page; + int dpms; +}; + +#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)-slave_priv) + +/* The TDA9988 series of devices use a paged register scheme.. to simplify + * things we encode the page # in upper bits of the register #. To read/ + * write a given register, we need to make sure CURPAGE register is set + * appropriately. Which implies reads/writes are not atomic. Fun! + */ + +#define REG(page, addr) (((page) 8) | (addr)) +#define REG2ADDR(reg) ((reg) 0xff) +#define REG2PAGE(reg) (((reg) 8) 0xff) + +#define REG_CURPAGE 0xff/* write */ + + +/* Page 00h: General Control */ +#define REG_VERSION_LSB REG(0x00, 0x00) /* read */ +#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */ +# define MAIN_CNTRL0_SR (1 0) +# define MAIN_CNTRL0_DECS (1 1) +# define MAIN_CNTRL0_DEHS (1 2) +# define MAIN_CNTRL0_CECS (1 3) +# define MAIN_CNTRL0_CEHS (1 4) +# define MAIN_CNTRL0_SCALER (1 7) +#define REG_VERSION_MSB REG(0x00, 0x02) /* read */ +#define REG_SOFTRESET REG(0x00, 0x0a) /* write */ +# define SOFTRESET_AUDIO (1 0) +# define SOFTRESET_I2C_MASTER (1 1) +#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */ +#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */ +#define REG_I2C_MASTERREG(0x00, 0x0d) /* read/write */ +# define I2C_MASTER_DIS_MM(1 0) +# define I2C_MASTER_DIS_FILT (1 1) +# define I2C_MASTER_APP_STRT_LAT (1 2) +#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ +#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ +#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ +# define INT_FLAGS_2_EDID_BLK_RD (1 1) +#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ +#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ +#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ +#define REG_ENA_APREG(0x00, 0x1e) /* read/write */ +#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */ +# define VIP_CNTRL_0_MIRR_A (1 7) +# define VIP_CNTRL_0_SWAP_A(x)(((x) 7) 4) +# define VIP_CNTRL_0_MIRR_B (1 3) +# define VIP_CNTRL_0_SWAP_B(x)(((x) 7) 0) +#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */ +# define VIP_CNTRL_1_MIRR_C (1 7) +# define VIP_CNTRL_1_SWAP_C(x)(((x) 7) 4) +# define VIP_CNTRL_1_MIRR_D (1 3) +# define VIP_CNTRL_1_SWAP_D(x)(((x) 7) 0) +#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */ +# define VIP_CNTRL_2_MIRR_E (1 7) +# define VIP_CNTRL_2_SWAP_E(x)(((x) 7) 4) +# define VIP_CNTRL_2_MIRR_F (1 3) +# define VIP_CNTRL_2_SWAP_F(x)(((x) 7) 0) +#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */ +# define VIP_CNTRL_3_X_TGL(1 0) +# define VIP_CNTRL_3_H_TGL(1 1) +# define VIP_CNTRL_3_V_TGL(1 2) +# define
[PATCH 4/4] RFC: drm/lcdc: add encoder slave
Add output panel driver for i2c encoder slaves. Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/lcdc/Kconfig | 12 ++ drivers/gpu/drm/lcdc/Makefile | 1 + drivers/gpu/drm/lcdc/lcdc_drv.c | 5 +- drivers/gpu/drm/lcdc/lcdc_slave.c | 384 ++ drivers/gpu/drm/lcdc/lcdc_slave.h | 26 +++ 5 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/lcdc/lcdc_slave.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_slave.h diff --git a/drivers/gpu/drm/lcdc/Kconfig b/drivers/gpu/drm/lcdc/Kconfig index 7806184..e88809c 100644 --- a/drivers/gpu/drm/lcdc/Kconfig +++ b/drivers/gpu/drm/lcdc/Kconfig @@ -10,3 +10,15 @@ config DRM_LCDC Choose this option if you have an TI SoC with LCDC display controller, for example AM33xx in beagle-bone, DA8xx, or OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver. + +menu I2C encoder or helper chips + depends on DRM DRM_KMS_HELPER I2C + +config DRM_I2C_NXP_TDA998X + tristate NXP Semiconductors TDA998X HDMI encoder + default m if DRM_LCDC + help + Support for NXP Semiconductors TDA998X HDMI encoders. + +endmenu + diff --git a/drivers/gpu/drm/lcdc/Makefile b/drivers/gpu/drm/lcdc/Makefile index 27d19ce..337e22f 100644 --- a/drivers/gpu/drm/lcdc/Makefile +++ b/drivers/gpu/drm/lcdc/Makefile @@ -4,6 +4,7 @@ lcdc-y := \ lcdc_crtc.o \ lcdc_tfp410.o \ lcdc_panel.o \ + lcdc_slave.o \ lcdc_drv.o obj-$(CONFIG_DRM_LCDC) += lcdc.o diff --git a/drivers/gpu/drm/lcdc/lcdc_drv.c b/drivers/gpu/drm/lcdc/lcdc_drv.c index ee892cb..643664f 100644 --- a/drivers/gpu/drm/lcdc/lcdc_drv.c +++ b/drivers/gpu/drm/lcdc/lcdc_drv.c @@ -21,6 +21,7 @@ #include lcdc_regs.h #include lcdc_tfp410.h #include lcdc_panel.h +#include lcdc_slave.h #include drm_fb_helper.h @@ -586,6 +587,7 @@ static int __init lcdc_drm_init(void) DBG(init); lcdc_tfp410_init(); lcdc_panel_init(); + lcdc_slave_init(); return platform_driver_register(lcdc_platform_driver); } @@ -594,10 +596,11 @@ static void __exit lcdc_drm_fini(void) DBG(fini); lcdc_tfp410_fini(); lcdc_panel_fini(); + lcdc_slave_fini(); platform_driver_unregister(lcdc_platform_driver); } -module_init(lcdc_drm_init); +late_initcall(lcdc_drm_init); module_exit(lcdc_drm_fini); MODULE_AUTHOR(Rob Clark robdcl...@gmail.com); diff --git a/drivers/gpu/drm/lcdc/lcdc_slave.c b/drivers/gpu/drm/lcdc/lcdc_slave.c new file mode 100644 index 000..8534c81 --- /dev/null +++ b/drivers/gpu/drm/lcdc/lcdc_slave.c @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + +#include linux/i2c.h +#include linux/of_i2c.h +#include linux/pinctrl/pinmux.h +#include linux/pinctrl/consumer.h +#include drm/drm_encoder_slave.h + +#include lcdc_drv.h + +struct slave_module { + struct lcdc_module base; + struct i2c_adapter *i2c; +}; +#define to_slave_module(x) container_of(x, struct slave_module, base) + +// TODO maybe this should come from DT? +static const struct lcdc_panel_info slave_info = { + .min_bpp= 16, + .max_bpp= 16, + .ac_bias= 255, + .ac_bias_intrpt = 0, + .dma_burst_sz = 16, + .bpp= 16, + .fdd= 0x80, + .tft_alt_mode = 0, + .stn_565_mode = 0, + .mono_8bit_mode = 0, + .invert_line_clock = 1, + .invert_frm_clock = 1, + .sync_edge = 0, + .sync_ctrl = 1, + .raster_order = 0, +}; + + +/* + * Encoder: + */ + +struct slave_encoder { + struct drm_encoder_slave base; + struct slave_module *mod; +}; +#define to_slave_encoder(x) container_of(to_encoder_slave(x), struct slave_encoder, base) + +static inline struct drm_encoder_slave_funcs * +get_slave_funcs(struct drm_encoder *enc) +{ + return to_encoder_slave(enc)-slave_funcs; +} + +static void slave_encoder_destroy(struct drm_encoder *encoder) +{ + struct slave_encoder *slave_encoder = to_slave_encoder
Re: [RFC] drm/lcdc: add TI LCD Controller DRM driver
On Mon, Dec 17, 2012 at 7:56 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On 2012-12-14 02:04, Rob Clark wrote: A simple DRM/KMS driver for the TI LCD Controller found in various smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the CMA helpers. Currently only the TFP410 DVI encoder is supported (tested with beaglebone + DVI cape). There are also various LCD displays, for which support can be added (as I get hw to test on), and an external i2c HDMI encoder found on some boards. The display controller supports a single CRTC. And the encoder+ connector are split out into sub-devices. Depending on which LCD or external encoder is actually present, the appropriate output module(s) will be loaded. Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/Kconfig| 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/lcdc/Kconfig | 11 + drivers/gpu/drm/lcdc/Makefile | 8 + drivers/gpu/drm/lcdc/lcdc_crtc.c | 544 + drivers/gpu/drm/lcdc/lcdc_drv.c| 604 + drivers/gpu/drm/lcdc/lcdc_drv.h| 162 ++ drivers/gpu/drm/lcdc/lcdc_regs.h | 154 ++ drivers/gpu/drm/lcdc/lcdc_tfp410.c | 424 ++ drivers/gpu/drm/lcdc/lcdc_tfp410.h | 26 ++ 10 files changed, 1936 insertions(+) create mode 100644 drivers/gpu/drm/lcdc/Kconfig create mode 100644 drivers/gpu/drm/lcdc/Makefile create mode 100644 drivers/gpu/drm/lcdc/lcdc_crtc.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_drv.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_drv.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_regs.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_tfp410.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_tfp410.h lcdc is quite a common term. The directory should perhaps be something like ti-lcdc? yeah.. but not one else was using it (other than internally to the driver).. I guess we could call it tilcdc or ti-lcdc Probably not relevant, but I wonder if the same LCDC was used in omap1... It'd be nice to get rid of the omap1 fb driver. would be interesting if you have any idea where to find hw to test with (museum?) I'm not very enthusiastic about adding ti-lcdc specific panel/chip drivers. It's not really a big deal if it's only kernel code, but you add device-tree bindings also, which is an external API that you need to support after adding it. I'd rather see the energy put to common display framework, and get this whole panel/chip driver issue solved in a generic manner. yeah, I was expecting to migrate to CDF once it exists, but needed something for now. I'm using the exercise to get my thoughts straight on how CDF should fit into KMS. (One thing I plan to add support for is an i2c connected hdmi encoder.. which looks like it would fit well in drivers/gpu/drm/i2c.. so the drm encoder-slave stuff might be the way.) If you have any suggestions on the DT bindings, I'd like to hear 'em. BR, -R Tomi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] drm/lcdc: add TI LCD Controller DRM driver
On Mon, Dec 17, 2012 at 8:39 AM, Rob Clark robdcl...@gmail.com wrote: I'm not very enthusiastic about adding ti-lcdc specific panel/chip drivers. It's not really a big deal if it's only kernel code, but you add device-tree bindings also, which is an external API that you need to support after adding it. I'd rather see the energy put to common display framework, and get this whole panel/chip driver issue solved in a generic manner. yeah, I was expecting to migrate to CDF once it exists, but needed something for now. I'm using the exercise to get my thoughts straight on how CDF should fit into KMS. (One thing I plan to add support for is an i2c connected hdmi encoder.. which looks like it would fit well in drivers/gpu/drm/i2c.. so the drm encoder-slave stuff might be the way.) If you have any suggestions on the DT bindings, I'd like to hear 'em. btw, a little bit of-topic, but speaking of DT... Anybody have any clue about how backlight devices are supposed to work in this brave new DT world? In the old days, the board file would stuff a fxn ptr to control backlight in pdata for the driver. But we don't have this any more. I think I need some way to retrieve the 'struct backlight_device' ptr associated with the panel driver, so that the appropriate dpms fxn ptrs can enable/disable the backlight. I'm thinking the dt file should have something that looks roughly like: /* Settings for CDTech_S035Q01 / LCD3 cape: */ panel { compatible = lcdc,panel; pinctrl-names = default; pinctrl-0 = bone_lcd3_cape_lcd_pins; panel-info { ac-bias = 255; ac-bias-intrpt= 0; dma-burst-sz = 16; bpp = 16; fdd = 0x80; tft-alt-mode = 0; stn-565-mode = 0; mono-8bit-mode= 0; invert-line-clock = 1; invert-frm-clock = 1; sync-edge = 0; sync-ctrl = 1; raster-order = 0; fifo-th = 0; }; display-timings { native-mode = timing0; timing0: 320x240 { hactive = 320; vactive = 240; hback-porch = 21; hfront-porch= 58; hsync-len = 47; vback-porch = 11; vfront-porch= 23; vsync-len = 2; clock-frequency = 800; }; }; backlight { compatible = tps65217-backlight; isel = 1; fdim = 200; tps = tps; /* link to the tps */ brightness = 100; }; }; display-timings is based on the of-videomode helpers patch.. panel-info probably needs to be made to be something more generic, but we need something to know how to configure the crtc properly.. but I'm not quite sure what to do with the backlight.. BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] drm/lcdc: add TI LCD Controller DRM driver
On Mon, Dec 17, 2012 at 9:26 AM, Sekhar Nori nori.sek...@gmail.com wrote: Hi Rob, On Monday, December 17, 2012, Rob Clark wrote: On Mon, Dec 17, 2012 at 8:39 AM, Rob Clark robdcl...@gmail.com wrote: I'm not very enthusiastic about adding ti-lcdc specific panel/chip drivers. It's not really a big deal if it's only kernel code, but you add device-tree bindings also, which is an external API that you need to support after adding it. I'd rather see the energy put to common display framework, and get this whole panel/chip driver issue solved in a generic manner. yeah, I was expecting to migrate to CDF once it exists, but needed something for now. I'm using the exercise to get my thoughts straight on how CDF should fit into KMS. (One thing I plan to add support for is an i2c connected hdmi encoder.. which looks like it would fit well in drivers/gpu/drm/i2c.. so the drm encoder-slave stuff might be the way.) If you have any suggestions on the DT bindings, I'd like to hear 'em. btw, a little bit of-topic, but speaking of DT... Anybody have any clue about how backlight devices are supposed to work in this brave new DT world? See Runtime interpreted power sequences here: http://lkml.indiana.edu/hypermail/linux/kernel/1208.2/00029.html It is an attempt to address this need. hmm, I'm not really sure that is what is needed.. or rather, it might perhaps make sense to have a generic backlight driver implementation that could be used where appropriate, but I'm a bit suspicious about that trying to cover absolutely everything. From the drm/display driver we don't even want to care how the backlight is implemented. You could have (just making something up hypothetically) a backlight controlled via a uart or some sort of other crazy magic.. and eventually the generic interpreter gets out of hand. Really I think we just want a way to retrieve a 'struct backlight_device *' that is created somewhere else. We don't care how that backlight driver is implemented. I don't think we want an interpreter.. we want a way to lookup backlight device by name or phandle or something like that. BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC] drm/lcdc: add TI LCD Controller DRM driver
A simple DRM/KMS driver for the TI LCD Controller found in various smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the CMA helpers. Currently only the TFP410 DVI encoder is supported (tested with beaglebone + DVI cape). There are also various LCD displays, for which support can be added (as I get hw to test on), and an external i2c HDMI encoder found on some boards. The display controller supports a single CRTC. And the encoder+ connector are split out into sub-devices. Depending on which LCD or external encoder is actually present, the appropriate output module(s) will be loaded. Signed-off-by: Rob Clark robdcl...@gmail.com --- drivers/gpu/drm/Kconfig| 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/lcdc/Kconfig | 11 + drivers/gpu/drm/lcdc/Makefile | 8 + drivers/gpu/drm/lcdc/lcdc_crtc.c | 544 + drivers/gpu/drm/lcdc/lcdc_drv.c| 604 + drivers/gpu/drm/lcdc/lcdc_drv.h| 162 ++ drivers/gpu/drm/lcdc/lcdc_regs.h | 154 ++ drivers/gpu/drm/lcdc/lcdc_tfp410.c | 424 ++ drivers/gpu/drm/lcdc/lcdc_tfp410.h | 26 ++ 10 files changed, 1936 insertions(+) create mode 100644 drivers/gpu/drm/lcdc/Kconfig create mode 100644 drivers/gpu/drm/lcdc/Makefile create mode 100644 drivers/gpu/drm/lcdc/lcdc_crtc.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_drv.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_drv.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_regs.h create mode 100644 drivers/gpu/drm/lcdc/lcdc_tfp410.c create mode 100644 drivers/gpu/drm/lcdc/lcdc_tfp410.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 983201b..255efcb 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -212,3 +212,5 @@ source drivers/gpu/drm/cirrus/Kconfig source drivers/gpu/drm/shmobile/Kconfig source drivers/gpu/drm/tegra/Kconfig + +source drivers/gpu/drm/lcdc/Kconfig diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 6f58c81..8e0a19a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -50,4 +50,5 @@ obj-$(CONFIG_DRM_UDL) += udl/ obj-$(CONFIG_DRM_AST) += ast/ obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/ obj-$(CONFIG_DRM_TEGRA) += tegra/ +obj-$(CONFIG_DRM_LCDC) += lcdc/ obj-y += i2c/ diff --git a/drivers/gpu/drm/lcdc/Kconfig b/drivers/gpu/drm/lcdc/Kconfig new file mode 100644 index 000..084b0a0 --- /dev/null +++ b/drivers/gpu/drm/lcdc/Kconfig @@ -0,0 +1,11 @@ +config DRM_LCDC + tristate DRM Support for TI LCDC Display Controller + depends on DRM OF + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER + help + Choose this option if you have an TI SoC with LCDC display + controller, for example AM33xx in beagle-bone, DA8xx, or + OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver. + diff --git a/drivers/gpu/drm/lcdc/Makefile b/drivers/gpu/drm/lcdc/Makefile new file mode 100644 index 000..db32161 --- /dev/null +++ b/drivers/gpu/drm/lcdc/Makefile @@ -0,0 +1,8 @@ +ccflags-y := -Iinclude/drm -Werror + +lcdc-y := \ + lcdc_crtc.o \ + lcdc_tfp410.o \ + lcdc_drv.o + +obj-$(CONFIG_DRM_LCDC) += lcdc.o diff --git a/drivers/gpu/drm/lcdc/lcdc_crtc.c b/drivers/gpu/drm/lcdc/lcdc_crtc.c new file mode 100644 index 000..052c2c1 --- /dev/null +++ b/drivers/gpu/drm/lcdc/lcdc_crtc.c @@ -0,0 +1,544 @@ +/* + * Copyright (C) 2012 Texas Instruments + * Author: Rob Clark robdcl...@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + +#include lcdc_drv.h +#include lcdc_regs.h + +struct lcdc_crtc { + struct drm_crtc base; + + const struct lcdc_panel_info *info; + uint32_t dirty; + dma_addr_t start, end; + struct drm_pending_vblank_event *event; + int dpms; + wait_queue_head_t frame_done_wq; + bool frame_done; +}; +#define to_lcdc_crtc(x) container_of(x, struct lcdc_crtc, base) + +static void set_scanout(struct drm_crtc *crtc, uint32_t stat) +{ + struct lcdc_crtc *lcdc_crtc = to_lcdc_crtc(crtc); + struct drm_device *dev = crtc-dev; + + pm_runtime_get_sync(dev-dev); + if (stat LCDC_END_OF_FRAME0) { + lcdc_write(dev, LCDC_DMA_FRM_BUF_BASE_ADDR_0_REG, + lcdc_crtc-start); + lcdc_write(dev
Re: [PATCH] staging: drm/omap: fix missing include on omap_crtc
On 11/28/2012 06:55 AM, Enric Balletbo i Serra wrote: From: Enric Balletbo i Serra eballe...@iseebcn.com This fixes following error: | ... | CC [M] drivers/staging/omapdrm/omap_crtc.o | .../omapdrm/omap_crtc.c:22:22: fatal error: drm_mode.h: No such file or directory | ... fwiw, I have this patch in my local tree that is fixing the same issue: https://patchwork.kernel.org/patch/1588461/ and I think I've seen at least one other patch for the same thing.. it would be nice to at least get one version of this fix in 3.7.. BR, -R Signed-off-by: Enric Balletbo i Serra eballe...@iseebcn.com --- drivers/staging/omapdrm/omap_crtc.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 732f2ad..1d54fe9 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -17,9 +17,9 @@ * this program. If not, see http://www.gnu.org/licenses/. */ -#include omap_drv.h +#include drm/drm_mode.h -#include drm_mode.h +#include omap_drv.h #include drm_crtc.h #include drm_crtc_helper.h -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm/omap: use omapdss low level API
On Fri, Nov 16, 2012 at 12:44 AM, Archit Taneja arc...@ti.com wrote: On Friday 16 November 2012 05:30 AM, Rob Clark wrote: +static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr, + const struct dss_lcd_mgr_config *config) +{ + struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); + DBG(%s, omap_crtc-name); + dispc_mgr_set_lcd_config(omap_crtc-channel, config); Maybe you should move this dispc write also to omap_crtc_pre_apply, the same way it's done for timings. We'll also be confident about having the clocks required if this is called in pre_apply. That was the first thing I had tried, although the order doesn't really work out well and lcd config ends up getting set on the n+1'th apply. Currently this is only called indirectly from omap_encoder_set_enabled() - dssdrv-enable() which always happens on apply worker. In fact no dispc or dssdev fxn that changes state is called outside of apply worker. (Only things like detect and reading edid are happening outside of apply worker.) When we get to the point of having more sophisticated panel drivers, these callbacks from the panel are probably going to need some sort of if (is_in_apply_worker()) sort of check. +static void apply_worker(struct work_struct *work) +{ + struct omap_crtc *omap_crtc = + container_of(work, struct omap_crtc, apply_work); + struct drm_crtc *crtc = omap_crtc-base; + struct drm_device *dev = crtc-dev; + struct omap_drm_apply *apply, *n; + bool need_apply; + + /* +* Synchronize everything on mode_config.mutex, to keep +* the callbacks and list modification all serialized +* with respect to modesetting ioctls from userspace. +*/ + mutex_lock(dev-mode_config.mutex); + dispc_runtime_get(); + + /* +* If we are still pending a previous update, wait.. when the +* pending update completes, we get kicked again. +*/ + if (omap_crtc-apply_irq.registered) + goto out; + + /* finish up previous apply's: */ + list_for_each_entry_safe(apply, n, + omap_crtc-pending_applies, pending_node) { + apply-post_apply(apply); + list_del(apply-pending_node); + } + + need_apply = !list_empty(omap_crtc-queued_applies); + + /* then handle the next round of of queued apply's: */ + list_for_each_entry_safe(apply, n, + omap_crtc-queued_applies, queued_node) { + apply-pre_apply(apply); + list_del(apply-queued_node); + apply-queued = false; + list_add_tail(apply-pending_node, + omap_crtc-pending_applies); + } + + if (need_apply) { + enum omap_channel channel = omap_crtc-channel; + + DBG(%s: GO, omap_crtc-name); + + if (dispc_mgr_is_enabled(channel)) { + omap_irq_register(dev, omap_crtc-apply_irq); + dispc_mgr_go(channel); + } else if (!dispc_mgr_go_busy(channel)) { I'm not clear about this. Why would GO be set in the first place if the manager isn't enabled? This could be replaced with a simple 'else' Yeah, that extra if should be redundant +static void omap_crtc_pre_apply(struct omap_drm_apply *apply) +{ + struct omap_crtc *omap_crtc = + container_of(apply, struct omap_crtc, apply); + struct drm_crtc *crtc = omap_crtc-base; + struct drm_encoder *encoder = NULL; + + DBG(%s: enabled=%d, full=%d, omap_crtc-name, + omap_crtc-enabled, omap_crtc-full_update); + + if (omap_crtc-full_update) { If I get it right, full_update refers to manager properties that previously used to propogate downstream from the output driver to dispc, i.e, things like timings and so on. and the ones which aren't full_update are upstream properties like transparency keys, default_color and so on? Well, it basically means power or timings have changed. So it means closer to full modeset vs pageflip. But this function does deal with one mismatch between DRM and DSS.. in DRM, everything gets setup in crtc - downstream order, whereas omapdss to accommodate more sophisticated panels does things in the reverse order. So the crtc here propagates timing/power state change to the encoder (which may turn into mgr op callbacks), rather than relying on the encoder-helper fxn ptrs called from KMS. And in fact other DRM drivers will need the same thing eventually if they are to support the common panel/display framework. So I think eventually a new / alternate set of crtc helpers (at least drm_crtc_helper_set_{config,mode})()) will be needed. But I think it would be easier to introduce after the atomic modeset changes
Re: [PATCH] ARM: add get_user() support for 8 byte types
On Thu, Nov 15, 2012 at 3:19 AM, Arnd Bergmann a...@arndb.de wrote: On Tuesday 13 November 2012, Russell King - ARM Linux wrote: You're missing something; that is one of the greatest powers of open source. The many eyes (and minds) effect. Someone out there probably has a solution to whatever problem, the trick is to find that person. :) I think we have a working solution for this for ARM. It won't be suitable for every arch, where they have 8-bit and 16-bit registers able to be allocated by the compiler, but for architectures where the minimum register size is 32-bit, what we have below should work. I don't mind at all adding the extension to ARM, and I think it's pretty cool that you guys actually found a working solution. The part that worries me is that we are making architecture independent code depend on a clever hack that may or may not be possible to implement on a given architecture, and that most architecture maintainers wouldn't know how to implement correctly even if it's possible. I could always send a 3rd version with a comment smashed on about why that works if you think this is a problem.. BR, -R Arnd -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ARM: add get_user() support for 8 byte types
On Thu, Nov 15, 2012 at 7:39 AM, Arnd Bergmann a...@arndb.de wrote: On Thursday 15 November 2012, Rob Clark wrote: On Thu, Nov 15, 2012 at 3:19 AM, Arnd Bergmann a...@arndb.de wrote: On Tuesday 13 November 2012, Russell King - ARM Linux wrote: You're missing something; that is one of the greatest powers of open source. The many eyes (and minds) effect. Someone out there probably has a solution to whatever problem, the trick is to find that person. :) I think we have a working solution for this for ARM. It won't be suitable for every arch, where they have 8-bit and 16-bit registers able to be allocated by the compiler, but for architectures where the minimum register size is 32-bit, what we have below should work. I don't mind at all adding the extension to ARM, and I think it's pretty cool that you guys actually found a working solution. The part that worries me is that we are making architecture independent code depend on a clever hack that may or may not be possible to implement on a given architecture, and that most architecture maintainers wouldn't know how to implement correctly even if it's possible. I could always send a 3rd version with a comment smashed on about why that works if you think this is a problem.. Comments are always good, so I'd surely like to see those get added. As I said, I don't have any objections to the addition of your patch to the ARM code, which sounds useful to have. ok, I'll send a v3 w/ some additional comments I still haven't heard a conclusive argument why we need to use get_user() rather than copy_from_user() in the DRM code. Is this about a fast path where you want to shave off a few cycles for each call, or does this simplify the code structure, or something else? well, it is mostly because it seemed like a good idea to first try to solve the root issue, rather than having to fix things up in each driver when someone from x86-world introduces a 64b get_user().. There are some other arch's that don't have 64b get_user(), but I don't think any that have any DRM drivers. If 64b get_user() is really not intended to be supported by all archs, it is better to remove it from x86 and the other arch's that do currently support it, rather than making it possible to write drivers that are broken on some archs. BR, -R Arnd -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: add get_user() support for 8 byte types
From: Rob Clark r...@ti.com A new atomic modeset/pageflip ioctl being developed in DRM requires get_user() to work for 64bit types (in addition to just put_user()). v1: original v2: pass correct size to check_uaccess, and better handling of narrowing double word read with __get_user_xb() (Russell King's suggestion) v3: explain in comment about why this works for narrowing fetch to 1, 2, or 4 byte type on ARM. Signed-off-by: Rob Clark r...@ti.com --- arch/arm/include/asm/uaccess.h | 22 +- arch/arm/lib/getuser.S | 17 - 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 7e1f760..4cfa793 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -100,6 +100,7 @@ static inline void set_fs(mm_segment_t fs) extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); +extern int __get_user_8(void *); #define __GUP_CLOBBER_1lr, cc #ifdef CONFIG_CPU_USE_DOMAINS @@ -108,6 +109,7 @@ extern int __get_user_4(void *); #define __GUP_CLOBBER_2 lr, cc #endif #define __GUP_CLOBBER_4lr, cc +#define __GUP_CLOBBER_8lr, cc #define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ @@ -118,11 +120,23 @@ extern int __get_user_4(void *); : 0 (__p), r (__l) \ : __GUP_CLOBBER_##__s) +/* + * Narrowing a double-word get into a single 32bit word register, which works + * for 1, 2, or 4 byte types on ARM because there are no integer registers + * smaller than 32bit + */ +#ifdef BIG_ENDIAN +#define __get_user_xb(__r2,__p,__e,__l,__s)\ + __get_user_x(__r2,(uintptr_t)__p + 4,__e,__l,__s) +#else +#define __get_user_xb __get_user_x +#endif + #define __get_user_check(x,p) \ ({ \ unsigned long __limit = current_thread_info()-addr_limit - 1; \ register const typeof(*(p)) __user *__p asm(r0) = (p);\ - register unsigned long __r2 asm(r2); \ + register typeof(x) __r2 asm(r2); \ register unsigned long __l asm(r1) = __limit; \ register int __e asm(r0); \ switch (sizeof(*(__p))) { \ @@ -135,6 +149,12 @@ extern int __get_user_4(void *); case 4: \ __get_user_x(__r2, __p, __e, __l, 4); \ break; \ + case 8: \ + if (sizeof((x)) 8)\ + __get_user_xb(__r2, __p, __e, __l, 4); \ + else\ + __get_user_x(__r2, __p, __e, __l, 8); \ + break; \ default: __e = __get_user_bad(); break; \ } \ x = (typeof(*(p))) __r2;\ diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 9b06bb4..ed98707 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -18,7 +18,7 @@ * Inputs: r0 contains the address * r1 contains the address limit, which must be preserved * Outputs:r0 is the error code - * r2 contains the zero-extended value + * r2, r3 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see asm/uaccess.h @@ -66,6 +66,19 @@ ENTRY(__get_user_4) mov pc, lr ENDPROC(__get_user_4) +ENTRY(__get_user_8) + check_uaccess r0, 8, r1, r2, __get_user_bad +#ifdef CONFIG_THUMB2_KERNEL +5: TUSER(ldr) r2, [r0] +6: TUSER(ldr) r3, [r0, #4] +#else +5: TUSER(ldr) r2, [r0], #4 +6: TUSER(ldr) r3, [r0] +#endif + mov r0, #0 + mov pc, lr +ENDPROC(__get_user_8) + __get_user_bad: mov r2, #0 mov r0, #-EFAULT @@ -77,4 +90,6 @@ ENDPROC(__get_user_bad) .long 2b, __get_user_bad .long 3b, __get_user_bad .long 4b, __get_user_bad + .long 5b, __get_user_bad + .long 6b, __get_user_bad .popsection -- 1.8.0 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: add get_user() support for 8 byte types
From: Rob Clark r...@ti.com A new atomic modeset/pageflip ioctl being developed in DRM requires get_user() to work for 64bit types (in addition to just put_user()). v1: original v2: pass correct size to check_uaccess, and better handling of narrowing double word read with __get_user_xb() (Russell King's suggestion) Signed-off-by: Rob Clark r...@ti.com --- arch/arm/include/asm/uaccess.h | 18 +- arch/arm/lib/getuser.S | 17 - 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 7e1f760..e2236ad 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -100,6 +100,7 @@ static inline void set_fs(mm_segment_t fs) extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); +extern int __get_user_8(void *); #define __GUP_CLOBBER_1lr, cc #ifdef CONFIG_CPU_USE_DOMAINS @@ -108,6 +109,7 @@ extern int __get_user_4(void *); #define __GUP_CLOBBER_2 lr, cc #endif #define __GUP_CLOBBER_4lr, cc +#define __GUP_CLOBBER_8lr, cc #define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ @@ -118,11 +120,19 @@ extern int __get_user_4(void *); : 0 (__p), r (__l) \ : __GUP_CLOBBER_##__s) +/* narrowing a double-word get into a single 32bit word register: */ +#ifdef BIG_ENDIAN +#define __get_user_xb(__r2,__p,__e,__l,__s)\ + __get_user_x(__r2,(uintptr_t)__p + 4,__e,__l,__s) +#else +#define __get_user_xb __get_user_x +#endif + #define __get_user_check(x,p) \ ({ \ unsigned long __limit = current_thread_info()-addr_limit - 1; \ register const typeof(*(p)) __user *__p asm(r0) = (p);\ - register unsigned long __r2 asm(r2); \ + register typeof(x) __r2 asm(r2); \ register unsigned long __l asm(r1) = __limit; \ register int __e asm(r0); \ switch (sizeof(*(__p))) { \ @@ -135,6 +145,12 @@ extern int __get_user_4(void *); case 4: \ __get_user_x(__r2, __p, __e, __l, 4); \ break; \ + case 8: \ + if (sizeof((x)) 8)\ + __get_user_xb(__r2, __p, __e, __l, 4); \ + else\ + __get_user_x(__r2, __p, __e, __l, 8); \ + break; \ default: __e = __get_user_bad(); break; \ } \ x = (typeof(*(p))) __r2;\ diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 9b06bb4..ed98707 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -18,7 +18,7 @@ * Inputs: r0 contains the address * r1 contains the address limit, which must be preserved * Outputs:r0 is the error code - * r2 contains the zero-extended value + * r2, r3 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see asm/uaccess.h @@ -66,6 +66,19 @@ ENTRY(__get_user_4) mov pc, lr ENDPROC(__get_user_4) +ENTRY(__get_user_8) + check_uaccess r0, 8, r1, r2, __get_user_bad +#ifdef CONFIG_THUMB2_KERNEL +5: TUSER(ldr) r2, [r0] +6: TUSER(ldr) r3, [r0, #4] +#else +5: TUSER(ldr) r2, [r0], #4 +6: TUSER(ldr) r3, [r0] +#endif + mov r0, #0 + mov pc, lr +ENDPROC(__get_user_8) + __get_user_bad: mov r2, #0 mov r0, #-EFAULT @@ -77,4 +90,6 @@ ENDPROC(__get_user_bad) .long 2b, __get_user_bad .long 3b, __get_user_bad .long 4b, __get_user_bad + .long 5b, __get_user_bad + .long 6b, __get_user_bad .popsection -- 1.8.0 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ARM: add get_user() support for 8 byte types
On Mon, Nov 12, 2012 at 4:46 AM, Will Deacon will.dea...@arm.com wrote: On Fri, Nov 09, 2012 at 09:17:33PM +, Rob Clark wrote: From: Rob Clark r...@ti.com A new atomic modeset/pageflip ioctl being developed in DRM requires get_user() to work for 64bit types (in addition to just put_user()). Signed-off-by: Rob Clark r...@ti.com --- arch/arm/include/asm/uaccess.h | 25 - arch/arm/lib/getuser.S | 17 - 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 7e1f760..2e3fdb2 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -100,6 +100,7 @@ static inline void set_fs(mm_segment_t fs) extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); +extern int __get_user_8(void *); #define __GUP_CLOBBER_1 lr, cc #ifdef CONFIG_CPU_USE_DOMAINS @@ -108,6 +109,7 @@ extern int __get_user_4(void *); #define __GUP_CLOBBER_2 lr, cc #endif #define __GUP_CLOBBER_4 lr, cc +#define __GUP_CLOBBER_8 lr, cc #define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ @@ -122,22 +124,35 @@ extern int __get_user_4(void *); ({ \ unsigned long __limit = current_thread_info()-addr_limit - 1; \ register const typeof(*(p)) __user *__p asm(r0) = (p);\ - register unsigned long __r2 asm(r2); \ register unsigned long __l asm(r1) = __limit; \ register int __e asm(r0); \ switch (sizeof(*(__p))) { \ - case 1: \ + case 1: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 1); \ + x = (typeof(*(p))) __r2;\ break; \ - case 2: \ + } \ + case 2: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 2); \ + x = (typeof(*(p))) __r2;\ break; \ - case 4: \ + } \ + case 4: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 4); \ + x = (typeof(*(p))) __r2;\ + break; \ + } \ + case 8: { \ + register unsigned long long __r2 asm(r2); \ Does this matter? For EABI, we'll pass in (r2, r3) and it's all handcrafted asm, so the compiler shouldn't care much. For OABI, I think you may have to do some more work to get the two words where you want them. Is the question whether the compiler is guaranteed to allocate r2 and r3 in all cases? I'm not quite sure, I confess to usually trying to avoid inline asm. But from looking at the disassembly (for little endian EABI build) it seemed to do the right thing. The only other idea I had was to explicitly declare two 'unsigned long's and then shift them into a 64bit x, although I'm open to suggestions if there is a better way. + __get_user_x(__r2, __p, __e, __l, 8); \ + x = (typeof(*(p))) __r2;\ break; \ + } \ default: __e = __get_user_bad(); break; \ } \ - x = (typeof(*(p))) __r2;\ __e;\ }) diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 9b06bb4..d05285c 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -18,7 +18,7 @@ * Inputs: r0 contains the address
Re: [PATCH] ARM: add get_user() support for 8 byte types
On Mon, Nov 12, 2012 at 8:38 AM, Will Deacon will.dea...@arm.com wrote: On Mon, Nov 12, 2012 at 01:46:57PM +, Rob Clark wrote: On Mon, Nov 12, 2012 at 4:46 AM, Will Deacon will.dea...@arm.com wrote: On Fri, Nov 09, 2012 at 09:17:33PM +, Rob Clark wrote: @@ -122,22 +124,35 @@ extern int __get_user_4(void *); ({ \ unsigned long __limit = current_thread_info()-addr_limit - 1; \ register const typeof(*(p)) __user *__p asm(r0) = (p);\ - register unsigned long __r2 asm(r2); \ register unsigned long __l asm(r1) = __limit; \ register int __e asm(r0); \ switch (sizeof(*(__p))) { \ - case 1: \ + case 1: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 1); \ + x = (typeof(*(p))) __r2;\ break; \ - case 2: \ + } \ + case 2: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 2); \ + x = (typeof(*(p))) __r2;\ break; \ - case 4: \ + } \ + case 4: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 4); \ + x = (typeof(*(p))) __r2;\ + break; \ + } \ + case 8: { \ + register unsigned long long __r2 asm(r2); \ Does this matter? For EABI, we'll pass in (r2, r3) and it's all handcrafted asm, so the compiler shouldn't care much. For OABI, I think you may have to do some more work to get the two words where you want them. Is the question whether the compiler is guaranteed to allocate r2 and r3 in all cases? I'm not quite sure, I confess to usually trying to avoid inline asm. But from looking at the disassembly (for little endian EABI build) it seemed to do the right thing. I can't recall how OABI represents 64-bit values and particularly whether this differs between little and big-endian, so I wondered whether you may have to do some marshalling when you assign x. However, a few quick experiments with GCC suggest that the register representation matches EABI in regards to word ordering (it just doesn't require an even base register), although it would be good to find this written down somewhere... yeah, I was kinda hoping that someone a bit closer to the compiler would speak up here :-) The only other idea I had was to explicitly declare two 'unsigned long's and then shift them into a 64bit x, although I'm open to suggestions if there is a better way. Can't you just use register unsigned long long for all cases? Even better, follow what put_user does and use typeof(*(p))? typeof(*(p) was my first try but: register typeof(*(p)) __r2 asm(r2); gives me the error: error: read-only variable ‘__r2’ used as ‘asm’ output I guess because 'const' ends up being part of the typeof *p? I suppose I could do typeof(x) instead BR, -R diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 9b06bb4..d05285c 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -18,7 +18,7 @@ * Inputs: r0 contains the address * r1 contains the address limit, which must be preserved * Outputs: r0 is the error code - * r2 contains the zero-extended value + * r2, r3 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see asm/uaccess.h @@ -66,6 +66,19 @@ ENTRY(__get_user_4) mov pc, lr ENDPROC(__get_user_4) +ENTRY(__get_user_8) + check_uaccess r0, 4, r1, r2, __get_user_bad Shouldn't you be passing 8 here, so that we validate the correct range? yes, sorry, I'll fix that +#ifdef CONFIG_THUMB2_KERNEL +5: TUSER(ldr)r2, [r0] +6: TUSER(ldr
Re: [PATCH] ARM: add get_user() support for 8 byte types
On Mon, Nov 12, 2012 at 1:27 PM, Russell King - ARM Linux li...@arm.linux.org.uk wrote: On Fri, Nov 09, 2012 at 03:17:33PM -0600, Rob Clark wrote: From: Rob Clark r...@ti.com A new atomic modeset/pageflip ioctl being developed in DRM requires get_user() to work for 64bit types (in addition to just put_user()). NAK. (I did write a better email explaining all the ins and outs of why this won't work and why 64-bit get_user isn't possible, but my editor crapped out and lost all that well written message; I don't fancy typing it all out again.) Nevertheless, int test_ptr(unsigned int **v, unsigned int **p) { return get_user(*v, p); } produces a warning, and you can't get away from that if you stick 64-bit support into get_user(). Actually, it seems like using 'register typeof(x) __r2 asm(r2);' does avoid that warning.. I don't know if that was the only argument against 64-bit get_user(). But it will at least be inconvenient that get_user() works for 64bit on x86 but not arm.. BR, -R Sorry, 64-bit get_user() is a no-no. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ARM: add get_user() support for 8 byte types
On Mon, Nov 12, 2012 at 5:08 PM, Russell King - ARM Linux li...@arm.linux.org.uk wrote: On Mon, Nov 12, 2012 at 01:58:32PM -0600, Rob Clark wrote: On Mon, Nov 12, 2012 at 1:27 PM, Russell King - ARM Linux li...@arm.linux.org.uk wrote: On Fri, Nov 09, 2012 at 03:17:33PM -0600, Rob Clark wrote: From: Rob Clark r...@ti.com A new atomic modeset/pageflip ioctl being developed in DRM requires get_user() to work for 64bit types (in addition to just put_user()). NAK. (I did write a better email explaining all the ins and outs of why this won't work and why 64-bit get_user isn't possible, but my editor crapped out and lost all that well written message; I don't fancy typing it all out again.) Nevertheless, int test_ptr(unsigned int **v, unsigned int **p) { return get_user(*v, p); } produces a warning, and you can't get away from that if you stick 64-bit support into get_user(). Actually, it seems like using 'register typeof(x) __r2 asm(r2);' does avoid that warning.. That seems to pass the checks I've done on it so far, and seems rather obvious (there's been a number of people looking at this, none of whom have come up with that solution). Provided the final cast is kept (which is there to ensure proper typechecking), it seems like it might be a solution. I'm sort of thinking maybe we want to change 'switch (sizeof(*(__p)))' with 'switch (sizeof(typeof(x)))' in case someone ignores the compiler warning when they try something like: uint32_t x; uint64_t *p = ...; get_user(x, p); that was my one concern about 'register typeof(x) __r2 ...', but I think just changing the switch condition is enough. But maybe good to have some eyes on in case there is something else I'm not thinking of. BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ARM: add get_user() support for 8 byte types
On Mon, Nov 12, 2012 at 5:53 PM, Russell King - ARM Linux li...@arm.linux.org.uk wrote: On Mon, Nov 12, 2012 at 05:33:41PM -0600, Rob Clark wrote: I'm sort of thinking maybe we want to change 'switch (sizeof(*(__p)))' with 'switch (sizeof(typeof(x)))' in case someone ignores the compiler warning when they try something like: Definitely not. Ttype of access is controlled by the pointer, not by the size of what it's being assigned to. Switching that around is likely to break stuff hugely. Consider this: unsigned char __user *p; int val; get_user(val, p); If the pointer type is used to determine the access size, a char will be accessed. This is legal - because we end up assigning an unsigned character to an int. If the size of the destination was used, we'd access an int instead, which is larger than the pointer, and probably the wrong thing to do anyway. Think of get_user(a, b) as being a special accessor having the ultimate semantics of: a = *b; but done in a safe way with error checking. uint32_t x; uint64_t *p = ...; get_user(x, p); that was my one concern about 'register typeof(x) __r2 ...', but I think just changing the switch condition is enough. But maybe good to have some eyes on in case there is something else I'm not thinking of. And what should happen in the above is exactly the same as what happens if you do: x = *p; with those types. For ARM, that would be a 64-bit access (if the compiler decides not to optimize away the upper 32-bit access) followed by a narrowing cast down to 32-bit. With get_user() of course, there's no option not to optimize it away. However, this _does_ reveal a bug with your approach. With sizeof(*p) being 8, and the type of __r2 being a 32-bit quantity, the compiler will choose the 64-bit accessor, which will corrupt r3 - and the compiler won't know that r3 has been corrupted. right, that is what I was worried about.. but what about something along the lines of: case 8: { \ if (sizeof(x) 8) \ __get_user_x(__r2, __p, __e, __l, 4); \ else\ __get_user_x(__r2, __p, __e, __l, 8); \ break; \ } \ maybe we need a special variant of __get_user_8() instead to get the right 32bits on big vs little endian systems, but I think something roughly along these lines could work. Or maybe in sizeof(x)8 case, we just __get_user_bad().. I'm not 100% sure on whether this is supposed to be treated as an error case at compile time or not. BR, -R That's too unsafe. I just tried a variant of your approach, but got lots of warnings again: register unsigned long long __r2 asm(r2); __get_user_x(__r2, __p, __e, 8, lr); x = (typeof(*(__p))) ((typeof(x))__r2); because typeof(x) in the test_ptr() case ends up being a pointer itself. So, back to the drawing board, and I think back to the original position of we don't support this. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: add get_user() support for 8 byte types
From: Rob Clark r...@ti.com A new atomic modeset/pageflip ioctl being developed in DRM requires get_user() to work for 64bit types (in addition to just put_user()). Signed-off-by: Rob Clark r...@ti.com --- arch/arm/include/asm/uaccess.h | 25 - arch/arm/lib/getuser.S | 17 - 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 7e1f760..2e3fdb2 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -100,6 +100,7 @@ static inline void set_fs(mm_segment_t fs) extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); +extern int __get_user_8(void *); #define __GUP_CLOBBER_1lr, cc #ifdef CONFIG_CPU_USE_DOMAINS @@ -108,6 +109,7 @@ extern int __get_user_4(void *); #define __GUP_CLOBBER_2 lr, cc #endif #define __GUP_CLOBBER_4lr, cc +#define __GUP_CLOBBER_8lr, cc #define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ @@ -122,22 +124,35 @@ extern int __get_user_4(void *); ({ \ unsigned long __limit = current_thread_info()-addr_limit - 1; \ register const typeof(*(p)) __user *__p asm(r0) = (p);\ - register unsigned long __r2 asm(r2); \ register unsigned long __l asm(r1) = __limit; \ register int __e asm(r0); \ switch (sizeof(*(__p))) { \ - case 1: \ + case 1: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 1); \ + x = (typeof(*(p))) __r2;\ break; \ - case 2: \ + } \ + case 2: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 2); \ + x = (typeof(*(p))) __r2;\ break; \ - case 4: \ + } \ + case 4: { \ + register unsigned long __r2 asm(r2); \ __get_user_x(__r2, __p, __e, __l, 4); \ + x = (typeof(*(p))) __r2;\ + break; \ + } \ + case 8: { \ + register unsigned long long __r2 asm(r2); \ + __get_user_x(__r2, __p, __e, __l, 8); \ + x = (typeof(*(p))) __r2;\ break; \ + } \ default: __e = __get_user_bad(); break; \ } \ - x = (typeof(*(p))) __r2;\ __e;\ }) diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 9b06bb4..d05285c 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -18,7 +18,7 @@ * Inputs: r0 contains the address * r1 contains the address limit, which must be preserved * Outputs:r0 is the error code - * r2 contains the zero-extended value + * r2, r3 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see asm/uaccess.h @@ -66,6 +66,19 @@ ENTRY(__get_user_4) mov pc, lr ENDPROC(__get_user_4) +ENTRY(__get_user_8) + check_uaccess r0, 4, r1, r2, __get_user_bad +#ifdef CONFIG_THUMB2_KERNEL +5: TUSER(ldr) r2, [r0] +6: TUSER(ldr) r3, [r0, #4] +#else +5: TUSER(ldr) r2, [r0], #4 +6: TUSER(ldr) r3, [r0] +#endif + mov r0, #0 + mov pc, lr +ENDPROC(__get_user_8) + __get_user_bad: mov r2, #0 mov r0, #-EFAULT @@ -77,4
Re: [PATCH 12/12] OMAPDSS: DPI: always use DSI PLL if available
On Wed, Nov 7, 2012 at 4:01 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On 2012-11-06 16:40, Rob Clark wrote: I mean, similar to how we handle the subdev for dmm.. the omap_drm_init() does the platform_driver_register() for the dmm device before the platform_driver_register() for omapdrm itself, so we know if there is a dmm device, the driver gets probed first before omapdrm. Well, I consider that a bit hacky too. That's not how linux device framework is supposed to be used. I know it makes life easier to do the registering like that, though. It could be a matter of iterating through a list, or something like this.. that is basically an implementation detail. But the end result is that the order the drivers are registered is controlled so the probe sequence works out properly (not to mention suspend/resume sequence). I feel that this kind of solution just tries to solve the generic problem of init/suspend ordering in a single driver, instead of fixing the device framework itself. Or, of course it's possible that our drive architecture just sucks, and the device framework is fine. In that case the workaround is even worse, and we should fix our drivers. well, I guess by splitting things up into many pieces, we push the device framework in ways that it is not pushed on desktop. But I've enough on my plate so I wasn't going to volunteer to try and fix that ;-) controlling the order that the drivers are registered is currently the most straightforward way to not have problems w/ probe/init/suspend.. I think we should support proper hotplugging of the panels. This would fix the problem about init order, but it would also give us device hotplug support. Obviously nobody is going to solder panel to a running board, but I don't see any reason why panels, or, more likely, panels on an add-on boards (like the capes being discussed in omap ml) would not be hotpluggable using whatever connector is used on the particular use case. And even if we don't support removing of the devices, things like the add-on capes could cause the panel on the cape to be identified at some late time (the panel is not described in the board file or DT data, but found at runtime depending on the ID of the cape). This would add another step to the init sequence that should be just right, if we don't support hotplug. If capes are really hot-pluggable, then maybe it is worth thinking about how to make this more dynamic. Although it is a bigger problem, which involves userspace being aware that connectors can dynamically appear/disappear. And the dynamic disappearing is something I worry about more.. it adds the possibility of all sorts of interesting race conditions, such as connectors disappearing in the middle of modeset. I prefer not making things more complicated and error prone than they need to be. If there is not a legitimate use case for connector hw dynamically appearing/disappearing then I don't think we should go there. It sounds nice and simple and clean, but in reality I think it just introduces a whole lot of ways for things to go wrong. A wise Yes, I agree that it complicates things. man once said: https://github.com/robclark/kernel-omap4/blob/master/Documentation/SubmittingPatches#L700 I've done things simple lots of times in the omapdss driver, only to have to rewrite the thing in more complex way later to accommodate new scenarios. I think it's good to write the code in a bit more generic way than the use case at the moment of writing requires, because more often than not, it'll save time in the future. well, if it is not effecting userspace ABI, then I think, when in doubt I prefer to start simple. It can always be changed later if needed. Hotplugging is not some abstract future scenario, we already have hardware that could use it. For example, omap3 SDP board has a switchable output to DVI or LCD panel. In this case we know what the two options are, but the disabled component is still effectually removed from the system, and plugged back in when it's enabled. I would look at this as two different connectors which can not be used at the same time. You have this scenario with desktop graphics cards. Hotplug is not a high priority item, but I do wish we get it supported in common panel framework. Then it's at least possible to extend drm in the future to support it. Anyway, this makes me wonder... omapdrm currently maps the elements of the whole video pipeline to drm elements (encoder, connector, etc). Would it make more sense to just map the DISPC to these drm elements? Connector would then be the output from DISPC. I think: plane-overlay crtc-manager is pretty clear. And really encoder-output should be the way it is.. on the branch w/ omapdss/omapdrm kms re-write, this is how it is for plane/crtc, except for now: encoder+connector-dssdev Basically the encoder is doing the control stuff (power on/off, set timings
Re: [PATCH 12/12] OMAPDSS: DPI: always use DSI PLL if available
On Wed, Nov 7, 2012 at 9:13 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On 2012-11-07 16:32, Rob Clark wrote: On Wed, Nov 7, 2012 at 4:01 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: Hotplugging is not some abstract future scenario, we already have hardware that could use it. For example, omap3 SDP board has a switchable output to DVI or LCD panel. In this case we know what the two options are, but the disabled component is still effectually removed from the system, and plugged back in when it's enabled. I would look at this as two different connectors which can not be used at the same time. You have this scenario with desktop graphics cards. Yes, that's an option with fixed amount of display devices. But doesn't work for capes. Only if capes are hotpluggable.. otherwise probe what cape(s?) are present at boot time (is this possible to detect a cape from sw?), and create the associated connector(s). Anyways, I think we are stretching a bit hard for use cases for hot-pluggable panels.. I just prefer to ignore hotplug for now and come back to it when there is a more legitimate use-case. Hotplug is not a high priority item, but I do wish we get it supported in common panel framework. Then it's at least possible to extend drm in the future to support it. Anyway, this makes me wonder... omapdrm currently maps the elements of the whole video pipeline to drm elements (encoder, connector, etc). Would it make more sense to just map the DISPC to these drm elements? Connector would then be the output from DISPC. I think: plane-overlay crtc-manager is pretty clear. And really encoder-output should be the way it is.. on the branch w/ omapdss/omapdrm kms I'm not so sure. The output (dpi/dsi/hdmi...) is the second step in our chain. The primary output is in the DISPC module, the overlay manager. That's where the timings, pixel clock, etc. are programmed. The second step, our output, is really a converter IP. It receives the primary output, converts it and outputs something else. Just like an external converter chip would do. the timings, pixel clock, vblank/framedone irqs, that all maps to crtc. encoder == converter, so I think this fits. An encoder takes pixel data from a CRTC and converts it to a format suitable for any attached connectors (from drm docbook) And the output can be quite a bit anything. For example, with DBI or DSI command mode outputs we don't have any of the conventional video timings. It doesn't make sense to program, say, video blanking periods to those outputs. But even with DBI and DSI we do have video blanking periods in the DISPC's output, the ovl mgr. the encoder has mode_fixup() which can alter the timings that end up getting set, which might be a way to account for this. I guess really it should be the panel driver that is telling the encoder what adjusted timings to give to the crtc.. so the panel driver doesn't quite map to connector. Of course, at the end of the chain we have a panel that uses normal video timings (well, most likely but not necessarily), and so we could program those timings at the end of the chain, in the block before the panel. But even then the encoder doesn't really map to the DSS's output block, as the DSS's output block may not have the conventional timings (like DBI), or they may be something totally different than what we get in the end of the chain to the panel. So I think mapping encoder to output will not work with multiple display blocks in a chain. Thus I'd see the encoder would better match the DISPC's output, or alternatively perhaps the block which is just before the panel (whatever that is, sometimes it can be OMAP's DSI/HDMI/etc). However, the latter may be a bit strange as the block could be an external component, possibly hotpluggable. re-write, this is how it is for plane/crtc, except for now: encoder+connector-dssdev Basically the encoder is doing the control stuff (power on/off, set timings, etc), and the connector is only doing non control stuff (detect, reading edid, etc). But I think this will probably change a bit as CFP comes into the picture. Currently the drm connector is somewhat a passive element, but I think this will have to change a bit w/ CFP. This would map the drm elements to the static hardware blocks, and the meaning of those blocks would be quite similar to what they are in the desktop world (I guess). The panel driver, the external chips, and the DSS internal output blocks (dsi, dpi, ...) would be handled separately from those drm elements. The DSS internal blocks are static, of course, but they can be effectively considered the same way as external chips. I think dsi/dpi/etc map to encoder. The big question is where the panel's fit. But to userspace somehow this should look like connectors. I think: encoder-output connector-panel could work.. although connector is less passive than KMS currently assumes
Re: [PATCH 12/12] OMAPDSS: DPI: always use DSI PLL if available
On Tue, Nov 6, 2012 at 7:41 AM, Tomi Valkeinen to...@iki.fi wrote: On 2012-11-05 16:21, Rob Clark wrote: On 11/05/2012 02:55 AM, Tomi Valkeinen wrote: But even then, choosing the manager is not easy, as whoever chooses the manager needs to observe all the possible displays used at the same time... Right. I was wondering if omapfb/omapdrm could understand the 'all possible displays information' better compared to a panel's probe. Even omapdrm/omafb can't be perfect because we could insert a panel driver module at any time, and omapfb/omapdrm may miss that out. True, omapdrm/fb may have a better idea. It's still unclear though. Currently we have quite strict order in the sequence the modules need to be loaded, which is quite bad and causes issues. We should make things more dynamic, so that the initialization of the drivers could happen more freely. But that creates more problems: when booting up, omapfb starts. But omapfb can't know if all the panel drivers have already been loaded. omapfb may see that DVI is the default display, but what should it do if DVI doesn't have a driver yet? It could wait, but perhaps the driver for DVI will never even be loaded. The encoder which is connected to the crtc (manager) is picked by combination of encoder-possible_crtcs bitmask and connector-best_encoder(). We could keep things limited so that the association of crtc to encoder (manager to output, roughly) never changes, but this isn't really the right thing to do. It is better that the dssdev not rely on knowing the manager it is attached to at probe time, but instead grab resources more dynamically. Also, at the moment we don't really have any notification to userspace about new encoders/connectors showing up (or conversely, being removed). Only about existing connectors being plugged/unplugged. The closest analogy is perhaps the USB display devices, but even there it is only the entire drm device that is plugged/unplugged. And TBH I don't really see the point in supporting panel drivers being dynamically loaded. It isn't like someone is dynamically soldering on a new display connector to some board that is running. I think omapfb or omapdrm probe should trigger registering the compiled-in panel drivers, so that it can be sure that the dssdev's pop up before it goes and creates drm connector objects. Currently we have to hack around this in omapdrm with late_initcall() to ensure the panel drivers are probed first, but that is an ugly hack that I'd like to get rid of. We have panel devices and panel drivers, each of which can appear at any time. Both are needed for the panel probe to happen. If we don't support device hotplugging (dynamic creation of devices), we need to use late_initcall for omapfb/drm. At least I don't see any other option. You say that omapdrm should trigger registering of the drivers. How would that work? Do you mean that the panel drivers would register themselves to some common list, and omapdrm would go through this list when drm is loaded, calling probe for the items in the list? I guess that's doable, but... It's not how kernel drivers are supposed to work, and so doesn't sound very clean approach to me. I mean, similar to how we handle the subdev for dmm.. the omap_drm_init() does the platform_driver_register() for the dmm device before the platform_driver_register() for omapdrm itself, so we know if there is a dmm device, the driver gets probed first before omapdrm. It could be a matter of iterating through a list, or something like this.. that is basically an implementation detail. But the end result is that the order the drivers are registered is controlled so the probe sequence works out properly (not to mention suspend/resume sequence). I think we should support proper hotplugging of the panels. This would fix the problem about init order, but it would also give us device hotplug support. Obviously nobody is going to solder panel to a running board, but I don't see any reason why panels, or, more likely, panels on an add-on boards (like the capes being discussed in omap ml) would not be hotpluggable using whatever connector is used on the particular use case. And even if we don't support removing of the devices, things like the add-on capes could cause the panel on the cape to be identified at some late time (the panel is not described in the board file or DT data, but found at runtime depending on the ID of the cape). This would add another step to the init sequence that should be just right, if we don't support hotplug. If capes are really hot-pluggable, then maybe it is worth thinking about how to make this more dynamic. Although it is a bigger problem, which involves userspace being aware that connectors can dynamically appear/disappear. And the dynamic disappearing is something I worry about more.. it adds the possibility of all sorts of interesting race conditions, such as connectors
Re: [PATCH 12/12] OMAPDSS: DPI: always use DSI PLL if available
On 11/05/2012 02:55 AM, Tomi Valkeinen wrote: But even then, choosing the manager is not easy, as whoever chooses the manager needs to observe all the possible displays used at the same time... Right. I was wondering if omapfb/omapdrm could understand the 'all possible displays information' better compared to a panel's probe. Even omapdrm/omafb can't be perfect because we could insert a panel driver module at any time, and omapfb/omapdrm may miss that out. True, omapdrm/fb may have a better idea. It's still unclear though. Currently we have quite strict order in the sequence the modules need to be loaded, which is quite bad and causes issues. We should make things more dynamic, so that the initialization of the drivers could happen more freely. But that creates more problems: when booting up, omapfb starts. But omapfb can't know if all the panel drivers have already been loaded. omapfb may see that DVI is the default display, but what should it do if DVI doesn't have a driver yet? It could wait, but perhaps the driver for DVI will never even be loaded. The encoder which is connected to the crtc (manager) is picked by combination of encoder-possible_crtcs bitmask and connector-best_encoder(). We could keep things limited so that the association of crtc to encoder (manager to output, roughly) never changes, but this isn't really the right thing to do. It is better that the dssdev not rely on knowing the manager it is attached to at probe time, but instead grab resources more dynamically. Also, at the moment we don't really have any notification to userspace about new encoders/connectors showing up (or conversely, being removed). Only about existing connectors being plugged/unplugged. The closest analogy is perhaps the USB display devices, but even there it is only the entire drm device that is plugged/unplugged. And TBH I don't really see the point in supporting panel drivers being dynamically loaded. It isn't like someone is dynamically soldering on a new display connector to some board that is running. I think omapfb or omapdrm probe should trigger registering the compiled-in panel drivers, so that it can be sure that the dssdev's pop up before it goes and creates drm connector objects. Currently we have to hack around this in omapdrm with late_initcall() to ensure the panel drivers are probed first, but that is an ugly hack that I'd like to get rid of. BR, -R -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] drm/omap: only advertise rotation prop if supported
From: Rob Clark r...@ti.com For hardware that does not have DMM/TILER, there is no rotation, so no point in getting userspace's hopes up. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_drv.c | 27 +++ drivers/staging/omapdrm/omap_plane.c | 34 ++ 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 2bf7259..e4f3cd8 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -670,19 +670,22 @@ static void dev_lastclose(struct drm_device *dev) DBG(lastclose: dev=%p, dev); - /* need to restore default rotation state.. not sure if there is -* a cleaner way to restore properties to default state? Maybe -* a flag that properties should automatically be restored to -* default state on lastclose? -*/ - for (i = 0; i priv-num_crtcs; i++) { - drm_object_property_set_value(priv-crtcs[i]-base, - priv-rotation_prop, 0); - } + if (priv-rotation_prop) { + /* need to restore default rotation state.. not sure +* if there is a cleaner way to restore properties to +* default state? Maybe a flag that properties should +* automatically be restored to default state on +* lastclose? +*/ + for (i = 0; i priv-num_crtcs; i++) { + drm_object_property_set_value(priv-crtcs[i]-base, + priv-rotation_prop, 0); + } - for (i = 0; i priv-num_planes; i++) { - drm_object_property_set_value(priv-planes[i]-base, - priv-rotation_prop, 0); + for (i = 0; i priv-num_planes; i++) { + drm_object_property_set_value(priv-planes[i]-base, + priv-rotation_prop, 0); + } } ret = drm_fb_helper_restore_fbdev_mode(priv-fbdev); diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c index 4bde639..1b3a9fe 100644 --- a/drivers/staging/omapdrm/omap_plane.c +++ b/drivers/staging/omapdrm/omap_plane.c @@ -416,23 +416,25 @@ void omap_plane_install_properties(struct drm_plane *plane, struct omap_drm_private *priv = dev-dev_private; struct drm_property *prop; - prop = priv-rotation_prop; - if (!prop) { - const struct drm_prop_enum_list props[] = { - { DRM_ROTATE_0, rotate-0 }, - { DRM_ROTATE_90, rotate-90 }, - { DRM_ROTATE_180, rotate-180 }, - { DRM_ROTATE_270, rotate-270 }, - { DRM_REFLECT_X, reflect-x }, - { DRM_REFLECT_Y, reflect-y }, - }; - prop = drm_property_create_bitmask(dev, 0, rotation, - props, ARRAY_SIZE(props)); - if (prop == NULL) - return; - priv-rotation_prop = prop; + if (priv-has_dmm) { + prop = priv-rotation_prop; + if (!prop) { + const struct drm_prop_enum_list props[] = { + { DRM_ROTATE_0, rotate-0 }, + { DRM_ROTATE_90, rotate-90 }, + { DRM_ROTATE_180, rotate-180 }, + { DRM_ROTATE_270, rotate-270 }, + { DRM_REFLECT_X, reflect-x }, + { DRM_REFLECT_Y, reflect-y }, + }; + prop = drm_property_create_bitmask(dev, 0, rotation, + props, ARRAY_SIZE(props)); + if (prop == NULL) + return; + priv-rotation_prop = prop; + } + drm_object_attach_property(obj, prop, 0); } - drm_object_attach_property(obj, prop, 0); prop = priv-zorder_prop; if (!prop) { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] drm/omap: fix issue w/ fb attached to multiple CRTCs
From: Rob Clark r...@ti.com When the fb is detached from one CRTC/plane, paddr was set back to zero. But really we don't want to do this because the fb could still be attached to other CRTC/plane(s). This originally worked like this to catch cases of freeing a pinned fb (but with the refcnt'ing this should no longer be needed). Also, there is checking in the GEM code for freeing a pinned GEM object, so this extra level of checking is redundant. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_fb.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c index 446801d..75d2ff1 100644 --- a/drivers/staging/omapdrm/omap_fb.c +++ b/drivers/staging/omapdrm/omap_fb.c @@ -253,6 +253,7 @@ int omap_framebuffer_replace(struct drm_framebuffer *a, int ret = 0, i, na, nb; struct omap_framebuffer *ofba = to_omap_framebuffer(a); struct omap_framebuffer *ofbb = to_omap_framebuffer(b); + uint32_t pinned_mask = 0; na = a ? drm_format_num_planes(a-pixel_format) : 0; nb = b ? drm_format_num_planes(b-pixel_format) : 0; @@ -263,25 +264,24 @@ int omap_framebuffer_replace(struct drm_framebuffer *a, pa = (i na) ? ofba-planes[i] : NULL; pb = (i nb) ? ofbb-planes[i] : NULL; - if (pa) { + if (pa) unpin(arg, pa-bo); - pa-paddr = 0; - } if (pb !ret) { ret = omap_gem_get_paddr(pb-bo, pb-paddr, true); - if (!ret) + if (!ret) { omap_gem_dma_sync(pb-bo, DMA_TO_DEVICE); + pinned_mask |= (1 i); + } } } if (ret) { /* something went wrong.. unpin what has been pinned */ for (i = 0; i nb; i++) { - struct plane *pb = ofba-planes[i]; - if (pb-paddr) { + if (pinned_mask (1 i)) { + struct plane *pb = ofba-planes[i]; unpin(arg, pb-bo); - pb-paddr = 0; } } } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm/omap: add more new timings fields
On Mon, Sep 10, 2012 at 12:50 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Fri, 2012-09-07 at 12:59 -0500, Rob Clark wrote: From: Rob Clark r...@ti.com Without these, DVI is broken. Signed-off-by: Rob Clark r...@ti.com --- Greg, it looks like the omapdss changes which added these fields, as well as the interlaced field, where merged in Linux 3.5-rc5. So I think both this and the 'update for interlaced' patch are needed for both 3.6 and 3.5. The omapdss timing and interlace changes were merged in 3.6 merge window, they were not merged in 3.5 merge window (and even less in 3.5-rc5)... ok, git-log must be playing tricks on me... then these patches are only needed for 3.6 BR, -R Tomi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] drm/omap: add more new timings fields
From: Rob Clark r...@ti.com Without these, DVI is broken. Signed-off-by: Rob Clark r...@ti.com --- Greg, it looks like the omapdss changes which added these fields, as well as the interlaced field, where merged in Linux 3.5-rc5. So I think both this and the 'update for interlaced' patch are needed for both 3.6 and 3.5. drivers/staging/omapdrm/omap_connector.c | 24 1 file changed, 24 insertions(+) diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5f4a89b..55e9c86 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -52,6 +52,16 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, if (timings-interlace) mode-flags |= DRM_MODE_FLAG_INTERLACE; + + if (timings-hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + mode-flags |= DRM_MODE_FLAG_PHSYNC; + else + mode-flags |= DRM_MODE_FLAG_NHSYNC; + + if (timings-vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + mode-flags |= DRM_MODE_FLAG_PVSYNC; + else + mode-flags |= DRM_MODE_FLAG_NVSYNC; } static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -70,6 +80,20 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings-vbp = mode-vtotal - mode-vsync_end; timings-interlace = !!(mode-flags DRM_MODE_FLAG_INTERLACE); + + if (mode-flags DRM_MODE_FLAG_PHSYNC) + timings-hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + else + timings-hsync_level = OMAPDSS_SIG_ACTIVE_LOW; + + if (mode-flags DRM_MODE_FLAG_PVSYNC) + timings-vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + else + timings-vsync_level = OMAPDSS_SIG_ACTIVE_LOW; + + timings-data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + timings-de_level = OMAPDSS_SIG_ACTIVE_HIGH; + timings-sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; } static void omap_connector_dpms(struct drm_connector *connector, int mode) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Converting OMAP's custom vram allocator
On Wed, Sep 5, 2012 at 5:08 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: Hi, OMAP has a custom video ram allocator, which I'd like to remove and use the standard dma allocation functions. There are two problems for which I'd like to hear suggestions or comments: First one is that the dma_alloc_* functions map the allocated memory for cpu use. In many cases with OMAP DSS (display subsystem) this is not needed: the memory may be written only by the SGX or the DSP, and it's only read by the DSS, so it's never touched by the CPU. see dma_alloc_attrs() and DMA_ATTR_NO_KERNEL_MAPPING This is even more true when using VRFB on omap3 (and probably TILER on omap4) for rotation, as VRFB hides the actual memory and offers rotated views. In this case the backend memory is never accessed by anyone else than VRFB. just fwiw, we don't actually need contiguous memory on o4/tiler :-) (well, at least if you ignore things like secure playback) Is there a way to allocate the memory without creating a mapping? While it won't break anything as such, the allocated areas can be quite large thus causing large areas of the kernel's memory space to be needlessly reserved. The second case is passing a framebuffer address from the bootloader to the kernel. Often with mobile devices the bootloader will initialize the display hardware, showing a company logo or such. To keep the image on the screen when kernel starts we need to reserve the same physical memory area early at boot, and use that for the framebuffer. with a bit of handwaving, this is possible. You can pass a base address to dma_declare_contiguous() when you setup your device's CMA pool. Although that doesn't really guarantee you're allocation from that pool is at offset zero, I suppose. I'm not sure if there's any actual problem with this one, presuming there is a solution for the first case. Somehow the memory is reserved at early boot time, and this is passed to the fb driver. But can the memory be managed the same way as in normal case (for example freeing it), or does it need to be handled as a special case? special-casing it might be better.. although possibly a dma attr could be added for this to tell dma_alloc_from_contiguous() that we need a particular address within the CMA pool. It seems a bit like a hack, but OTOH I guess pretty much every consumer device would need a hack like this. BR, -R Tomi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] drm/omap: update for interlaced
From: Rob Clark r...@ti.com 'struct omap_video_timings' was updated w/ a 'bool interlaced'. Without a matching update in omap_connector, this field could have undefined values from the stack, which isn't quite ideal. Update the fxns to convert omapdss-drm timings structs, and zero-init 'struct omap_video_timings' when it is declared on stack to avoid issues like this in the future. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_connector.c | 17 - 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5e2856c..5f4a89b 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -48,13 +48,10 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode-vsync_end = mode-vsync_start + timings-vsw; mode-vtotal = mode-vsync_end + timings-vbp; - /* note: whether or not it is interlaced, +/- h/vsync, etc, -* which should be set in the mode flags, is not exposed in -* the omap_video_timings struct.. but hdmi driver tracks -* those separately so all we have to have to set the mode -* is the way to recover these timings values, and the -* omap_dss_driver would do the rest. -*/ + mode-flags = 0; + + if (timings-interlace) + mode-flags |= DRM_MODE_FLAG_INTERLACE; } static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -71,6 +68,8 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings-vfp = mode-vsync_start - mode-vdisplay; timings-vsw = mode-vsync_end - mode-vsync_start; timings-vbp = mode-vtotal - mode-vsync_end; + + timings-interlace = !!(mode-flags DRM_MODE_FLAG_INTERLACE); } static void omap_connector_dpms(struct drm_connector *connector, int mode) @@ -187,7 +186,7 @@ static int omap_connector_get_modes(struct drm_connector *connector) } } else { struct drm_display_mode *mode = drm_mode_create(dev); - struct omap_video_timings timings; + struct omap_video_timings timings = {0}; dssdrv-get_timings(dssdev, timings); @@ -291,7 +290,7 @@ void omap_connector_mode_set(struct drm_connector *connector, struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector-dssdev; struct omap_dss_driver *dssdrv = dssdev-driver; - struct omap_video_timings timings; + struct omap_video_timings timings = {0}; copy_timings_drm_to_omap(timings, mode); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] drm/omap: invert dimensions on crtc when rotated
From: Rob Clark r...@ti.com If rotated 90 or 270, we need to invert the dimensions used by drm core for calculating if the dimensions of an attached fb are correct. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_crtc.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 98a10bc..dade3de 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -195,6 +195,13 @@ static int omap_crtc_set_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t val) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_drm_private *priv = crtc-dev-dev_private; + + if (property == priv-rotation_prop) { + crtc-invert_dimensions = + !!(val ((1LL DRM_ROTATE_90) | (1LL DRM_ROTATE_270))); + } + return omap_plane_set_property(omap_crtc-plane, property, val); } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] drm: support for rotated scanout
From: Rob Clark r...@ti.com For drivers that can support rotated scanout, the extra parameter checking in drm-core, while nice, tends to get confused. To solve this drivers can set the crtc or plane invert_dimensions field so that the dimension checking takes into account the rotation that the driver is performing. v1: original v2: remove invert_dimensions from plane, at Ville's suggestion. Userspace can give rotated src coordinates, so invert_dimensions is not required for planes. Signed-off-by: Rob Clark r...@ti.com --- drivers/gpu/drm/drm_crtc.c | 46 +--- include/drm/drm_crtc.h |5 + 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 08a7aa7..901de9a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -377,6 +377,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, crtc-dev = dev; crtc-funcs = funcs; + crtc-invert_dimensions = false; mutex_lock(dev-mode_config.mutex); @@ -1852,6 +1853,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, DRM_DEBUG_KMS([CRTC:%d]\n, crtc-base.id); if (crtc_req-mode_valid) { + int hdisplay, vdisplay; /* If we have a mode we need a framebuffer. */ /* If we pass -1, set the mode with the currently bound fb */ if (crtc_req-fb_id == -1) { @@ -1887,14 +1889,20 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - if (mode-hdisplay fb-width || - mode-vdisplay fb-height || - crtc_req-x fb-width - mode-hdisplay || - crtc_req-y fb-height - mode-vdisplay) { - DRM_DEBUG_KMS(Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n, - mode-hdisplay, mode-vdisplay, - crtc_req-x, crtc_req-y, - fb-width, fb-height); + hdisplay = mode-hdisplay; + vdisplay = mode-vdisplay; + + if (crtc-invert_dimensions) + swap(hdisplay, vdisplay); + + if (hdisplay fb-width || + vdisplay fb-height || + crtc_req-x fb-width - hdisplay || + crtc_req-y fb-height - vdisplay) { + DRM_DEBUG_KMS(Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n, + fb-width, fb-height, + hdisplay, vdisplay, crtc_req-x, crtc_req-y, + crtc-invert_dimensions ? (inverted) : ); ret = -ENOSPC; goto out; } @@ -3489,6 +3497,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, struct drm_framebuffer *fb; struct drm_pending_vblank_event *e = NULL; unsigned long flags; + int hdisplay, vdisplay; int ret = -EINVAL; if (page_flip-flags ~DRM_MODE_PAGE_FLIP_FLAGS || @@ -3518,14 +3527,19 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, goto out; fb = obj_to_fb(obj); - if (crtc-mode.hdisplay fb-width || - crtc-mode.vdisplay fb-height || - crtc-x fb-width - crtc-mode.hdisplay || - crtc-y fb-height - crtc-mode.vdisplay) { - DRM_DEBUG_KMS(Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n, - fb-width, fb-height, - crtc-mode.hdisplay, crtc-mode.vdisplay, - crtc-x, crtc-y); + hdisplay = crtc-mode.hdisplay; + vdisplay = crtc-mode.vdisplay; + + if (crtc-invert_dimensions) + swap(hdisplay, vdisplay); + + if (hdisplay fb-width || + vdisplay fb-height || + crtc-x fb-width - hdisplay || + crtc-y fb-height - vdisplay) { + DRM_DEBUG_KMS(Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n, + fb-width, fb-height, hdisplay, vdisplay, crtc-x, crtc-y, + crtc-invert_dimensions ? (inverted) : ); ret = -ENOSPC; goto out; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index ced3625..7ba9b39 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -358,6 +358,9 @@ struct drm_crtc_funcs { * @enabled: is this CRTC enabled? * @mode: current mode timings * @hwmode: mode timings as programmed to hw regs + * @invert_dimensions: for purposes of error checking crtc vs fb sizes, + *invert the width/height of the crtc. This is used if the driver + *is performing 90 or 270 degree rotated scanout * @x: x position
[PATCH] drm/omap: hold a ref to the bo while waiting for flip
From: Rob Clark r...@ti.com Since the plane hasn't yet taken a reference, we need to hold a reference while waiting to ensure the backing GEM bo doesn't get freed from under us. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_crtc.c | 16 ++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index dade3de..732f2ad 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -155,6 +155,7 @@ static void page_flip_cb(void *arg) struct drm_crtc *crtc = arg; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_framebuffer *old_fb = omap_crtc-old_fb; + struct drm_gem_object *bo; omap_crtc-old_fb = NULL; @@ -165,6 +166,9 @@ static void page_flip_cb(void *arg) * cycle.. for now go for correctness and later figure out speed.. */ omap_plane_on_endwin(omap_crtc-plane, vblank_cb, crtc); + + bo = omap_framebuffer_bo(crtc-fb, 0); + drm_gem_object_unreference_unlocked(bo); } static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, @@ -173,6 +177,7 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, { struct drm_device *dev = crtc-dev; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct drm_gem_object *bo; DBG(%d - %d, crtc-fb ? crtc-fb-base.id : -1, fb-base.id); @@ -185,8 +190,15 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, omap_crtc-event = event; crtc-fb = fb; - omap_gem_op_async(omap_framebuffer_bo(fb, 0), OMAP_GEM_READ, - page_flip_cb, crtc); + /* +* Hold a reference temporarily until the crtc is updated +* and takes the reference to the bo. This avoids it +* getting freed from under us: +*/ + bo = omap_framebuffer_bo(fb, 0); + drm_gem_object_reference(bo); + + omap_gem_op_async(bo, OMAP_GEM_READ, page_flip_cb, crtc); return 0; } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] Expose the OMAP Z-Order property through DRM
On Thu, Aug 16, 2012 at 8:00 AM, Ville Syrjälä ville.syrj...@linux.intel.com wrote: On Wed, Aug 15, 2012 at 03:18:02PM -0500, Rob Clark wrote: From: Andre Renaud an...@bluewatersys.com Added support for zorder changes through DRM plane properties Signed-off-by: Andre Renaud an...@bluewatersys.com Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_drv.h |1 + drivers/staging/omapdrm/omap_plane.c | 19 +++ 2 files changed, 20 insertions(+) diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index b103d28..9dc72d1 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h @@ -62,6 +62,7 @@ struct omap_drm_private { /* properties: */ struct drm_property *rotation_prop; + struct drm_property *zorder_prop; }; /* this should probably be in drm-core to standardize amongst drivers */ diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c index 6931d06..4bde639 100644 --- a/drivers/staging/omapdrm/omap_plane.c +++ b/drivers/staging/omapdrm/omap_plane.c @@ -433,6 +433,15 @@ void omap_plane_install_properties(struct drm_plane *plane, priv-rotation_prop = prop; } drm_object_attach_property(obj, prop, 0); + +prop = priv-zorder_prop; +if (!prop) { + prop = drm_property_create_range(dev, 0, zorder, 0, 3); + if (prop == NULL) + return; + priv-zorder_prop = prop; + } + drm_object_attach_property(obj, prop, 0); } int omap_plane_set_property(struct drm_plane *plane, @@ -452,6 +461,16 @@ int omap_plane_set_property(struct drm_plane *plane, ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); else ret = 0; + } else if (property == priv-zorder_prop) { + struct omap_overlay *ovl = omap_plane-ovl; + + DBG(%s: zorder: %d, ovl-name, (uint32_t)val); + omap_plane-info.zorder = val; What would happen when there's a conflicting assignment between two planes? non-good things.. basically as part of re-working the omapdss-omapdrm stuff, I'll have a good point in omapdrm before setting GO bit(s) where I can calculate the actual z-order from that is set from userspace. If two planes had same z-order from userspace, omapdrm would simply put one in front of the other. If the planes aren't overlapping, this is fine. I tried to think of a decent way to do this stuff, but some hardware can have rather complicated stacking order limitations. One idea I came up with was to have an enum prop on the crtc, where the individual enum value names would somehow describe the whole stacking order within the crtc. That way user space couldn't even try to use an unsupported configuration. The downside is that user space would need to parse those strings if it wants to do some automagic stacking order changes, which means the string format would need some though. I was thinking about this, but then you run into the same issue if you move a plane from one CRTC to another without userspace setting the property again. In the end if userspace is ambiguous the driver has to just arbitrarily pick some z-order to keep the hw happy. BR, -R -- Ville Syrjälä Intel OTC -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] drm/omap: properties patches
From: Rob Clark r...@ti.com Re-sending the earlier rotation property patch, plus Andre's z-order property patch rebased on latest staging-next. Andre Renaud (1): Expose the OMAP Z-Order property through DRM Rob Clark (1): staging: drm/omap: add rotation properties drivers/staging/omapdrm/omap_crtc.c | 10 +++ drivers/staging/omapdrm/omap_dmm_tiler.c | 47 +++-- drivers/staging/omapdrm/omap_dmm_tiler.h | 17 - drivers/staging/omapdrm/omap_drv.c | 17 + drivers/staging/omapdrm/omap_drv.h | 33 - drivers/staging/omapdrm/omap_fb.c| 99 ++ drivers/staging/omapdrm/omap_gem.c | 43 +++- drivers/staging/omapdrm/omap_plane.c | 111 -- 8 files changed, 331 insertions(+), 46 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] staging: drm/omap: add rotation properties
From: Rob Clark r...@ti.com Use tiled buffers for rotated/reflected scanout, with CRTC and plane properties as the interface for userspace to configure rotation. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_crtc.c | 10 +++ drivers/staging/omapdrm/omap_dmm_tiler.c | 47 -- drivers/staging/omapdrm/omap_dmm_tiler.h | 17 - drivers/staging/omapdrm/omap_drv.c | 17 + drivers/staging/omapdrm/omap_drv.h | 32 +- drivers/staging/omapdrm/omap_fb.c| 99 +- drivers/staging/omapdrm/omap_gem.c | 43 - drivers/staging/omapdrm/omap_plane.c | 92 --- 8 files changed, 311 insertions(+), 46 deletions(-) diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 62e0022..98a10bc 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -191,10 +191,18 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, return 0; } +static int omap_crtc_set_property(struct drm_crtc *crtc, + struct drm_property *property, uint64_t val) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + return omap_plane_set_property(omap_crtc-plane, property, val); +} + static const struct drm_crtc_funcs omap_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .destroy = omap_crtc_destroy, .page_flip = omap_crtc_page_flip_locked, + .set_property = omap_crtc_set_property, }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { @@ -231,6 +239,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, drm_crtc_init(dev, crtc, omap_crtc_funcs); drm_crtc_helper_add(crtc, omap_crtc_helper_funcs); + omap_plane_install_properties(omap_crtc-plane, crtc-base); + return crtc; fail: diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index ec7a5c8..3ae3955 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -404,8 +404,26 @@ int tiler_release(struct tiler_block *block) * Utils */ -/* calculate the tiler space address of a pixel in a view orientation */ -static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y) +/* calculate the tiler space address of a pixel in a view orientation... + * below description copied from the display subsystem section of TRM: + * + * When the TILER is addressed, the bits: + * [28:27] = 0x0 for 8-bit tiled + * 0x1 for 16-bit tiled + * 0x2 for 32-bit tiled + * 0x3 for page mode + * [31:29] = 0x0 for 0-degree view + * 0x1 for 180-degree view + mirroring + * 0x2 for 0-degree view + mirroring + * 0x3 for 180-degree view + * 0x4 for 270-degree view + mirroring + * 0x5 for 270-degree view + * 0x6 for 90-degree view + * 0x7 for 90-degree view + mirroring + * Otherwise the bits indicated the corresponding bit address to access + * the SDRAM. + */ +static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y) { u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment; @@ -417,8 +435,11 @@ static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y) x_mask = MASK(x_bits); y_mask = MASK(y_bits); - if (x 0 || x x_mask || y 0 || y y_mask) + if (x 0 || x x_mask || y 0 || y y_mask) { + DBG(invalid coords: %u 0 || %u %u || %u 0 || %u %u, + x, x, x_mask, y, y, y_mask); return 0; + } /* account for mirroring */ if (orient MASK_X_INVERT) @@ -439,11 +460,22 @@ dma_addr_t tiler_ssptr(struct tiler_block *block) { BUG_ON(!validfmt(block-fmt)); - return TILVIEW_8BIT + tiler_get_address(0, block-fmt, + return TILVIEW_8BIT + tiler_get_address(block-fmt, 0, block-area.p0.x * geom[block-fmt].slot_w, block-area.p0.y * geom[block-fmt].slot_h); } +dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient, + uint32_t x, uint32_t y) +{ + struct tcm_pt *p = block-area.p0; + BUG_ON(!validfmt(block-fmt)); + + return tiler_get_address(block-fmt, orient, + (p-x * geom[block-fmt].slot_w) + x, + (p-y * geom[block-fmt].slot_h) + y); +} + void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h) { BUG_ON(!validfmt(fmt)); @@ -451,11 +483,14 @@ void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h) *h = round_up(*h, geom[fmt].slot_h); } -uint32_t tiler_stride(enum tiler_fmt fmt) +uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient) { BUG_ON(!validfmt(fmt)); - return 1 (CONT_WIDTH_BITS + geom
[PATCH 2/2] Expose the OMAP Z-Order property through DRM
From: Andre Renaud an...@bluewatersys.com Added support for zorder changes through DRM plane properties Signed-off-by: Andre Renaud an...@bluewatersys.com Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_drv.h |1 + drivers/staging/omapdrm/omap_plane.c | 19 +++ 2 files changed, 20 insertions(+) diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index b103d28..9dc72d1 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h @@ -62,6 +62,7 @@ struct omap_drm_private { /* properties: */ struct drm_property *rotation_prop; + struct drm_property *zorder_prop; }; /* this should probably be in drm-core to standardize amongst drivers */ diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c index 6931d06..4bde639 100644 --- a/drivers/staging/omapdrm/omap_plane.c +++ b/drivers/staging/omapdrm/omap_plane.c @@ -433,6 +433,15 @@ void omap_plane_install_properties(struct drm_plane *plane, priv-rotation_prop = prop; } drm_object_attach_property(obj, prop, 0); + +prop = priv-zorder_prop; +if (!prop) { + prop = drm_property_create_range(dev, 0, zorder, 0, 3); + if (prop == NULL) + return; + priv-zorder_prop = prop; + } + drm_object_attach_property(obj, prop, 0); } int omap_plane_set_property(struct drm_plane *plane, @@ -452,6 +461,16 @@ int omap_plane_set_property(struct drm_plane *plane, ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); else ret = 0; + } else if (property == priv-zorder_prop) { + struct omap_overlay *ovl = omap_plane-ovl; + + DBG(%s: zorder: %d, ovl-name, (uint32_t)val); + omap_plane-info.zorder = val; + + if (ovl-is_enabled(ovl)) + ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); + else + ret = 0; } return ret; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 09/13] OMAPDSS: SDI: Create a function to set timings
On Tue, Aug 14, 2012 at 11:56 AM, Archit Taneja arc...@ti.com wrote: On Tuesday 14 August 2012 07:14 PM, Tomi Valkeinen wrote: On Thu, 2012-08-09 at 17:19 +0530, Archit Taneja wrote: Create function omapdss_sdi_set_timings(). Configuring new timings is done the same way as before, SDI is disabled, and re-enabled with the new timings in dssdev. This just moves the code from the panel drivers to the SDI driver. The panel drivers shouldn't be aware of how SDI manages to configure a new set of timings. This should be taken care of by the SDI driver itself. I'm not sure about this one. Although I see that dpi.c does currently the same thing as you're doing in your patch. Even HDMI does the same thing. One thing is that we should try to remove dssdev uses from the output drivers, including use of dssdev-state. Yes, we could do that by keeping a state of the output(and also checking state of the manager) The other thing is that I don't think the output driver should disable enable the output during set timings. I think sdi's set_timings should return EBUSY if the output is enabled. The same way as other configuration functions should (like dpi_set_data_lines or such). I'm actually not sure if even the panel driver should disable enable the output during set_timings. Perhaps it should be the caller's (omapdrm or such) responsibility My reasoning here is that disabling enabling the video output is not invisible to the upper layers, so doing it in secret may be bad. Then again, perhaps timings can be changed freely on some other platforms, and then it'd be nice if the panel driver wouldn't disable enable the output. So I'm again not quite sure what's the best way to handle this... (of the dssdev-state I'm sure, its use should be removed from omapdss). Any thoughts? I guess it depends on how drm/fb want to use it. I guess an output should have a set_timings() kind of op if it can do it seamlessly. I guess we can do that easily in DPI, for example, we could reduce the fps from 60 to 30 without causing an artefacts(I think). For outputs which can't do it, we could remove the set_timings totally. fwiw, drm wouldn't try to change timings on the fly.. or at least it is bracketed by a call to the driver's crtc-prepare() and crtc-commit() fxns (which in our case disable/enable output). I haven't seen much userspace that tries to do things like this, except maybe some apps like xbmc which seem to have some options to attempt to change timings to align w/ video playback framerate. I am a bit curious how many tv's and drivers could support this in a glitch-free way. BR, -R However, it'll be kind of inconsistent for some outputs to set timings, and for others to not, and if in the future drm/fb gets exposed to ops too, we may have dirty checks to see if set_timings is populated or not. The easiest way would be to make all set_timings just update the copy of the timings output has, and expect drm/fb to disable and re enable the panel. We may end up doing unnecessary gpio resets and configuration of the panels though. Archit -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] staging: omapdrm: Remove unnecessary memcpy
On Thu, Aug 9, 2012 at 12:13 AM, Andy Gross andy.gr...@ti.com wrote: Removed the unnecessary copy of the memory page addresses when programming the DMM/PAT and all support code for the lut copy. The original intent was to have this code in place for suspend/resume functionality w.r.t. DEVICE_OFF. Performance analysis showed that the extra copy from uncached memory led to a fairly hefty penalty when programming large 1D or 2D buffers. This can be implemented in a more efficient manner when we actually have to support DEVICE_OFF suspend/resume operations. This patch itself is ok, but I'd like to wait a bit and merge this together w/ a 2nd patch that handles saving the PAT state in the suspend path. BR, -R Signed-off-by: Andy Gross andy.gr...@ti.com --- drivers/staging/omapdrm/omap_dmm_priv.h |6 -- drivers/staging/omapdrm/omap_dmm_tiler.c | 25 + 2 files changed, 1 insertions(+), 30 deletions(-) diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h b/drivers/staging/omapdrm/omap_dmm_priv.h index 08b22e9..09ebc50 100644 --- a/drivers/staging/omapdrm/omap_dmm_priv.h +++ b/drivers/staging/omapdrm/omap_dmm_priv.h @@ -141,9 +141,6 @@ struct refill_engine { /* only one trans per engine for now */ struct dmm_txn txn; - /* offset to lut associated with container */ - u32 *lut_offset; - wait_queue_head_t wait_for_refill; struct list_head idle_node; @@ -176,9 +173,6 @@ struct dmm { /* array of LUT - TCM containers */ struct tcm **tcm; - /* LUT table storage */ - u32 *lut; - /* allocation list and lock */ struct list_head alloc_head; }; diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index ec7a5c8..80d3f8a 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -24,7 +24,6 @@ #include linux/interrupt.h #include linux/dma-mapping.h #include linux/slab.h -#include linux/vmalloc.h #include linux/delay.h #include linux/mm.h #include linux/time.h @@ -184,9 +183,6 @@ static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area, int columns = (1 + area-x1 - area-x0); int rows = (1 + area-y1 - area-y0); int i = columns*rows; - u32 *lut = omap_dmm-lut + (engine-tcm-lut_id * omap_dmm-lut_width * - omap_dmm-lut_height) + - (area-y0 * omap_dmm-lut_width) + area-x0; pat = alloc_dma(txn, sizeof(struct pat), pat_pa); @@ -209,10 +205,6 @@ static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area, page_to_phys(pages[n]) : engine-dmm-dummy_pa; } - /* fill in lut with new addresses */ - for (i = 0; i rows; i++, lut += omap_dmm-lut_width) - memcpy(lut, data[i*columns], columns * sizeof(u32)); - txn-last_pat = pat; return 0; @@ -504,8 +496,6 @@ static int omap_dmm_remove(struct platform_device *dev) if (omap_dmm-dummy_page) __free_page(omap_dmm-dummy_page); - vfree(omap_dmm-lut); - if (omap_dmm-irq 0) free_irq(omap_dmm-irq, omap_dmm); @@ -521,7 +511,7 @@ static int omap_dmm_probe(struct platform_device *dev) { int ret = -EFAULT, i; struct tcm_area area = {0}; - u32 hwinfo, pat_geom, lut_table_size; + u32 hwinfo, pat_geom; struct resource *mem; omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL); @@ -593,16 +583,6 @@ static int omap_dmm_probe(struct platform_device *dev) */ writel(0x7e7e7e7e, omap_dmm-base + DMM_PAT_IRQENABLE_SET); - lut_table_size = omap_dmm-lut_width * omap_dmm-lut_height * - omap_dmm-num_lut; - - omap_dmm-lut = vmalloc(lut_table_size * sizeof(*omap_dmm-lut)); - if (!omap_dmm-lut) { - dev_err(dev-dev, could not allocate lut table\n); - ret = -ENOMEM; - goto fail; - } - omap_dmm-dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32); if (!omap_dmm-dummy_page) { dev_err(dev-dev, could not allocate dummy page\n); @@ -685,9 +665,6 @@ static int omap_dmm_probe(struct platform_device *dev) .p1.y = omap_dmm-container_height - 1, }; - for (i = 0; i lut_table_size; i++) - omap_dmm-lut[i] = omap_dmm-dummy_pa; - /* initialize all LUTs to dummy page entries */ for (i = 0; i omap_dmm-num_lut; i++) { area.tcm = omap_dmm-tcm[i]; -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list:
Re: [PATCH] staging: omapdrm: Fix DMM sparse warnings
On Thu, Aug 9, 2012 at 12:14 AM, Andy Gross andy.gr...@ti.com wrote: Fix the following sparse warnings: drivers/staging/omapdrm/omap_dmm_tiler.c:123:13: warning: symbol 'omap_dmm_irq_handler' was not declared. Should it be static? drivers/staging/omapdrm/omap_dmm_tiler.c:370:24: warning: Using plain integer as NULL pointer Signed-off-by: Andy Gross andy.gr...@ti.com Signed-off-by: Rob Clark rob.cl...@linaro.org --- drivers/staging/omapdrm/omap_dmm_tiler.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index 8619783..ec7a5c8 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -120,7 +120,7 @@ static int wait_status(struct refill_engine *engine, uint32_t wait_mask) return 0; } -irqreturn_t omap_dmm_irq_handler(int irq, void *arg) +static irqreturn_t omap_dmm_irq_handler(int irq, void *arg) { struct dmm *dmm = arg; uint32_t status = readl(dmm-base + DMM_PAT_IRQSTATUS); @@ -367,7 +367,7 @@ struct tiler_block *tiler_reserve_1d(size_t size) int num_pages = (size + PAGE_SIZE - 1) PAGE_SHIFT; if (!block) - return 0; + return ERR_PTR(-ENOMEM); block-fmt = TILFMT_PAGE; -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 0/3] solving omapdrm/omapdss layering issues
On Fri, Aug 3, 2012 at 1:01 AM, Semwal, Sumit sumit.sem...@ti.com wrote: Hi Rob, Tomi, On Thu, Aug 2, 2012 at 7:46 PM, Rob Clark rob.cl...@linaro.org wrote: On Thu, Aug 2, 2012 at 8:15 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Thu, 2012-08-02 at 07:45 -0500, Rob Clark wrote: On Thu, Aug 2, 2012 at 2:13 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Wed, 2012-08-01 at 09:25 -0500, Rob Clark wrote: On Wed, Aug 1, 2012 at 4:21 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: I guess the fact is that DRM concepts do not really match the OMAP DSS hardware, and we'll have to use whatever gives us least problems. Actually, I think it does map fairly well to the hardware.. at least more so than to omapdss ;-) Hm, I'm not sure I understand, omapdss concepts map directly to the hardware. I think it is mainly exposing the encoder and panel as two separate entities.. which seems to be what Archit is working on I still don't follow =) They are separate entities. Omapdss models the HW quite directly, I think. It doesn't expose everything, though, as the output drivers (dsi.c, dpi.c etc) are used via the panel drivers. right.. so we just need to expose the output drivers as separate entities, and let omapdrm propagate information such as timings between them in case of something like DVI bridge from DPI, this seems pretty straightforward.. only the connector needs to know about DDC stuff, which i2c to use and that sort of thing. So at kms level we would have (for example) an omap_dpi_encoder which would be the same for DPI panel (connector) or DPI-DVI bridge. For HDMI I'm still looking through the code to see how this would work. Honestly I've looked less at this part of code and encoder related registers in the TRM, compared to the ovl/mgr parts, but at least from the 'DSS overview' picture in the TRM it seems to make sense ;-) KMS even exposes the idea that certain crtcs can connect to only certain encoders. Or that you could you could have certain connectors switched between encoders. For example if you had a hw w/ DPI out, and some mux to switch that back and forth between a DPI lcd panel and a DPI-DVI bridge. (Ok, I'm not aware of any board that actually does this, but it is in theory possible.) So we could expose possible video chain topologies to userspace in this way. OMAP3 SDP board has such a setup, with manual switch to select between LCD and DVI. ahh, good to know.. so I'm not crazy for wanting to expose this possibility to userspace The other thing is that we don't need to propagate timings from the panel up to the mgr at the dss level.. kms is already handling this for us. In my latest version, which I haven't pushed, I removed the 'struct omap_overlay_mgr' ptr from 'struct omap_dss_device'. You're thinking only about simple DPI cases. Consider this example, with a DSI-to-DP bridge chip. What we have is the following flow of data: DISPC - DSI - DSI-2-DP - DP monitor The timings you are thinking about are in the DISPC, but here they are only one part of the link. And here the DISPC timings are not actually the timings what the user is interested about. The user wants his timings to be between DSI-2-DP chip and the DP monitor. Timings programmed to DISPC are not the same. The timings for DISPC come from the DSI driver, and they may be very different than the user's timings. With DSI video mode, the DISPC timings would have some resemblance to the user's timings, mainly the time to send one line would be the same. With DSI cmd mode, the DISPC timings would be something totally different, most likely with 0 blank times and as fast pixel clock as possible. hmm, well kms already has a concept of adjusted_timings, which could perhaps be used here to propagate the timings between crtc-encoder.. although the order is probably backwards from what we want (it comes from the crtc to the encoder.. and if I understand properly we want it the other way and actually possibly from the connector). But that isn't to say that internally in omapdrm the crtc couldn't get the adjusted timings from the connector. So I still think the parameter flow doesn't need to be 'under the hood' in omapdss. And fwiw, the adjusted_timings stuff is handled by drm_crtc_helper fxns, so if the way the core kms handles it isn't what we want, we can just plug in our own fxn instead of using drm_crtc_helper_set_mode(), so that isn't really a big problem. What omapdss does currently is that you set the user's timings to the right side of the chain, which propagate back to DSS. This allows the DSI-2-DP bridge use DSI timings that work optimally for the bridge, and DSI driver will use DISPC timings that work optimally for it. And it's not only about timings above, but also other settings related to the busses between the components. Clock dividers, polarities, stuff like that. I expect we could handle other settings
Re: [RFC 0/3] solving omapdrm/omapdss layering issues
On Thu, Aug 2, 2012 at 8:15 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Thu, 2012-08-02 at 07:45 -0500, Rob Clark wrote: On Thu, Aug 2, 2012 at 2:13 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Wed, 2012-08-01 at 09:25 -0500, Rob Clark wrote: On Wed, Aug 1, 2012 at 4:21 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: I guess the fact is that DRM concepts do not really match the OMAP DSS hardware, and we'll have to use whatever gives us least problems. Actually, I think it does map fairly well to the hardware.. at least more so than to omapdss ;-) Hm, I'm not sure I understand, omapdss concepts map directly to the hardware. I think it is mainly exposing the encoder and panel as two separate entities.. which seems to be what Archit is working on I still don't follow =) They are separate entities. Omapdss models the HW quite directly, I think. It doesn't expose everything, though, as the output drivers (dsi.c, dpi.c etc) are used via the panel drivers. right.. so we just need to expose the output drivers as separate entities, and let omapdrm propagate information such as timings between them in case of something like DVI bridge from DPI, this seems pretty straightforward.. only the connector needs to know about DDC stuff, which i2c to use and that sort of thing. So at kms level we would have (for example) an omap_dpi_encoder which would be the same for DPI panel (connector) or DPI-DVI bridge. For HDMI I'm still looking through the code to see how this would work. Honestly I've looked less at this part of code and encoder related registers in the TRM, compared to the ovl/mgr parts, but at least from the 'DSS overview' picture in the TRM it seems to make sense ;-) KMS even exposes the idea that certain crtcs can connect to only certain encoders. Or that you could you could have certain connectors switched between encoders. For example if you had a hw w/ DPI out, and some mux to switch that back and forth between a DPI lcd panel and a DPI-DVI bridge. (Ok, I'm not aware of any board that actually does this, but it is in theory possible.) So we could expose possible video chain topologies to userspace in this way. OMAP3 SDP board has such a setup, with manual switch to select between LCD and DVI. ahh, good to know.. so I'm not crazy for wanting to expose this possibility to userspace The other thing is that we don't need to propagate timings from the panel up to the mgr at the dss level.. kms is already handling this for us. In my latest version, which I haven't pushed, I removed the 'struct omap_overlay_mgr' ptr from 'struct omap_dss_device'. You're thinking only about simple DPI cases. Consider this example, with a DSI-to-DP bridge chip. What we have is the following flow of data: DISPC - DSI - DSI-2-DP - DP monitor The timings you are thinking about are in the DISPC, but here they are only one part of the link. And here the DISPC timings are not actually the timings what the user is interested about. The user wants his timings to be between DSI-2-DP chip and the DP monitor. Timings programmed to DISPC are not the same. The timings for DISPC come from the DSI driver, and they may be very different than the user's timings. With DSI video mode, the DISPC timings would have some resemblance to the user's timings, mainly the time to send one line would be the same. With DSI cmd mode, the DISPC timings would be something totally different, most likely with 0 blank times and as fast pixel clock as possible. hmm, well kms already has a concept of adjusted_timings, which could perhaps be used here to propagate the timings between crtc-encoder.. although the order is probably backwards from what we want (it comes from the crtc to the encoder.. and if I understand properly we want it the other way and actually possibly from the connector). But that isn't to say that internally in omapdrm the crtc couldn't get the adjusted timings from the connector. So I still think the parameter flow doesn't need to be 'under the hood' in omapdss. And fwiw, the adjusted_timings stuff is handled by drm_crtc_helper fxns, so if the way the core kms handles it isn't what we want, we can just plug in our own fxn instead of using drm_crtc_helper_set_mode(), so that isn't really a big problem. What omapdss does currently is that you set the user's timings to the right side of the chain, which propagate back to DSS. This allows the DSI-2-DP bridge use DSI timings that work optimally for the bridge, and DSI driver will use DISPC timings that work optimally for it. And it's not only about timings above, but also other settings related to the busses between the components. Clock dividers, polarities, stuff like that. I expect we could handle other settings in the same way as the timings. I think the problem was there were some cases, like ovl updates before setting the mgr, where the user_info_dirty flag would be cleared
Re: [PATCH] staging: drm/omap: remove reclaim_buffers callback
On Wed, Aug 1, 2012 at 4:32 AM, Chandrabhanu Mahapatra cmahapa...@ti.com wrote: The reclaim_buffers callback has already been removed by Daniel Vetter daniel.vet...@ffwll.ch with his patch drm: kill reclaim_buffers callback for which the kernel compilation fails with omapdrm support. So, the callback for reclaim_buffers is removed from omapdrm. Signed-off-by: Chandrabhanu Mahapatra cmahapa...@ti.com Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_drv.c |1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 342645a..b8e79eb 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -778,7 +778,6 @@ static struct drm_driver omap_drm_driver = { .irq_postinstall = dev_irq_postinstall, .irq_uninstall = dev_irq_uninstall, .irq_handler = dev_irq_handler, - .reclaim_buffers = drm_core_reclaim_buffers, #ifdef CONFIG_DEBUG_FS .debugfs_init = omap_debugfs_init, .debugfs_cleanup = omap_debugfs_cleanup, -- 1.7.10 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm: refcnt drm_framebuffer
On Wed, Aug 1, 2012 at 6:36 AM, Ville Syrjälä ville.syrj...@linux.intel.com wrote: On Tue, Jul 31, 2012 at 02:28:29PM -0500, Rob Clark wrote: On Tue, Jul 31, 2012 at 12:47 PM, Chris Wilson ch...@chris-wilson.co.uk wrote: On Tue, 31 Jul 2012 12:41:28 -0500, Rob Clark rob.cl...@linaro.org wrote: On Tue, Jul 31, 2012 at 12:00 PM, Chris Wilson ch...@chris-wilson.co.uk wrote: On Tue, 31 Jul 2012 11:20:21 -0500, Rob Clark rob.cl...@linaro.org wrote: From: Rob Clark r...@ti.com This simplifies drm fb lifetime, and if the crtc/plane needs to hold a ref to the fb when disabling a pipe until the next vblank, this avoids the need to make disabling an overlay synchronous. This is a problem that shows up when userspace is using a drm plane to implement a hw cursor.. making overlay disable synchronous causes a performance problem when x11 is rapidly enabling/disabling the hw cursor. But not making it synchronous opens up a race condition for crashing if userspace turns around and immediately deletes the fb. Refcnt'ing the fb makes it possible to solve this problem. Presumably you have a follow-on patch putting the new refcnt to use so that we can judge whether you truly need refcnting on the fb itself in addition to the refcnted object and the various hw bookkeeping that needs to be performed? Yes, I do.. although it is a bit experimental at this point, so not really ready to be submitted as anything other than an RFC.. it is part of omapdrm kms re-write to use dispc directly rather than go thru omapdss. (With omapdss we don't hit this issue because disabling overlays is forced to be synchronous.. so instead we have the performance problem I mentioned.) I *could* just rely on the GEM refcnt, but that gets messier when you take into account multi-planar formats. I suppose I also could have my own internal refcnt'd object to hold the set of GEM objects associated w/ the fb, but, well, that seems a bit silly. And refcnt'ing the fb had been mentioned previously as a good thing to do (I think it was danvet?) Sure, there are a few places in the code that have caused ordering issues in the past due to lack of refcnting the fb... But since you haven't fixed up those cases, I'm looking for justification for adding that extra bit of complexity. Adding a new interface and no users is just asking for trouble. hmm, I did realize that drm_plane cleanup only happens as a result of drm_framebuffer_cleanup().. which doesn't work too well if the driver is holding a ref to the fb :-/ so I guess at a minimum I need to fix plane cleanup to be part of drm_fb_helper_restore_fbdev_mode() Your patch would still significantly change the behavior of drm_mode_rmfb(). Currently it disables all planes and crtcs which currently use the fb, and it removes the fb id from the idr so that no new users of the fb can appear afterwards. Not that I really like the current behaviour of drm_mode_rmfb(), but it's been like that always, so changing it doesn't seem acceptable. yeah, I'm working on an update that decouples the crtc/plane shutdown from deleting the fb, which should address these issues BR, -R -- Ville Syrjälä Intel OTC -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 0/3] solving omapdrm/omapdss layering issues
On Wed, Aug 1, 2012 at 4:21 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Tue, 2012-07-31 at 09:45 -0500, Rob Clark wrote: On Tue, Jul 31, 2012 at 8:40 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: It's not really about being friendly. Omapdss tries to do as little as possible, while still supporting all its HW features. Shadow registers are a bit tricky creating this mess. What I mean by 'friendly' is it tries to abstract this for simple users, like an fbdev driver. But this really quickly breaks down w/ a No, that's not what omapdss tries to do. I'm not trying to hide the shadow registers and the GO bit behind the omapdss API, I'm just trying to make it work. The omapdss API was made with omapfb, so it's true that the API may not be good for omapdrm. But I'm happy to change the API. And btw, I think the current mapping of drm_encoder to mgr in omapdrm is not correct. I'm just in the process of shuffling things around. I think drm/kms actually maps quite nicely to the underlying hardware with the following arrangement: drm_plane - ovl drm_crtc - mgr drm_encoder - DSI/DPI/HDMI/VENC encoder drm_connector - pretty much what we call a panel driver today Hmm, what was the arrangement earlier? it was previously: plane - ovl crtc - placeholder encoder - mgr connector - dssdev (encoder+panel) although crtc is really the point where you should enable/disable vblank irqs, so the new arrangement is somewhat cleaner (although on my branch the encoder/connector part are not finished yet) I guess the fact is that DRM concepts do not really match the OMAP DSS hardware, and we'll have to use whatever gives us least problems. Actually, I think it does map fairly well to the hardware.. at least more so than to omapdss ;-) The one area that kms mismatches a bit is decoupling of ovl from mgr that we have in our hw.. I've partially solved that a while back w/ the patch in drm to add private planes so the omap_crtc internally uses an omap_plane. It isn't exposed to userspace to be able to re-use the planes from unused crtcs, although I have some ideas about that (but not yet time to work on it). It would be quite useful if you could look at the omap_drm_apply mechanism I had in omapdrm, because that seems like a quite straightforward way to deal w/ shadowed registers. I think it will Yes, it seems straightforward, but it's not =). I had a look at your omapdrm-on-dispc-2 branch. What you are doing there is quite similar to what omapdss was doing earlier. It's not going to work reliably with multiple outputs and fifomerge. Configuring things like overlay color mode are quite simple. They only affect that one overlay. Also things like manager default bg color are simple, they affect only that one manager. But enabling/disabling an overlay or a manager, changing the destination mgr of an overlay, fifomerge... Those are not simple. You can't do them directly, as you do in your branch. As an example, consider the case of enabling an overlay (vid1), and moving fifo buffers from currently enabled overlay (gfx) to vid1: you'll first need to take the fifo buffers from gfx, set GO, and wait for the settings to take effect. Only then you can set the fifo buffers for vid1, enable it and set GO bit. hmm, it does sound like it needs a bit of a state machine to deal with multi-step updates.. although that makes races more of a problem, which was something I was trying hard to avoid. For enabling/disabling an output (manager+encoder), this is relatively infrequent, so it can afford to block to avoid races. (Like userspace enabling and then rapidly disabling an output part way through the enable.) But enabling/disabling an overlay, or adjusting position or scanout address must not block. And ideally, if possible, switching an overlay between two managers should not block. For fifomerge, if I understand correctly, it shouldn't really be needed for functionality, but mainly as a power optimization? If this is the case I wonder about an approach of disabling fifomerge when there are ongoing setting changes, and then setting it after things settle down? I'll have to think about it, but I was trying to avoid needing a multi-step state machine to avoid the associated race conditions, but if this is not possible then it is not possible. I didn't write omapdss's apply.c for fun or to make omapfb simpler. I made it because the shadow register system is complex, and we need to handle the tricky cases somewhere. So, as I said before, I believe you'll just end up writing similar code to what is currently in apply.c. It won't be as simple as your current branch. Also, as I mentioned earlier, you'll also need to handle the output side of the shadow registers. These come from the output drivers (DPI, DSI, etc, and indirectly from panel drivers). They are not currently handled in the best manner in omapdss, but Archit is working on that and in his
Re: [RFC 0/3] solving omapdrm/omapdss layering issues
On Wed, Aug 1, 2012 at 11:46 AM, Archit Taneja arc...@ti.com wrote: Hi, On Wednesday 01 August 2012 07:55 PM, Rob Clark wrote: On Wed, Aug 1, 2012 at 4:21 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Tue, 2012-07-31 at 09:45 -0500, Rob Clark wrote: On Tue, Jul 31, 2012 at 8:40 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: It's not really about being friendly. Omapdss tries to do as little as possible, while still supporting all its HW features. Shadow registers are a bit tricky creating this mess. What I mean by 'friendly' is it tries to abstract this for simple users, like an fbdev driver. But this really quickly breaks down w/ a No, that's not what omapdss tries to do. I'm not trying to hide the shadow registers and the GO bit behind the omapdss API, I'm just trying to make it work. The omapdss API was made with omapfb, so it's true that the API may not be good for omapdrm. But I'm happy to change the API. And btw, I think the current mapping of drm_encoder to mgr in omapdrm is not correct. I'm just in the process of shuffling things around. I think drm/kms actually maps quite nicely to the underlying hardware with the following arrangement: drm_plane - ovl drm_crtc - mgr drm_encoder - DSI/DPI/HDMI/VENC encoder drm_connector - pretty much what we call a panel driver today Hmm, what was the arrangement earlier? it was previously: plane - ovl crtc - placeholder encoder - mgr connector - dssdev (encoder+panel) although crtc is really the point where you should enable/disable vblank irqs, so the new arrangement is somewhat cleaner (although on my branch the encoder/connector part are not finished yet) I guess the fact is that DRM concepts do not really match the OMAP DSS hardware, and we'll have to use whatever gives us least problems. Actually, I think it does map fairly well to the hardware.. at least more so than to omapdss ;-) The one area that kms mismatches a bit is decoupling of ovl from mgr that we have in our hw.. I've partially solved that a while back w/ the patch in drm to add private planes so the omap_crtc internally uses an omap_plane. It isn't exposed to userspace to be able to re-use the planes from unused crtcs, although I have some ideas about that (but not yet time to work on it). It would be quite useful if you could look at the omap_drm_apply mechanism I had in omapdrm, because that seems like a quite straightforward way to deal w/ shadowed registers. I think it will Yes, it seems straightforward, but it's not =). I had a look at your omapdrm-on-dispc-2 branch. What you are doing there is quite similar to what omapdss was doing earlier. It's not going to work reliably with multiple outputs and fifomerge. Configuring things like overlay color mode are quite simple. They only affect that one overlay. Also things like manager default bg color are simple, they affect only that one manager. But enabling/disabling an overlay or a manager, changing the destination mgr of an overlay, fifomerge... Those are not simple. You can't do them directly, as you do in your branch. As an example, consider the case of enabling an overlay (vid1), and moving fifo buffers from currently enabled overlay (gfx) to vid1: you'll first need to take the fifo buffers from gfx, set GO, and wait for the settings to take effect. Only then you can set the fifo buffers for vid1, enable it and set GO bit. hmm, it does sound like it needs a bit of a state machine to deal with multi-step updates.. although that makes races more of a problem, which was something I was trying hard to avoid. For enabling/disabling an output (manager+encoder), this is relatively infrequent, so it can afford to block to avoid races. (Like userspace enabling and then rapidly disabling an output part way through the enable.) But enabling/disabling an overlay, or adjusting position or scanout address must not block. And ideally, if possible, switching an overlay between two managers should not block. For fifomerge, if I understand correctly, it shouldn't really be needed for functionality, but mainly as a power optimization? If this is the case I wonder about an approach of disabling fifomerge when there are ongoing setting changes, and then setting it after things settle down? I'll have to think about it, but I was trying to avoid needing a multi-step state machine to avoid the associated race conditions, but if this is not possible then it is not possible. I didn't write omapdss's apply.c for fun or to make omapfb simpler. I made it because the shadow register system is complex, and we need to handle the tricky cases somewhere. So, as I said before, I believe you'll just end up writing similar code to what is currently in apply.c. It won't be as simple as your current branch. Also, as I mentioned earlier, you'll also need to handle the output side of the shadow registers. These come from
Re: [RFC 0/3] solving omapdrm/omapdss layering issues
On Wed, Aug 1, 2012 at 11:53 AM, Rob Clark rob.cl...@linaro.org wrote: On Wed, Aug 1, 2012 at 11:46 AM, Archit Taneja arc...@ti.com wrote: Hi, On Wednesday 01 August 2012 07:55 PM, Rob Clark wrote: On Wed, Aug 1, 2012 at 4:21 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Tue, 2012-07-31 at 09:45 -0500, Rob Clark wrote: On Tue, Jul 31, 2012 at 8:40 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: It's not really about being friendly. Omapdss tries to do as little as possible, while still supporting all its HW features. Shadow registers are a bit tricky creating this mess. What I mean by 'friendly' is it tries to abstract this for simple users, like an fbdev driver. But this really quickly breaks down w/ a No, that's not what omapdss tries to do. I'm not trying to hide the shadow registers and the GO bit behind the omapdss API, I'm just trying to make it work. The omapdss API was made with omapfb, so it's true that the API may not be good for omapdrm. But I'm happy to change the API. And btw, I think the current mapping of drm_encoder to mgr in omapdrm is not correct. I'm just in the process of shuffling things around. I think drm/kms actually maps quite nicely to the underlying hardware with the following arrangement: drm_plane - ovl drm_crtc - mgr drm_encoder - DSI/DPI/HDMI/VENC encoder drm_connector - pretty much what we call a panel driver today Hmm, what was the arrangement earlier? it was previously: plane - ovl crtc - placeholder encoder - mgr connector - dssdev (encoder+panel) although crtc is really the point where you should enable/disable vblank irqs, so the new arrangement is somewhat cleaner (although on my branch the encoder/connector part are not finished yet) I guess the fact is that DRM concepts do not really match the OMAP DSS hardware, and we'll have to use whatever gives us least problems. Actually, I think it does map fairly well to the hardware.. at least more so than to omapdss ;-) The one area that kms mismatches a bit is decoupling of ovl from mgr that we have in our hw.. I've partially solved that a while back w/ the patch in drm to add private planes so the omap_crtc internally uses an omap_plane. It isn't exposed to userspace to be able to re-use the planes from unused crtcs, although I have some ideas about that (but not yet time to work on it). It would be quite useful if you could look at the omap_drm_apply mechanism I had in omapdrm, because that seems like a quite straightforward way to deal w/ shadowed registers. I think it will Yes, it seems straightforward, but it's not =). I had a look at your omapdrm-on-dispc-2 branch. What you are doing there is quite similar to what omapdss was doing earlier. It's not going to work reliably with multiple outputs and fifomerge. Configuring things like overlay color mode are quite simple. They only affect that one overlay. Also things like manager default bg color are simple, they affect only that one manager. But enabling/disabling an overlay or a manager, changing the destination mgr of an overlay, fifomerge... Those are not simple. You can't do them directly, as you do in your branch. As an example, consider the case of enabling an overlay (vid1), and moving fifo buffers from currently enabled overlay (gfx) to vid1: you'll first need to take the fifo buffers from gfx, set GO, and wait for the settings to take effect. Only then you can set the fifo buffers for vid1, enable it and set GO bit. hmm, it does sound like it needs a bit of a state machine to deal with multi-step updates.. although that makes races more of a problem, which was something I was trying hard to avoid. For enabling/disabling an output (manager+encoder), this is relatively infrequent, so it can afford to block to avoid races. (Like userspace enabling and then rapidly disabling an output part way through the enable.) But enabling/disabling an overlay, or adjusting position or scanout address must not block. And ideally, if possible, switching an overlay between two managers should not block. For fifomerge, if I understand correctly, it shouldn't really be needed for functionality, but mainly as a power optimization? If this is the case I wonder about an approach of disabling fifomerge when there are ongoing setting changes, and then setting it after things settle down? I'll have to think about it, but I was trying to avoid needing a multi-step state machine to avoid the associated race conditions, but if this is not possible then it is not possible. I didn't write omapdss's apply.c for fun or to make omapfb simpler. I made it because the shadow register system is complex, and we need to handle the tricky cases somewhere. So, as I said before, I believe you'll just end up writing similar code to what is currently in apply.c. It won't be as simple as your current branch. Also, as I mentioned earlier, you'll also
Re: [PATCH] staging: drm/omap: remove reclaim_buffers callback
On Wed, Aug 1, 2012 at 8:20 AM, Chandrabhanu Mahapatra cmahapa...@ti.com wrote: The reclaim_buffers callback has already been removed by Daniel Vetter daniel.vet...@ffwll.ch with his patch drm: kill reclaim_buffers callback (b0071efe82). As a result the kernel compilation fails with omapdrm support and so the callback for reclaim_buffers is being removed from omapdrm. Signed-off-by: Chandrabhanu Mahapatra cmahapa...@ti.com Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_drv.c |1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 342645a..b8e79eb 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -778,7 +778,6 @@ static struct drm_driver omap_drm_driver = { .irq_postinstall = dev_irq_postinstall, .irq_uninstall = dev_irq_uninstall, .irq_handler = dev_irq_handler, - .reclaim_buffers = drm_core_reclaim_buffers, #ifdef CONFIG_DEBUG_FS .debugfs_init = omap_debugfs_init, .debugfs_cleanup = omap_debugfs_cleanup, -- 1.7.10 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 0/3] solving omapdrm/omapdss layering issues
On Wed, Aug 1, 2012 at 12:38 PM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Wed, 2012-08-01 at 11:53 -0500, Rob Clark wrote: Ok.. this would help. I'll take a look. I do request that interfaces/panels don't set any mgr/timing related registers. I had to comment all this stuff out in my prototype. Really we want to set the timings separately on the crtc (mgr) / encoder (interface) / connector (panel.. not sure if it is needed, though?). KMS will take care of propagating the timings through the pipeline. If we only had auto-update displays, and only the video timings were shadow register, it'd work. Unfortunately we have other registers as shadow registers also, like DISPC_CONTROL1, DISPC_CONFIG1 and DISPC_DIVISOR1. well, I was kinda thinking we just do all the register access from the corresponding crtc (mgr)'s GO/apply sequencing.. so if, for example, you change resolution, then the plane, crtc, encoder, panel all queue up via omap_crtc_apply() on their associated crtc, and then at the right time from pre_apply() fxns call the appropriate omapdss/dispc function(s) for register updates. I think that would work well for everything but mgr enable/disable (which is infrequent, so ok to block for a few vblanks), and fifomerge, which I'm a bit on the fence about. But we should think if this could be somehow be changed, so that all the shadow register info would come from one place. I do find it a bit unlikely with a quick thought, though. Well, hmm. Perhaps... Omapdrm (or omapfb etc) doesn't really need to know about the values of those registers, it just needs to control the GO bit. So perhaps if we had some method to inform omapdrm that these things have changed, and omapdrm would then set the GO bit as soon as possible. Well, what I'm doing now is basically, if I update anything in any of the omap_*_info structs, I schedule an apply, and from pre_apply callback push the changes down to dispc.. I was thinking to follow the same for encoder and probably connector. (Not sure if doing things like setting timings at hdmi need to be GO bit sync'd? Maybe this could be bypassed for the connector, but if not it is easy enough just to use the same mechanism that the plane/crtc/encoder are already using.) But there are some tricky stuff, like the divisors... Well, we need to think about this. I think, if I understand properly, the most tricky thing is the shared clocks.. although I'm not really sure if we can actually change things like the core clock when you plug in a 2nd display w/out loosing sync on the first? That's seems like a tricky thing either way. Anything else, that is only effecting a single crtc-encoder-connector chain can have register programming sync'd to that mgr's GO bit. BR, -R Tomi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 0/3] solving omapdrm/omapdss layering issues
On Tue, Jul 31, 2012 at 8:40 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: Hi, On Fri, 2012-07-27 at 20:07 -0500, Rob Clark wrote: From: Rob Clark r...@ti.com I've been working for the better part of the week on solving some of the omapdss vs kms mismatches, which is one of the bigger remaining issues in the TODO before moving omapdrm out of staging. The biggest place that this shows up is in GO bit handling. Basically, some of the scanout related registers in DSS hw block are only shadow registers, and if the GO bit is set during the vblank the hw copies into the actual registers (not accessible to CPU) and clears the GO bit. When the GO bit is set, there is no safe way to update these registers without undefined results. So omapdss tries to be friendly and abstract this, by buffering up the updated state, and applying it It's not really about being friendly. Omapdss tries to do as little as possible, while still supporting all its HW features. Shadow registers are a bit tricky creating this mess. What I mean by 'friendly' is it tries to abstract this for simple users, like an fbdev driver. But this really quickly breaks down w/ a more sophisticated user. Which is why I've been more in favor of making omapdss less of a layer. The idea of using it as some helper functions which handle a bit the variation of different generations of hw while not abstracting the fundamental operating concepts of DSS IP block (ie. GO bit stuff) seems perfect to me. So dispc plus dss_feature stuff seems like just what I'm looking for. on the next vblank once the GO bit is cleared. But this causes all sorts of mayhem at the omapdrm layer, which would like to unpin the previous scanout buffer(s) on the next vblank (or endwin) irq. Due to the buffering in omapdss, we have no way to know on a vblank if we have switched to the scanout buffer or not. Basically it works ok as long as userspace is only ever updating on layer (either crtc or drm plane) at a time. But throw together hw mouse cursor (drm plane) plus a window manager like compiz which does page flips, or wayland (weston drm compositor) with hw composition (drm plane), and things start to fail in a big way. I've tried a few approaches to preserve the omapdss more or less as it is, by adding callbacks for when GO bit is cleared, etc. But the sequencing of setting up connector/encoder/crtc is not really what omapdss expects, and would generally end up confusing the apply layer in omapdss (it would end up not programming various registers because various dirty flags would get cleared, for example mgr updated before overlay connected, etc). Can you give more info what the problem is? It shouldn't end up not programming registers, except if there's a bug there. Yeah, it is probably just a bug.. and a bug could be fixed. But with all that extra code it is certainly a lot harder to debug. So 'could' and 'should' are maybe two different things. Didn't the apply-id stuff I proposed some months ago have enough stuff to make this work? I guess the approach I was trying was similar to that proposal.. it probably could be made to work. But I am really not a big fan of unnecessary complexity. And unnecessary layering adds complexity. This is why in general most of the drm folks have preferred an approach of helper fxns rather than layers. And I tend to agree with them. The thing about shadow registers is that we need to manage them in one central place. And the same shadow registers are used for both the composition stuff (overlays etc) and output stuff (video timings configuration). If omapdrm handles the composition shadow registers, it also needs to handle all the other shadow registers. Yup.. I'm handling it in a central place :-) basically all the register programming is coming through the 'struct omap_drm_apply' mechanism, so it is all aligned to vblank/framedone and GO bit status. So probably that isn't strictly needed, because I'm treating all registers as shadow'd registers, but that seemed like a clean approach. Finally, in frustration, this afternoon I hit upon an idea. Why not just use the dispc code in omapdss, which is basically a stateless layer of helper functions, and bypass the stateful layer of omapdss. If you do this, you'll need to implement all the stuff of the stateful layer in omapdrm. You can't just call the dispc funcs and expect things to work reliably. Things like enabling/disabling overlays with fifomerge requires possibly multiple vsyncs. And output related shadow registers may be changed separately from the composition side. All the dispc fxn calls (except whatever is done directly from the 'omap_dss_device', which I haven't converted over yet) are done synchronized to the ovl mgrs GO bit. I haven't hooked up fifomerge yet, although looking at the apply code in omapdss, that looks like it should be pretty straightforward to hook into the same omap_drm_apply mechanism
[PATCH] drm: refcnt drm_framebuffer
From: Rob Clark r...@ti.com This simplifies drm fb lifetime, and if the crtc/plane needs to hold a ref to the fb when disabling a pipe until the next vblank, this avoids the need to make disabling an overlay synchronous. This is a problem that shows up when userspace is using a drm plane to implement a hw cursor.. making overlay disable synchronous causes a performance problem when x11 is rapidly enabling/disabling the hw cursor. But not making it synchronous opens up a race condition for crashing if userspace turns around and immediately deletes the fb. Refcnt'ing the fb makes it possible to solve this problem. Signed-off-by: Rob Clark r...@ti.com --- drivers/gpu/drm/drm_crtc.c| 38 ++--- drivers/gpu/drm/exynos/exynos_drm_fbdev.c |4 +-- drivers/gpu/drm/i915/intel_display.c |4 +-- include/drm/drm_crtc.h|4 +++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 08a7aa7..2f928a3 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -294,6 +294,8 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, { int ret; + kref_init(fb-refcount); + ret = drm_mode_object_get(dev, fb-base, DRM_MODE_OBJECT_FB); if (ret) return ret; @@ -307,6 +309,36 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, } EXPORT_SYMBOL(drm_framebuffer_init); +static void drm_framebuffer_free(struct kref *kref) +{ + struct drm_framebuffer *fb = + container_of(kref, struct drm_framebuffer, refcount); + fb-funcs-destroy(fb); +} + +/** + * drm_framebuffer_unreference - unref a framebuffer + * + * LOCKING: + * Caller must hold mode config lock. + */ +void drm_framebuffer_unreference(struct drm_framebuffer *fb) +{ + struct drm_device *dev = fb-dev; + WARN_ON(!mutex_is_locked(dev-mode_config.mutex)); + kref_put(fb-refcount, drm_framebuffer_free); +} +EXPORT_SYMBOL(drm_framebuffer_unreference); + +/** + * drm_framebuffer_reference - incr the fb refcnt + */ +void drm_framebuffer_reference(struct drm_framebuffer *fb) +{ + kref_get(fb-refcount); +} +EXPORT_SYMBOL(drm_framebuffer_reference); + /** * drm_framebuffer_cleanup - remove a framebuffer object * @fb: framebuffer to remove @@ -1031,7 +1063,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) } list_for_each_entry_safe(fb, fbt, dev-mode_config.fb_list, head) { - fb-funcs-destroy(fb); + drm_framebuffer_unreference(fb); } list_for_each_entry_safe(crtc, ct, dev-mode_config.crtc_list, head) { @@ -2339,7 +2371,7 @@ int drm_mode_rmfb(struct drm_device *dev, /* TODO unhock the destructor from the buffer object */ list_del(fb-filp_head); - fb-funcs-destroy(fb); + drm_framebuffer_unreference(fb); out: mutex_unlock(dev-mode_config.mutex); @@ -2490,7 +2522,7 @@ void drm_fb_release(struct drm_file *priv) mutex_lock(dev-mode_config.mutex); list_for_each_entry_safe(fb, tfb, priv-fbs, filp_head) { list_del(fb-filp_head); - fb-funcs-destroy(fb); + drm_framebuffer_unreference(fb); } mutex_unlock(dev-mode_config.mutex); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index d5586cc..05695d6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -266,8 +266,8 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev, /* release drm framebuffer and real buffer */ if (fb_helper-fb fb_helper-fb-funcs) { fb = fb_helper-fb; - if (fb fb-funcs-destroy) - fb-funcs-destroy(fb); + if (fb) + drm_framebuffer_unreference(fb); } /* release linux framebuffer */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a8538ac..a9d2328 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5467,7 +5467,7 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) { DRM_DEBUG_KMS(failed to set mode on load-detect pipe\n); if (old-release_fb) - old-release_fb-funcs-destroy(old-release_fb); + drm_framebuffer_unreference(old-release_fb); crtc-fb = old_fb; return false; } @@ -5497,7 +5497,7 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, drm_helper_disable_unused_functions(dev); if (old-release_fb) - old-release_fb-funcs
Re: [PATCH] drm: refcnt drm_framebuffer
On Tue, Jul 31, 2012 at 12:00 PM, Chris Wilson ch...@chris-wilson.co.uk wrote: On Tue, 31 Jul 2012 11:20:21 -0500, Rob Clark rob.cl...@linaro.org wrote: From: Rob Clark r...@ti.com This simplifies drm fb lifetime, and if the crtc/plane needs to hold a ref to the fb when disabling a pipe until the next vblank, this avoids the need to make disabling an overlay synchronous. This is a problem that shows up when userspace is using a drm plane to implement a hw cursor.. making overlay disable synchronous causes a performance problem when x11 is rapidly enabling/disabling the hw cursor. But not making it synchronous opens up a race condition for crashing if userspace turns around and immediately deletes the fb. Refcnt'ing the fb makes it possible to solve this problem. Presumably you have a follow-on patch putting the new refcnt to use so that we can judge whether you truly need refcnting on the fb itself in addition to the refcnted object and the various hw bookkeeping that needs to be performed? Yes, I do.. although it is a bit experimental at this point, so not really ready to be submitted as anything other than an RFC.. it is part of omapdrm kms re-write to use dispc directly rather than go thru omapdss. (With omapdss we don't hit this issue because disabling overlays is forced to be synchronous.. so instead we have the performance problem I mentioned.) I *could* just rely on the GEM refcnt, but that gets messier when you take into account multi-planar formats. I suppose I also could have my own internal refcnt'd object to hold the set of GEM objects associated w/ the fb, but, well, that seems a bit silly. And refcnt'ing the fb had been mentioned previously as a good thing to do (I think it was danvet?) BR, -R -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ dri-devel mailing list dri-de...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm: refcnt drm_framebuffer
On Tue, Jul 31, 2012 at 12:47 PM, Chris Wilson ch...@chris-wilson.co.uk wrote: On Tue, 31 Jul 2012 12:41:28 -0500, Rob Clark rob.cl...@linaro.org wrote: On Tue, Jul 31, 2012 at 12:00 PM, Chris Wilson ch...@chris-wilson.co.uk wrote: On Tue, 31 Jul 2012 11:20:21 -0500, Rob Clark rob.cl...@linaro.org wrote: From: Rob Clark r...@ti.com This simplifies drm fb lifetime, and if the crtc/plane needs to hold a ref to the fb when disabling a pipe until the next vblank, this avoids the need to make disabling an overlay synchronous. This is a problem that shows up when userspace is using a drm plane to implement a hw cursor.. making overlay disable synchronous causes a performance problem when x11 is rapidly enabling/disabling the hw cursor. But not making it synchronous opens up a race condition for crashing if userspace turns around and immediately deletes the fb. Refcnt'ing the fb makes it possible to solve this problem. Presumably you have a follow-on patch putting the new refcnt to use so that we can judge whether you truly need refcnting on the fb itself in addition to the refcnted object and the various hw bookkeeping that needs to be performed? Yes, I do.. although it is a bit experimental at this point, so not really ready to be submitted as anything other than an RFC.. it is part of omapdrm kms re-write to use dispc directly rather than go thru omapdss. (With omapdss we don't hit this issue because disabling overlays is forced to be synchronous.. so instead we have the performance problem I mentioned.) I *could* just rely on the GEM refcnt, but that gets messier when you take into account multi-planar formats. I suppose I also could have my own internal refcnt'd object to hold the set of GEM objects associated w/ the fb, but, well, that seems a bit silly. And refcnt'ing the fb had been mentioned previously as a good thing to do (I think it was danvet?) Sure, there are a few places in the code that have caused ordering issues in the past due to lack of refcnting the fb... But since you haven't fixed up those cases, I'm looking for justification for adding that extra bit of complexity. Adding a new interface and no users is just asking for trouble. fwiw, my line of reasoning was: from userspace perspective, once you do drm_mode_rmfb(), the fb is gone, so I didn't change where it gets removed from the list of fb's or anything like that. Instead I just left it so that a driver could, if it wants, take an extra ref temporarily to the fb to keep it around for a bit. I didn't change any of the existing drivers, other than update the to call drm_framebuffer_unreference() instead of fb-funcs-delete() directly, because I didn't want to break anything in existing drivers, and I figured the new behavior was better as an opt-in by individual drivers when they want to take advantage of refcnt'ing. But if you have suggestions about related cleanups that should be made, I'm willing to take that on. Anyways, like I mentioned, I'm still a little ways from being ready to submit anything other than RFC patches in omapdrm to use fb refcnt'ing, so this isn't something that needs to be merged immediately. But it seemed like low risk and like it would be something that other drivers could take advantage of, so I figured it was worth sending this patch now. BR, -R -Chris -- Chris Wilson, Intel Open Source Technology Centre -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drm: refcnt drm_framebuffer
On Tue, Jul 31, 2012 at 12:47 PM, Chris Wilson ch...@chris-wilson.co.uk wrote: On Tue, 31 Jul 2012 12:41:28 -0500, Rob Clark rob.cl...@linaro.org wrote: On Tue, Jul 31, 2012 at 12:00 PM, Chris Wilson ch...@chris-wilson.co.uk wrote: On Tue, 31 Jul 2012 11:20:21 -0500, Rob Clark rob.cl...@linaro.org wrote: From: Rob Clark r...@ti.com This simplifies drm fb lifetime, and if the crtc/plane needs to hold a ref to the fb when disabling a pipe until the next vblank, this avoids the need to make disabling an overlay synchronous. This is a problem that shows up when userspace is using a drm plane to implement a hw cursor.. making overlay disable synchronous causes a performance problem when x11 is rapidly enabling/disabling the hw cursor. But not making it synchronous opens up a race condition for crashing if userspace turns around and immediately deletes the fb. Refcnt'ing the fb makes it possible to solve this problem. Presumably you have a follow-on patch putting the new refcnt to use so that we can judge whether you truly need refcnting on the fb itself in addition to the refcnted object and the various hw bookkeeping that needs to be performed? Yes, I do.. although it is a bit experimental at this point, so not really ready to be submitted as anything other than an RFC.. it is part of omapdrm kms re-write to use dispc directly rather than go thru omapdss. (With omapdss we don't hit this issue because disabling overlays is forced to be synchronous.. so instead we have the performance problem I mentioned.) I *could* just rely on the GEM refcnt, but that gets messier when you take into account multi-planar formats. I suppose I also could have my own internal refcnt'd object to hold the set of GEM objects associated w/ the fb, but, well, that seems a bit silly. And refcnt'ing the fb had been mentioned previously as a good thing to do (I think it was danvet?) Sure, there are a few places in the code that have caused ordering issues in the past due to lack of refcnting the fb... But since you haven't fixed up those cases, I'm looking for justification for adding that extra bit of complexity. Adding a new interface and no users is just asking for trouble. hmm, I did realize that drm_plane cleanup only happens as a result of drm_framebuffer_cleanup().. which doesn't work too well if the driver is holding a ref to the fb :-/ so I guess at a minimum I need to fix plane cleanup to be part of drm_fb_helper_restore_fbdev_mode() BR, -R -Chris -- Chris Wilson, Intel Open Source Technology Centre -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 0/3] solving omapdrm/omapdss layering issues
From: Rob Clark r...@ti.com I've been working for the better part of the week on solving some of the omapdss vs kms mismatches, which is one of the bigger remaining issues in the TODO before moving omapdrm out of staging. The biggest place that this shows up is in GO bit handling. Basically, some of the scanout related registers in DSS hw block are only shadow registers, and if the GO bit is set during the vblank the hw copies into the actual registers (not accessible to CPU) and clears the GO bit. When the GO bit is set, there is no safe way to update these registers without undefined results. So omapdss tries to be friendly and abstract this, by buffering up the updated state, and applying it on the next vblank once the GO bit is cleared. But this causes all sorts of mayhem at the omapdrm layer, which would like to unpin the previous scanout buffer(s) on the next vblank (or endwin) irq. Due to the buffering in omapdss, we have no way to know on a vblank if we have switched to the scanout buffer or not. Basically it works ok as long as userspace is only ever updating on layer (either crtc or drm plane) at a time. But throw together hw mouse cursor (drm plane) plus a window manager like compiz which does page flips, or wayland (weston drm compositor) with hw composition (drm plane), and things start to fail in a big way. I've tried a few approaches to preserve the omapdss more or less as it is, by adding callbacks for when GO bit is cleared, etc. But the sequencing of setting up connector/encoder/crtc is not really what omapdss expects, and would generally end up confusing the apply layer in omapdss (it would end up not programming various registers because various dirty flags would get cleared, for example mgr updated before overlay connected, etc). Finally, in frustration, this afternoon I hit upon an idea. Why not just use the dispc code in omapdss, which is basically a stateless layer of helper functions, and bypass the stateful layer of omapdss. Since KMS helper functions already give us the correct sequence for setting up the hardware, this turned out to be rather easy. And fit it quite nicely with my mechanism to queue up updates when the GO bit is not clear. And, unlike my previous attempts, it actually worked.. not only that, but it worked on the first boot! So I am pretty happy about how this is shaping up. Not only is it simpler that my previous attepmts, and solves a few tricky buffer unpin related issues. But it also makes it very easy to wire in the missing userspace vblank event handling without resorting to duct- tape. Obviously there is stuff still missing, and some hacks. This is really just a proof of concept at this stage. But I wanted to send an RFC so we could start discussing how to move forward. Ie. could we reasonably add support to build dispc as a library of stateless helper functions, sharing it and the panel drivers between omapdrm and the legacy omapdss based drivers. Or is there no clean way to do that, in which case we should just copy the code we need into omapdrm, and leave the deprecated omapdss as it is for legacy drivers. Rob Clark (3): OMAPDSS: expose dispc for use from omapdrm omap2+: use dss_dispc hwmod for omapdrm drm/omap: use dispc directly arch/arm/mach-omap2/drm.c| 24 +- drivers/staging/omapdrm/Makefile |1 + drivers/staging/omapdrm/omap_connector.c | 20 +- drivers/staging/omapdrm/omap_crtc.c | 42 ++-- drivers/staging/omapdrm/omap_drv.c | 70 +- drivers/staging/omapdrm/omap_drv.h | 64 - drivers/staging/omapdrm/omap_encoder.c | 213 ++--- drivers/staging/omapdrm/omap_irq.c | 133 +++ drivers/staging/omapdrm/omap_plane.c | 382 +- drivers/video/omap2/dss/apply.c |4 +- drivers/video/omap2/dss/dispc.c | 76 -- drivers/video/omap2/dss/dss.h|2 + drivers/video/omap2/dss/hdmi.c | 18 +- 13 files changed, 628 insertions(+), 421 deletions(-) create mode 100644 drivers/staging/omapdrm/omap_irq.c -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 1/3] OMAPDSS: expose dispc for use from omapdrm
From: Rob Clark r...@ti.com Not very clean, just for proof of concept. Signed-off-by: Rob Clark r...@ti.com --- drivers/video/omap2/dss/apply.c |4 ++- drivers/video/omap2/dss/dispc.c | 76 ++- drivers/video/omap2/dss/dss.h |2 ++ drivers/video/omap2/dss/hdmi.c | 18 +- 4 files changed, 73 insertions(+), 27 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index ab22cc2..c9a9b80 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -699,6 +699,8 @@ static void dss_write_regs(void) static void dss_set_go_bits(void) { + dump_stack(); +#if 0 const int num_mgrs = omap_dss_get_num_overlay_managers(); int i; @@ -722,7 +724,7 @@ static void dss_set_go_bits(void) dispc_mgr_go(mgr-id); } - +#endif } static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index e6ea47e..bdb0bde 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -352,7 +352,7 @@ static void dispc_restore_context(void) if (dss_has_feature(FEAT_MGR_LCD2)) RR(CONTROL2); /* clear spurious SYNC_LOST_DIGIT interrupts */ - dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); + dispc_clear_irqs(DISPC_IRQ_SYNC_LOST_DIGIT); /* * enable last so IRQs won't trigger before @@ -376,6 +376,7 @@ int dispc_runtime_get(void) WARN_ON(r 0); return r 0 ? r : 0; } +EXPORT_SYMBOL_GPL(dispc_runtime_get); void dispc_runtime_put(void) { @@ -386,6 +387,7 @@ void dispc_runtime_put(void) r = pm_runtime_put_sync(dispc.pdev-dev); WARN_ON(r 0 r != -ENOSYS); } +EXPORT_SYMBOL_GPL(dispc_runtime_put); static inline bool dispc_mgr_is_lcd(enum omap_channel channel) { @@ -410,6 +412,7 @@ u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) return 0; } } +EXPORT_SYMBOL_GPL(dispc_mgr_get_vsync_irq); u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) { @@ -440,6 +443,7 @@ bool dispc_mgr_go_busy(enum omap_channel channel) else return REG_GET(DISPC_CONTROL, bit, bit) == 1; } +EXPORT_SYMBOL_GPL(dispc_mgr_go_busy); void dispc_mgr_go(enum omap_channel channel) { @@ -483,6 +487,7 @@ void dispc_mgr_go(enum omap_channel channel) else REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); } +EXPORT_SYMBOL_GPL(dispc_mgr_go); static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) { @@ -844,6 +849,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) } dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); } +EXPORT_SYMBOL_GPL(dispc_ovl_set_channel_out); static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) { @@ -2236,6 +2242,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, return 0; } +EXPORT_SYMBOL_GPL(dispc_ovl_setup); int dispc_ovl_enable(enum omap_plane plane, bool enable) { @@ -2256,6 +2263,7 @@ static void dispc_disable_isr(void *data, u32 mask) struct completion *compl = data; complete(compl); } +EXPORT_SYMBOL_GPL(dispc_ovl_enable); static void _enable_lcd_out(enum omap_channel channel, bool enable) { @@ -2318,6 +2326,10 @@ static void _enable_digit_out(bool enable) dispc_read_reg(DISPC_CONTROL); } +/* TODO revisit how this and dispc_mgr_enable_lcd_out() should + * work w/ omapdrm handling the irqs.. ideally we'd just have + * a dispc helper fxn to call from the omapdrm irq handling. + */ static void dispc_mgr_enable_digit_out(bool enable) { struct completion frame_done_completion; @@ -2381,7 +2393,7 @@ static void dispc_mgr_enable_digit_out(bool enable) unsigned long flags; spin_lock_irqsave(dispc.irq_lock, flags); dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT; - dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); + dispc_clear_irqs(DISPC_IRQ_SYNC_LOST_DIGIT); _omap_dispc_set_irqs(); spin_unlock_irqrestore(dispc.irq_lock, flags); } @@ -2410,6 +2422,7 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable) else BUG(); } +EXPORT_SYMBOL_GPL(dispc_mgr_enable); void dispc_lcd_enable_signal_polarity(bool act_high) { @@ -2529,6 +2542,7 @@ void dispc_mgr_setup(enum omap_channel channel, dispc_mgr_set_cpr_coef(channel, info-cpr_coefs); } } +EXPORT_SYMBOL_GPL(dispc_mgr_setup); void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) { @@ -2705,6 +2719,7 @@ void dispc_mgr_set_timings(enum omap_channel channel, dispc_mgr_set_size(channel, t.x_res, t.y_res); } +EXPORT_SYMBOL_GPL
[RFC 2/3] omap2+: use dss_dispc hwmod for omapdrm
From: Rob Clark r...@ti.com We need this so that platform_get_irq() works when drm core sets up the irq handling. Signed-off-by: Rob Clark r...@ti.com --- arch/arm/mach-omap2/drm.c | 24 +++- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c index 4ab7b6a..f7a2444 100644 --- a/arch/arm/mach-omap2/drm.c +++ b/arch/arm/mach-omap2/drm.c @@ -33,18 +33,6 @@ #include plat/drm.h #if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE) - -static struct omap_drm_platform_data omapdrm_platdata; - -static struct platform_device omap_drm_device = { - .dev = { - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = omapdrm_platdata, - }, - .name = omapdrm, - .id = 0, -}; - static int __init omap_init_drm(void) { struct omap_hwmod *oh = NULL; @@ -60,8 +48,16 @@ static int __init omap_init_drm(void) oh-name); } - return platform_device_register(omap_drm_device); + /* lookup and populate DSS information: */ + oh = omap_hwmod_lookup(dss_dispc); + pdev = omap_device_build(omapdrm, -1, oh, NULL, 0, NULL, 0, + false); + WARN(IS_ERR(pdev), Could not build omap_device for omapdrm\n); + if (!pdev) + return -EINVAL; + + return 0; } arch_initcall(omap_init_drm); @@ -69,12 +65,14 @@ arch_initcall(omap_init_drm); void __init omapdrm_reserve_vram(void) { #ifdef CONFIG_CMA +#if 0 /* TODO add this back for omap3 */ /* * Create private 32MiB contiguous memory area for omapdrm.0 device * TODO revisit size.. if uc/wc buffers are allocated from CMA pages * then the amount of memory we need goes up.. */ dma_declare_contiguous(omap_drm_device.dev, 32 * SZ_1M, 0, 0); +#endif #else # warning CMA is not enabled, there may be limitations about scanout buffer allocations on OMAP3 and earlier #endif -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 3/3] drm/omap: use dispc directly
From: Rob Clark r...@ti.com This is still work in progress, but it nicely solves the omapdss vs drm impedence mismatches, and properly fixes unpin confusion vs GO bit status. As an added bonus, we also no longer leave the last overlay buffer pinned. Adding the previously missing vblank event handling for userspace should be pretty trivial now too. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/Makefile |1 + drivers/staging/omapdrm/omap_connector.c | 20 +- drivers/staging/omapdrm/omap_crtc.c | 42 ++-- drivers/staging/omapdrm/omap_drv.c | 70 +- drivers/staging/omapdrm/omap_drv.h | 64 - drivers/staging/omapdrm/omap_encoder.c | 213 ++--- drivers/staging/omapdrm/omap_irq.c | 133 +++ drivers/staging/omapdrm/omap_plane.c | 382 +- 8 files changed, 544 insertions(+), 381 deletions(-) create mode 100644 drivers/staging/omapdrm/omap_irq.c diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile index 1ca0e00..d85e058 100644 --- a/drivers/staging/omapdrm/Makefile +++ b/drivers/staging/omapdrm/Makefile @@ -5,6 +5,7 @@ ccflags-y := -Iinclude/drm -Werror omapdrm-y := omap_drv.o \ + omap_irq.o \ omap_debugfs.o \ omap_crtc.o \ omap_plane.o \ diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5e2856c..577ae32 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -284,16 +284,17 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = { }; /* called from encoder when mode is set, to propagate settings to the dssdev */ -void omap_connector_mode_set(struct drm_connector *connector, - struct drm_display_mode *mode) +int omap_connector_mode_set(struct drm_connector *connector, + struct drm_display_mode *mode, + struct omap_video_timings *timings) { struct drm_device *dev = connector-dev; struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector-dssdev; struct omap_dss_driver *dssdrv = dssdev-driver; - struct omap_video_timings timings; + int ret; - copy_timings_drm_to_omap(timings, mode); + copy_timings_drm_to_omap(timings, mode); DBG(%s: set mode: %d:\%s\ %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x, omap_connector-dssdev-name, @@ -303,12 +304,15 @@ void omap_connector_mode_set(struct drm_connector *connector, mode-vdisplay, mode-vsync_start, mode-vsync_end, mode-vtotal, mode-type, mode-flags); - if (dssdrv-check_timings(dssdev, timings)) { - dev_err(dev-dev, could not set timings\n); - return; + ret = dssdrv-check_timings(dssdev, timings); + if (ret) { + dev_err(dev-dev, could not set timings: %d\n, ret); + return ret; } - dssdrv-set_timings(dssdev, timings); + dssdrv-set_timings(dssdev, timings); + + return 0; } /* flush an area of the framebuffer (in case of manual update display that diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 7479dcb..3024dcd 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -33,7 +33,6 @@ struct omap_crtc { /* if there is a pending flip, these will be non-null: */ struct drm_pending_vblank_event *event; - struct drm_framebuffer *old_fb; }; static void omap_crtc_destroy(struct drm_crtc *crtc) @@ -78,7 +77,8 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc, return omap_plane_mode_set(plane, crtc, crtc-fb, 0, 0, mode-hdisplay, mode-vdisplay, x 16, y 16, - mode-hdisplay 16, mode-vdisplay 16); + mode-hdisplay 16, mode-vdisplay 16, + NULL, NULL); } static void omap_crtc_prepare(struct drm_crtc *crtc) @@ -102,10 +102,11 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_plane *plane = omap_crtc-plane; struct drm_display_mode *mode = crtc-mode; - return plane-funcs-update_plane(plane, crtc, crtc-fb, + return omap_plane_mode_set(plane, crtc, crtc-fb, 0, 0, mode-hdisplay, mode-vdisplay, x 16, y 16, - mode-hdisplay 16, mode-vdisplay 16); + mode-hdisplay 16, mode-vdisplay 16, + NULL, NULL); } static void omap_crtc_load_lut(struct drm_crtc *crtc) @@ -154,17 +155,17 @@ static void page_flip_cb(void *arg) { struct drm_crtc *crtc = arg; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct
Re: [PATCH] staging: drm/omap: add rotation properties
On Fri, Jun 29, 2012 at 5:46 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote: On Wed, 2012-06-27 at 09:06 -0500, Rob Clark wrote: From: Rob Clark r...@ti.com Use tiled buffers for rotated/reflected scanout, with CRTC and plane properties as the interface for userspace to configure rotation. Signed-off-by: Rob Clark r...@ti.com +/* this should probably be in drm-core to standardize amongst drivers */ +#define DRM_ROTATE_0 0 +#define DRM_ROTATE_90 1 +#define DRM_ROTATE_180 2 +#define DRM_ROTATE_270 3 +#define DRM_REFLECT_X 4 +#define DRM_REFLECT_Y 5 Are both reflect X and Y needed? You can get all the possible orientations with just one of the reflects. And I think the word mirror represents nicely what the reflect does, i.e. if you look at the mirror, the image you see is flipped horizontally. fwiw these values are aligned with what is used in userspace xrandr.. an earlier version of this patch used just 3 bits, which where aligned with what the omap hw uses and can describe all possible combinations of mirroring and isomorphic rotation (x-invert, y-invert, and xy-flip). But the advantage of the xrandr approach is you can more easily leave out bits for rotation/mirroring modes that your hw does not support.. for example if some hw supports only certain rotations or does not support mirror/reflect. BR, -R Tomi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] staging: drm/omap: add rotation properties
On Wed, Jun 27, 2012 at 9:06 AM, Rob Clark rob.cl...@linaro.org wrote: From: Rob Clark r...@ti.com Use tiled buffers for rotated/reflected scanout, with CRTC and plane properties as the interface for userspace to configure rotation. btw, I assume the potential controversial part of the patch would be the property names/values exposed to userspace, because we probably should try to standardize property names/values wherever possible. There is one difference, AFAIU, from the rotation properties proposed for the intel driver, in that in the omap case these properties are actually instructing the hw to do the rotation, rather than just informing the driver that rotation was done via a shadow buffer in userspace. BR, -R Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_crtc.c | 17 + drivers/staging/omapdrm/omap_dmm_tiler.c | 47 -- drivers/staging/omapdrm/omap_dmm_tiler.h | 17 - drivers/staging/omapdrm/omap_drv.c | 17 + drivers/staging/omapdrm/omap_drv.h | 32 +- drivers/staging/omapdrm/omap_fb.c | 99 +- drivers/staging/omapdrm/omap_gem.c | 43 - drivers/staging/omapdrm/omap_plane.c | 92 --- 8 files changed, 318 insertions(+), 46 deletions(-) diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 8b864af..7479dcb 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -191,10 +191,25 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, return 0; } +static int omap_crtc_set_property(struct drm_crtc *crtc, + struct drm_property *property, uint64_t val) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_drm_private *priv = crtc-dev-dev_private; + + if (property == priv-rotation_prop) { + crtc-invert_dimensions = + !!(val ((1LL DRM_ROTATE_90) | (1LL DRM_ROTATE_270))); + } + + return omap_plane_set_property(omap_crtc-plane, property, val); +} + static const struct drm_crtc_funcs omap_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .destroy = omap_crtc_destroy, .page_flip = omap_crtc_page_flip_locked, + .set_property = omap_crtc_set_property, }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { @@ -231,6 +246,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, drm_crtc_init(dev, crtc, omap_crtc_funcs); drm_crtc_helper_add(crtc, omap_crtc_helper_funcs); + omap_plane_install_properties(omap_crtc-plane, crtc-base); + return crtc; fail: diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index 9d83060..68da290 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -401,8 +401,26 @@ int tiler_release(struct tiler_block *block) * Utils */ -/* calculate the tiler space address of a pixel in a view orientation */ -static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y) +/* calculate the tiler space address of a pixel in a view orientation... + * below description copied from the display subsystem section of TRM: + * + * When the TILER is addressed, the bits: + * [28:27] = 0x0 for 8-bit tiled + * 0x1 for 16-bit tiled + * 0x2 for 32-bit tiled + * 0x3 for page mode + * [31:29] = 0x0 for 0-degree view + * 0x1 for 180-degree view + mirroring + * 0x2 for 0-degree view + mirroring + * 0x3 for 180-degree view + * 0x4 for 270-degree view + mirroring + * 0x5 for 270-degree view + * 0x6 for 90-degree view + * 0x7 for 90-degree view + mirroring + * Otherwise the bits indicated the corresponding bit address to access + * the SDRAM. + */ +static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y) { u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment; @@ -414,8 +432,11 @@ static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y) x_mask = MASK(x_bits); y_mask = MASK(y_bits); - if (x 0 || x x_mask || y 0 || y y_mask) + if (x 0 || x x_mask || y 0 || y y_mask) { + DBG(invalid coords: %u 0 || %u %u || %u 0 || %u %u, + x, x, x_mask, y, y, y_mask); return 0; + } /* account for mirroring */ if (orient MASK_X_INVERT) @@ -436,11 +457,22 @@ dma_addr_t tiler_ssptr(struct tiler_block *block) { BUG_ON(!validfmt(block-fmt)); - return TILVIEW_8BIT + tiler_get_address(0, block-fmt, + return TILVIEW_8BIT + tiler_get_address(block-fmt, 0
[PATCH] staging: drm/omap: add rotation properties
From: Rob Clark r...@ti.com Use tiled buffers for rotated/reflected scanout, with CRTC and plane properties as the interface for userspace to configure rotation. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_crtc.c | 17 + drivers/staging/omapdrm/omap_dmm_tiler.c | 47 -- drivers/staging/omapdrm/omap_dmm_tiler.h | 17 - drivers/staging/omapdrm/omap_drv.c | 17 + drivers/staging/omapdrm/omap_drv.h | 32 +- drivers/staging/omapdrm/omap_fb.c| 99 +- drivers/staging/omapdrm/omap_gem.c | 43 - drivers/staging/omapdrm/omap_plane.c | 92 --- 8 files changed, 318 insertions(+), 46 deletions(-) diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 8b864af..7479dcb 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -191,10 +191,25 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, return 0; } +static int omap_crtc_set_property(struct drm_crtc *crtc, + struct drm_property *property, uint64_t val) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_drm_private *priv = crtc-dev-dev_private; + + if (property == priv-rotation_prop) { + crtc-invert_dimensions = + !!(val ((1LL DRM_ROTATE_90) | (1LL DRM_ROTATE_270))); + } + + return omap_plane_set_property(omap_crtc-plane, property, val); +} + static const struct drm_crtc_funcs omap_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .destroy = omap_crtc_destroy, .page_flip = omap_crtc_page_flip_locked, + .set_property = omap_crtc_set_property, }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { @@ -231,6 +246,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, drm_crtc_init(dev, crtc, omap_crtc_funcs); drm_crtc_helper_add(crtc, omap_crtc_helper_funcs); + omap_plane_install_properties(omap_crtc-plane, crtc-base); + return crtc; fail: diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index 9d83060..68da290 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -401,8 +401,26 @@ int tiler_release(struct tiler_block *block) * Utils */ -/* calculate the tiler space address of a pixel in a view orientation */ -static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y) +/* calculate the tiler space address of a pixel in a view orientation... + * below description copied from the display subsystem section of TRM: + * + * When the TILER is addressed, the bits: + * [28:27] = 0x0 for 8-bit tiled + * 0x1 for 16-bit tiled + * 0x2 for 32-bit tiled + * 0x3 for page mode + * [31:29] = 0x0 for 0-degree view + * 0x1 for 180-degree view + mirroring + * 0x2 for 0-degree view + mirroring + * 0x3 for 180-degree view + * 0x4 for 270-degree view + mirroring + * 0x5 for 270-degree view + * 0x6 for 90-degree view + * 0x7 for 90-degree view + mirroring + * Otherwise the bits indicated the corresponding bit address to access + * the SDRAM. + */ +static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y) { u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment; @@ -414,8 +432,11 @@ static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y) x_mask = MASK(x_bits); y_mask = MASK(y_bits); - if (x 0 || x x_mask || y 0 || y y_mask) + if (x 0 || x x_mask || y 0 || y y_mask) { + DBG(invalid coords: %u 0 || %u %u || %u 0 || %u %u, + x, x, x_mask, y, y, y_mask); return 0; + } /* account for mirroring */ if (orient MASK_X_INVERT) @@ -436,11 +457,22 @@ dma_addr_t tiler_ssptr(struct tiler_block *block) { BUG_ON(!validfmt(block-fmt)); - return TILVIEW_8BIT + tiler_get_address(0, block-fmt, + return TILVIEW_8BIT + tiler_get_address(block-fmt, 0, block-area.p0.x * geom[block-fmt].slot_w, block-area.p0.y * geom[block-fmt].slot_h); } +dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient, + uint32_t x, uint32_t y) +{ + struct tcm_pt *p = block-area.p0; + BUG_ON(!validfmt(block-fmt)); + + return tiler_get_address(block-fmt, orient, + (p-x * geom[block-fmt].slot_w) + x, + (p-y * geom[block-fmt].slot_h) + y); +} + void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h) { BUG_ON(!validfmt(fmt)); @@ -448,11 +480,14 @@ void tiler_align(enum tiler_fmt fmt
Re: [PATCH] staging: drm/omap: add rotation properties
On Wed, Jun 27, 2012 at 2:40 PM, Greg KH g...@kroah.com wrote: On Wed, Jun 27, 2012 at 09:06:26AM -0500, Rob Clark wrote: From: Rob Clark r...@ti.com Use tiled buffers for rotated/reflected scanout, with CRTC and plane properties as the interface for userspace to configure rotation. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/omap_crtc.c | 17 + drivers/staging/omapdrm/omap_dmm_tiler.c | 47 -- drivers/staging/omapdrm/omap_dmm_tiler.h | 17 - drivers/staging/omapdrm/omap_drv.c | 17 + drivers/staging/omapdrm/omap_drv.h | 32 +- drivers/staging/omapdrm/omap_fb.c | 99 +- drivers/staging/omapdrm/omap_gem.c | 43 - drivers/staging/omapdrm/omap_plane.c | 92 --- 8 files changed, 318 insertions(+), 46 deletions(-) That's great you are adding new features, but how goes the progress to get this driver out of the drivers/staging/ area and moved to the real part of the kernel? I don't want to keep taking new features without seeing some progress on getting the code cleaned up and moved out first. Oh, heh, well I suppose the first thing to do is send a patch to clean up the TODO file.. I just noticed that I'd been forgetting to update it. BR, -R thanks, greg k-h -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] staging: drm/omap: update TODO
From: Rob Clark r...@ti.com Update TODO file, which had been neglected. Signed-off-by: Rob Clark r...@ti.com --- drivers/staging/omapdrm/TODO |7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO index 55b1837..938c788 100644 --- a/drivers/staging/omapdrm/TODO +++ b/drivers/staging/omapdrm/TODO @@ -1,9 +1,7 @@ TODO -. check error handling/cleanup paths -. add drm_plane / overlay support . add video decode/encode support (via syslink3 + codec-engine) -. still some rough edges with flipping.. event back to userspace should - really come after VSYNC interrupt + . NOTE: with dmabuf this probably could be split into different driver +so perhaps this TODO doesn't belong here . where should we do eviction (detatch_pages())? We aren't necessarily accessing the pages via a GART, so maybe we need some other threshold to put a cap on the # of pages that can be pin'd. (It is mostly only @@ -27,7 +25,6 @@ TODO CRTC's should be disabled, and on resume the LUT should be reprogrammed before CRTC's are re-enabled, to prevent DSS from trying to DMA from a buffer mapped in DMM/TILER before LUT is reloaded. -. Add debugfs information for DMM/TILER Userspace: . git://github.com/robclark/xf86-video-omap.git -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html