Ilija Hadzic's Virtual CRTCs feature discuss
Hi every one I'm currently working on VirtualMonitor in my leisure time. It allows you to use compute/tablet/smartphone as a second monitor for your primary computer. please refer to http://virtualmonitor.github.io for more information. Currently I have released very basic version for windows2000-windows7 to demonstrate the project is feasible. When I was trying to make a further step on windows, I realized it is difficult for an individual, as it is not open source and also without technical support from Microsoft. Then I want to move to linux, and I found Ilija Hadzic's post about Virtual CRTCs. his post is here: http://lists.freedesktop.org/archives/dri-devel/2011-November/015975.html In his implementation, GPU driver can create arbitrary number of CRTCs (configurable by user) instead of only those CRTCs that represent real hardware. It is very useful not only for VirtualMonitor, but also VNC/Virtualization/USB display etc. based on this implementation those application will be able to take full advantage of the physical graphic card(3D acceleration). I want raise Ilijia's original question agian, if anybody in this community think Virtual CRTCs is useful, and willing to work together to make a further progress. My thought is if can implement a driver independent layer between dri and vendor specific GPU driver, with some general API. maybe implement this based one vendor related GPU first? e.g. based on Ilijia's implementation for Radeon as a daemon? GPU driver is not my expertise, If some expert from this community think this feature is interesting, and willing to initiate a project for this feature, that will be great. Then people can work and discuss together. Any comments regarding to Virtual CRTC or VirtualMonitor are very welcome. Thanks. Best wishes Derek -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20140818/515550ec/attachment-0001.html>
Ilija Hadzic's Virtual CRTCs feature discuss
Hi, Daniel Thanks for your response! Talking about v4l's virtual gpu driver? Could you please tell some more informations. is this driver in git.linuxtv.org/cgit.cgi/media_tree.git I want to take a look this driver. but I can't find it in their git repository. Or is there any introduction post related this driver? Thanks. Best wishes Derek On Mon, Aug 25, 2014 at 6:12 AM, Daniel Vetter wrote: > On Mon, Aug 18, 2014 at 03:35:16PM -0700, Derek wrote: > > Hi every one > > I'm currently working on VirtualMonitor in my leisure time. It allows you > > to use compute/tablet/smartphone as a second monitor for your primary > > computer. please refer to http://virtualmonitor.github.io for more > > information. Currently I have released very basic version for > > windows2000-windows7 to demonstrate the project is feasible. When I was > > trying to make a further step on windows, I realized it is difficult for > an > > individual, as it is not open source and also without technical support > > from Microsoft. > > > > Then I want to move to linux, and I found Ilija Hadzic's post about > Virtual > > CRTCs. his post is here: > > > http://lists.freedesktop.org/archives/dri-devel/2011-November/015975.html > > In his implementation, GPU driver can create arbitrary number of CRTCs > > (configurable by user) instead of only those CRTCs that represent real > > hardware. > > It is very useful not only for VirtualMonitor, but also > > VNC/Virtualization/USB display etc. based on this implementation those > > application will be able to take full advantage of the physical graphic > > card(3D acceleration). > > > > I want raise Ilijia's original question agian, if anybody in this > community > > think Virtual CRTCs is useful, and willing to work together to make a > > further progress. > > My thought is if can implement a driver independent layer between dri and > > vendor specific GPU driver, with some general API. maybe implement this > > based one vendor related GPU first? e.g. based on Ilijia's implementation > > for Radeon as a daemon? > > > > GPU driver is not my expertise, If some expert from this community think > > this feature is interesting, and willing to initiate a project for this > > feature, that will be great. Then people can work and discuss together. > > > > Any comments regarding to Virtual CRTC or VirtualMonitor are very > welcome. > > Thanks. > > I think the concept is overall sound (haven't looked at the old patches in > detail).For the actual implementation I think a separate virtual drm > driver is now > the better approach, since with dma-buf and soon native fence support we > can do this now properly. > > And especially now that we have multi-gpu support in X it should integrate > almost seamlessly into X (and other display managers with multi-gpu > support). Instead of requering special support in all drivers. > > Another thing for which iirc no one ever proposed a decent solution is > synchronization to consumers of the frontbuffers for virtual gpus. So I > guess the driver-private ioctl interface to make that magic work will be > key. > > A (configurable) virtual gpu should also be really useful for automated > testing, e.g. of hot-plug and unplug (both drm core and userspace). The > v4l folks have such a driver (recently massively revamped for 3.18) and it > looks extremely useful. > > For the configuration interface I guess a few simple module options to get > started should be enough, eventually we can switch to configfs (or > similar) to be able to configure and create/destroy virtual gpus at > runtime. > > Just my random thoughts, probably good to kickstart the discussion with > some quick patches and chat with people on #dri-devel on freenode irc. > > Cheers, Daniel > -- > Daniel Vetter > Software Engineer, Intel Corporation > +41 (0) 79 365 57 48 - http://blog.ffwll.ch > -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20140825/7fba0a62/attachment-0001.html>
Ilija Hadzic's Virtual CRTCs feature discuss
Thanks for loop dri-devel back. I didn't realize that I clicked "reply" instead of "reply-all" :( Best wishes Derek On Wed, Aug 27, 2014 at 10:54 AM, Daniel Vetter wrote: > Please don't drop mailing lists, especially when you've dug out some > good information like the stuff below. Readding dri-devel. > -Danel > > On Wed, Aug 27, 2014 at 7:21 PM, Derek wrote: > > Hi Daniel > > Thanks, Hans Verkuil's git repository is here > > git://linuxtv.org/hverkuil/media_tree.git. branch name vivid2. > > his slide is here: > > > http://events.linuxfoundation.org/sites/events/files/slides/v4l2-testing.pdf > > And I'm agree that it isn't for virtual drm driver. > > > > I found that there are two virtual drm driver in kernel source code. > > first one is vmwgfx driver/gpu/drm/vmwgfx > > according to > > http://mesa3d.org/vmware-guest.html > > This driver gives a Linux virtual machine access to the host's GPU for > > hardware-accelerated 3D. > > > > another one is gxl drivers/gpu/drm/gxl > > It is for readhat virtualization KVM + spice. > > > > and seems drm infrastructure support virtual driver already. just search > > DRM_MODE_ENCODER_VIRTUAL/DRM_MODE_CONNECTOR_VIRTUAL > > > > both driver need user space XServer driver support. > > > > I will take a look these drivers find out if i can use similar driver to > > create virtual CRTC based on drm without extra userspace xserver driver. > and > > develop a virtualMonitor which allow you to use compute, tablet, > smartphone > > as a second monitor for your primary computer. an example page is > > http://virtualmonitor.github.io > > > > Thanks a lots > > > > Best wishes > > Derek > > > > > > > > On Tue, Aug 26, 2014 at 1:18 AM, Daniel Vetter wrote: > >> > >> On Mon, Aug 25, 2014 at 12:02:09PM -0700, Derek wrote: > >> > Hi, Daniel > >> > Thanks for your response! > >> > Talking about v4l's virtual gpu driver? Could you please tell some > more > >> > informations. is this driver in > >> > git.linuxtv.org/cgit.cgi/media_tree.git > >> > I want to take a look this driver. but I can't find it in their git > >> > repository. Or is there any introduction post related this driver? > >> > Thanks. > >> > >> It isn't merged yet afaik, but Hans Verkuil has made a nice presentation > >> about it at LinuxCon. Unfortunately the linuxcon page doesn't even have > >> the slides afaics. > >> > >> > >> > http://lccona14.sched.org/event/2e156d3ce84309b2932f2e7a512904e0#.U_xCcjSmXmE > >> > >> The driver was called vidid (there's an older one called vidi > apparently). > >> But I don't think it's a good model for a virtual drm driver, if that's > >> why you want to look at it. Just mentioned it to show that there's lots > of > >> uses for virtual drivers. > >> -Daniel > >> > >> > > >> > Best wishes > >> > Derek > >> > > >> > > >> > On Mon, Aug 25, 2014 at 6:12 AM, Daniel Vetter > wrote: > >> > > >> > > On Mon, Aug 18, 2014 at 03:35:16PM -0700, Derek wrote: > >> > > > Hi every one > >> > > > I'm currently working on VirtualMonitor in my leisure time. It > >> > > > allows you > >> > > > to use compute/tablet/smartphone as a second monitor for your > >> > > > primary > >> > > > computer. please refer to http://virtualmonitor.github.io for > more > >> > > > information. Currently I have released very basic version for > >> > > > windows2000-windows7 to demonstrate the project is feasible. When > I > >> > > > was > >> > > > trying to make a further step on windows, I realized it is > difficult > >> > > > for > >> > > an > >> > > > individual, as it is not open source and also without technical > >> > > > support > >> > > > from Microsoft. > >> > > > > >> > > > Then I want to move to linux, and I found Ilija Hadzic's post > about > >> > > Virtual > >> > > > CRTCs. his post is here: > >> > > > > >> > > > >> > > > http://lists.freedesktop.org/archives/dri-devel/2011-November/015975.html > >> > &g
[PATCH 2/5] dt-bindings: display/panel: Expand rotation documentation
This adds to the rotation documentation to explain how drivers should use the property and gives an example of the property in a devicetree node. Signed-off-by: Derek Basehore --- .../bindings/display/panel/panel.txt | 32 +++ 1 file changed, 32 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel.txt b/Documentation/devicetree/bindings/display/panel/panel.txt index e2e6867852b8..f35d62d933fc 100644 --- a/Documentation/devicetree/bindings/display/panel/panel.txt +++ b/Documentation/devicetree/bindings/display/panel/panel.txt @@ -2,3 +2,35 @@ Common display properties - - rotation:Display rotation in degrees counter clockwise (0,90,180,270) + +Property read from the device tree using of of_drm_get_panel_orientation + +The panel driver may apply the rotation at the TCON level, which will +make the panel look like it isn't rotated to the kernel and any other +software. + +If not, a panel orientation property should be added through the SoC +vendor DRM code using the drm_connector_init_panel_orientation_property +function. + +Example: + panel: panel@0 { + compatible = "boe,himax8279d8p"; + reg = <0>; + enable-gpios = <&pio 45 0>; + pp33-gpios = <&pio 35 0>; + pp18-gpios = <&pio 36 0>; + pinctrl-names = "default", "state_3300mv", "state_1800mv"; + pinctrl-0 = <&panel_pins_default>; + pinctrl-1 = <&panel_pins_3300mv>; + pinctrl-2 = <&panel_pins_1800mv>; + backlight = <&backlight_lcd0>; + rotation = <180>; + status = "okay"; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 4/5] drm/connector: Split out orientation quirk detection
This removes the orientation quirk detection from the code to add an orientation property to a panel. This is used only for legacy x86 systems, yet we'd like to start using this on device tree systems where quirk detection like this is not needed. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_connector.c | 16 drivers/gpu/drm/i915/vlv_dsi.c | 13 + include/drm/drm_connector.h | 2 +- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index e17586aaa80f..58a09b65028b 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1894,31 +1894,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c index bfe2891eac37..113129996530 100644 --- a/drivers/gpu/drm/i915/vlv_dsi.c +++ b/drivers/gpu/drm/i915/vlv_dsi.c @@ -1650,6 +1650,7 @@ static void intel_dsi_add_properties(struct intel_connector *connector) if (connector->panel.fixed_mode) { u32 allowed_scalers; + int orientation; allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN); if (!HAS_GMCH(dev_priv)) @@ -1660,12 +1661,16 @@ static void intel_dsi_add_properties(struct intel_connector *connector) connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; - connector->base.display_info.panel_orientation = - vlv_dsi_get_panel_orientation(connector); - drm_connector_init_panel_orientation_property( - &connector->base, + orientation = drm_get_panel_orientation_quirk( connector->panel.fixed_mode->hdisplay, connector->panel.fixed_mode->vdisplay); + if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = orientation; + else + connector->display_info.panel_orientation = + intel_dsi_get_panel_orientation(connector); + + drm_connector_init_panel_orientation_property(&connector->base); } } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 47e749b74e5f..c2992f7a0dd5 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1370,7 +1370,7 @@ void drm_connector_set_link_status_property(struct drm_connector *connector, void drm_connector_set_vrr_capable_property( struct drm_connector *connector, bool capable); int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height); + struct drm_connector *connector); int drm_connector_attach_max_bpc_property(struct drm_connector *connector, int min, int max); -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 5/5] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 4a0b9150a7bb..08ffdc7526dd 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -782,10 +782,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 1/5] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 41 + include/drm/drm_panel.h | 7 +++ 2 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..3b689ce4a51a 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -172,6 +172,47 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the rotation of the panel using a + * device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The rotation in the + * device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, int *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 8c738c0e6e9f..13631b2efbaa 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -197,11 +197,18 @@ int drm_panel_detach(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +int *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +int of_drm_get_panel_orientation(const struct device_node *np, +int *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 3/5] drm/panel: Add attach/detach callbacks
This adds the attach/detach callbacks. These are for setting up internal state for the connector/panel pair that can't be done at probe (since the connector doesn't exist) and which don't need to be repeatedly done for every get/modes, prepare, or enable callback. Values such as the panel orientation, and display size can be filled in for the connector. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 14 ++ include/drm/drm_panel.h | 4 2 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 3b689ce4a51a..72f67678d9d5 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,12 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + int ret; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + if (panel->funcs->attach) { + ret = panel->funcs->attach(panel); + if (ret < 0) { + panel->connector = NULL; + panel->drm = NULL; + return ret; + } + } + return 0; } EXPORT_SYMBOL(drm_panel_attach); @@ -128,6 +139,9 @@ EXPORT_SYMBOL(drm_panel_attach); */ int drm_panel_detach(struct drm_panel *panel) { + if (panel->funcs->detach) + panel->funcs->detach(panel); + panel->connector = NULL; panel->drm = NULL; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 13631b2efbaa..e136e3a3c996 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -37,6 +37,8 @@ struct display_timing; * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel + * @detach: detach panel->connector (clear internal state, etc.) + * @attach: attach panel->connector (update internal state, etc.) * @prepare: turn on panel and perform set up * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and @@ -70,6 +72,8 @@ struct display_timing; struct drm_panel_funcs { int (*disable)(struct drm_panel *panel); int (*unprepare)(struct drm_panel *panel); + void (*detach)(struct drm_panel *panel); + int (*attach)(struct drm_panel *panel); int (*prepare)(struct drm_panel *panel); int (*enable)(struct drm_panel *panel); int (*get_modes)(struct drm_panel *panel); -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 0/5] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. Derek Basehore (5): drm/panel: Add helper for reading DT rotation dt-bindings: display/panel: Expand rotation documentation drm/panel: Add attach/detach callbacks drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property .../bindings/display/panel/panel.txt | 32 +++ drivers/gpu/drm/drm_connector.c | 16 ++ drivers/gpu/drm/drm_panel.c | 55 +++ drivers/gpu/drm/i915/vlv_dsi.c| 13 +++-- drivers/gpu/drm/mediatek/mtk_dsi.c| 8 +++ include/drm/drm_connector.h | 2 +- include/drm/drm_panel.h | 11 7 files changed, 120 insertions(+), 17 deletions(-) -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 4/5] drm/connector: Split out orientation quirk detection
This removes the orientation quirk detection from the code to add an orientation property to a panel. This is used only for legacy x86 systems, yet we'd like to start using this on devicetree systems where quirk detection like this is not needed. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_connector.c | 16 drivers/gpu/drm/i915/intel_dp.c | 14 +++--- drivers/gpu/drm/i915/vlv_dsi.c | 14 ++ include/drm/drm_connector.h | 2 +- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index e17586aaa80f..58a09b65028b 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1894,31 +1894,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b099a9dc28fd..72ab090ea97a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include "i915_debugfs.h" @@ -7281,9 +7282,16 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_connector->panel.backlight.power = intel_edp_backlight_power; intel_panel_setup_backlight(connector, pipe); - if (fixed_mode) - drm_connector_init_panel_orientation_property( - connector, fixed_mode->hdisplay, fixed_mode->vdisplay); + if (fixed_mode) { + int orientation = drm_get_panel_orientation_quirk( + fixed_mode->hdisplay, fixed_mode->vdisplay); + + if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = + orientation; + + drm_connector_init_panel_orientation_property(connector); + } return true; diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c index bfe2891eac37..27f86a787f60 100644 --- a/drivers/gpu/drm/i915/vlv_dsi.c +++ b/drivers/gpu/drm/i915/vlv_dsi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "i915_drv.h" #include "intel_atomic.h" @@ -1650,6 +1651,7 @@ static void intel_dsi_add_properties(struct intel_connector *connector) if (connector->panel.fixed_mode) { u32 allowed_scalers; + int orientation; allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN); if (!HAS_GMCH(dev_priv)) @@ -1660,12 +1662,16 @@ static void intel_dsi_add_properties(struct intel_connector *connector) connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; - connector->base.display_info.panel_orientation = - vlv_dsi_get_panel_orientation(connector); - drm_connector_init_panel_orientation_property( - &connector->base, + orientation = drm_get_panel_orientation_quirk( connector->panel.fixed_mode->hdisplay,
[PATCH 1/5] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 41 + include/drm/drm_panel.h | 7 +++ 2 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..3b689ce4a51a 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -172,6 +172,47 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the rotation of the panel using a + * device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The rotation in the + * device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, int *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 8c738c0e6e9f..13631b2efbaa 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -197,11 +197,18 @@ int drm_panel_detach(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +int *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +int of_drm_get_panel_orientation(const struct device_node *np, +int *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 3/5] drm/panel: Add attach/detach callbacks
This adds the attach/detach callbacks. These are for setting up internal state for the connector/panel pair that can't be done at probe (since the connector doesn't exist) and which don't need to be repeatedly done for every get/modes, prepare, or enable callback. Values such as the panel orientation, and display size can be filled in for the connector. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 14 ++ include/drm/drm_panel.h | 4 2 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 3b689ce4a51a..72f67678d9d5 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,12 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + int ret; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + if (panel->funcs->attach) { + ret = panel->funcs->attach(panel); + if (ret < 0) { + panel->connector = NULL; + panel->drm = NULL; + return ret; + } + } + return 0; } EXPORT_SYMBOL(drm_panel_attach); @@ -128,6 +139,9 @@ EXPORT_SYMBOL(drm_panel_attach); */ int drm_panel_detach(struct drm_panel *panel) { + if (panel->funcs->detach) + panel->funcs->detach(panel); + panel->connector = NULL; panel->drm = NULL; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 13631b2efbaa..e136e3a3c996 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -37,6 +37,8 @@ struct display_timing; * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel + * @detach: detach panel->connector (clear internal state, etc.) + * @attach: attach panel->connector (update internal state, etc.) * @prepare: turn on panel and perform set up * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and @@ -70,6 +72,8 @@ struct display_timing; struct drm_panel_funcs { int (*disable)(struct drm_panel *panel); int (*unprepare)(struct drm_panel *panel); + void (*detach)(struct drm_panel *panel); + int (*attach)(struct drm_panel *panel); int (*prepare)(struct drm_panel *panel); int (*enable)(struct drm_panel *panel); int (*get_modes)(struct drm_panel *panel); -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH v2 0/5] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v2 changes: fixed build errors in i915 Derek Basehore (5): drm/panel: Add helper for reading DT rotation dt-bindings: display/panel: Expand rotation documentation drm/panel: Add attach/detach callbacks drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property .../bindings/display/panel/panel.txt | 32 +++ drivers/gpu/drm/drm_connector.c | 16 ++ drivers/gpu/drm/drm_panel.c | 55 +++ drivers/gpu/drm/i915/vlv_dsi.c| 13 +++-- drivers/gpu/drm/mediatek/mtk_dsi.c| 8 +++ include/drm/drm_connector.h | 2 +- include/drm/drm_panel.h | 11 7 files changed, 120 insertions(+), 17 deletions(-) -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 5/5] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 4a0b9150a7bb..08ffdc7526dd 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -782,10 +782,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH 2/5] dt-bindings: display/panel: Expand rotation documentation
This adds to the rotation documentation to explain how drivers should use the property and gives an example of the property in a devicetree node. Signed-off-by: Derek Basehore --- .../bindings/display/panel/panel.txt | 32 +++ 1 file changed, 32 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel.txt b/Documentation/devicetree/bindings/display/panel/panel.txt index e2e6867852b8..f35d62d933fc 100644 --- a/Documentation/devicetree/bindings/display/panel/panel.txt +++ b/Documentation/devicetree/bindings/display/panel/panel.txt @@ -2,3 +2,35 @@ Common display properties - - rotation:Display rotation in degrees counter clockwise (0,90,180,270) + +Property read from the device tree using of of_drm_get_panel_orientation + +The panel driver may apply the rotation at the TCON level, which will +make the panel look like it isn't rotated to the kernel and any other +software. + +If not, a panel orientation property should be added through the SoC +vendor DRM code using the drm_connector_init_panel_orientation_property +function. + +Example: + panel: panel@0 { + compatible = "boe,himax8279d8p"; + reg = <0>; + enable-gpios = <&pio 45 0>; + pp33-gpios = <&pio 35 0>; + pp18-gpios = <&pio 36 0>; + pinctrl-names = "default", "state_3300mv", "state_1800mv"; + pinctrl-0 = <&panel_pins_default>; + pinctrl-1 = <&panel_pins_3300mv>; + pinctrl-2 = <&panel_pins_1800mv>; + backlight = <&backlight_lcd0>; + rotation = <180>; + status = "okay"; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; -- 2.22.0.rc2.383.gf4fbbf30c2-goog
[PATCH v3 0/4] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v3 changes: -changed from attach/detach callbacks to directly setting fixed panel values in drm_panel_attach -removed update to Documentation -added separate function for quirked panel orientation property init v2 changes: fixed build errors in i915 Derek Basehore (4): drm/panel: Add helper for reading DT rotation drm/panel: set display info in panel attach drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property drivers/gpu/drm/drm_connector.c| 45 ++- drivers/gpu/drm/drm_panel.c| 70 ++ drivers/gpu/drm/i915/intel_dp.c| 4 +- drivers/gpu/drm/i915/vlv_dsi.c | 5 +-- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 include/drm/drm_connector.h| 2 + include/drm/drm_panel.h| 21 + 7 files changed, 138 insertions(+), 17 deletions(-) -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v3 1/4] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 42 + include/drm/drm_panel.h | 7 +++ 2 files changed, 49 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..507099af4b57 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -172,6 +172,48 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the rotation of the panel using a + * device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The rotation in the + * device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 8c738c0e6e9f..3564952f1a4f 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -197,11 +197,18 @@ int drm_panel_detach(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v3 3/4] drm/connector: Split out orientation quirk detection
Not every platform needs quirk detection for panel orientation, so split the drm_connector_init_panel_orientation_property into two functions. One for platforms without the need for quirks, and the other for platforms that need quirks. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_connector.c | 45 - drivers/gpu/drm/i915/intel_dp.c | 4 +-- drivers/gpu/drm/i915/vlv_dsi.c | 5 ++-- include/drm/drm_connector.h | 2 ++ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index e17586aaa80f..c4b01adf927a 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1894,31 +1894,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; @@ -1941,6 +1933,35 @@ int drm_connector_init_panel_orientation_property( } EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); +/** + * drm_connector_init_panel_orientation_property_quirk - + * initialize the connecters panel_orientation property with a quirk + * override + * @connector: connector for which to init the panel-orientation property. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * + * This function will check for platform specific (e.g. DMI based) quirks + * overriding display_info.panel_orientation first, then if panel_orientation + * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the + * "panel orientation" property to the connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_init_panel_orientation_property_quirk( + struct drm_connector *connector, int width, int height) +{ + int orientation_quirk; + + orientation_quirk = drm_get_panel_orientation_quirk(width, height); + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = orientation_quirk; + + return drm_connector_init_panel_orientation_property(connector); +} +EXPORT_SYMBOL(drm_connector_init_panel_orientation_property_quirk); + int drm_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b099a9dc28fd..7d4e61cf5463 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -7282,8 +7282,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_panel_setup_backlight(connector, pipe); if (fixed_mode) - drm_connector_init_panel_orientation_property( - connector, fixed_mode->hdisplay, fixed_mode->vdisplay); + drm_connector_init_panel_orientation_property_quirk(connector, + fixed_mode->hdisplay, fixed_mode->vdisplay); return true; diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c index bfe2891eac37..fa9833dbe359 100644 --- a/drivers/gpu/drm/i915/vlv_dsi.c +++ b/drivers/gpu/drm/i915/vlv_dsi.c @@ -1650,6 +1650,7 @@ static
[PATCH v4 4/4] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 4a0b9150a7bb..08ffdc7526dd 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -782,10 +782,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v3 2/4] drm/panel: set display info in panel attach
Devicetree systems can set panel orientation via a panel binding, but there's no way, as is, to propagate this setting to the connector, where the property need to be added. To address this, this patch sets orientation, as well as other fixed values for the panel, in the drm_panel_attach function. These values are stored from probe in the drm_panel struct. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 28 include/drm/drm_panel.h | 14 ++ 2 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 507099af4b57..5690fca30236 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,11 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + struct drm_display_info *info; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + info = &connector->display_info; + info->width_mm = panel->width_mm; + info->height_mm = panel->height_mm; + info->bpc = panel->bpc; + info->panel_orientation = panel->orientation; + info->bus_flags = panel->bus_flags; + if (panel->bus_formats) + drm_display_info_set_bus_formats(&connector->display_info, +panel->bus_formats, +panel->num_bus_formats); return 0; } @@ -128,6 +140,22 @@ EXPORT_SYMBOL(drm_panel_attach); */ int drm_panel_detach(struct drm_panel *panel) { + struct drm_display_info *info; + + if (!panel->connector) + goto out; + + info = &panel->connector->display_info; + info->width_mm = 0; + info->height_mm = 0; + info->bpc = 0; + info->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + info->bus_flags = 0; + kfree(info->bus_formats); + info->bus_formats = NULL; + info->num_bus_formats = 0; + +out: panel->connector = NULL; panel->drm = NULL; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 3564952f1a4f..760ca5865962 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -37,6 +37,8 @@ struct display_timing; * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel + * @detach: detach panel->connector (clear internal state, etc.) + * @attach: attach panel->connector (update internal state, etc.) * @prepare: turn on panel and perform set up * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and @@ -93,6 +95,18 @@ struct drm_panel { const struct drm_panel_funcs *funcs; + /* +* panel information to be set in the connector when the panel is +* attached. +*/ + unsigned int width_mm; + unsigned int height_mm; + unsigned int bpc; + int orientation; + const u32 *bus_formats; + unsigned int num_bus_formats; + u32 bus_flags; + struct list_head list; }; -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v4 2/4] drm/panel: set display info in panel attach
Devicetree systems can set panel orientation via a panel binding, but there's no way, as is, to propagate this setting to the connector, where the property need to be added. To address this, this patch sets orientation, as well as other fixed values for the panel, in the drm_panel_attach function. These values are stored from probe in the drm_panel struct. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 28 include/drm/drm_panel.h | 14 ++ 2 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 169bab54d52d..ca01095470a9 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,11 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + struct drm_display_info *info; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + info = &connector->display_info; + info->width_mm = panel->width_mm; + info->height_mm = panel->height_mm; + info->bpc = panel->bpc; + info->panel_orientation = panel->orientation; + info->bus_flags = panel->bus_flags; + if (panel->bus_formats) + drm_display_info_set_bus_formats(&connector->display_info, +panel->bus_formats, +panel->num_bus_formats); return 0; } @@ -128,6 +140,22 @@ EXPORT_SYMBOL(drm_panel_attach); */ int drm_panel_detach(struct drm_panel *panel) { + struct drm_display_info *info; + + if (!panel->connector) + goto out; + + info = &panel->connector->display_info; + info->width_mm = 0; + info->height_mm = 0; + info->bpc = 0; + info->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + info->bus_flags = 0; + kfree(info->bus_formats); + info->bus_formats = NULL; + info->num_bus_formats = 0; + +out: panel->connector = NULL; panel->drm = NULL; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 3564952f1a4f..760ca5865962 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -37,6 +37,8 @@ struct display_timing; * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel + * @detach: detach panel->connector (clear internal state, etc.) + * @attach: attach panel->connector (update internal state, etc.) * @prepare: turn on panel and perform set up * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and @@ -93,6 +95,18 @@ struct drm_panel { const struct drm_panel_funcs *funcs; + /* +* panel information to be set in the connector when the panel is +* attached. +*/ + unsigned int width_mm; + unsigned int height_mm; + unsigned int bpc; + int orientation; + const u32 *bus_formats; + unsigned int num_bus_formats; + u32 bus_flags; + struct list_head list; }; -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v4 1/4] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 43 + include/drm/drm_panel.h | 7 ++ 2 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..169bab54d52d 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -172,6 +172,49 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the orientation of the panel through + * the "rotation" binding from a device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The orientation of the + * panel is expressed as a property name "rotation" in the device tree. The + * rotation in the device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 8c738c0e6e9f..3564952f1a4f 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -197,11 +197,18 @@ int drm_panel_detach(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v4 0/4] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v4 changes: -fixed some changes made to the i915 driver -clarified comments on of orientation helper v3 changes: -changed from attach/detach callbacks to directly setting fixed panel values in drm_panel_attach -removed update to Documentation -added separate function for quirked panel orientation property init v2 changes: fixed build errors in i915 Derek Basehore (4): drm/panel: Add helper for reading DT rotation drm/panel: set display info in panel attach drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property drivers/gpu/drm/drm_connector.c| 45 ++- drivers/gpu/drm/drm_panel.c| 70 ++ drivers/gpu/drm/i915/intel_dp.c| 4 +- drivers/gpu/drm/i915/vlv_dsi.c | 5 +-- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 include/drm/drm_connector.h| 2 + include/drm/drm_panel.h| 21 + 7 files changed, 138 insertions(+), 17 deletions(-) -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v4 3/4] drm/connector: Split out orientation quirk detection
Not every platform needs quirk detection for panel orientation, so split the drm_connector_init_panel_orientation_property into two functions. One for platforms without the need for quirks, and the other for platforms that need quirks. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_connector.c | 45 - drivers/gpu/drm/i915/intel_dp.c | 4 +-- drivers/gpu/drm/i915/vlv_dsi.c | 2 +- include/drm/drm_connector.h | 2 ++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index e17586aaa80f..c4b01adf927a 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1894,31 +1894,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; @@ -1941,6 +1933,35 @@ int drm_connector_init_panel_orientation_property( } EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); +/** + * drm_connector_init_panel_orientation_property_quirk - + * initialize the connecters panel_orientation property with a quirk + * override + * @connector: connector for which to init the panel-orientation property. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * + * This function will check for platform specific (e.g. DMI based) quirks + * overriding display_info.panel_orientation first, then if panel_orientation + * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the + * "panel orientation" property to the connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_init_panel_orientation_property_quirk( + struct drm_connector *connector, int width, int height) +{ + int orientation_quirk; + + orientation_quirk = drm_get_panel_orientation_quirk(width, height); + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = orientation_quirk; + + return drm_connector_init_panel_orientation_property(connector); +} +EXPORT_SYMBOL(drm_connector_init_panel_orientation_property_quirk); + int drm_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b099a9dc28fd..7d4e61cf5463 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -7282,8 +7282,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_panel_setup_backlight(connector, pipe); if (fixed_mode) - drm_connector_init_panel_orientation_property( - connector, fixed_mode->hdisplay, fixed_mode->vdisplay); + drm_connector_init_panel_orientation_property_quirk(connector, + fixed_mode->hdisplay, fixed_mode->vdisplay); return true; diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c index bfe2891eac37..aca99ece045e 100644 --- a/drivers/gpu/drm/i915/vlv_dsi.c +++ b/drivers/gpu/drm/i915/vlv_dsi.c @@ -1662,7 +1662,7 @@ static
[PATCH v4 4/4] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 4a0b9150a7bb..08ffdc7526dd 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -782,10 +782,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.22.0.410.gd8fdbe21b5-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 1/4] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 43 + include/drm/drm_panel.h | 7 ++ 2 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..169bab54d52d 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -172,6 +172,49 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the orientation of the panel through + * the "rotation" binding from a device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The orientation of the + * panel is expressed as a property name "rotation" in the device tree. The + * rotation in the device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 8c738c0e6e9f..3564952f1a4f 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -197,11 +197,18 @@ int drm_panel_detach(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v5 3/4] drm/connector: Split out orientation quirk detection
Not every platform needs quirk detection for panel orientation, so split the drm_connector_init_panel_orientation_property into two functions. One for platforms without the need for quirks, and the other for platforms that need quirks. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_connector.c | 45 ++--- drivers/gpu/drm/i915/display/intel_dp.c | 4 +-- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- include/drm/drm_connector.h | 2 ++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index b3f2cf7eae9c..52777d647494 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1892,31 +1892,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; @@ -1939,6 +1931,35 @@ int drm_connector_init_panel_orientation_property( } EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); +/** + * drm_connector_init_panel_orientation_property_quirk - + * initialize the connecters panel_orientation property with a quirk + * override + * @connector: connector for which to init the panel-orientation property. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * + * This function will check for platform specific (e.g. DMI based) quirks + * overriding display_info.panel_orientation first, then if panel_orientation + * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the + * "panel orientation" property to the connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_init_panel_orientation_property_quirk( + struct drm_connector *connector, int width, int height) +{ + int orientation_quirk; + + orientation_quirk = drm_get_panel_orientation_quirk(width, height); + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = orientation_quirk; + + return drm_connector_init_panel_orientation_property(connector); +} +EXPORT_SYMBOL(drm_connector_init_panel_orientation_property_quirk); + int drm_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8f7188d71d08..45b637419085 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -7068,8 +7068,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_panel_setup_backlight(connector, pipe); if (fixed_mode) - drm_connector_init_panel_orientation_property( - connector, fixed_mode->hdisplay, fixed_mode->vdisplay); + drm_connector_init_panel_orientation_property_quirk(connector, + fixed_mode->hdisplay, fixed_mode->vdisplay); return true; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index e272d826210a..dd7fa806f95c 100644 --- a/drivers/gpu/drm/i91
[PATCH v5 0/4] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v5 changes: -rebased v4 changes: -fixed some changes made to the i915 driver -clarified comments on of orientation helper v3 changes: -changed from attach/detach callbacks to directly setting fixed panel values in drm_panel_attach -removed update to Documentation -added separate function for quirked panel orientation property init v2 changes: fixed build errors in i915 Derek Basehore (4): drm/panel: Add helper for reading DT rotation drm/panel: set display info in panel attach drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property drivers/gpu/drm/drm_connector.c| 45 ++- drivers/gpu/drm/drm_panel.c| 70 ++ drivers/gpu/drm/i915/intel_dp.c| 4 +- drivers/gpu/drm/i915/vlv_dsi.c | 5 +-- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 include/drm/drm_connector.h| 2 + include/drm/drm_panel.h| 21 + 7 files changed, 138 insertions(+), 17 deletions(-) -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v5 4/4] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index b91c4616644a..2920458ae2fb 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -790,10 +790,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.22.0.410.gd8fdbe21b5-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 2/4] drm/panel: set display info in panel attach
Devicetree systems can set panel orientation via a panel binding, but there's no way, as is, to propagate this setting to the connector, where the property need to be added. To address this, this patch sets orientation, as well as other fixed values for the panel, in the drm_panel_attach function. These values are stored from probe in the drm_panel struct. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 28 include/drm/drm_panel.h | 14 ++ 2 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 169bab54d52d..ca01095470a9 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,11 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + struct drm_display_info *info; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + info = &connector->display_info; + info->width_mm = panel->width_mm; + info->height_mm = panel->height_mm; + info->bpc = panel->bpc; + info->panel_orientation = panel->orientation; + info->bus_flags = panel->bus_flags; + if (panel->bus_formats) + drm_display_info_set_bus_formats(&connector->display_info, +panel->bus_formats, +panel->num_bus_formats); return 0; } @@ -128,6 +140,22 @@ EXPORT_SYMBOL(drm_panel_attach); */ int drm_panel_detach(struct drm_panel *panel) { + struct drm_display_info *info; + + if (!panel->connector) + goto out; + + info = &panel->connector->display_info; + info->width_mm = 0; + info->height_mm = 0; + info->bpc = 0; + info->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + info->bus_flags = 0; + kfree(info->bus_formats); + info->bus_formats = NULL; + info->num_bus_formats = 0; + +out: panel->connector = NULL; panel->drm = NULL; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 3564952f1a4f..760ca5865962 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -37,6 +37,8 @@ struct display_timing; * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel + * @detach: detach panel->connector (clear internal state, etc.) + * @attach: attach panel->connector (update internal state, etc.) * @prepare: turn on panel and perform set up * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and @@ -93,6 +95,18 @@ struct drm_panel { const struct drm_panel_funcs *funcs; + /* +* panel information to be set in the connector when the panel is +* attached. +*/ + unsigned int width_mm; + unsigned int height_mm; + unsigned int bpc; + int orientation; + const u32 *bus_formats; + unsigned int num_bus_formats; + u32 bus_flags; + struct list_head list; }; -- 2.22.0.410.gd8fdbe21b5-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 0/4] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v6 changes: -added enum declaration to drm_panel.h header v5 changes: -rebased v4 changes: -fixed some changes made to the i915 driver -clarified comments on of orientation helper v3 changes: -changed from attach/detach callbacks to directly setting fixed panel values in drm_panel_attach -removed update to Documentation -added separate function for quirked panel orientation property init v2 changes: fixed build errors in i915 Derek Basehore (4): drm/panel: Add helper for reading DT rotation drm/panel: set display info in panel attach drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property drivers/gpu/drm/drm_connector.c| 45 ++- drivers/gpu/drm/drm_panel.c| 70 ++ drivers/gpu/drm/i915/intel_dp.c| 4 +- drivers/gpu/drm/i915/vlv_dsi.c | 5 +-- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 include/drm/drm_connector.h| 2 + include/drm/drm_panel.h| 21 + 7 files changed, 138 insertions(+), 17 deletions(-) -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v6 3/4] drm/connector: Split out orientation quirk detection
Not every platform needs quirk detection for panel orientation, so split the drm_connector_init_panel_orientation_property into two functions. One for platforms without the need for quirks, and the other for platforms that need quirks. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_connector.c | 45 ++--- drivers/gpu/drm/i915/display/intel_dp.c | 4 +-- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- include/drm/drm_connector.h | 2 ++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index b3f2cf7eae9c..52777d647494 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1892,31 +1892,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; @@ -1939,6 +1931,35 @@ int drm_connector_init_panel_orientation_property( } EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); +/** + * drm_connector_init_panel_orientation_property_quirk - + * initialize the connecters panel_orientation property with a quirk + * override + * @connector: connector for which to init the panel-orientation property. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * + * This function will check for platform specific (e.g. DMI based) quirks + * overriding display_info.panel_orientation first, then if panel_orientation + * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the + * "panel orientation" property to the connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_init_panel_orientation_property_quirk( + struct drm_connector *connector, int width, int height) +{ + int orientation_quirk; + + orientation_quirk = drm_get_panel_orientation_quirk(width, height); + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = orientation_quirk; + + return drm_connector_init_panel_orientation_property(connector); +} +EXPORT_SYMBOL(drm_connector_init_panel_orientation_property_quirk); + int drm_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8f7188d71d08..45b637419085 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -7068,8 +7068,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_panel_setup_backlight(connector, pipe); if (fixed_mode) - drm_connector_init_panel_orientation_property( - connector, fixed_mode->hdisplay, fixed_mode->vdisplay); + drm_connector_init_panel_orientation_property_quirk(connector, + fixed_mode->hdisplay, fixed_mode->vdisplay); return true; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index e272d826210a..dd7fa806f95c 100644 --- a/drivers/gpu/drm/i91
[PATCH v6 2/4] drm/panel: set display info in panel attach
Devicetree systems can set panel orientation via a panel binding, but there's no way, as is, to propagate this setting to the connector, where the property need to be added. To address this, this patch sets orientation, as well as other fixed values for the panel, in the drm_panel_attach function. These values are stored from probe in the drm_panel struct. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 28 include/drm/drm_panel.h | 14 ++ 2 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 169bab54d52d..ca01095470a9 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,11 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + struct drm_display_info *info; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + info = &connector->display_info; + info->width_mm = panel->width_mm; + info->height_mm = panel->height_mm; + info->bpc = panel->bpc; + info->panel_orientation = panel->orientation; + info->bus_flags = panel->bus_flags; + if (panel->bus_formats) + drm_display_info_set_bus_formats(&connector->display_info, +panel->bus_formats, +panel->num_bus_formats); return 0; } @@ -128,6 +140,22 @@ EXPORT_SYMBOL(drm_panel_attach); */ int drm_panel_detach(struct drm_panel *panel) { + struct drm_display_info *info; + + if (!panel->connector) + goto out; + + info = &panel->connector->display_info; + info->width_mm = 0; + info->height_mm = 0; + info->bpc = 0; + info->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + info->bus_flags = 0; + kfree(info->bus_formats); + info->bus_formats = NULL; + info->num_bus_formats = 0; + +out: panel->connector = NULL; panel->drm = NULL; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index a18c59f136ab..1760c11e0298 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -39,6 +39,8 @@ enum drm_panel_orientation; * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel + * @detach: detach panel->connector (clear internal state, etc.) + * @attach: attach panel->connector (update internal state, etc.) * @prepare: turn on panel and perform set up * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and @@ -95,6 +97,18 @@ struct drm_panel { const struct drm_panel_funcs *funcs; + /* +* panel information to be set in the connector when the panel is +* attached. +*/ + unsigned int width_mm; + unsigned int height_mm; + unsigned int bpc; + int orientation; + const u32 *bus_formats; + unsigned int num_bus_formats; + u32 bus_flags; + struct list_head list; }; -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v6 4/4] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index b91c4616644a..2920458ae2fb 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -790,10 +790,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v6 1/4] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 43 + include/drm/drm_panel.h | 9 2 files changed, 52 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..169bab54d52d 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -172,6 +172,49 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the orientation of the panel through + * the "rotation" binding from a device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The orientation of the + * panel is expressed as a property name "rotation" in the device tree. The + * rotation in the device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 8c738c0e6e9f..a18c59f136ab 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -33,6 +33,8 @@ struct drm_device; struct drm_panel; struct display_timing; +enum drm_panel_orientation; + /** * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) @@ -197,11 +199,18 @@ int drm_panel_detach(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v7 4/4] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index b91c4616644a..2920458ae2fb 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -790,10 +790,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v7 3/4] drm/connector: Split out orientation quirk detection
Not every platform needs quirk detection for panel orientation, so split the drm_connector_init_panel_orientation_property into two functions. One for platforms without the need for quirks, and the other for platforms that need quirks. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_connector.c | 45 ++--- drivers/gpu/drm/i915/display/intel_dp.c | 4 +-- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- include/drm/drm_connector.h | 2 ++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index b3f2cf7eae9c..52777d647494 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1892,31 +1892,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; @@ -1939,6 +1931,35 @@ int drm_connector_init_panel_orientation_property( } EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); +/** + * drm_connector_init_panel_orientation_property_quirk - + * initialize the connecters panel_orientation property with a quirk + * override + * @connector: connector for which to init the panel-orientation property. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * + * This function will check for platform specific (e.g. DMI based) quirks + * overriding display_info.panel_orientation first, then if panel_orientation + * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the + * "panel orientation" property to the connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_init_panel_orientation_property_quirk( + struct drm_connector *connector, int width, int height) +{ + int orientation_quirk; + + orientation_quirk = drm_get_panel_orientation_quirk(width, height); + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = orientation_quirk; + + return drm_connector_init_panel_orientation_property(connector); +} +EXPORT_SYMBOL(drm_connector_init_panel_orientation_property_quirk); + int drm_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0bdb7ecc5a81..975196c86e50 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -7063,8 +7063,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_panel_setup_backlight(connector, pipe); if (fixed_mode) - drm_connector_init_panel_orientation_property( - connector, fixed_mode->hdisplay, fixed_mode->vdisplay); + drm_connector_init_panel_orientation_property_quirk(connector, + fixed_mode->hdisplay, fixed_mode->vdisplay); return true; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index e272d826210a..dd7fa806f95c 100644 --- a/drivers/gpu/drm/i91
[PATCH v7 2/4] drm/panel: set display info in panel attach
Devicetree systems can set panel orientation via a panel binding, but there's no way, as is, to propagate this setting to the connector, where the property need to be added. To address this, this patch sets orientation, as well as other fixed values for the panel, in the drm_panel_attach function. These values are stored from probe in the drm_panel struct. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 28 include/drm/drm_panel.h | 14 ++ 2 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 169bab54d52d..ca01095470a9 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,11 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + struct drm_display_info *info; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + info = &connector->display_info; + info->width_mm = panel->width_mm; + info->height_mm = panel->height_mm; + info->bpc = panel->bpc; + info->panel_orientation = panel->orientation; + info->bus_flags = panel->bus_flags; + if (panel->bus_formats) + drm_display_info_set_bus_formats(&connector->display_info, +panel->bus_formats, +panel->num_bus_formats); return 0; } @@ -128,6 +140,22 @@ EXPORT_SYMBOL(drm_panel_attach); */ int drm_panel_detach(struct drm_panel *panel) { + struct drm_display_info *info; + + if (!panel->connector) + goto out; + + info = &panel->connector->display_info; + info->width_mm = 0; + info->height_mm = 0; + info->bpc = 0; + info->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + info->bus_flags = 0; + kfree(info->bus_formats); + info->bus_formats = NULL; + info->num_bus_formats = 0; + +out: panel->connector = NULL; panel->drm = NULL; diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index fc7da55f41d9..a6a881b987dd 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -39,6 +39,8 @@ enum drm_panel_orientation; * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel + * @detach: detach panel->connector (clear internal state, etc.) + * @attach: attach panel->connector (update internal state, etc.) * @prepare: turn on panel and perform set up * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and @@ -95,6 +97,18 @@ struct drm_panel { const struct drm_panel_funcs *funcs; + /* +* panel information to be set in the connector when the panel is +* attached. +*/ + unsigned int width_mm; + unsigned int height_mm; + unsigned int bpc; + int orientation; + const u32 *bus_formats; + unsigned int num_bus_formats; + u32 bus_flags; + struct list_head list; }; -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v7 1/4] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore --- drivers/gpu/drm/drm_panel.c | 43 + include/drm/drm_panel.h | 9 2 files changed, 52 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..169bab54d52d 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -172,6 +172,49 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the orientation of the panel through + * the "rotation" binding from a device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The orientation of the + * panel is expressed as a property name "rotation" in the device tree. The + * rotation in the device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 8c738c0e6e9f..fc7da55f41d9 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -33,6 +33,8 @@ struct drm_device; struct drm_panel; struct display_timing; +enum drm_panel_orientation; + /** * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) @@ -197,11 +199,18 @@ int drm_panel_detach(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +static inline int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v7 0/4] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v7 changes: -forgot to add static inline v6 changes: -added enum declaration to drm_panel.h header v5 changes: -rebased v4 changes: -fixed some changes made to the i915 driver -clarified comments on of orientation helper v3 changes: -changed from attach/detach callbacks to directly setting fixed panel values in drm_panel_attach -removed update to Documentation -added separate function for quirked panel orientation property init v2 changes: fixed build errors in i915 Derek Basehore (4): drm/panel: Add helper for reading DT rotation drm/panel: set display info in panel attach drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property drivers/gpu/drm/drm_connector.c| 45 ++- drivers/gpu/drm/drm_panel.c| 70 ++ drivers/gpu/drm/i915/intel_dp.c| 4 +- drivers/gpu/drm/i915/vlv_dsi.c | 5 +-- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 include/drm/drm_connector.h| 2 + include/drm/drm_panel.h| 21 + 7 files changed, 138 insertions(+), 17 deletions(-) -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v10 0/2] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v10 changes: -Adapted to drm_panel_attach changes, so panel orientation is now set for the connector in get_modes -Dropped patch that was already accepted v9 changes: -Changed to copying display properties from another copy of drm_display_info in drm_panel_attach. v8 changes: -added reviewed-by tags -fixed conflict with i915 patch that recently landed -Added additional documentation v7 changes: -forgot to add static inline v6 changes: -added enum declaration to drm_panel.h header v5 changes: -rebased v4 changes: -fixed some changes made to the i915 driver -clarified comments on of orientation helper v3 changes: -changed from attach/detach callbacks to directly setting fixed panel values in drm_panel_attach -removed update to Documentation -added separate function for quirked panel orientation property init v2 changes: fixed build errors in i915 Derek Basehore (4): drm/panel: Add helper for reading DT rotation drm/panel: set display info in panel attach drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property drivers/gpu/drm/drm_connector.c| 45 ++- drivers/gpu/drm/drm_panel.c| 70 ++ drivers/gpu/drm/i915/intel_dp.c| 4 +- drivers/gpu/drm/i915/vlv_dsi.c | 5 +-- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 include/drm/drm_connector.h| 2 + include/drm/drm_panel.h| 21 + 7 files changed, 138 insertions(+), 17 deletions(-) -- 2.22.0.410.gd8fdbe21b5-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v10 1/2] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore Reviewed-by: Sam Ravnborg --- drivers/gpu/drm/drm_panel.c | 43 + include/drm/drm_panel.h | 9 2 files changed, 52 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 8c7bac85a793..5557c75301f1 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -300,6 +300,49 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the orientation of the panel through + * the "rotation" binding from a device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The orientation of the + * panel is expressed as a property name "rotation" in the device tree. The + * rotation in the device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif #if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE) diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 6193cb555acc..781c735f0f9b 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -35,6 +35,8 @@ struct drm_device; struct drm_panel; struct display_timing; +enum drm_panel_orientation; + /** * struct drm_panel_funcs - perform operations on a given panel * @@ -191,11 +193,18 @@ int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +static inline int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #if IS_ENABLED(CONFIG_DRM_PANEL) && (IS_BUILTIN(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ -- 2.25.0.265.gbab2e86ba0-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v10 2/2] drm/panel: read panel orientation for BOE tv101wum-nl6
This reads the DT setting for the panel rotation to set the panel orientation in the get_modes callback. Signed-off-by: Derek Basehore --- drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index 48a164257d18..ee2d96413900 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,7 @@ struct boe_panel { const struct panel_desc *desc; + enum drm_panel_orientation orientation; struct regulator *pp1800; struct regulator *avee; struct regulator *avdd; @@ -717,6 +719,7 @@ static int boe_panel_get_modes(struct drm_panel *panel, connector->display_info.width_mm = boe->desc->size.width_mm; connector->display_info.height_mm = boe->desc->size.height_mm; connector->display_info.bpc = boe->desc->bpc; + drm_connector_set_panel_orientation(connector, boe->orientation); return 1; } @@ -756,6 +759,9 @@ static int boe_panel_add(struct boe_panel *boe) drm_panel_init(&boe->base, dev, &boe_panel_funcs, DRM_MODE_CONNECTOR_DSI); + err = of_drm_get_panel_orientation(dev->of_node, &boe->orientation); + if (err < 0) + return err; err = drm_panel_of_backlight(&boe->base); if (err) -- 2.25.0.265.gbab2e86ba0-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v8 0/4] Panel rotation patches
This adds the plumbing for reading panel rotation from the devicetree and sets up adding a panel property for the panel orientation on Mediatek SoCs when a rotation is present. v8 changes: -added reviewed-by tags -fixed conflict with i915 patch that recently landed -Added additional documentation v7 changes: -forgot to add static inline v6 changes: -added enum declaration to drm_panel.h header v5 changes: -rebased v4 changes: -fixed some changes made to the i915 driver -clarified comments on of orientation helper v3 changes: -changed from attach/detach callbacks to directly setting fixed panel values in drm_panel_attach -removed update to Documentation -added separate function for quirked panel orientation property init v2 changes: fixed build errors in i915 Derek Basehore (4): drm/panel: Add helper for reading DT rotation drm/panel: set display info in panel attach drm/connector: Split out orientation quirk detection drm/mtk: add panel orientation property drivers/gpu/drm/drm_connector.c| 45 ++- drivers/gpu/drm/drm_panel.c| 70 ++ drivers/gpu/drm/i915/intel_dp.c| 4 +- drivers/gpu/drm/i915/vlv_dsi.c | 5 +-- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 include/drm/drm_connector.h| 2 + include/drm/drm_panel.h| 21 + 7 files changed, 138 insertions(+), 17 deletions(-) -- 2.22.0.410.gd8fdbe21b5-goog
[PATCH v8 3/4] drm/connector: Split out orientation quirk detection
Not every platform needs quirk detection for panel orientation, so split the drm_connector_init_panel_orientation_property into two functions. One for platforms without the need for quirks, and the other for platforms that need quirks. Signed-off-by: Derek Basehore Acked-by: Sam Ravnborg --- drivers/gpu/drm/drm_connector.c | 45 ++--- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 4 +-- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- include/drm/drm_connector.h | 2 ++ 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 4c766624b20d..faef25683faf 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1989,31 +1989,23 @@ EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); * drm_connector_init_panel_orientation_property - * initialize the connecters panel_orientation property * @connector: connector for which to init the panel-orientation property. - * @width: width in pixels of the panel, used for panel quirk detection - * @height: height in pixels of the panel, used for panel quirk detection * * This function should only be called for built-in panels, after setting * connector->display_info.panel_orientation first (if known). * - * This function will check for platform specific (e.g. DMI based) quirks - * overriding display_info.panel_orientation first, then if panel_orientation - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the - * "panel orientation" property to the connector. + * This function will check if the panel_orientation is not + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN. If not, it will attach the "panel + * orientation" property to the connector. * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_init_panel_orientation_property( - struct drm_connector *connector, int width, int height) + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_display_info *info = &connector->display_info; struct drm_property *prop; - int orientation_quirk; - - orientation_quirk = drm_get_panel_orientation_quirk(width, height); - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) - info->panel_orientation = orientation_quirk; if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return 0; @@ -2036,6 +2028,35 @@ int drm_connector_init_panel_orientation_property( } EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); +/** + * drm_connector_init_panel_orientation_property_quirk - + * initialize the connecters panel_orientation property with a quirk + * override + * @connector: connector for which to init the panel-orientation property. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * + * This function will check for platform specific (e.g. DMI based) quirks + * overriding display_info.panel_orientation first, then if panel_orientation + * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the + * "panel orientation" property to the connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_init_panel_orientation_property_quirk( + struct drm_connector *connector, int width, int height) +{ + int orientation_quirk; + + orientation_quirk = drm_get_panel_orientation_quirk(width, height); + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + connector->display_info.panel_orientation = orientation_quirk; + + return drm_connector_init_panel_orientation_property(connector); +} +EXPORT_SYMBOL(drm_connector_init_panel_orientation_property_quirk); + int drm_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 6e398c33a524..483287984090 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1538,7 +1538,7 @@ static void icl_dsi_add_properties(struct intel_connector *connector) connector->base.display_info.panel_orientation = intel_dsi_get_panel_orientation(connector); - drm_connector_init_panel_orientation_property(&connector->base, + drm_connector_init_panel_orientation_property_quirk(&connector->base, connector->panel.fixed_mode->hdisplay, connector->panel.fixed_mode->vdisplay); } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
[PATCH v8 2/4] drm/panel: set display info in panel attach
Devicetree systems can set panel orientation via a panel binding, but there's no way, as is, to propagate this setting to the connector, where the property need to be added. To address this, this patch sets orientation, as well as other fixed values for the panel, in the drm_panel_attach function. These values are stored from probe in the drm_panel struct. Signed-off-by: Derek Basehore Reviewed-by: Sam Ravnborg --- drivers/gpu/drm/drm_panel.c | 28 + include/drm/drm_panel.h | 50 + 2 files changed, 78 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 0909b53b74e6..1cd2b56c9fe6 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -104,11 +104,23 @@ EXPORT_SYMBOL(drm_panel_remove); */ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) { + struct drm_display_info *info; + if (panel->connector) return -EBUSY; panel->connector = connector; panel->drm = connector->dev; + info = &connector->display_info; + info->width_mm = panel->width_mm; + info->height_mm = panel->height_mm; + info->bpc = panel->bpc; + info->panel_orientation = panel->orientation; + info->bus_flags = panel->bus_flags; + if (panel->bus_formats) + drm_display_info_set_bus_formats(&connector->display_info, +panel->bus_formats, +panel->num_bus_formats); return 0; } @@ -126,6 +138,22 @@ EXPORT_SYMBOL(drm_panel_attach); */ void drm_panel_detach(struct drm_panel *panel) { + struct drm_display_info *info; + + if (!panel->connector) + goto out; + + info = &panel->connector->display_info; + info->width_mm = 0; + info->height_mm = 0; + info->bpc = 0; + info->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + info->bus_flags = 0; + kfree(info->bus_formats); + info->bus_formats = NULL; + info->num_bus_formats = 0; + +out: panel->connector = NULL; panel->drm = NULL; } diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index d16158deacdc..f3587a54b8ac 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -141,6 +141,56 @@ struct drm_panel { */ const struct drm_panel_funcs *funcs; + /** +* @width_mm: +* +* Physical width in mm. +*/ + unsigned int width_mm; + + /** +* @height_mm: +* +* Physical height in mm. +*/ + unsigned int height_mm; + + /** +* @bpc: +* +* Maximum bits per color channel. Used by HDMI and DP outputs. +*/ + unsigned int bpc; + + /** +* @orientation +* +* Installation orientation of the panel with respect to the chassis. +*/ + int orientation; + + /** +* @bus_formats +* +* Pixel data format on the wire. +*/ + const u32 *bus_formats; + + /** +* @num_bus_formats: +* +* Number of elements pointed to by @bus_formats +*/ + unsigned int num_bus_formats; + + /** +* @bus_flags: +* +* Additional information (like pixel signal polarity) for the pixel +* data on the bus. +*/ + u32 bus_flags; + /** * @list: * -- 2.23.0.351.gc4317032e6-goog
[PATCH v8 1/4] drm/panel: Add helper for reading DT rotation
This adds a helper function for reading the rotation (panel orientation) from the device tree. Signed-off-by: Derek Basehore Reviewed-by: Sam Ravnborg --- drivers/gpu/drm/drm_panel.c | 43 + include/drm/drm_panel.h | 9 2 files changed, 52 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 6b0bf42039cf..0909b53b74e6 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -264,6 +264,49 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the orientation of the panel through + * the "rotation" binding from a device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The orientation of the + * panel is expressed as a property name "rotation" in the device tree. The + * rotation in the device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. -EERROR otherwise. + */ +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 624bd15ecfab..d16158deacdc 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -34,6 +34,8 @@ struct drm_device; struct drm_panel; struct display_timing; +enum drm_panel_orientation; + /** * struct drm_panel_funcs - perform operations on a given panel * @@ -165,11 +167,18 @@ int drm_panel_get_modes(struct drm_panel *panel); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, +enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } +static inline int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #endif -- 2.23.0.351.gc4317032e6-goog
[PATCH v8 4/4] drm/mtk: add panel orientation property
This inits the panel orientation property for the mediatek dsi driver if the panel orientation (connector.display_info.panel_orientation) is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN. Signed-off-by: Derek Basehore Acked-by: Sam Ravnborg Reviewed-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 224afb666881..2936932344eb 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -792,10 +792,18 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) DRM_ERROR("Failed to attach panel to drm\n"); goto err_connector_cleanup; } + + ret = drm_connector_init_panel_orientation_property(&dsi->conn); + if (ret) { + DRM_ERROR("Failed to init panel orientation\n"); + goto err_panel_detach; + } } return 0; +err_panel_detach: + drm_panel_detach(dsi->panel); err_connector_cleanup: drm_connector_cleanup(&dsi->conn); return ret; -- 2.23.0.351.gc4317032e6-goog
[PATCH v11 0/4] Allow USB devices to remain runtime-suspended when sleeping
On Mon, Nov 02, 2015 at 02:50:40AM +0100, Rafael J. Wysocki wrote: > > I've queued up this series for the second half of the v4.4 merge window. > > Thanks, > Rafael > > > ___ > linux-arm-kernel mailing list > linux-arm-kernel at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel What's the status of this patch series? I haven't seen the patches posted for v4.4, plus there's the issue that Dan found that needs to be addressed. Is there a new revision of the patch series being worked on?
[PATCH] drm/connector: hdmi: Increase HDMI_MAX_INFOFRAME_SIZE to 30
The DRM infoframe is 26 bytes, with a 4 byte header this gives us 30. The current limit of 29 prevents us from writing DRM infoframes. Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 2 +- drivers/gpu/drm/drm_debugfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 7854820089ec..cc7747d33fdf 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -521,7 +521,7 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); -#define HDMI_MAX_INFOFRAME_SIZE29 +#define HDMI_MAX_INFOFRAME_SIZE30 static int clear_device_infoframe(struct drm_connector *connector, enum hdmi_infoframe_type type) diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 6b239a24f1df..3439fd65275a 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -520,7 +520,7 @@ static const struct file_operations drm_connector_fops = { .write = connector_write }; -#define HDMI_MAX_INFOFRAME_SIZE29 +#define HDMI_MAX_INFOFRAME_SIZE30 static ssize_t audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) -- 2.45.2
[PATCH v2] drm/connector: hdmi: Increase HDMI_MAX_INFOFRAME_SIZE to 30
The largest infoframe we create is the DRM (Dynamic Range Mastering) infoframe which is 26 bytes + a 4 byte header, for a total of 30 bytes. With HDMI_MAX_INFOFRAME_SIZE set to 29 bytes, as it is now, we allocate too little space to pack a DRM infoframe in write_device_infoframe(), leading to an ENOSPC return from hdmi_infoframe_pack(), and never calling the connector's write_infoframe() vfunc. Increase HDMI_MAX_INFOFRAME_SIZE to 30 so we can successfully write DRM infoframes. The drm_debugfs code is similarly updated. Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 2 +- drivers/gpu/drm/drm_debugfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 7854820089ec..cc7747d33fdf 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -521,7 +521,7 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); -#define HDMI_MAX_INFOFRAME_SIZE29 +#define HDMI_MAX_INFOFRAME_SIZE30 static int clear_device_infoframe(struct drm_connector *connector, enum hdmi_infoframe_type type) diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 6b239a24f1df..3439fd65275a 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -520,7 +520,7 @@ static const struct file_operations drm_connector_fops = { .write = connector_write }; -#define HDMI_MAX_INFOFRAME_SIZE29 +#define HDMI_MAX_INFOFRAME_SIZE30 static ssize_t audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) -- 2.45.2
[PATCH v3] drm/connector: hdmi: Fix writing Dynamic Range Mastering infoframes
The largest infoframe we create is the DRM (Dynamic Range Mastering) infoframe which is 26 bytes + a 4 byte header, for a total of 30 bytes. With HDMI_MAX_INFOFRAME_SIZE set to 29 bytes, as it is now, we allocate too little space to pack a DRM infoframe in write_device_infoframe(), leading to an ENOSPC return from hdmi_infoframe_pack(), and never calling the connector's write_infoframe() vfunc. Instead of having HDMI_MAX_INFOFRAME_SIZE defined in two places, replace HDMI_MAX_INFOFRAME_SIZE with HDMI_INFOFRAME_SIZE(MAX) and make MAX the same size as the DRM infoframe. Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 4 +--- drivers/gpu/drm/drm_debugfs.c | 4 +--- include/linux/hdmi.h| 3 +++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 7854820089ec..feb7a3a75981 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -521,8 +521,6 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); -#define HDMI_MAX_INFOFRAME_SIZE29 - static int clear_device_infoframe(struct drm_connector *connector, enum hdmi_infoframe_type type) { @@ -563,7 +561,7 @@ static int write_device_infoframe(struct drm_connector *connector, { const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; struct drm_device *dev = connector->dev; - u8 buffer[HDMI_MAX_INFOFRAME_SIZE]; + u8 buffer[HDMI_INFOFRAME_SIZE(MAX)]; int ret; int len; diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 6b239a24f1df..9d3e6dd68810 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -520,8 +520,6 @@ static const struct file_operations drm_connector_fops = { .write = connector_write }; -#define HDMI_MAX_INFOFRAME_SIZE29 - static ssize_t audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) { @@ -579,7 +577,7 @@ static ssize_t _f##_read_infoframe(struct file *filp, \ struct drm_connector *connector; \ union hdmi_infoframe *frame; \ struct drm_device *dev; \ - u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \ + u8 buf[HDMI_INFOFRAME_SIZE(MAX)]; \ ssize_t len = 0; \ \ connector = filp->private_data; \ diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 3bb87bf6bc65..3a442a59919e 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -59,6 +59,9 @@ enum hdmi_infoframe_type { #define HDMI_DRM_INFOFRAME_SIZE26 #define HDMI_VENDOR_INFOFRAME_SIZE 4 +/* The biggest infoframe size */ +#define HDMI_MAX_INFOFRAME_SIZEHDMI_DRM_INFOFRAME_SIZE + #define HDMI_INFOFRAME_SIZE(type) \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) -- 2.45.2
Re: [PATCH v3] drm/connector: hdmi: Fix writing Dynamic Range Mastering infoframes
On 2024-08-27 05:19, Jani Nikula wrote: On Tue, 27 Aug 2024, Maxime Ripard wrote: Hi, On Mon, Aug 26, 2024 at 07:10:11AM GMT, Derek Foreman wrote: The largest infoframe we create is the DRM (Dynamic Range Mastering) infoframe which is 26 bytes + a 4 byte header, for a total of 30 bytes. With HDMI_MAX_INFOFRAME_SIZE set to 29 bytes, as it is now, we allocate too little space to pack a DRM infoframe in write_device_infoframe(), leading to an ENOSPC return from hdmi_infoframe_pack(), and never calling the connector's write_infoframe() vfunc. Instead of having HDMI_MAX_INFOFRAME_SIZE defined in two places, replace HDMI_MAX_INFOFRAME_SIZE with HDMI_INFOFRAME_SIZE(MAX) and make MAX the same size as the DRM infoframe. Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 4 +--- drivers/gpu/drm/drm_debugfs.c | 4 +--- include/linux/hdmi.h| 3 +++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 7854820089ec..feb7a3a75981 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -521,8 +521,6 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); -#define HDMI_MAX_INFOFRAME_SIZE 29 - static int clear_device_infoframe(struct drm_connector *connector, enum hdmi_infoframe_type type) { @@ -563,7 +561,7 @@ static int write_device_infoframe(struct drm_connector *connector, { const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; struct drm_device *dev = connector->dev; - u8 buffer[HDMI_MAX_INFOFRAME_SIZE]; + u8 buffer[HDMI_INFOFRAME_SIZE(MAX)]; int ret; int len; diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 6b239a24f1df..9d3e6dd68810 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -520,8 +520,6 @@ static const struct file_operations drm_connector_fops = { .write = connector_write }; -#define HDMI_MAX_INFOFRAME_SIZE 29 - static ssize_t audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) { @@ -579,7 +577,7 @@ static ssize_t _f##_read_infoframe(struct file *filp, \ struct drm_connector *connector; \ union hdmi_infoframe *frame; \ struct drm_device *dev; \ - u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \ + u8 buf[HDMI_INFOFRAME_SIZE(MAX)]; \ ssize_t len = 0; \ \ connector = filp->private_data; \ diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 3bb87bf6bc65..3a442a59919e 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -59,6 +59,9 @@ enum hdmi_infoframe_type { #define HDMI_DRM_INFOFRAME_SIZE26 #define HDMI_VENDOR_INFOFRAME_SIZE 4 +/* The biggest infoframe size */ +#define HDMI_MAX_INFOFRAME_SIZEHDMI_DRM_INFOFRAME_SIZE Thanks for that patch, it was definitely an oversight on my part. The spec defines the max size of an infoframe to be 30 bytes, so we should probably use that here? Hmm, I think the spec (I'm looking at 1.3a, which I think is the latest freely available version from hdmi.org?) says a maximum length of 27 bytes, not including the 3 byte header + the checksum byte. So I think 31? I'm seeing this in section 5.3.5 / Table 5-14. Defining it like this allows the use of HDMI_INFOFRAME_SIZE(MAX) which adds the header size. Having some macros include the header size and some others not would be confusing, I think. Or then the whole thing needs to be renamed. How about: #define HDMI_MAX_INFOFRAME_SIZE 27 Then we can use HDMI_DRM_INFOFRAME_SIZE(MAX) to get 31 Would that be ok? Thanks, Derek BR, Jani. Maxime
[PATCH v4] drm/connector: hdmi: Fix writing Dynamic Range Mastering infoframes
The largest infoframe we create is the DRM (Dynamic Range Mastering) infoframe which is 26 bytes + a 4 byte header, for a total of 30 bytes. With HDMI_MAX_INFOFRAME_SIZE set to 29 bytes, as it is now, we allocate too little space to pack a DRM infoframe in write_device_infoframe(), leading to an ENOSPC return from hdmi_infoframe_pack(), and never calling the connector's write_infoframe() vfunc. Instead of having HDMI_MAX_INFOFRAME_SIZE defined in two places, replace HDMI_MAX_INFOFRAME_SIZE with HDMI_INFOFRAME_SIZE(MAX) and make MAX 27 bytes - which is defined by the HDMI specification to be the largest infoframe payload. Fixes: f378b77227bc ("drm/connector: hdmi: Add Infoframes generation") Fixes: c602e4959a0c ("drm/connector: hdmi: Create Infoframe DebugFS entries") Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 4 +--- drivers/gpu/drm/drm_debugfs.c | 4 +--- include/linux/hdmi.h| 9 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 7854820089ec..feb7a3a75981 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -521,8 +521,6 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); -#define HDMI_MAX_INFOFRAME_SIZE29 - static int clear_device_infoframe(struct drm_connector *connector, enum hdmi_infoframe_type type) { @@ -563,7 +561,7 @@ static int write_device_infoframe(struct drm_connector *connector, { const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; struct drm_device *dev = connector->dev; - u8 buffer[HDMI_MAX_INFOFRAME_SIZE]; + u8 buffer[HDMI_INFOFRAME_SIZE(MAX)]; int ret; int len; diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 6b239a24f1df..9d3e6dd68810 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -520,8 +520,6 @@ static const struct file_operations drm_connector_fops = { .write = connector_write }; -#define HDMI_MAX_INFOFRAME_SIZE29 - static ssize_t audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) { @@ -579,7 +577,7 @@ static ssize_t _f##_read_infoframe(struct file *filp, \ struct drm_connector *connector; \ union hdmi_infoframe *frame; \ struct drm_device *dev; \ - u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \ + u8 buf[HDMI_INFOFRAME_SIZE(MAX)]; \ ssize_t len = 0; \ \ connector = filp->private_data; \ diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 3bb87bf6bc65..455f855bc084 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -59,6 +59,15 @@ enum hdmi_infoframe_type { #define HDMI_DRM_INFOFRAME_SIZE26 #define HDMI_VENDOR_INFOFRAME_SIZE 4 +/* + * HDMI 1.3a table 5-14 states that the largest InfoFrame_length is 27, + * not including the packet header or checksum byte. We include the + * checksum byte in HDMI_INFOFRAME_HEADER_SIZE, so this should allow + * HDMI_INFOFRAME_SIZE(MAX) to be the largest buffer we could ever need + * for any HDMI infoframe. + */ +#define HDMI_MAX_INFOFRAME_SIZE27 + #define HDMI_INFOFRAME_SIZE(type) \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) -- 2.45.2
Re: [PATCH v4] drm/connector: hdmi: Fix writing Dynamic Range Mastering infoframes
Gentle ping - is there anything more I need to do before this can land? Thanks, Derek On 2024-08-28 03:31, Jani Nikula wrote: On Tue, 27 Aug 2024, Derek Foreman wrote: The largest infoframe we create is the DRM (Dynamic Range Mastering) infoframe which is 26 bytes + a 4 byte header, for a total of 30 bytes. With HDMI_MAX_INFOFRAME_SIZE set to 29 bytes, as it is now, we allocate too little space to pack a DRM infoframe in write_device_infoframe(), leading to an ENOSPC return from hdmi_infoframe_pack(), and never calling the connector's write_infoframe() vfunc. Instead of having HDMI_MAX_INFOFRAME_SIZE defined in two places, replace HDMI_MAX_INFOFRAME_SIZE with HDMI_INFOFRAME_SIZE(MAX) and make MAX 27 bytes - which is defined by the HDMI specification to be the largest infoframe payload. Fixes: f378b77227bc ("drm/connector: hdmi: Add Infoframes generation") Fixes: c602e4959a0c ("drm/connector: hdmi: Create Infoframe DebugFS entries") Superfluous blank line. Can be fixed while applying. Reviewed-by: Jani Nikula Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 4 +--- drivers/gpu/drm/drm_debugfs.c | 4 +--- include/linux/hdmi.h| 9 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 7854820089ec..feb7a3a75981 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -521,8 +521,6 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); -#define HDMI_MAX_INFOFRAME_SIZE 29 - static int clear_device_infoframe(struct drm_connector *connector, enum hdmi_infoframe_type type) { @@ -563,7 +561,7 @@ static int write_device_infoframe(struct drm_connector *connector, { const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; struct drm_device *dev = connector->dev; - u8 buffer[HDMI_MAX_INFOFRAME_SIZE]; + u8 buffer[HDMI_INFOFRAME_SIZE(MAX)]; int ret; int len; diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 6b239a24f1df..9d3e6dd68810 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -520,8 +520,6 @@ static const struct file_operations drm_connector_fops = { .write = connector_write }; -#define HDMI_MAX_INFOFRAME_SIZE 29 - static ssize_t audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) { @@ -579,7 +577,7 @@ static ssize_t _f##_read_infoframe(struct file *filp, \ struct drm_connector *connector; \ union hdmi_infoframe *frame; \ struct drm_device *dev; \ - u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \ + u8 buf[HDMI_INFOFRAME_SIZE(MAX)]; \ ssize_t len = 0; \ \ connector = filp->private_data; \ diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 3bb87bf6bc65..455f855bc084 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -59,6 +59,15 @@ enum hdmi_infoframe_type { #define HDMI_DRM_INFOFRAME_SIZE26 #define HDMI_VENDOR_INFOFRAME_SIZE 4 +/* + * HDMI 1.3a table 5-14 states that the largest InfoFrame_length is 27, + * not including the packet header or checksum byte. We include the + * checksum byte in HDMI_INFOFRAME_HEADER_SIZE, so this should allow + * HDMI_INFOFRAME_SIZE(MAX) to be the largest buffer we could ever need + * for any HDMI infoframe. + */ +#define HDMI_MAX_INFOFRAME_SIZE27 + #define HDMI_INFOFRAME_SIZE(type) \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE)
[PATCH] drm/connector: Allow clearing hdr infoframe
When a display isn't presenting HDR content, the infoframe shouldn't be present at all. Currently if we set the HDR_OUTPUT_METADATA blob, we'll set a Dynamic Range and Mastering (DRM) infoframe. If we remove that blob later, the DRM infoframe will linger in its previous state, when we expect it to clear. Disable the infoframe when no output metadata is present to prevent this from happening. Fixes: f378b77227bc4 ("drm/connector: hdmi: Add Infoframes generation") Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index feb7a3a75981..1cc4b49b1013 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -398,6 +398,8 @@ static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector, &infoframe->data.drm; int ret; + infoframe->set = false; + if (connector->max_bpc < 10) return 0; -- 2.45.2
Re: [PATCH] drm/connector: Allow clearing hdr infoframe
On 2024-11-29 17:40, Dmitry Baryshkov wrote: On Fri, Nov 29, 2024 at 03:38:01PM -0600, Derek Foreman wrote: When a display isn't presenting HDR content, the infoframe shouldn't be present at all. Currently if we set the HDR_OUTPUT_METADATA blob, we'll set a Dynamic Range and Mastering (DRM) infoframe. If we remove that blob later, the DRM infoframe will linger in its previous state, when we expect it to clear. Disable the infoframe when no output metadata is present to prevent this from happening. Fixes: f378b77227bc4 ("drm/connector: hdmi: Add Infoframes generation") Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 2 ++ 1 file changed, 2 insertions(+) The fix is fine, however please consider extending it to other infoframe types. Clear infoframe->set in the beginning of the corresponding function. I thought that might be the case, but the other infoframes looked like they would only be cleared if there was an error, where the DRM infoframe was the only one that must be intentionally cleared. I wasn't certain if it was better to leave a stale infoframe in the highly unlikely case that creating the new one caused an error, or to have the infoframe disappear entirely. I'll make a new patch to replace this one, and include AVI, SPD, and VSIF infoframes this time. Thanks, Derek diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index feb7a3a75981..1cc4b49b1013 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -398,6 +398,8 @@ static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector, &infoframe->data.drm; int ret; + infoframe->set = false; + if (connector->max_bpc < 10) return 0; -- 2.45.2
[PATCH] drm/connector: Allow clearing HDMI infoframes
Our infoframe setting code currently lacks the ability to clear infoframes. For some of the infoframes, we only need to replace them, so if an error occurred when generating a new infoframe we would leave a stale frame instead of clearing the frame. However, the Dynamic Range and Mastering (DRM) infoframe should only be present when displaying HDR content (ie: the HDR_OUTPUT_METADATA blob is set). If we can't clear infoframes, the stale DRM infoframe will remain and we can never set the display back to SDR mode. With this change, we clear infoframes when they can not, or should not, be generated. This fixes switching to an SDR mode from an HDR one. Fixes: f378b77227bc4 ("drm/connector: hdmi: Add Infoframes generation") Signed-off-by: Derek Foreman --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index feb7a3a75981..936a8f95d80f 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -347,6 +347,8 @@ static int hdmi_generate_avi_infoframe(const struct drm_connector *connector, is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL; int ret; + infoframe->set = false; + ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode); if (ret) return ret; @@ -376,6 +378,8 @@ static int hdmi_generate_spd_infoframe(const struct drm_connector *connector, &infoframe->data.spd; int ret; + infoframe->set = false; + ret = hdmi_spd_infoframe_init(frame, connector->hdmi.vendor, connector->hdmi.product); @@ -398,6 +402,8 @@ static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector, &infoframe->data.drm; int ret; + infoframe->set = false; + if (connector->max_bpc < 10) return 0; @@ -425,6 +431,8 @@ static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector *conne &infoframe->data.vendor.hdmi; int ret; + infoframe->set = false; + if (!info->has_hdmi_infoframe) return 0; -- 2.45.2
Re: [PATCH] drm/connector: Allow clearing HDMI infoframes
Just a ping - is there anything further I need to do here? On 2024-12-03 03:45, AngeloGioacchino Del Regno wrote: Il 02/12/24 19:19, Derek Foreman ha scritto: Our infoframe setting code currently lacks the ability to clear infoframes. For some of the infoframes, we only need to replace them, so if an error occurred when generating a new infoframe we would leave a stale frame instead of clearing the frame. However, the Dynamic Range and Mastering (DRM) infoframe should only be present when displaying HDR content (ie: the HDR_OUTPUT_METADATA blob is set). If we can't clear infoframes, the stale DRM infoframe will remain and we can never set the display back to SDR mode. With this change, we clear infoframes when they can not, or should not, be generated. This fixes switching to an SDR mode from an HDR one. Fixes: f378b77227bc4 ("drm/connector: hdmi: Add Infoframes generation") Signed-off-by: Derek Foreman Reviewed-by: AngeloGioacchino Del Regno
[PATCH] drm/rockchip: Don't change hdmi reference clock rate
The code that changes hdmi->ref_clk was accidentally copied from downstream code that sets a different clock. We don't actually want to set any clock here at all. Setting this clock incorrectly leads to incorrect timings for DDC, CEC, and HDCP signal generation. No Fixes listed, as the theoretical timing error in DDC appears to still be within tolerances and harmless - and HDCP and CEC are not yet supported. Signed-off-by: Derek Foreman --- drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 13 - 1 file changed, 13 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c index e498767a0a66..cebd72bf1ef2 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c @@ -54,7 +54,6 @@ struct rockchip_hdmi_qp { struct regmap *regmap; struct regmap *vo_regmap; struct rockchip_encoder encoder; - struct clk *ref_clk; struct dw_hdmi_qp *hdmi; struct phy *phy; struct gpio_desc *enable_gpio; @@ -81,7 +80,6 @@ static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder) if (crtc && crtc->state) { rate = drm_hdmi_compute_mode_clock(&crtc->state->adjusted_mode, 8, HDMI_COLORSPACE_RGB); - clk_set_rate(hdmi->ref_clk, rate); /* * FIXME: Temporary workaround to pass pixel clock rate * to the PHY driver until phy_configure_opts_hdmi @@ -330,17 +328,6 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, return ret; } - for (i = 0; i < ret; i++) { - if (!strcmp(clks[i].id, "ref")) { - hdmi->ref_clk = clks[1].clk; - break; - } - } - if (!hdmi->ref_clk) { - drm_err(hdmi, "Missing ref clock\n"); - return -EINVAL; - } - hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(hdmi->enable_gpio)) { -- 2.45.2