[Intel-gfx] [PATCH 2/3] pwm: lpss: Add intel-gfx as consumer device in lookup table
v2: Rebase on latest code and correct the device name in lookup table (viric) Remove lookup table on driver remove Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96571 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90075 Cc: cbroo...@gmail.com Cc: jani.nik...@linux.intel.com Tested-by: Lluís Batlle i Rossell <vi...@viric.name> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/pwm/pwm-lpss-platform.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 5d6ed15..f157a6d 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -40,6 +40,11 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = { .bypass = true, }; +/* PWM consumed by the Intel GFX */ +static struct pwm_lookup lpss_pwm_lookup[] = { + PWM_LOOKUP("80860F09:00", 0, ":00:02.0", "pwm_lpss", 0, PWM_POLARITY_NORMAL), +}; + static int pwm_lpss_probe_platform(struct platform_device *pdev) { const struct pwm_lpss_boardinfo *info; @@ -60,6 +65,9 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev) platform_set_drvdata(pdev, lpwm); + /* Register intel-gfx device as allowed consumer */ + pwm_add_table(lpss_pwm_lookup, ARRAY_SIZE(lpss_pwm_lookup)); + pm_runtime_set_active(>dev); pm_runtime_enable(>dev); @@ -71,6 +79,10 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev) struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev); pm_runtime_disable(>dev); + + /* remove lookup table */ + pwm_remove_table(lpss_pwm_lookup, ARRAY_SIZE(lpss_pwm_lookup)); + return pwm_lpss_remove(lpwm); } -- 2.7.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/3] drm/i915: Add support for LPSS PWM on devices that support it
v2: Add bugzilla links Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96571 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90075 Cc: cbroo...@gmail.com Cc: jani.nik...@linux.intel.com Tested-by: Lluís Batlle i Rossell <vi...@viric.name> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_panel.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index d56d1c2..4d84c561 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -36,6 +36,7 @@ #include "intel_drv.h" #define CRC_PMIC_PWM_PERIOD_NS 21333 +#define LPSS_PWM_PERIOD_NS 10240 /* CRC PMIC based PWM Information */ struct intel_pwm_info crc_pwm_info = { @@ -44,6 +45,13 @@ struct intel_pwm_info crc_pwm_info = { .dev = NULL, }; +/* LPSS based PWM Information */ +struct intel_pwm_info lpss_pwm_info = { + .period_ns = LPSS_PWM_PERIOD_NS, + .name = "pwm_lpss", + .dev = NULL, +}; + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -1658,10 +1666,16 @@ static int pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe) { struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = >panel; - struct intel_pwm_info *pwm = _pwm_info; + struct intel_pwm_info *pwm; int retval; + if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) + pwm = _pwm_info; + else /* PPS_BLC_SOC */ + pwm = _pwm_info; + /* Get the PWM chip for backlight control */ pwm->dev = pwm_get(dev->dev, pwm->name); if (IS_ERR(pwm->dev)) { -- 2.7.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 0/3] Reviving the PWM_LPSS patches yet again
Hi All, Its been long since I have been sitting on these after I had received Tested-by for the same by Lluís for atleast the backlight working fine. The related bugs are - https://bugs.freedesktop.org/show_bug.cgi?id=96571 https://bugs.freedesktop.org/show_bug.cgi?id=90075 Rebased the code on latest code and sending again. Still display was not working on devices referenced in these bugs but backlight control was tested to be working at that time. DSI issues of panel display not comming up is tracked separately at - https://bugs.freedesktop.org/show_bug.cgi?id=96923 and should be again tested with latest drm-tip. Module ordering problem remains still and for testing we should for now enable LPSS_PWM as in built with i915 as module. Regards Shobhit Shobhit Kumar (3): drm/i915: Encapsulate the pwm_device in a pwm_info structure pwm: lpss: Add intel-gfx as consumer device in lookup table drm/i915: Add support for LPSS PWM on devices that support it drivers/gpu/drm/i915/intel_drv.h | 8 - drivers/gpu/drm/i915/intel_panel.c | 61 +++--- drivers/pwm/pwm-lpss-platform.c| 12 3 files changed, 62 insertions(+), 19 deletions(-) -- 2.7.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/3] drm/i915: Encapsulate the pwm_device in a pwm_info structure
pwm_info helps in encapsulating the PWM period_ns values and will form basis of adding new pwm devices which can then be genrically used by initializing proper pwm_info structure in the backlight setup call. v2: Rebase on latest code. Add BZ details Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96571 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90075 Cc: cbroo...@gmail.com Cc: jani.nik...@linux.intel.com Tested-by: Lluís Batlle i Rossell <vi...@viric.name> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_drv.h | 8 ++- drivers/gpu/drm/i915/intel_panel.c | 47 +++--- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cc13706..17af59c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -263,6 +263,12 @@ struct intel_encoder { const struct drm_connector *audio_connector; }; +struct intel_pwm_info { + struct pwm_device *dev; + unsigned int period_ns; + char *name; +}; + struct intel_panel { struct drm_display_mode *fixed_mode; struct drm_display_mode *downclock_mode; @@ -282,7 +288,7 @@ struct intel_panel { /* PWM chip */ bool util_pin_active_low; /* bxt+ */ u8 controller; /* bxt+ only */ - struct pwm_device *pwm; + struct intel_pwm_info *pwm; struct backlight_device *device; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index c8103f8..d56d1c2 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -37,6 +37,13 @@ #define CRC_PMIC_PWM_PERIOD_NS 21333 +/* CRC PMIC based PWM Information */ +struct intel_pwm_info crc_pwm_info = { + .period_ns = CRC_PMIC_PWM_PERIOD_NS, + .name = "pwm_backlight", + .dev = NULL, +}; + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -536,10 +543,11 @@ static u32 bxt_get_backlight(struct intel_connector *connector) static u32 pwm_get_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; + struct intel_pwm_info *pwm = panel->backlight.pwm; int duty_ns; - duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); - return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); + duty_ns = pwm_get_duty_cycle(pwm->dev); + return DIV_ROUND_UP(duty_ns * 100, pwm->period_ns); } static u32 intel_panel_get_backlight(struct intel_connector *connector) @@ -628,9 +636,10 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) static void pwm_set_backlight(struct intel_connector *connector, u32 level) { struct intel_panel *panel = >panel; - int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + struct intel_pwm_info *pwm = panel->backlight.pwm; + int duty_ns = DIV_ROUND_UP(level * pwm->period_ns, 100); - pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); + pwm_config(pwm->dev, duty_ns, pwm->period_ns); } static void @@ -799,11 +808,12 @@ static void bxt_disable_backlight(struct intel_connector *connector) static void pwm_disable_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; + struct intel_pwm_info *pwm = panel->backlight.pwm; /* Disable the backlight */ - pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); + pwm_config(pwm->dev, 0, pwm->period_ns); usleep_range(2000, 3000); - pwm_disable(panel->backlight.pwm); + pwm_disable(pwm->dev); } void intel_panel_disable_backlight(struct intel_connector *connector) @@ -1090,7 +1100,7 @@ static void pwm_enable_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; - pwm_enable(panel->backlight.pwm); + pwm_enable(panel->backlight.pwm->dev); intel_panel_actually_set_backlight(connector, panel->backlight.level); } @@ -1649,12 +1659,13 @@ static int pwm_setup_backlight(struct intel_connector *connector, { struct drm_device *dev = connector->base.dev; struct intel_panel *panel = >panel; + struct intel_pwm_info *pwm = _pwm_info; int retval; /* Get the PWM chip for backlight control */ - panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight"); - if (IS_ERR(panel->backlight.pwm)) { - DRM_ERROR("Failed to own the pwm chip\n"); + pwm->dev = pwm_get(dev->dev, pwm->name); + if (IS_ERR(pwm->dev)) { + DRM_ERROR("Failed to own the pwm chi
Re: [Intel-gfx] [PATCH] drm/i915: Return -EPROBE_DEFER if we cannot get GPIO or PWM in dsi_init
On Sat, Jul 16, 2016 at 3:12 AM, Stephen J <stephenj...@gmail.com> wrote: > On Fri, Jul 15, 2016 at 3:08 AM, Shobhit Kumar <ku...@shobhit.info> wrote: >> >> On Fri, Jul 15, 2016 at 2:33 PM, Shobhit Kumar <shobhit.ku...@intel.com> >> wrote: >> > On devices that have MIPI DSI panel control and PWM control comming from >> > CRC PMIC, we need the gpio and pwm exported from the intel_soc_pmic >> > driver. Defer probing for later in case we fail to get these devices. >> > >> > v2: Rebased on latest drm-intel-nightly >> > Added failure check for pwm_get which got missed out >> > >> >> [snip] >> >> > diff --git a/drivers/gpu/drm/i915/i915_drv.c >> > b/drivers/gpu/drm/i915/i915_drv.c >> > index b9a8117..9bfe0c8 100644 >> > --- a/drivers/gpu/drm/i915/i915_drv.c >> > +++ b/drivers/gpu/drm/i915/i915_drv.c >> > @@ -648,6 +648,9 @@ static int i915_load_modeset_init(struct drm_device >> > *dev) >> > /* Important: The output setup functions called by modeset_init >> > need >> > * working irqs for e.g. gmbus and dp aux transfers. */ >> > intel_modeset_init(dev); >> > + ret = intel_modeset_init(dev); >> > + if (ret == -EPROBE_DEFER) >> > + goto cleanup_deffered_probe; > > Did you intend to call intel_modeset_init twice? In my tests, I > removed the first copy because it seemed like a mistake. > Nope I did not. It was a mistake. Thanks for pointing out. >> > >> > intel_guc_init(dev); >> > >> > @@ -675,6 +678,7 @@ cleanup_gem: >> > i915_gem_fini(dev); >> > cleanup_irq: >> > intel_guc_fini(dev); >> > +cleanup_deffered_probe: >> > drm_irq_uninstall(dev); >> > intel_teardown_gmbus(dev); >> > cleanup_csr: >> > diff --git a/drivers/gpu/drm/i915/i915_drv.h >> > b/drivers/gpu/drm/i915/i915_drv.h >> > index 03e1bfa..a9eed22 100644 >> > --- a/drivers/gpu/drm/i915/i915_drv.h >> > +++ b/drivers/gpu/drm/i915/i915_drv.h >> > @@ -3778,7 +3778,7 @@ void intel_device_info_dump(struct drm_i915_private >> > *dev_priv); >> > >> > /* modesetting */ >> > extern void intel_modeset_init_hw(struct drm_device *dev); >> > -extern void intel_modeset_init(struct drm_device *dev); >> > +extern int intel_modeset_init(struct drm_device *dev); >> > extern void intel_modeset_gem_init(struct drm_device *dev); >> > extern void intel_modeset_cleanup(struct drm_device *dev); >> > extern int intel_connector_register(struct drm_connector *); >> > diff --git a/drivers/gpu/drm/i915/intel_display.c >> > b/drivers/gpu/drm/i915/intel_display.c >> > index be3b2ca..b1250f2 100644 >> > [snip] > > When testing on drm-intel-nightly, my system froze with your patch. I > can't get a full dmesg because I haven't yet found a way to trigger > the problem after I can get an ssh session up. > > The relevant logs I see before freeze are: > [drm] Initialized drm 1.1.0 20060810 > [drm] Memory usable by graphics device = 2048M > fb: switching to inteldrmfb from EFI VGA > > console is stuck at this point, my guess is that modeset fails and > that isn't handled well. The screen does not go black, the log > messages just stay on screen indefinitely. Will try to force deferred probe on one of my device which has serial console to get the serial logs and debug deferred probe in general. Regards Shobhit > > If I blacklist i915 and let X load the module (or manually load it > later), everything seems to run fine and backlight works, but that was > also true before applying the patch. > > Regards, > Stephen ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Return -EPROBE_DEFER if we cannot get GPIO or PWM in dsi_init
On Fri, Jul 15, 2016 at 2:33 PM, Shobhit Kumar <shobhit.ku...@intel.com> wrote: > On devices that have MIPI DSI panel control and PWM control comming from > CRC PMIC, we need the gpio and pwm exported from the intel_soc_pmic > driver. Defer probing for later in case we fail to get these devices. > > v2: Rebased on latest drm-intel-nightly > Added failure check for pwm_get which got missed out > Just an attempt and is untested yet because of lack of device which use CRC PMIC or LPSS. Hopefully can get some testing help from Stephen and Viric who have such devices. Regards Shobhit > Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> > --- > drivers/gpu/drm/i915/i915_drv.c | 4 > drivers/gpu/drm/i915/i915_drv.h | 2 +- > drivers/gpu/drm/i915/intel_display.c | 25 +++-- > drivers/gpu/drm/i915/intel_drv.h | 2 +- > drivers/gpu/drm/i915/intel_dsi.c | 24 +--- > 5 files changed, 42 insertions(+), 15 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index b9a8117..9bfe0c8 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -648,6 +648,9 @@ static int i915_load_modeset_init(struct drm_device *dev) > /* Important: The output setup functions called by modeset_init need > * working irqs for e.g. gmbus and dp aux transfers. */ > intel_modeset_init(dev); > + ret = intel_modeset_init(dev); > + if (ret == -EPROBE_DEFER) > + goto cleanup_deffered_probe; > > intel_guc_init(dev); > > @@ -675,6 +678,7 @@ cleanup_gem: > i915_gem_fini(dev); > cleanup_irq: > intel_guc_fini(dev); > +cleanup_deffered_probe: > drm_irq_uninstall(dev); > intel_teardown_gmbus(dev); > cleanup_csr: > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 03e1bfa..a9eed22 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -3778,7 +3778,7 @@ void intel_device_info_dump(struct drm_i915_private > *dev_priv); > > /* modesetting */ > extern void intel_modeset_init_hw(struct drm_device *dev); > -extern void intel_modeset_init(struct drm_device *dev); > +extern int intel_modeset_init(struct drm_device *dev); > extern void intel_modeset_gem_init(struct drm_device *dev); > extern void intel_modeset_cleanup(struct drm_device *dev); > extern int intel_connector_register(struct drm_connector *); > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index be3b2ca..b1250f2 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -14612,11 +14612,12 @@ static bool intel_crt_present(struct drm_device > *dev) > return true; > } > > -static void intel_setup_outputs(struct drm_device *dev) > +static int intel_setup_outputs(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = to_i915(dev); > struct intel_encoder *encoder; > bool dpd_is_edp = false; > + int ret = 0; > > /* > * intel_edp_init_connector() depends on this completing first, to > @@ -14638,7 +14639,9 @@ static void intel_setup_outputs(struct drm_device > *dev) > intel_ddi_init(dev, PORT_B); > intel_ddi_init(dev, PORT_C); > > - intel_dsi_init(dev); > + ret = intel_dsi_init(dev); > + if (ret == -EPROBE_DEFER) > + return ret; > } else if (HAS_DDI(dev)) { > int found; > > @@ -14742,7 +14745,9 @@ static void intel_setup_outputs(struct drm_device > *dev) > intel_hdmi_init(dev, CHV_HDMID, PORT_D); > } > > - intel_dsi_init(dev); > + ret = intel_dsi_init(dev); > + if (ret == -EPROBE_DEFER) > + return ret; > } else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) { > bool found = false; > > @@ -14795,6 +14800,8 @@ static void intel_setup_outputs(struct drm_device > *dev) > intel_init_pch_refclk(dev); > > drm_helper_move_panel_connectors_to_head(dev); > + > + return 0; > } > > static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) > @@ -15539,7 +15546,7 @@ fail: > drm_modeset_acquire_fini(); > } > > -void intel_modeset_init(struct drm_device *dev) > +int intel_modeset_init(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = to_i915(dev); > struct i915_gg
[Intel-gfx] [PATCH] drm/i915: Return -EPROBE_DEFER if we cannot get GPIO or PWM in dsi_init
On devices that have MIPI DSI panel control and PWM control comming from CRC PMIC, we need the gpio and pwm exported from the intel_soc_pmic driver. Defer probing for later in case we fail to get these devices. v2: Rebased on latest drm-intel-nightly Added failure check for pwm_get which got missed out Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.c | 4 drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 25 +++-- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_dsi.c | 24 +--- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b9a8117..9bfe0c8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -648,6 +648,9 @@ static int i915_load_modeset_init(struct drm_device *dev) /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ intel_modeset_init(dev); + ret = intel_modeset_init(dev); + if (ret == -EPROBE_DEFER) + goto cleanup_deffered_probe; intel_guc_init(dev); @@ -675,6 +678,7 @@ cleanup_gem: i915_gem_fini(dev); cleanup_irq: intel_guc_fini(dev); +cleanup_deffered_probe: drm_irq_uninstall(dev); intel_teardown_gmbus(dev); cleanup_csr: diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 03e1bfa..a9eed22 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3778,7 +3778,7 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv); /* modesetting */ extern void intel_modeset_init_hw(struct drm_device *dev); -extern void intel_modeset_init(struct drm_device *dev); +extern int intel_modeset_init(struct drm_device *dev); extern void intel_modeset_gem_init(struct drm_device *dev); extern void intel_modeset_cleanup(struct drm_device *dev); extern int intel_connector_register(struct drm_connector *); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index be3b2ca..b1250f2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14612,11 +14612,12 @@ static bool intel_crt_present(struct drm_device *dev) return true; } -static void intel_setup_outputs(struct drm_device *dev) +static int intel_setup_outputs(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_encoder *encoder; bool dpd_is_edp = false; + int ret = 0; /* * intel_edp_init_connector() depends on this completing first, to @@ -14638,7 +14639,9 @@ static void intel_setup_outputs(struct drm_device *dev) intel_ddi_init(dev, PORT_B); intel_ddi_init(dev, PORT_C); - intel_dsi_init(dev); + ret = intel_dsi_init(dev); + if (ret == -EPROBE_DEFER) + return ret; } else if (HAS_DDI(dev)) { int found; @@ -14742,7 +14745,9 @@ static void intel_setup_outputs(struct drm_device *dev) intel_hdmi_init(dev, CHV_HDMID, PORT_D); } - intel_dsi_init(dev); + ret = intel_dsi_init(dev); + if (ret == -EPROBE_DEFER) + return ret; } else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) { bool found = false; @@ -14795,6 +14800,8 @@ static void intel_setup_outputs(struct drm_device *dev) intel_init_pch_refclk(dev); drm_helper_move_panel_connectors_to_head(dev); + + return 0; } static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) @@ -15539,7 +15546,7 @@ fail: drm_modeset_acquire_fini(); } -void intel_modeset_init(struct drm_device *dev) +int intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct i915_ggtt *ggtt = _priv->ggtt; @@ -15564,7 +15571,7 @@ void intel_modeset_init(struct drm_device *dev) intel_init_pm(dev); if (INTEL_INFO(dev)->num_pipes == 0) - return; + return 0; /* * There may be no VBT; and if the BIOS enabled SSC we can @@ -15632,7 +15639,11 @@ void intel_modeset_init(struct drm_device *dev) /* Just disable it once at startup */ i915_disable_vga(dev); - intel_setup_outputs(dev); + + /* Check if we encountered -EPROBE_DEFER while initializing DSI */ + ret = intel_setup_outputs(dev); + if (ret) + return ret; drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev); @@ -15667,6 +15678,8 @@ void intel_modeset_init(struct drm_device *dev) * since the w
Re: [Intel-gfx] [RFC v2] drm/i915/chv: Clip cursor for CHV pipe C HW Cursor pos < 0
On Wed, Jun 29, 2016 at 6:24 PM, Shobhit Kumar <shobhit.ku...@linux.intel.com> wrote: > > From: Shobhit Kumar <shobhit.ku...@intel.com> > > CHV pipe C hits underrun when we get negative crtc_x values of cursor. > To avoid this we clip and shift the cursor image by negative crtc_x > value. > > v2: Make a copy of cursor plane state and allocate new gem object and fb > for clipped cursor and use that in case of negative cursor position > > v3: Updated error handling > Pin the gem object before use. Summarizing the discussion with Ville and Chris on IRC few days back - 1. This indeed does break the uabi which expects coherent writing into cursor plane (Chris) 2. Doing this with single buffer in kernel might result in tearing. We will need triple buffering (Ville) 3. Some continuous rendering tools might break (Chris) 4. Animated cursor might break (Chris). But then update plane call should copy back the original buffer every time and animated cursor should work as long as this is not filtered. So still recommendation remains to use SW cursor, though in theory clipping is possible but with additional complexity. Regards Shobhit > > Signed-off-by: Akshu Agrawal <akshu.agra...@intel.com> > Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> > --- > drivers/gpu/drm/i915/i915_drv.h | 7 ++ > drivers/gpu/drm/i915/intel_display.c | 131 > ++- > 2 files changed, 137 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 724d34b..1e59c02 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -2041,6 +2041,13 @@ struct drm_i915_private { > struct intel_encoder *dig_port_map[I915_MAX_PORTS]; > > /* > + * Temporary copy of cursor plane state for CHV PIPE_C > + * Will be initialized only when crtc_x < 0 as there is a > + * HW bug causing pipe underrun > + */ > + struct intel_plane_state *cursor_state; > + > + /* > * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your > patch > * will be rejected. Instead look for a better place. > */ > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index c3b5dc8..e6c103a 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -14456,6 +14456,132 @@ intel_update_cursor_plane(struct drm_plane *plane, > intel_crtc_update_cursor(crtc, state); > } > > +static void > +intel_update_chv_pipe_c_cursor_plane(struct drm_plane *plane, > + const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state *state) > +{ > + struct drm_crtc *crtc = crtc_state->base.crtc; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + struct drm_device *dev = plane->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); > + struct drm_i915_gem_object *cur_obj = NULL, *use_obj = NULL; > + uint32_t addr; > + struct intel_plane_state *cursor_state = dev_priv->cursor_state; > + const struct intel_plane_state *use_state; > + char __iomem *src, *dst; > + bool pinned = true; > + > + if (state->visible && state->base.crtc_x < 0) { > + int bytes_per_pixel = state->base.fb->bits_per_pixel / 8; > + int x = state->base.crtc_x; > + int width = state->base.crtc_w; > + int height = state->base.crtc_h; > + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; > + int i; > + > + if (!cursor_state) { > + cursor_state = kzalloc(sizeof(*cursor_state), > GFP_KERNEL); > + if (!cursor_state) { > + use_state = state; > + use_obj = obj; > + goto update; > + } > + > + memcpy(cursor_state, state, sizeof(*state)); > + > + /* Allocate new gem object */ > + cur_obj = i915_gem_object_create(dev, obj->base.size); > + if (IS_ERR(cur_obj)) > + goto gem_err; > + > + mode_cmd.width = cursor_state->base.fb->width; > + mode_cmd.height = cursor_state->base.fb->height; > + mode_cmd.pitches[0] = > cur
Re: [Intel-gfx] [RFC v2] drm/i915/chv: Clip cursor for CHV pipe C HW Cursor pos < 0
On 06/29/2016 06:24 PM, Shobhit Kumar wrote: From: Shobhit Kumar <shobhit.ku...@intel.com> CHV pipe C hits underrun when we get negative crtc_x values of cursor. To avoid this we clip and shift the cursor image by negative crtc_x value. v2: Make a copy of cursor plane state and allocate new gem object and fb for clipped cursor and use that in case of negative cursor position v3: Updated error handling Pin the gem object before use. Need someone to look at this patch. Daniel does this align with your suggestions ? Regards Shobhit Signed-off-by: Akshu Agrawal <akshu.agra...@intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 7 ++ drivers/gpu/drm/i915/intel_display.c | 131 ++- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 724d34b..1e59c02 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2041,6 +2041,13 @@ struct drm_i915_private { struct intel_encoder *dig_port_map[I915_MAX_PORTS]; /* + * Temporary copy of cursor plane state for CHV PIPE_C + * Will be initialized only when crtc_x < 0 as there is a + * HW bug causing pipe underrun + */ + struct intel_plane_state *cursor_state; + + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c3b5dc8..e6c103a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14456,6 +14456,132 @@ intel_update_cursor_plane(struct drm_plane *plane, intel_crtc_update_cursor(crtc, state); } +static void +intel_update_chv_pipe_c_cursor_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *state) +{ + struct drm_crtc *crtc = crtc_state->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + struct drm_i915_gem_object *cur_obj = NULL, *use_obj = NULL; + uint32_t addr; + struct intel_plane_state *cursor_state = dev_priv->cursor_state; + const struct intel_plane_state *use_state; + char __iomem *src, *dst; + bool pinned = true; + + if (state->visible && state->base.crtc_x < 0) { + int bytes_per_pixel = state->base.fb->bits_per_pixel / 8; + int x = state->base.crtc_x; + int width = state->base.crtc_w; + int height = state->base.crtc_h; + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + int i; + + if (!cursor_state) { + cursor_state = kzalloc(sizeof(*cursor_state), GFP_KERNEL); + if (!cursor_state) { + use_state = state; + use_obj = obj; + goto update; + } + + memcpy(cursor_state, state, sizeof(*state)); + + /* Allocate new gem object */ + cur_obj = i915_gem_object_create(dev, obj->base.size); + if (IS_ERR(cur_obj)) + goto gem_err; + + mode_cmd.width = cursor_state->base.fb->width; + mode_cmd.height = cursor_state->base.fb->height; + mode_cmd.pitches[0] = cursor_state->base.fb->pitches[0]; + mode_cmd.pixel_format = cursor_state->base.fb->pixel_format; + + cursor_state->base.fb = intel_framebuffer_create(dev, _cmd, cur_obj); + if (IS_ERR(cursor_state->base.fb)) { + drm_gem_object_unreference_unlocked(_obj->base); + goto gem_err; + } + + if (i915_gem_obj_ggtt_pin(cur_obj, 0, 0) < 0) { + drm_gem_object_unreference_unlocked(_obj->base); + pinned = false; + goto cleanup; + } + + dev_priv->cursor_state = cursor_state; + } else + cur_obj = intel_fb_obj(cursor_state->base.fb); + + src = ioremap_wc(dev_priv->ggtt.mappable_base + + i915_gem_obj_ggtt_offset(obj), + obj->base.size);
Re: [Intel-gfx] [RFC v2] drm/i915/chv: Clip cursor for CHV pipe C HW Cursor pos < 0
On 06/29/2016 06:24 PM, Shobhit Kumar wrote: From: Shobhit Kumar <shobhit.ku...@intel.com> CHV pipe C hits underrun when we get negative crtc_x values of cursor. To avoid this we clip and shift the cursor image by negative crtc_x value. v2: Make a copy of cursor plane state and allocate new gem object and fb for clipped cursor and use that in case of negative cursor position v3: Updated error handling Pin the gem object before use. I tested a modified version of this on 3.18 kernel on ChromeOS. Does work fine, but few WARN dumps from might_sleep() in atomic context while allocating cursor gem bo. I can allocate it one time during plane creation but how do I know the size of incoming bo ? If I allocate for say large cursor 256x256, ioremap_wc also has same WARN dumps. Need to remap in update function. Any hints how to go about it ? Maybe I should do this hack in check_plane rather than update plane ? Regards Shobhit Signed-off-by: Akshu Agrawal <akshu.agra...@intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 7 ++ drivers/gpu/drm/i915/intel_display.c | 131 ++- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 724d34b..1e59c02 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2041,6 +2041,13 @@ struct drm_i915_private { struct intel_encoder *dig_port_map[I915_MAX_PORTS]; /* + * Temporary copy of cursor plane state for CHV PIPE_C + * Will be initialized only when crtc_x < 0 as there is a + * HW bug causing pipe underrun + */ + struct intel_plane_state *cursor_state; + + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c3b5dc8..e6c103a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14456,6 +14456,132 @@ intel_update_cursor_plane(struct drm_plane *plane, intel_crtc_update_cursor(crtc, state); } +static void +intel_update_chv_pipe_c_cursor_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *state) +{ + struct drm_crtc *crtc = crtc_state->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + struct drm_i915_gem_object *cur_obj = NULL, *use_obj = NULL; + uint32_t addr; + struct intel_plane_state *cursor_state = dev_priv->cursor_state; + const struct intel_plane_state *use_state; + char __iomem *src, *dst; + bool pinned = true; + + if (state->visible && state->base.crtc_x < 0) { + int bytes_per_pixel = state->base.fb->bits_per_pixel / 8; + int x = state->base.crtc_x; + int width = state->base.crtc_w; + int height = state->base.crtc_h; + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + int i; + + if (!cursor_state) { + cursor_state = kzalloc(sizeof(*cursor_state), GFP_KERNEL); + if (!cursor_state) { + use_state = state; + use_obj = obj; + goto update; + } + + memcpy(cursor_state, state, sizeof(*state)); + + /* Allocate new gem object */ + cur_obj = i915_gem_object_create(dev, obj->base.size); + if (IS_ERR(cur_obj)) + goto gem_err; + + mode_cmd.width = cursor_state->base.fb->width; + mode_cmd.height = cursor_state->base.fb->height; + mode_cmd.pitches[0] = cursor_state->base.fb->pitches[0]; + mode_cmd.pixel_format = cursor_state->base.fb->pixel_format; + + cursor_state->base.fb = intel_framebuffer_create(dev, _cmd, cur_obj); + if (IS_ERR(cursor_state->base.fb)) { + drm_gem_object_unreference_unlocked(_obj->base); + goto gem_err; + } + + if (i915_gem_obj_ggtt_pin(cur_obj, 0, 0) < 0) { + drm_gem_object_unreference_unlocked(_obj->base); + pinned = false; +
[Intel-gfx] [RFC v2] drm/i915/chv: Clip cursor for CHV pipe C HW Cursor pos < 0
From: Shobhit Kumar <shobhit.ku...@intel.com> CHV pipe C hits underrun when we get negative crtc_x values of cursor. To avoid this we clip and shift the cursor image by negative crtc_x value. v2: Make a copy of cursor plane state and allocate new gem object and fb for clipped cursor and use that in case of negative cursor position v3: Updated error handling Pin the gem object before use. Signed-off-by: Akshu Agrawal <akshu.agra...@intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 7 ++ drivers/gpu/drm/i915/intel_display.c | 131 ++- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 724d34b..1e59c02 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2041,6 +2041,13 @@ struct drm_i915_private { struct intel_encoder *dig_port_map[I915_MAX_PORTS]; /* + * Temporary copy of cursor plane state for CHV PIPE_C + * Will be initialized only when crtc_x < 0 as there is a + * HW bug causing pipe underrun + */ + struct intel_plane_state *cursor_state; + + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c3b5dc8..e6c103a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14456,6 +14456,132 @@ intel_update_cursor_plane(struct drm_plane *plane, intel_crtc_update_cursor(crtc, state); } +static void +intel_update_chv_pipe_c_cursor_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *state) +{ + struct drm_crtc *crtc = crtc_state->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + struct drm_i915_gem_object *cur_obj = NULL, *use_obj = NULL; + uint32_t addr; + struct intel_plane_state *cursor_state = dev_priv->cursor_state; + const struct intel_plane_state *use_state; + char __iomem *src, *dst; + bool pinned = true; + + if (state->visible && state->base.crtc_x < 0) { + int bytes_per_pixel = state->base.fb->bits_per_pixel / 8; + int x = state->base.crtc_x; + int width = state->base.crtc_w; + int height = state->base.crtc_h; + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + int i; + + if (!cursor_state) { + cursor_state = kzalloc(sizeof(*cursor_state), GFP_KERNEL); + if (!cursor_state) { + use_state = state; + use_obj = obj; + goto update; + } + + memcpy(cursor_state, state, sizeof(*state)); + + /* Allocate new gem object */ + cur_obj = i915_gem_object_create(dev, obj->base.size); + if (IS_ERR(cur_obj)) + goto gem_err; + + mode_cmd.width = cursor_state->base.fb->width; + mode_cmd.height = cursor_state->base.fb->height; + mode_cmd.pitches[0] = cursor_state->base.fb->pitches[0]; + mode_cmd.pixel_format = cursor_state->base.fb->pixel_format; + + cursor_state->base.fb = intel_framebuffer_create(dev, _cmd, cur_obj); + if (IS_ERR(cursor_state->base.fb)) { + drm_gem_object_unreference_unlocked(_obj->base); + goto gem_err; + } + + if (i915_gem_obj_ggtt_pin(cur_obj, 0, 0) < 0) { + drm_gem_object_unreference_unlocked(_obj->base); + pinned = false; + goto cleanup; + } + + dev_priv->cursor_state = cursor_state; + } else + cur_obj = intel_fb_obj(cursor_state->base.fb); + + src = ioremap_wc(dev_priv->ggtt.mappable_base + + i915_gem_obj_ggtt_offset(obj), + obj->base.size); + + dst = ioremap_wc(dev_priv->ggtt.mappable_base + + i915_gem_obj_ggtt_offset(cur_obj), +
Re: [Intel-gfx] [RFC] drm/i915/chv: Clip cursor for CHV pipe C HW Cursor pos < 0
Daniel, On 06/28/2016 05:57 PM, Shobhit Kumar wrote: From: Shobhit Kumar <shobhit.ku...@intel.com> CHV pipe C hits underrun when we get negative crtc_x values of cursor. To avoid this we clip and shift the cursor image by negative crtc_x value. v2: Make a copy of cursor plane state and allocate new gem object and fb for clipped cursor and use that in case of negative cursor position This patch is not yet tested and most likely not even complete and is sent for early review of the approach. Will test it and update the status here. Regards Shobhit Signed-off-by: Akshu Agrawal <akshu.agra...@intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 7 ++ drivers/gpu/drm/i915/intel_display.c | 122 ++- 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 724d34b..1e59c02 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2041,6 +2041,13 @@ struct drm_i915_private { struct intel_encoder *dig_port_map[I915_MAX_PORTS]; /* + * Temporary copy of cursor plane state for CHV PIPE_C + * Will be initialized only when crtc_x < 0 as there is a + * HW bug causing pipe underrun + */ + struct intel_plane_state *cursor_state; + + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c3b5dc8..c4988d5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14456,6 +14456,123 @@ intel_update_cursor_plane(struct drm_plane *plane, intel_crtc_update_cursor(crtc, state); } +static void +intel_update_chv_pipe_c_cursor_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *state) +{ + struct drm_crtc *crtc = crtc_state->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + struct drm_i915_gem_object *cur_obj = NULL, *use_obj = NULL; + uint32_t addr; + struct intel_plane_state *cursor_state = dev_priv->cursor_state; + const struct intel_plane_state *use_state; + char __iomem *src, *dst; + + if (state->visible && state->base.crtc_x < 0) { + int bytes_per_pixel = state->base.fb->bits_per_pixel / 8; + int x = state->base.crtc_x; + int width = state->base.crtc_w; + int height = state->base.crtc_h; + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + int i; + + if (!cursor_state) { + cursor_state = kzalloc(sizeof(*cursor_state), GFP_KERNEL); + if (!cursor_state) { + use_state = state; + use_obj = obj; + goto update; + } + + memcpy(cursor_state, state, sizeof(*state)); + cursor_state->base.crtc_x = 0; + + /* Allocate new gem object */ + cur_obj = i915_gem_object_create(dev, obj->base.size); + if (IS_ERR(cur_obj)) { + kfree(cursor_state); + use_state = state; + use_obj = obj; + goto update; + } + + mode_cmd.width = cursor_state->base.fb->width; + mode_cmd.height = cursor_state->base.fb->height; + mode_cmd.pitches[0] = cursor_state->base.fb->pitches[0]; + mode_cmd.pixel_format = cursor_state->base.fb->pixel_format; + + cursor_state->base.fb = intel_framebuffer_create(dev, _cmd, cur_obj); + if (IS_ERR(cursor_state->base.fb)) { + drm_gem_object_unreference_unlocked(_obj->base); + kfree(cursor_state); + use_state = state; + use_obj = obj; + goto update; + } + + dev_priv->cursor_state = cursor_state; + } else + cur_obj = intel_fb_obj(cursor_state->base.fb); + + src = ioremap_wc(dev_priv->ggtt.mappable_base + +
[Intel-gfx] [RFC] drm/i915/chv: Clip cursor for CHV pipe C HW Cursor pos < 0
From: Shobhit Kumar <shobhit.ku...@intel.com> CHV pipe C hits underrun when we get negative crtc_x values of cursor. To avoid this we clip and shift the cursor image by negative crtc_x value. v2: Make a copy of cursor plane state and allocate new gem object and fb for clipped cursor and use that in case of negative cursor position Signed-off-by: Akshu Agrawal <akshu.agra...@intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 7 ++ drivers/gpu/drm/i915/intel_display.c | 122 ++- 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 724d34b..1e59c02 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2041,6 +2041,13 @@ struct drm_i915_private { struct intel_encoder *dig_port_map[I915_MAX_PORTS]; /* + * Temporary copy of cursor plane state for CHV PIPE_C + * Will be initialized only when crtc_x < 0 as there is a + * HW bug causing pipe underrun + */ + struct intel_plane_state *cursor_state; + + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c3b5dc8..c4988d5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14456,6 +14456,123 @@ intel_update_cursor_plane(struct drm_plane *plane, intel_crtc_update_cursor(crtc, state); } +static void +intel_update_chv_pipe_c_cursor_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *state) +{ + struct drm_crtc *crtc = crtc_state->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + struct drm_i915_gem_object *cur_obj = NULL, *use_obj = NULL; + uint32_t addr; + struct intel_plane_state *cursor_state = dev_priv->cursor_state; + const struct intel_plane_state *use_state; + char __iomem *src, *dst; + + if (state->visible && state->base.crtc_x < 0) { + int bytes_per_pixel = state->base.fb->bits_per_pixel / 8; + int x = state->base.crtc_x; + int width = state->base.crtc_w; + int height = state->base.crtc_h; + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + int i; + + if (!cursor_state) { + cursor_state = kzalloc(sizeof(*cursor_state), GFP_KERNEL); + if (!cursor_state) { + use_state = state; + use_obj = obj; + goto update; + } + + memcpy(cursor_state, state, sizeof(*state)); + cursor_state->base.crtc_x = 0; + + /* Allocate new gem object */ + cur_obj = i915_gem_object_create(dev, obj->base.size); + if (IS_ERR(cur_obj)) { + kfree(cursor_state); + use_state = state; + use_obj = obj; + goto update; + } + + mode_cmd.width = cursor_state->base.fb->width; + mode_cmd.height = cursor_state->base.fb->height; + mode_cmd.pitches[0] = cursor_state->base.fb->pitches[0]; + mode_cmd.pixel_format = cursor_state->base.fb->pixel_format; + + cursor_state->base.fb = intel_framebuffer_create(dev, _cmd, cur_obj); + if (IS_ERR(cursor_state->base.fb)) { + drm_gem_object_unreference_unlocked(_obj->base); + kfree(cursor_state); + use_state = state; + use_obj = obj; + goto update; + } + + dev_priv->cursor_state = cursor_state; + } else + cur_obj = intel_fb_obj(cursor_state->base.fb); + + src = ioremap_wc(dev_priv->ggtt.mappable_base + + i915_gem_obj_ggtt_offset(obj), + obj->base.size); + + dst = ioremap_wc(dev_priv->ggtt.mappable_base + + i915_gem_obj_ggtt_offset(cur_ob
Re: [Intel-gfx] [PATCH 2/2] drm/i915: Crop cursor image for CHV pipe C cursor issue
On Mon, Jun 13, 2016 at 7:52 PM, Daniel Vetterwrote: > On Fri, Jun 10, 2016 at 03:14:36PM +0530, Agrawal, Akshu wrote: >> On 6/8/2016 2:10 PM, Daniel Vetter wrote: >> > On Wed, Jun 08, 2016 at 01:57:44PM +0530, Akshu Agrawal wrote: >> > > CHV pipe C hits underrun when we get -ve X values of cursor. To avoid >> > > this we crop the cursor image for by -ve X value and thus use '0' as >> > > least X value. >> > >> > You're talking about "-ve" here and there's absolutely no "-ve" anywhere >> > in your patch. That makes your commit message non-understandable. >> >> Will change -ve to "negative" for better readability. >> >> > >> > But I think I get what you're doing here, and nope, you can't override the >> > cursor image like that. If we go with this w/a then you need to allocate a >> > new cursor gem bo instead. This is userspace-visible. >> >> Can't we use the same gem bo? As we are calling >> "i915_gem_object_set_to_gtt_domain" to get write access for CPU after >> unbinding from GTT. > > Userspace can write to the underlying bo without telling us. That'll cause > tearing. And it could also read from it, which would result in even more > serious bugs. > > We can't just change userspace-visible state for a w/a. Same reasoning > applies to the crtc_state stuff. Again we need copies, to avoid > accidentally confusion userspace. > Agreed Daniel. Though chances user space doing something like this are less, but nevertheless it can happen. > With all those copies it's probably best to write a special > atomic_update_plane function for cursor pipe C, to avoid spreading all of > them all over the driver. Is implementing a intel_chv_update_pipe_c_cursor_plane and initializing that as the update_plane callback in case of PIPE C on CHV during cursor plane creation is what you have in mind ? We can then implement the copies inside this function. No too sure on the atomic path so just want to confirm if this will work well. Regards Shobhit > -Daniel > >> >> Regards, >> Akshu >> > >> > For similar reasons you're also not allowed to change crtc->state. >> > -Daniel >> > >> > > Signed-off-by: Akshu Agrawal >> > > --- >> > > drivers/gpu/drm/i915/intel_display.c | 113 >> > > +++ >> > > drivers/gpu/drm/i915/intel_drv.h | 3 + >> > > 2 files changed, 116 insertions(+) >> > > >> > > diff --git a/drivers/gpu/drm/i915/intel_display.c >> > > b/drivers/gpu/drm/i915/intel_display.c >> > > index bca9245..e6e6568 100644 >> > > --- a/drivers/gpu/drm/i915/intel_display.c >> > > +++ b/drivers/gpu/drm/i915/intel_display.c >> > > @@ -14279,6 +14279,81 @@ void intel_create_rotation_property(struct >> > > drm_device *dev, struct intel_plane * >> > > plane->base.state->rotation); >> > > } >> > > >> > > +static void vlv_unpin_buffer_obj(struct drm_i915_gem_object *obj, >> > > + char __iomem *buffer_start) >> > > +{ >> > > + iounmap(buffer_start); >> > > + i915_gem_object_ggtt_unpin(obj); >> > > +} >> > > + >> > > +static char __iomem *vlv_pin_and_map_buffer_obj >> > > + (struct drm_i915_gem_object *obj) >> > > +{ >> > > + struct drm_i915_private *dev_priv = obj->base.dev->dev_private; >> > > + char __iomem *buffer_start; >> > > + int ret; >> > > + >> > > + ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); >> > > + if (ret) >> > > + return NULL; >> > > + >> > > + ret = i915_gem_object_set_to_gtt_domain(obj, true); >> > > + if (ret) { >> > > + i915_gem_object_ggtt_unpin(obj); >> > > + return NULL; >> > > + } >> > > + >> > > + buffer_start = ioremap_wc(dev_priv->gtt.mappable_base + >> > > + i915_gem_obj_ggtt_offset(obj), obj->base.size); >> > > + if (buffer_start == NULL) { >> > > + i915_gem_object_ggtt_unpin(obj); >> > > + return NULL; >> > > + } >> > > + >> > > + return buffer_start; >> > > +} >> > > + >> > > +static int vlv_cursor_crop(struct intel_plane_state *state, >> > > + int prev_x) >> > > +{ >> > > + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); >> > > + struct drm_framebuffer *fb = state->base.fb; >> > > + char __iomem *buffer = state->vlv_cursor_image; >> > > + char __iomem *base, *cursor_base; >> > > + int size = obj->base.size; >> > > + int i, x = state->base.crtc_x; >> > > + int bytes_per_pixel = fb->bits_per_pixel / 8; >> > > + >> > > + base = vlv_pin_and_map_buffer_obj(obj); >> > > + if (base == NULL) >> > > + return -ENOMEM; >> > > + >> > > + if (prev_x >= 0) { >> > > + if (buffer != NULL) >> > > + kfree(buffer); >> > > + buffer = kzalloc(size, GFP_KERNEL); >> > > + state->vlv_cursor_image = buffer; >> > > + if (buffer == NULL) >> > > + return -ENOMEM; >> > > + memcpy(buffer, base, size); >> > > + } >> > > + cursor_base = buffer; >> > > + x = -x; >> > > + for (i = 0; i <
Re: [Intel-gfx] [PATCH v5 45/46] drm: i915: switch to the atomic PWM API
On Thursday 31 March 2016 12:04 PM, Jani Nikula wrote: [aggressively trimmed the recipient list, can't seem to be able to send this otherwise] On Wed, 30 Mar 2016, Boris Brezillon <boris.brezil...@free-electrons.com> wrote: pwm_config/enable/disable() have been deprecated and should be replaced by pwm_apply_state(). Signed-off-by: Boris Brezillon <boris.brezil...@free-electrons.com> Reviewed-by: Jani Nikula <jani.nik...@intel.com> Cc: Shobhit, any additional comments? Looks good to me. Reviewed-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_panel.c | 39 +- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 21ee647..b86bd20 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -538,10 +538,10 @@ static u32 bxt_get_backlight(struct intel_connector *connector) static u32 pwm_get_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; - int duty_ns; + struct pwm_state pstate; - duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); - return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); + pwm_get_state(panel->backlight.pwm, ); + return DIV_ROUND_UP(pstate.duty_cycle * 100, CRC_PMIC_PWM_PERIOD_NS); } static u32 intel_panel_get_backlight(struct intel_connector *connector) @@ -630,9 +630,12 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) static void pwm_set_backlight(struct intel_connector *connector, u32 level) { struct intel_panel *panel = >panel; - int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + struct pwm_state pstate; - pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); + pwm_get_state(panel->backlight.pwm, ); + pstate.duty_cycle = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + pstate.period = CRC_PMIC_PWM_PERIOD_NS; + pwm_apply_state(panel->backlight.pwm, ); } static void @@ -801,11 +804,15 @@ static void bxt_disable_backlight(struct intel_connector *connector) static void pwm_disable_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; + struct pwm_state pstate; /* Disable the backlight */ - pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); + pwm_get_state(panel->backlight.pwm, ); + pstate.duty_cycle = 0; + pwm_apply_state(panel->backlight.pwm, ); usleep_range(2000, 3000); - pwm_disable(panel->backlight.pwm); + pstate.enabled = false; + pwm_apply_state(panel->backlight.pwm, ); } void intel_panel_disable_backlight(struct intel_connector *connector) @@ -1068,8 +1075,11 @@ static void bxt_enable_backlight(struct intel_connector *connector) static void pwm_enable_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; + struct pwm_state pstate; - pwm_enable(panel->backlight.pwm); + pwm_get_state(panel->backlight.pwm, ); + pstate.enabled = true; + pwm_apply_state(panel->backlight.pwm, ); intel_panel_actually_set_backlight(connector, panel->backlight.level); } @@ -1630,6 +1640,7 @@ static int pwm_setup_backlight(struct intel_connector *connector, { struct drm_device *dev = connector->base.dev; struct intel_panel *panel = >panel; + struct pwm_state pstate; int retval; /* Get the PWM chip for backlight control */ @@ -1640,8 +1651,10 @@ static int pwm_setup_backlight(struct intel_connector *connector, return -ENODEV; } - retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS, - CRC_PMIC_PWM_PERIOD_NS); + pwm_get_state(panel->backlight.pwm, ); + pstate.period = CRC_PMIC_PWM_PERIOD_NS; + pstate.duty_cycle = CRC_PMIC_PWM_PERIOD_NS; + retval = pwm_apply_state(panel->backlight.pwm, ); if (retval < 0) { DRM_ERROR("Failed to configure the pwm chip\n"); pwm_put(panel->backlight.pwm); @@ -1651,9 +1664,9 @@ static int pwm_setup_backlight(struct intel_connector *connector, panel->backlight.min = 0; /* 0% */ panel->backlight.max = 100; /* 100% */ - panel->backlight.level = DIV_ROUND_UP( -pwm_get_duty_cycle(panel->backlight.pwm) * 100, -CRC_PMIC_PWM_PERIOD_NS); + pwm_get_state(panel->backlight.pwm, ); + panel->backlight.level = DIV_ROUND_UP(pstate.duty_cycle * 100, + pstate.period); panel->backlight.enabled = panel->backlight.level !=
[Intel-gfx] [v2 3/6] drm/i915/skl+: calculate plane pixel rate
From: "Kumar, Mahesh"Don't use pipe pixel rate for plane pixel rate. Calculate plane pixel according to formula adjusted plane_pixel_rate = adjusted pipe_pixel_rate * downscale ammount downscale amount = max[1, src_h/dst_h] * max[1, src_w/dst_w] if 90/270 rotation use rotated width & height v2: use intel_plane_state->visible instead of (fb == NULL) as per Matt's comment. Cc: matthew.d.ro...@intel.com Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_pm.c | 88 +++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bc97012..bb2b1c7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -638,6 +638,8 @@ struct intel_plane_wm_parameters { u64 tiling; unsigned int rotation; uint16_t fifo_size; + /* Stores the adjusted plane pixel rate for WM calculation for SKL+ */ + uint32_t plane_pixel_rate; }; struct intel_plane { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 708f329..40fff09 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2782,6 +2782,48 @@ skl_wm_plane_id(const struct intel_plane *plane) } } +/* + * This function takes drm_plane_state as input + * and decides the downscale amount according to the formula + * + * downscale amount = Max[1, Horizontal source size / Horizontal dest size] + * + * Return value is multiplied by 1000 to retain fractional part + * Caller should take care of dividing & Rounding off the value + */ +static uint32_t +skl_plane_downscale_amount(const struct intel_plane *intel_plane) +{ + struct drm_plane_state *pstate = intel_plane->base.state; + struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); + uint32_t downscale_h, downscale_w; + uint32_t src_w, src_h, dst_w, dst_h, tmp; + + /* If plane not visible return amount as unity */ + if (!intel_pstate->visible) + return 1000; + + src_w = drm_rect_width(_pstate->src) >> 16; + src_h = drm_rect_height(_pstate->src) >> 16; + + dst_w = drm_rect_width(_pstate->dst); + dst_h = drm_rect_height(_pstate->dst); + + if (intel_rotation_90_or_270(pstate->rotation)) + swap(dst_w, dst_h); + + /* Multiply by 1000 for precision */ + tmp = (1000 * src_h) / dst_h; + downscale_h = max_t(uint32_t, 1000, tmp); + + tmp = (1000 * src_w) / dst_w; + downscale_w = max_t(uint32_t, 1000, tmp); + + /* Reducing precision to 3 decimal places */ + return DIV_ROUND_UP(downscale_h * downscale_w, 1000); +} + + static void skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, const struct intel_crtc_state *cstate, @@ -3183,10 +3225,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, swap(width, height); bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0); - method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate), + method1 = skl_wm_method1(intel_plane->wm.plane_pixel_rate, bytes_per_pixel, latency); - method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate), + method2 = skl_wm_method2(intel_plane->wm.plane_pixel_rate, cstate->base.adjusted_mode.crtc_htotal, width, bytes_per_pixel, @@ -3627,6 +3669,45 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, } } +static uint32_t +skl_plane_pixel_rate(struct intel_crtc_state *cstate, struct intel_plane *plane) +{ + uint32_t adjusted_pixel_rate; + uint32_t downscale_amount; + + /* +* adjusted plane pixel rate = adjusted pipe pixel rate +* Plane pixel rate = adjusted plane pixel rate * plane down scale +* amount +*/ + adjusted_pixel_rate = skl_pipe_pixel_rate(cstate); + downscale_amount = skl_plane_downscale_amount(plane); + + return DIV_ROUND_UP(adjusted_pixel_rate * downscale_amount, + 1000); +} + +static void skl_set_plane_pixel_rate(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct intel_plane *intel_plane = NULL; + struct drm_device *dev = crtc->dev; + + if (!intel_crtc->active) + return; + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + struct drm_plane *plane = _plane->base; + + if (!to_intel_plane_state(plane->state)->visible) + continue; + +
[Intel-gfx] [v2 2/6] drm/i915/skl+: calculate ddb minimum allocation
From: "Kumar, Mahesh"don't always use 8 ddb as minimum, instead calculate using proper algorithm. v2: optimizations as per Matt's comments. Cc: matthew.d.ro...@intel.com Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_pm.c | 50 ++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d55e5d0..708f329 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2928,6 +2928,51 @@ skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate) return total_data_rate; } +static uint16_t +skl_ddb_min_alloc(const struct intel_crtc *crtc, + const struct drm_plane *plane, int y) +{ + struct drm_framebuffer *fb = plane->state->fb; + struct intel_plane_state *pstate = to_intel_plane_state(plane->state); + uint32_t src_w, src_h; + uint32_t min_scanlines = 8; + uint8_t bytes_per_pixel; + + /* For packed formats, no y-plane, return 0 */ + if (y && !fb && !(fb->pixel_format == DRM_FORMAT_NV12)) + return 0; + + /* For Non Y-tile return 8-blocks */ + if (!(fb->modifier[0] == I915_FORMAT_MOD_Y_TILED) && + !(fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) + return 8; + + src_w = drm_rect_width(>src) >> 16; + src_h = drm_rect_height(>src) >> 16; + + if (intel_rotation_90_or_270(plane->state->rotation)) + swap(src_w, src_h); + + bytes_per_pixel = y ? drm_format_plane_cpp(fb->pixel_format, 0) : + drm_format_plane_cpp(fb->pixel_format, 1); + + if (intel_rotation_90_or_270(plane->state->rotation)) { + switch (bytes_per_pixel) { + case 1: + min_scanlines = 32; + break; + case 2: + min_scanlines = 16; + break; + case 8: + WARN(1, "Unsupported pixel depth for rotation"); + } + } + + return DIV_ROUND_UP((4 * src_w / (y ? 1 : 2) * bytes_per_pixel), 512) * + min_scanlines/4 + 3; +} + static void skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct skl_ddb_allocation *ddb /* out */) @@ -2964,7 +3009,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, /* 1. Allocate the mininum required blocks for each active plane */ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { struct drm_plane *plane = _plane->base; - struct drm_framebuffer *fb = plane->state->fb; int id = skl_wm_plane_id(intel_plane); if (!to_intel_plane_state(plane->state)->visible) @@ -2973,9 +3017,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - minimum[id] = 8; + minimum[id] = skl_ddb_min_alloc(intel_crtc, plane, 0); alloc_size -= minimum[id]; - y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0; + y_minimum[id] = skl_ddb_min_alloc(intel_crtc, plane, 1); alloc_size -= y_minimum[id]; } -- 2.5.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 4/6] drm/i915/skl+: Use scaling amount for plane data rate calculation
From: "Kumar, Mahesh"if downscaling is enabled plane data rate increases according to scaling amount. take scaling amount under consideration while calculating plane data rate v2: Address Matt's comments, where data rate was overridden because of missing else. Cc: matthew.d.ro...@intel.com Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_pm.c | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 40fff09..a9f9396 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2912,6 +2912,8 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, { struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); struct drm_framebuffer *fb = pstate->fb; + struct intel_plane *intel_plane = to_intel_plane(pstate->plane); + uint32_t down_scale_amount, data_rate; uint32_t width = 0, height = 0; width = drm_rect_width(_pstate->src) >> 16; @@ -2923,15 +2925,20 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, /* for planar format */ if (fb->pixel_format == DRM_FORMAT_NV12) { if (y) /* y-plane data rate */ - return width * height * + data_rate = width * height * drm_format_plane_cpp(fb->pixel_format, 0); else/* uv-plane data rate */ - return (width / 2) * (height / 2) * + data_rate = (width / 2) * (height / 2) * drm_format_plane_cpp(fb->pixel_format, 1); - } + } else + /* for packed formats */ + data_rate = width * height * + drm_format_plane_cpp(fb->pixel_format, 0); + + down_scale_amount = skl_plane_downscale_amount(intel_plane); + + return DIV_ROUND_UP((data_rate * down_scale_amount), 1000); - /* for packed formats */ - return width * height * drm_format_plane_cpp(fb->pixel_format, 0); } /* -- 2.5.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 1/6] drm/i915/skl+: Use plane size for relative data rate calculation
From: "Kumar, Mahesh"Use plane size for relative data rate calculation. don't always use pipe source width & height. adjust height & width according to rotation. use plane size for watermark calculations also. v2: Address Matt's comments. Use intel_plane_state->visible to avoid divide-by-zero error. Where FB was present but not visible so causing total data rate to be zero, hence divide-by-zero. Cc: matthew.d.ro...@intel.com Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_pm.c | 42 ++--- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 20bf854..d55e5d0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2868,25 +2868,28 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, const struct drm_plane_state *pstate, int y) { - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); struct drm_framebuffer *fb = pstate->fb; + uint32_t width = 0, height = 0; + + width = drm_rect_width(_pstate->src) >> 16; + height = drm_rect_height(_pstate->src) >> 16; + + if (intel_rotation_90_or_270(pstate->rotation)) + swap(width, height); /* for planar format */ if (fb->pixel_format == DRM_FORMAT_NV12) { if (y) /* y-plane data rate */ - return intel_crtc->config->pipe_src_w * - intel_crtc->config->pipe_src_h * + return width * height * drm_format_plane_cpp(fb->pixel_format, 0); else/* uv-plane data rate */ - return (intel_crtc->config->pipe_src_w/2) * - (intel_crtc->config->pipe_src_h/2) * + return (width / 2) * (height / 2) * drm_format_plane_cpp(fb->pixel_format, 1); } /* for packed formats */ - return intel_crtc->config->pipe_src_w * - intel_crtc->config->pipe_src_h * - drm_format_plane_cpp(fb->pixel_format, 0); + return width * height * drm_format_plane_cpp(fb->pixel_format, 0); } /* @@ -2905,9 +2908,8 @@ skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate) for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { const struct drm_plane_state *pstate = intel_plane->base.state; - if (pstate->fb == NULL) + if (!to_intel_plane_state(pstate)->visible) continue; - if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR) continue; @@ -2965,8 +2967,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct drm_framebuffer *fb = plane->state->fb; int id = skl_wm_plane_id(intel_plane); - if (fb == NULL) + if (!to_intel_plane_state(plane->state)->visible) continue; + if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; @@ -2992,7 +2995,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uint16_t plane_blocks, y_plane_blocks = 0; int id = skl_wm_plane_id(intel_plane); - if (pstate->fb == NULL) + if (!to_intel_plane_state(pstate)->visible) continue; if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; @@ -3116,28 +3119,37 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, { struct drm_plane *plane = _plane->base; struct drm_framebuffer *fb = plane->state->fb; + struct intel_plane_state *intel_pstate = + to_intel_plane_state(plane->state); uint32_t latency = dev_priv->wm.skl_latency[level]; uint32_t method1, method2; uint32_t plane_bytes_per_line, plane_blocks_per_line; uint32_t res_blocks, res_lines; uint32_t selected_result; uint8_t bytes_per_pixel; + uint32_t width = 0, height = 0; - if (latency == 0 || !cstate->base.active || !fb) + if (latency == 0 || !cstate->base.active || !intel_pstate->visible) return false; + width = drm_rect_width(_pstate->src) >> 16; + height = drm_rect_height(_pstate->src) >> 16; + + if (intel_rotation_90_or_270(plane->state->rotation)) + swap(width, height); + bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0); method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
[Intel-gfx] [v2 5/6] drm/i915: Add support to parse DMI table and get platform memory info
This is needed for WM computation workaround for arbitrated display bandwidth. v2: Address Matt's review comments - Be more paranoid while dmi decoding - Also add support for decoding speed from configured memory speed if availble in DMI memory entry Cc: matthew.d.ro...@intel.com Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_dma.c | 47 + drivers/gpu/drm/i915/i915_drv.h | 6 ++ 2 files changed, 53 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d70d96f..320143b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -49,6 +49,7 @@ #include #include #include +#include static int i915_getparam(struct drm_device *dev, void *data, @@ -855,6 +856,49 @@ static void intel_init_dpio(struct drm_i915_private *dev_priv) } } +static void dmi_decode_memory_info(const struct dmi_header *hdr, void *priv) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) priv; + const u8 *data = (const u8 *) hdr; + uint16_t size, mem_speed; + +#define DMI_CONF_MEM_SPEED_OFFSET 0x20 +#define DMI_MEM_SPEED_OFFSET 0x15 +#define DMI_MEM_SIZE_OFFSET0x0C + + if (hdr->type == DMI_ENTRY_MEM_DEVICE) { + /* Found a memory channel ? */ + size = (uint16_t) (*((uint16_t *)(data + DMI_MEM_SIZE_OFFSET))); + if (size == 0) + return; + + dev_priv->dmi.mem_channel++; + + /* Get the speed */ + if (hdr->length > DMI_CONF_MEM_SPEED_OFFSET) + mem_speed = + (uint16_t) (*((uint16_t *)(data + DMI_CONF_MEM_SPEED_OFFSET))); + else if (hdr->length > DMI_MEM_SPEED_OFFSET) + mem_speed = + (uint16_t) (*((uint16_t *)(data + DMI_MEM_SPEED_OFFSET))); + else + mem_speed = -1; + + /* +* Check all channels have same speed +* else mark speed as invalid +*/ + if (dev_priv->dmi.mem_speed == 0) { + if (mem_speed > 0) + dev_priv->dmi.mem_speed = mem_speed; + else + dev_priv->dmi.mem_speed = -1; + } else if (dev_priv->dmi.mem_speed > 0 && + dev_priv->dmi.mem_speed != mem_speed) + dev_priv->dmi.mem_speed = -1; + } +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -882,6 +926,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->dev_private = dev_priv; dev_priv->dev = dev; + /* walk the dmi device table for getting platform memory information */ + dmi_walk(dmi_decode_memory_info, (void *) dev_priv); + /* Setup the write-once "constant" device info */ device_info = (struct intel_device_info *)_priv->info; memcpy(device_info, info, sizeof(dev_priv->info)); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 211af53..b040e7a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1968,6 +1968,12 @@ struct drm_i915_private { * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. */ + + /* DMI data for memory bandwidth calculation */ + struct { + uint16_t mem_channel; + int16_t mem_speed; + } dmi; }; static inline struct drm_i915_private *to_i915(const struct drm_device *dev) -- 2.5.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 6/6] drm/i915/skl: WA for watermark calculation based on Arbitrated Display BW
From: "Kumar, Mahesh" <mahesh1.ku...@intel.com> If the arbitary display bandwidth is > 60% of memory bandwith, for x-tile we should increase latency at all levels by 15us. If the arbitary dsplay bandwidth is greater than 20% of memory bandwith in case of y-tile being enabled, double the scan lines v2: Update the commit message to explain the WA (shobhit) v3: - Address Damien's comment, use DIV_ROUND_UP_ULL macro - Check both mem_speed and mem_channel to be valid before applying WA(shobhit) Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 9 drivers/gpu/drm/i915/intel_pm.c | 92 + 2 files changed, 101 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b040e7a..450e6d3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1624,6 +1624,12 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_MAX, }; +enum watermark_memory_wa { + WATERMARK_WA_NONE, + WATERMARK_WA_X_TILED, + WATERMARK_WA_Y_TILED, +}; + struct intel_pipe_crc_entry { uint32_t frame; uint32_t crc[5]; @@ -1926,6 +1932,9 @@ struct drm_i915_private { /* Committed wm config */ struct intel_wm_config config; + /* This stores if WaterMark memory workaround is needed */ + enum watermark_memory_wa mem_wa; + /* * The skl_wm_values structure is a bit too big for stack * allocation, so we keep the staging struct where we store diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a9f9396..da5ff34 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3225,6 +3225,11 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (latency == 0 || !cstate->base.active || !intel_pstate->visible) return false; + if (dev_priv->wm.mem_wa != WATERMARK_WA_NONE) { + if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + latency += 15; + } + width = drm_rect_width(_pstate->src) >> 16; height = drm_rect_height(_pstate->src) >> 16; @@ -3265,6 +3270,9 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, WARN(1, "Unsupported pixel depth for rotation"); } } + if (dev_priv->wm.mem_wa == WATERMARK_WA_Y_TILED) + min_scanlines *= 2; + y_tile_minimum = plane_blocks_per_line * min_scanlines; selected_result = max(method2, y_tile_minimum); } else { @@ -3715,6 +3723,89 @@ static void skl_set_plane_pixel_rate(struct drm_crtc *crtc) } +static void +skl_set_display_memory_wa(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = NULL; + struct intel_plane *intel_plane = NULL; + uint32_t num_active_crtc = 0; + uint64_t max_pixel_rate_pipe = 0; + uint64_t display_bw = 0, available_bw = 0; + bool y_tile_enabled = false; + int memory_portion = 0; + + /* Verify that we got proper memory information */ + if (dev_priv->dmi.mem_channel == 0 || dev_priv->dmi.mem_speed == -1) { + dev_priv->wm.mem_wa = WATERMARK_WA_NONE; + return; + } + + for_each_intel_crtc(dev, intel_crtc) { + uint64_t max_pixel_rate_plane = 0; + uint64_t pipe_bw; + uint32_t num_active_plane = 0; + const struct intel_crtc_state *cstate = NULL; + + if (!intel_crtc->active) + continue; + cstate = to_intel_crtc_state(intel_crtc->base.state); + num_active_crtc++; + + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + struct drm_plane *plane = _plane->base; + struct drm_framebuffer *fb = plane->state->fb; + uint64_t plane_bw, interm_bw = 1000; + + if (fb == NULL) + continue; + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + num_active_plane++; + + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED) + y_tile_enabled = true; + + /* +* planeBW = pixel_rate(MHz) * BPP * plane downscale +* amount *
Re: [Intel-gfx] [PATCH 0/7] Misc WM fixes and Arbitrated Display Bandwidth WA for SKL
On Fri, Jan 15, 2016 at 10:32 AM, Kumar, Shobhit < shobhit.ku...@linux.intel.com> wrote: > On 01/15/2016 07:18 AM, Matt Roper wrote: > >> On Thu, Jan 14, 2016 at 05:32:41PM +0530, Shobhit Kumar wrote: >> >>> Hi, >>> This series add a set of updates to the WM calculation and also enables >>> arbitrated display bandwidth based WA. Some of these patches do overlap >>> with Matts work but we wanted to send them out as we have them in our >>> internal testing for early review. Most likley some of them can be >>> superceded by patches from Matt, or can be re-used if deemed necessary. >>> >> >> I've left some feedback on your patches, but it was all pretty minor; >> they look pretty good overall. So I think we should polish up this set >> and merge it; I've got more SKL WM work coming (more atomic-y watermark >> calculation and programming) but I'll hold off on that until your series >> lands so that I don't cause too much thrash. >> > > Thanks Matt for the quick review. I will get the comments addressed and > final patches uploaded quickly. > We have the updated patches ready. Just completing some testing. Should be posting sometime this week. Regards Shobhit > > Regards > Shobhit > > >> Thanks. >> >> >> Matt >> >> >>> Especially "drm/i915/skl+: Use fb size for relative data rate >>> calculation" >>> this already addresses some of Ville's comment on similar patch from >>> Matt. >>> >>> Regards >>> Shobhit >>> >>> Kumar, Mahesh (6): >>>drm/i915/skl+: Use proper bytes_per_pixel during WM calculation >>>drm/i915/skl+: Use fb size for relative data rate calculation >>>drm/i915/skl+: calculate ddb minimum allocation >>>drm/i915/skl+: calculate plane pixel rate. >>>drm/i915/skl+: Use scaling amount for plane data rate calculation >>>drm/i915/skl: WA for watermark calculation based on Arbitrated Display >>> BW >>> >>> Shobhit Kumar (1): >>>drm/i915: Add support to parse DMI table and get platform memory info >>> >>> drivers/gpu/drm/i915/i915_dma.c | 19 +++ >>> drivers/gpu/drm/i915/i915_drv.h | 15 ++ >>> drivers/gpu/drm/i915/intel_drv.h | 2 + >>> drivers/gpu/drm/i915/intel_pm.c | 294 >>> +-- >>> 4 files changed, 316 insertions(+), 14 deletions(-) >>> >>> -- >>> 2.4.3 >>> >>> >> ___ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915: Retry few time if gpiod_get fails during intel_dsi_init
INTEL_SOC_PMIC is loading later than I915 failing the gpiod_get and pwm_get calls in i915. Add a retry to give time for the INTEL_SOC_PMIC to load. This was fine till now but broke in latest kernel. Maybe load time for the INTEL_SOC_PMIC has increased. Since the lookup tables for GPIO (panel enable) and PWM both are exported by same intel_soc_pmic driver, just retrying for the driver to load in intel_dsi_init is sufficient. By the time we come to setup_backlight, pwm would have been exported as well. Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_dsi.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 91cef35..e309ef6 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1192,10 +1192,14 @@ void intel_dsi_init(struct drm_device *dev) * Panel control. */ if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { + int retry = 4; + do { intel_dsi->gpio_panel = gpiod_get(dev->dev, "panel", GPIOD_OUT_HIGH); + msleep(50); + } while (IS_ERR(intel_dsi->gpio_panel) && --retry); - if (IS_ERR(intel_dsi->gpio_panel)) { + if (!retry) { DRM_ERROR("Failed to own gpio for panel control\n"); intel_dsi->gpio_panel = NULL; } -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/7] drm/i915/skl+: Use proper bytes_per_pixel during WM calculation
From: "Kumar, Mahesh"Don't always use bytes_per_pixel using y_plane=0, instead use it according to pixel format. If NV12 use y_plane eqal to 1 Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_pm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9df9e9a..68f21b9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3185,7 +3185,9 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (latency == 0 || !cstate->base.active || !fb) return false; - bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0); + bytes_per_pixel = (fb->pixel_format == DRM_FORMAT_NV12) ? + drm_format_plane_cpp(fb->pixel_format, 1) : + drm_format_plane_cpp(fb->pixel_format, 0); method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate), bytes_per_pixel, latency); -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 6/7] drm/i915: Add support to parse DMI table and get platform memory info
This is needed for WM computation workaround for arbitrated display bandwidth. Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_dma.c | 19 +++ drivers/gpu/drm/i915/i915_drv.h | 6 ++ 2 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a0f5659..03c3131 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -49,6 +49,7 @@ #include #include #include +#include static int i915_getparam(struct drm_device *dev, void *data, @@ -855,6 +856,21 @@ static void intel_init_dpio(struct drm_i915_private *dev_priv) } } +static void dmi_decode_memory_info(const struct dmi_header *hdr, void *priv) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) priv; + const u8 *data = (const u8 *) hdr; + + if (hdr->type == 17 && hdr->length > 0x17) { + + /* Found a memory channel */ + dev_priv->dmi.mem_channel++; + + /* Get the speed */ + dev_priv->dmi.mem_speed = (uint16_t) (*((uint16_t *)(data + 0x15))); + } +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -882,6 +898,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->dev_private = dev_priv; dev_priv->dev = dev; + /* walk the dmi device table for getting platform memory information */ + dmi_walk(dmi_decode_memory_info, (void *) dev_priv); + /* Setup the write-once "constant" device info */ device_info = (struct intel_device_info *)_priv->info; memcpy(device_info, info, sizeof(dev_priv->info)); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 104bd18..f588993 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1962,6 +1962,12 @@ struct drm_i915_private { * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. */ + + /* DMI data for memory bandwidth calculation */ + struct { + uint16_t mem_channel; + uint16_t mem_speed; + } dmi; }; static inline struct drm_i915_private *to_i915(const struct drm_device *dev) -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 4/7] drm/i915/skl+: calculate plane pixel rate.
From: "Kumar, Mahesh"Don't use pipe pixel rate for plane pixel rate. Calculate plane pixel according to formula adjusted plane_pixel_rate = adjusted pipe_pixel_rate * downscale ammount downscale amount = max[1, src_h/dst_h] * max[1, src_w/dst_w] if 90/270 rotation use rotated width & height Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_pm.c | 95 +++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 059b46e..49f237e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -661,6 +661,8 @@ struct intel_plane_wm_parameters { u64 tiling; unsigned int rotation; uint16_t fifo_size; +/* Stores the adjusted plane pixel rate for WM calculation */ + uint32_t plane_pixel_rate; }; struct intel_plane { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 64b39ec..ffcc56a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2841,6 +2841,54 @@ skl_wm_plane_id(const struct intel_plane *plane) } } +/* + * This function takes drm_plane_state as input + * and decides the downscale amount according to the formula + * + * downscale amount = Max[1, Horizontal source size / Horizontal dest size] + * + * Return value is multiplied by 1000 to retain fractional part + * Caller should take care of dividing & Rounding off the value + */ +static uint32_t +skl_plane_downscale_amount(const struct intel_plane *intel_plane) +{ + struct drm_plane_state *pstate = intel_plane->base.state; + struct intel_crtc *crtc = to_intel_crtc(pstate->crtc); + struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); + uint32_t downscale_h, downscale_w; + uint32_t src_w, src_h, dst_w, dst_h, tmp; + + if (drm_rect_width(_pstate->src)) { + src_w = drm_rect_width(_pstate->src) >> 16; + src_h = drm_rect_height(_pstate->src) >> 16; + } else { + src_w = crtc->config->pipe_src_w; + src_h = crtc->config->pipe_src_h; + } + + dst_w = drm_rect_width(_pstate->dst); + dst_h = drm_rect_height(_pstate->dst); + + if (intel_rotation_90_or_270(pstate->rotation)) + swap(dst_w, dst_h); + + /* If destination height & wight are zero return amount as unity */ + if (dst_w == 0 || dst_h == 0) + return 1000; + + /* Multiply by 1000 for precision */ + tmp = (1000 * src_h) / dst_h; + downscale_h = max_t(uint32_t, 1000, tmp); + + tmp = (1000 * src_w) / dst_w; + downscale_w = max_t(uint32_t, 1000, tmp); + + /* Reducing precision to 3 decimal places */ + return DIV_ROUND_UP(downscale_h * downscale_w, 1000); +} + + static void skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, const struct intel_crtc_state *cstate, @@ -3265,10 +3313,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, bytes_per_pixel = (fb->pixel_format == DRM_FORMAT_NV12) ? drm_format_plane_cpp(fb->pixel_format, 1) : drm_format_plane_cpp(fb->pixel_format, 0); - method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate), + method1 = skl_wm_method1(intel_plane->wm.plane_pixel_rate, bytes_per_pixel, latency); - method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate), + method2 = skl_wm_method2(intel_plane->wm.plane_pixel_rate, cstate->base.adjusted_mode.crtc_htotal, width, bytes_per_pixel, @@ -3709,6 +3757,46 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, } } +static uint32_t +skl_plane_pixel_rate(struct intel_crtc_state *cstate, struct intel_plane *plane) +{ + uint32_t adjusted_pixel_rate; + uint32_t downscale_amount; + + /* +* adjusted plane pixel rate = adjusted pipe pixel rate +* Plane pixel rate = adjusted plane pixel rate * plane down scale +* amount +*/ + adjusted_pixel_rate = skl_pipe_pixel_rate(cstate); + downscale_amount = skl_plane_downscale_amount(plane); + + return DIV_ROUND_UP(adjusted_pixel_rate * downscale_amount, + 1000); +} + +static void skl_set_plane_pixel_rate(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct intel_plane *intel_plane = NULL; + struct drm_device *dev = crtc->dev; + + if (!intel_crtc->active) + return;
[Intel-gfx] [PATCH 0/7] Misc WM fixes and Arbitrated Display Bandwidth WA for SKL
Hi, This series add a set of updates to the WM calculation and also enables arbitrated display bandwidth based WA. Some of these patches do overlap with Matts work but we wanted to send them out as we have them in our internal testing for early review. Most likley some of them can be superceded by patches from Matt, or can be re-used if deemed necessary. Especially "drm/i915/skl+: Use fb size for relative data rate calculation" this already addresses some of Ville's comment on similar patch from Matt. Regards Shobhit Kumar, Mahesh (6): drm/i915/skl+: Use proper bytes_per_pixel during WM calculation drm/i915/skl+: Use fb size for relative data rate calculation drm/i915/skl+: calculate ddb minimum allocation drm/i915/skl+: calculate plane pixel rate. drm/i915/skl+: Use scaling amount for plane data rate calculation drm/i915/skl: WA for watermark calculation based on Arbitrated Display BW Shobhit Kumar (1): drm/i915: Add support to parse DMI table and get platform memory info drivers/gpu/drm/i915/i915_dma.c | 19 +++ drivers/gpu/drm/i915/i915_drv.h | 15 ++ drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_pm.c | 294 +-- 4 files changed, 316 insertions(+), 14 deletions(-) -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 5/7] drm/i915/skl+: Use scaling amount for plane data rate calculation
From: "Kumar, Mahesh"Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_pm.c | 12 +--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ffcc56a..dc08494 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2978,6 +2978,8 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); struct drm_framebuffer *fb = pstate->fb; + struct intel_plane *intel_plane = to_intel_plane(pstate->plane); + uint32_t down_scale_amount, data_rate; uint32_t width = 0, height = 0; if (drm_rect_width(_pstate->src)) { @@ -2994,15 +2996,19 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, /* for planar format */ if (fb->pixel_format == DRM_FORMAT_NV12) { if (y) /* y-plane data rate */ - return width * height * + data_rate = width * height * drm_format_plane_cpp(fb->pixel_format, 0); else/* uv-plane data rate */ - return (width / 2) * (height / 2) * + data_rate = (width / 2) * (height / 2) * drm_format_plane_cpp(fb->pixel_format, 1); } /* for packed formats */ - return width * height * drm_format_plane_cpp(fb->pixel_format, 0); + data_rate = width * height * drm_format_plane_cpp(fb->pixel_format, 0); + down_scale_amount = skl_plane_downscale_amount(intel_plane); + + return DIV_ROUND_UP((data_rate * down_scale_amount), 1000); + } /* -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/7] drm/i915/skl+: Use fb size for relative data rate calculation
From: "Kumar, Mahesh"Use FB size for relative data rate calculation. don't always use pipe source width & height. adjust height & width according to rotation. Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_pm.c | 42 - 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 68f21b9..d33c4ff 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2928,24 +2928,33 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, int y) { struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); struct drm_framebuffer *fb = pstate->fb; + uint32_t width = 0, height = 0; + + if (drm_rect_width(_pstate->src)) { + width = drm_rect_width(_pstate->src) >> 16; + height = drm_rect_height(_pstate->src) >> 16; + } else { + width = intel_crtc->config->pipe_src_w; + height = intel_crtc->config->pipe_src_h; + } + + if (intel_rotation_90_or_270(pstate->rotation)) + swap(width, height); /* for planar format */ if (fb->pixel_format == DRM_FORMAT_NV12) { if (y) /* y-plane data rate */ - return intel_crtc->config->pipe_src_w * - intel_crtc->config->pipe_src_h * + return width * height * drm_format_plane_cpp(fb->pixel_format, 0); else/* uv-plane data rate */ - return (intel_crtc->config->pipe_src_w/2) * - (intel_crtc->config->pipe_src_h/2) * + return (width / 2) * (height / 2) * drm_format_plane_cpp(fb->pixel_format, 1); } /* for packed formats */ - return intel_crtc->config->pipe_src_w * - intel_crtc->config->pipe_src_h * - drm_format_plane_cpp(fb->pixel_format, 0); + return width * height * drm_format_plane_cpp(fb->pixel_format, 0); } /* @@ -3181,10 +3190,25 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t res_blocks, res_lines; uint32_t selected_result; uint8_t bytes_per_pixel; + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct intel_plane_state *intel_pstate = to_intel_plane_state(plane->state); + uint32_t width = 0, height = 0; if (latency == 0 || !cstate->base.active || !fb) return false; + if (drm_rect_width(_pstate->src)) { + width = drm_rect_width(_pstate->src) >> 16; + height = drm_rect_height(_pstate->src) >> 16; + } else { + width = intel_crtc->config->pipe_src_w; + height = intel_crtc->config->pipe_src_h; + } + + if (intel_rotation_90_or_270(plane->state->rotation)) + swap(width, height); + + /* for planar format */ bytes_per_pixel = (fb->pixel_format == DRM_FORMAT_NV12) ? drm_format_plane_cpp(fb->pixel_format, 1) : drm_format_plane_cpp(fb->pixel_format, 0); @@ -3193,12 +3217,12 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, latency); method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate), cstate->base.adjusted_mode.crtc_htotal, -cstate->pipe_src_w, +width, bytes_per_pixel, fb->modifier[0], latency); - plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel; + plane_bytes_per_line = width * bytes_per_pixel; plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/7] drm/i915/skl+: calculate ddb minimum allocation
From: "Kumar, Mahesh"don't always use 8 ddb as minimum, instead calculate using proper algorithm. Signed-off-by: Kumar, Mahesh --- drivers/gpu/drm/i915/intel_pm.c | 57 +++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d33c4ff..64b39ec 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2994,6 +2994,59 @@ skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate) return total_data_rate; } +static uint16_t +skl_ddb_min_alloc(const struct intel_crtc *crtc, + const struct drm_plane *plane, int y) +{ + struct drm_framebuffer *fb = plane->state->fb; + struct intel_plane_state *pstate = to_intel_plane_state(plane->state); + uint16_t min_alloc; + uint32_t src_w, src_h; + + /* For packed formats, no y-plane, return 0 */ + if (y && !(fb->pixel_format == DRM_FORMAT_NV12)) + return 0; + + if (drm_rect_width(>src)) { + src_w = drm_rect_width(>src) >> 16; + src_h = drm_rect_height(>src) >> 16; + } else { + src_w = crtc->config->pipe_src_w; + src_h = crtc->config->pipe_src_h; + } + + if (intel_rotation_90_or_270(plane->state->rotation)) + swap(src_w, src_h); + + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + uint32_t min_scanlines = 8; + uint8_t bytes_per_pixel = + y ? drm_format_plane_cpp(fb->pixel_format, 1) : + drm_format_plane_cpp(fb->pixel_format, 0); + + if (intel_rotation_90_or_270(plane->state->rotation)) { + switch (bytes_per_pixel) { + case 1: + min_scanlines = 32; + break; + case 2: + min_scanlines = 16; + break; + case 8: + WARN(1, "Unsupported pixel depth for rotation"); + } + } + min_alloc = DIV_ROUND_UP((4 * src_w / (y ? 1 : 2) * + bytes_per_pixel), 512) * min_scanlines/4 + 3; + } else { + min_alloc = 8; + } + + return min_alloc; +} + + static void skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct skl_ddb_allocation *ddb /* out */) @@ -3038,9 +3091,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - minimum[id] = 8; + minimum[id] = skl_ddb_min_alloc(intel_crtc, plane, 0); alloc_size -= minimum[id]; - y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0; + y_minimum[id] = skl_ddb_min_alloc(intel_crtc, plane, 1); alloc_size -= y_minimum[id]; } -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 7/7] drm/i915/skl: WA for watermark calculation based on Arbitrated Display BW
From: "Kumar, Mahesh" <mahesh1.ku...@intel.com> If the arbitary display bandwidth is > 60% of memory bandwith, for x-tile we should increase latency at all levels by 15us. If the arbitary dsplay bandwidth is greater than 20% of memory bandwith in case of y-tile being enabled, double the scan lines v2: Update the commit message to explain the WA (shobhit) Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 9 + drivers/gpu/drm/i915/intel_pm.c | 86 + 2 files changed, 95 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f588993..3c914a6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1620,6 +1620,12 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_MAX, }; +enum watermark_memory_wa { + WATERMARK_WA_NONE, + WATERMARK_WA_X_TILED, + WATERMARK_WA_Y_TILED, +}; + struct intel_pipe_crc_entry { uint32_t frame; uint32_t crc[5]; @@ -1915,6 +1921,9 @@ struct drm_i915_private { /* Committed wm config */ struct intel_wm_config config; + /* This stores if WaterMark memory workaround is needed */ + enum watermark_memory_wa mem_wa; + /* * The skl_wm_values structure is a bit too big for stack * allocation, so we keep the staging struct where we store diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index dc08494..fb59f4e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3304,6 +3304,11 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (latency == 0 || !cstate->base.active || !fb) return false; + if (dev_priv->wm.mem_wa != WATERMARK_WA_NONE) { + if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + latency += 15; + } + if (drm_rect_width(_pstate->src)) { width = drm_rect_width(_pstate->src) >> 16; height = drm_rect_height(_pstate->src) >> 16; @@ -3352,6 +3357,9 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, WARN(1, "Unsupported pixel depth for rotation"); } } + if (dev_priv->wm.mem_wa == WATERMARK_WA_Y_TILED) + min_scanlines *= 2; + y_tile_minimum = plane_blocks_per_line * min_scanlines; selected_result = max(method2, y_tile_minimum); } else { @@ -3803,6 +3811,83 @@ static void skl_set_plane_pixel_rate(struct drm_crtc *crtc) } +static void +skl_set_display_memory_wa(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = NULL; + struct intel_plane *intel_plane = NULL; + uint32_t num_active_crtc = 0; + uint64_t max_pixel_rate_pipe = 0; + uint64_t display_bw = 0, available_bw = 0; + bool y_tile_enabled = false; + int memory_portion = 0; + + for_each_intel_crtc(dev, intel_crtc) { + uint64_t max_pixel_rate_plane = 0; + uint64_t pipe_bw; + uint32_t num_active_plane = 0; + const struct intel_crtc_state *cstate = NULL; + + if (!intel_crtc->active) + continue; + cstate = to_intel_crtc_state(intel_crtc->base.state); + num_active_crtc++; + + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + struct drm_plane *plane = _plane->base; + struct drm_framebuffer *fb = plane->state->fb; + uint64_t plane_bw, interm_bw = 1000; + + if (fb == NULL) + continue; + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + num_active_plane++; + + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED) + y_tile_enabled = true; + + /* +* planeBW = pixel_rate(MHz) * BPP * plane downscale +* amount * pipe downscale amount; +* +* skl_pipe_pixel_rate return adjusted value according +* to downscaling amount +* pixel rate is in KHz & downscale factor is multiplied +* by 1000, so devide by 1000*1000 +*/ + interm_bw =
[Intel-gfx] [PATCH 1/3] drm/i915: Encapsulate the pwm_device in a pwm_info structure
pwm_info helps in encapsulating the PWM period_ns values and will form basis of adding new pwm devices which can then be genrically used by initializing proper pwm_info structure in the backlight setup call. Cc: cbroo...@gmail.com Cc: jani.nik...@linux.intel.com Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_drv.h | 8 ++- drivers/gpu/drm/i915/intel_panel.c | 45 -- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bdfe403..6f96769 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -161,6 +161,12 @@ struct intel_encoder { enum hpd_pin hpd_pin; }; +struct intel_pwm_info { + struct pwm_device *dev; + unsigned int period_ns; + char *name; +}; + struct intel_panel { struct drm_display_mode *fixed_mode; struct drm_display_mode *downclock_mode; @@ -179,7 +185,7 @@ struct intel_panel { /* PWM chip */ bool util_pin_active_low; /* bxt+ */ u8 controller; /* bxt+ only */ - struct pwm_device *pwm; + struct intel_pwm_info *pwm; struct backlight_device *device; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 21ee647..9e24c59 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -37,6 +37,13 @@ #define CRC_PMIC_PWM_PERIOD_NS 21333 +/* CRC PMIC based PWM Information */ +struct intel_pwm_info crc_pwm_info = { + .period_ns = CRC_PMIC_PWM_PERIOD_NS, + .name = "pwm_backlight", + .dev = NULL, +}; + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -538,10 +545,11 @@ static u32 bxt_get_backlight(struct intel_connector *connector) static u32 pwm_get_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; + struct intel_pwm_info *pwm = panel->backlight.pwm; int duty_ns; - duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); - return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); + duty_ns = pwm_get_duty_cycle(pwm->dev); + return DIV_ROUND_UP(duty_ns * 100, pwm->period_ns); } static u32 intel_panel_get_backlight(struct intel_connector *connector) @@ -630,9 +638,10 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) static void pwm_set_backlight(struct intel_connector *connector, u32 level) { struct intel_panel *panel = >panel; - int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + struct intel_pwm_info *pwm = panel->backlight.pwm; + int duty_ns = DIV_ROUND_UP(level * pwm->period_ns, 100); - pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); + pwm_config(pwm->dev, duty_ns, pwm->period_ns); } static void @@ -801,11 +810,12 @@ static void bxt_disable_backlight(struct intel_connector *connector) static void pwm_disable_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; + struct intel_pwm_info *pwm = panel->backlight.pwm; /* Disable the backlight */ - pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); + pwm_config(pwm->dev, 0, pwm->period_ns); usleep_range(2000, 3000); - pwm_disable(panel->backlight.pwm); + pwm_disable(pwm->dev); } void intel_panel_disable_backlight(struct intel_connector *connector) @@ -1069,7 +1079,7 @@ static void pwm_enable_backlight(struct intel_connector *connector) { struct intel_panel *panel = >panel; - pwm_enable(panel->backlight.pwm); + pwm_enable(panel->backlight.pwm->dev); intel_panel_actually_set_backlight(connector, panel->backlight.level); } @@ -1630,21 +1640,21 @@ static int pwm_setup_backlight(struct intel_connector *connector, { struct drm_device *dev = connector->base.dev; struct intel_panel *panel = >panel; + struct intel_pwm_info *pwm = _pwm_info; int retval; /* Get the PWM chip for backlight control */ - panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight"); - if (IS_ERR(panel->backlight.pwm)) { - DRM_ERROR("Failed to own the pwm chip\n"); + pwm->dev = pwm_get(dev->dev, pwm->name); + if (IS_ERR(pwm->dev)) { + DRM_ERROR("Failed to own the pwm chip: %s\n", pwm->name); panel->backlight.pwm = NULL; return -ENODEV; } - retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS, - CRC_PMIC_PWM_PERI
[Intel-gfx] [PATCH 0/3] LPSS PWM support for devices that support it
Hi, This is an untested attempt to enable LPSS PWM in the driver. As part of this did some restructuring for encapsulating the pwm_info inside the panel->backlight itself. This makes enabling LPSS PWM clean and simple. Not sending yet to pwm mailing list as this is all untested. C.B. please test the patches and see if they work at all for you. For testing Please enable - CONFIG_PWM_LPSS=y CONFIG_PWM_LPSS_PLATFORM=y Regards Shobhit Shobhit Kumar (3): drm/i915: Encapsulate the pwm_device in a pwm_info structure pwm: lpss: Add intel-gfx as consumer device in lookup table drm/i915: Add support for LPSS PWM on devices that support it drivers/gpu/drm/i915/intel_drv.h | 8 +- drivers/gpu/drm/i915/intel_panel.c | 59 +++--- drivers/pwm/pwm-lpss-platform.c| 8 ++ 3 files changed, 57 insertions(+), 18 deletions(-) -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/3] pwm: lpss: Add intel-gfx as consumer device in lookup table
Cc: cbroo...@gmail.com Cc: jani.nik...@linux.intel.com Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/pwm/pwm-lpss-platform.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 54433fc..910bc14 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -18,6 +18,11 @@ #include "pwm-lpss.h" +/* PWM consumed by the Intel GFX */ +static struct pwm_lookup lpss_pwm_lookup[] = { + PWM_LOOKUP("pwm-lpss", 0, ":00:02.0", "pwm_lpss", 0, PWM_POLARITY_NORMAL), +}; + static int pwm_lpss_probe_platform(struct platform_device *pdev) { const struct pwm_lpss_boardinfo *info; @@ -38,6 +43,9 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev) platform_set_drvdata(pdev, lpwm); + /* Register intel-gfx device as allowed consumer */ + pwm_add_table(lpss_pwm_lookup, ARRAY_SIZE(lpss_pwm_lookup)); + pm_runtime_set_active(>dev); pm_runtime_enable(>dev); -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/3] drm/i915: Add support for LPSS PWM on devices that support it
Cc: cbroo...@gmail.com Cc: jani.nik...@linux.intel.com Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_panel.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 9e24c59..16473fa 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -36,6 +36,7 @@ #include "intel_drv.h" #define CRC_PMIC_PWM_PERIOD_NS 21333 +#define LPSS_PWM_PERIOD_NS 10240 /* CRC PMIC based PWM Information */ struct intel_pwm_info crc_pwm_info = { @@ -44,6 +45,13 @@ struct intel_pwm_info crc_pwm_info = { .dev = NULL, }; +/* LPSS based PWM Information */ +struct intel_pwm_info lpss_pwm_info = { + .period_ns = LPSS_PWM_PERIOD_NS, + .name = "pwm_lpss", + .dev = NULL, +}; + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -1639,10 +1647,16 @@ static int pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe) { struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = >panel; - struct intel_pwm_info *pwm = _pwm_info; + struct intel_pwm_info *pwm; int retval; + if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) + pwm = _pwm_info; + else /* PPS_BLC_SOC */ + pwm = _pwm_info; + /* Get the PWM chip for backlight control */ pwm->dev = pwm_get(dev->dev, pwm->name); if (IS_ERR(pwm->dev)) { -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915: Wait for PP cycle delay only if panel is in power off sequence
During resume, while turning the EDP panel power on, we need not wait blindly for panel_power_cycle_delay. Check if panel power down sequence in progress and then only wait. This improves our resume time significantly. Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_dp.c | 17 - 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f335c92..10ec669 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -617,6 +617,20 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0; } +static bool edp_panel_off_seq(struct intel_dp *intel_dp) +{ + struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct drm_i915_private *dev_priv = dev->dev_private; + + lockdep_assert_held(_priv->pps_mutex); + + if (IS_VALLEYVIEW(dev) && + intel_dp->pps_pipe == INVALID_PIPE) + return false; + + return (I915_READ(_pp_stat_reg(intel_dp)) & PP_SEQUENCE_POWER_DOWN) != 0; +} + static bool edp_have_panel_vdd(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -2025,7 +2039,8 @@ static void edp_panel_on(struct intel_dp *intel_dp) port_name(dp_to_dig_port(intel_dp)->port))) return; - wait_panel_power_cycle(intel_dp); + if (edp_panel_off_seq(intel_dp)) + wait_panel_power_cycle(intel_dp); pp_ctrl_reg = _pp_ctrl_reg(intel_dp); pp = ironlake_get_pp_control(intel_dp); -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Wait for PP cycle delay only if panel is in power off sequence
On Wed, Dec 9, 2015 at 8:34 PM, Chris Wilson <ch...@chris-wilson.co.uk> wrote: > On Wed, Dec 09, 2015 at 08:07:10PM +0530, Shobhit Kumar wrote: >> On Wed, Dec 9, 2015 at 7:27 PM, Ville Syrjälä >> <ville.syrj...@linux.intel.com> wrote: >> > On Wed, Dec 09, 2015 at 06:51:48PM +0530, Shobhit Kumar wrote: >> >> During resume, while turning the EDP panel power on, we need not wait >> >> blindly for panel_power_cycle_delay. Check if panel power down sequence >> >> in progress and then only wait. This improves our resume time >> >> significantly. >> >> >> >> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> >> >> --- >> >> drivers/gpu/drm/i915/intel_dp.c | 17 - >> >> 1 file changed, 16 insertions(+), 1 deletion(-) >> >> >> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c >> >> b/drivers/gpu/drm/i915/intel_dp.c >> >> index f335c92..10ec669 100644 >> >> --- a/drivers/gpu/drm/i915/intel_dp.c >> >> +++ b/drivers/gpu/drm/i915/intel_dp.c >> >> @@ -617,6 +617,20 @@ static bool edp_have_panel_power(struct intel_dp >> >> *intel_dp) >> >> return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0; >> >> } >> >> >> >> +static bool edp_panel_off_seq(struct intel_dp *intel_dp) >> >> +{ >> >> + struct drm_device *dev = intel_dp_to_dev(intel_dp); >> >> + struct drm_i915_private *dev_priv = dev->dev_private; >> >> + >> >> + lockdep_assert_held(_priv->pps_mutex); >> >> + >> >> + if (IS_VALLEYVIEW(dev) && >> >> + intel_dp->pps_pipe == INVALID_PIPE) >> >> + return false; >> >> + >> >> + return (I915_READ(_pp_stat_reg(intel_dp)) & PP_SEQUENCE_POWER_DOWN) >> >> != 0; >> >> +} >> > >> > This doens't make sense to me. The power down cycle may have >> > completed just before, and so this would claim we don't have to >> > wait for the power_cycle_delay. >> >> Not sure I understand your concern correctly. You are right, power >> down cycle may have completed just before and if it has then we don't >> need to wait. But in case the power down cycle is in progress as per >> internal state, then we need to wait for it to complete. This will >> happen for example in non-suspend disable path and will be handled >> correctly. In case of actual suspend/resume, this would have >> successfully completed and will skip the wait as it is not needed >> before enabling panel power. >> >> > >> >> + >> >> static bool edp_have_panel_vdd(struct intel_dp *intel_dp) >> >> { >> >> struct drm_device *dev = intel_dp_to_dev(intel_dp); >> >> @@ -2025,7 +2039,8 @@ static void edp_panel_on(struct intel_dp *intel_dp) >> >>port_name(dp_to_dig_port(intel_dp)->port))) >> >> return; >> >> >> >> - wait_panel_power_cycle(intel_dp); >> >> + if (edp_panel_off_seq(intel_dp)) >> >> + wait_panel_power_cycle(intel_dp); > > Looking in from the side, I have no idea what this is meant to do. At > the very least you need your explanatory paragraph here which would > include what exactly you are waiting for at the start of edp_panel_on > (and please try and find a better name for edp_panel_off_seq()). I will add a comment. Basically I am not additionally waiting, but converting the wait which was already there to a conditional wait. The edp_panel_off_seq, checks if panel power down sequence is in progress. In that case we need to wait for the panel power cycle delay. If it is not in that sequence, there is no need to wait. I will make an attempt again on the naming in next patch update. Regards Shobhit > -Chris > > -- > Chris Wilson, Intel Open Source Technology Centre ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3] drm/i915/skl: While sanitizing cdclock check the SWF18 as well
SWF18 is set if the display has been intialized by the pre-os. It also gives what configuration is enabled on which pipe. In skl_sanitize_cdclk, the DPLL sanity check can pass even if GOP/VBIOS is not loaded as BIOS enables DPLL for integrated audio codec related programming. So fisrt check if SWF18 is set and then follow through with other DPLL and CDCLK verification. If not set then for sure we need to sanitize the cdclock. v2: Update the commit message for clarity (Siva) v3: Correct the mask to check for bits[23:0] instead of only bits[16:0]. Had missed checking for PIPE C altogether. Remaining are reserved (Siva) Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 8 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9ee9481..bd476ff 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5006,6 +5006,9 @@ enum skl_disp_power_wells { #define SWF1(i)(dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4) #define SWF3(i)(dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4) +/* VBIOS flag for display initialized status */ +#define GEN6_SWF18 (dev_priv->info.display_mmio_offset + 0x4F060) + /* Pipe B */ #define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000) #define _PIPEBCONF (dev_priv->info.display_mmio_offset + 0x71008) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 103cacb..81668b0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5761,6 +5761,14 @@ int skl_sanitize_cdclk(struct drm_i915_private *dev_priv) uint32_t cdctl = I915_READ(CDCLK_CTL); int freq = dev_priv->skl_boot_cdclk; + /* +* check if the pre-os intialized the display +* There is SWF18 scratchpad register defined which is set by the +* pre-os which can be used by the OS drivers to check the status +*/ + if ((I915_READ(GEN6_SWF18) & 0x00FF) == 0) + goto sanitize; + /* Is PLL enabled and locked ? */ if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK))) goto sanitize; -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v4] drm/i915/skl: While sanitizing cdclock check the SWF18 as well
SWF18 is set if the display has been intialized by the pre-os. It also gives what configuration is enabled on which pipe. In skl_sanitize_cdclk, the DPLL sanity check can pass even if GOP/VBIOS is not loaded as BIOS enables DPLL for integrated audio codec related programming. So fisrt check if SWF18 is set and then follow through with other DPLL and CDCLK verification. If not set then for sure we need to sanitize the cdclock. v2: Update the commit message for clarity (Siva) v3: Correct the mask to check for bits[23:0] instead of only bits[16:0]. Had missed checking for PIPE C altogether. Remaining are reserved (Siva) v4: Use ILK_SWF macro for SWF register definitions. Taken from Ville's patch http://lists.freedesktop.org/archives/intel-gfx/2015-November/079480.html Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 8 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9ee9481..e8f1d42 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5005,6 +5005,7 @@ enum skl_disp_power_wells { #define SWF0(i)(dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4) #define SWF1(i)(dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4) #define SWF3(i)(dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4) +#define SWF_ILK(i) (0x4F000 + (i) * 4) /* Pipe B */ #define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 103cacb..512747a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5761,6 +5761,14 @@ int skl_sanitize_cdclk(struct drm_i915_private *dev_priv) uint32_t cdctl = I915_READ(CDCLK_CTL); int freq = dev_priv->skl_boot_cdclk; + /* +* check if the pre-os intialized the display +* There is SWF18 scratchpad register defined which is set by the +* pre-os which can be used by the OS drivers to check the status +*/ + if ((I915_READ(SWF_ILK(0x18)) & 0x00FF) == 0) + goto sanitize; + /* Is PLL enabled and locked ? */ if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK))) goto sanitize; -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2] drm/i915/skl: While sanitizing cdclock check the SWF18 as well
SWF18 is set if the display has been intialized by the pre-os. It also gives what configuration is enabled on which pipe. In skl_sanitize_cdclk, the DPLL sanity check can pass even if GOP/VBIOS is not loaded as BIOS enables DPLL for integrated audio codec related programming. So fisrt check if SWF18 is set and then follow through with other DPLL and CDCLK verification. If not set then for sure we need to sanitize the cdclock. v2: Update the commit message for clarity (Siva) Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 8 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9ee9481..bd476ff 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5006,6 +5006,9 @@ enum skl_disp_power_wells { #define SWF1(i)(dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4) #define SWF3(i)(dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4) +/* VBIOS flag for display initialized status */ +#define GEN6_SWF18 (dev_priv->info.display_mmio_offset + 0x4F060) + /* Pipe B */ #define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000) #define _PIPEBCONF (dev_priv->info.display_mmio_offset + 0x71008) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 103cacb..0ecb35c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5761,6 +5761,14 @@ int skl_sanitize_cdclk(struct drm_i915_private *dev_priv) uint32_t cdctl = I915_READ(CDCLK_CTL); int freq = dev_priv->skl_boot_cdclk; + /* +* check if the pre-os intialized the display +* There is SWF18 scratchpad register defined which is set by the +* pre-os which can be used by the OS drivers to check the status +*/ + if ((I915_READ(GEN6_SWF18) & 0x00) == 0) + goto sanitize; + /* Is PLL enabled and locked ? */ if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK))) goto sanitize; -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] CDCLOCK Sanitization continued for SKL
The cdclock sanitization patch reviewed and merged at - http://patchwork.freedesktop.org/patch/msgid/1445344992-14658-1-git-send-email-shobhit.ku...@intel.com made the assumptions that DPLL should not be enabled when pre-os does not enable display and if it does then verify that the cdclock is corectly programmed as well. The BIOS was actually enabling DPLL as well while not following BSPEC sequence and writing cdclk register directly. I was working with BIOS team to correct this and found that due to a WA needed where audio codec will not be enumerated in OS if BIOS did not program the audio verbs which needed PG2 and DPLL enabling. More discussion revealed the following logic - 1. BIOS puts max cdclk for the platform in CDCLK_CTL. VBIOS/GOP reads that value and then programs cdclk to desired value. 2. It also then sets SWF18 to indicate to the OS that it has enabled display. Used for fastmodeset actually in windows. 3. It also sets SWF06 with this max cdclock(from what bios programmed in CDCLK_CTL) for OS to know. This patch uses point 2 above while sanitizing the cdclk. We can also update our logic for deciding max cdclock based on SWF06 if pre-os enables else directly from CDCLK_CTL (no pre-os display). That is not part of this patch. Shobhit Kumar (1): drm/i915/skl: While sanitizing cdclock check the SWF18 as well drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 8 2 files changed, 11 insertions(+) -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/skl: While sanitizing cdclock check the SWF18 as well
SWF18 is set if the display has been intialized by the pre-os. It also gives what configuration is enabled on which pipe. The DPLL and CDCLK verification checks can fail as the pre-os does initialize the DPLL for Audio codec initialization. So fisrt check if SWF18 is set and then follow through with other DPLL and CDCLK verification. Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 8 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9ee9481..bd476ff 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5006,6 +5006,9 @@ enum skl_disp_power_wells { #define SWF1(i)(dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4) #define SWF3(i)(dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4) +/* VBIOS flag for display initialized status */ +#define GEN6_SWF18 (dev_priv->info.display_mmio_offset + 0x4F060) + /* Pipe B */ #define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000) #define _PIPEBCONF (dev_priv->info.display_mmio_offset + 0x71008) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 103cacb..0ecb35c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5761,6 +5761,14 @@ int skl_sanitize_cdclk(struct drm_i915_private *dev_priv) uint32_t cdctl = I915_READ(CDCLK_CTL); int freq = dev_priv->skl_boot_cdclk; + /* +* check if the pre-os intialized the display +* There is SWF18 scratchpad register defined which is set by the +* pre-os which can be used by the OS drivers to check the status +*/ + if ((I915_READ(GEN6_SWF18) & 0x00) == 0) + goto sanitize; + /* Is PLL enabled and locked ? */ if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK))) goto sanitize; -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v4] drm/i915/skl: If needed sanitize bios programmed cdclk
Especially in cases where pre-os does not enable display, cdclk might not be in sane state. During sanitization initialize cdclk with maximum value till we get dynamic cdclk support. v2: Check if BIOS programmed correctly rather than always calling init - Do validation of programmed cdctl and what it is expected - Only do slk_init_cdclk if validation failed else reuse BIOS programmed value v3: Move the validation logic in a separate sanitize function (Ville) v4: No need to check LCPLL after sanitize and use max_cdclk_freq instead of hardcoded value (Ville) Cc: Imre Deak <imre.d...@intel.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 31 +++ drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index b25e99a..824b863 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2949,8 +2949,8 @@ void intel_ddi_pll_init(struct drm_device *dev) cdclk_freq = dev_priv->display.get_display_clock_speed(dev); dev_priv->skl_boot_cdclk = cdclk_freq; - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) - DRM_ERROR("LCPLL1 is disabled\n"); + if (skl_sanitize_cdclk(dev_priv)) + DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n"); else intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); } else if (IS_BROXTON(dev)) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5f37f84..4933b72 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5784,6 +5784,37 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) DRM_ERROR("DBuf power enable timeout\n"); } +int skl_sanitize_cdclk(struct drm_i915_private *dev_priv) +{ + uint32_t lcpll1 = I915_READ(LCPLL1_CTL); + uint32_t cdctl = I915_READ(CDCLK_CTL); + int freq = dev_priv->skl_boot_cdclk; + + /* Is PLL enabled and locked ? */ + if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK))) + goto sanitize; + + /* DPLL okay; verify the cdclock +* +* Noticed in some instances that the freq selection is correct but +* decimal part is programmed wrong from BIOS where pre-os does not +* enable display. Verify the same as well. +*/ + if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq))) + /* All well; nothing to sanitize */ + return false; +sanitize: + /* +* As of now initialize with max cdclk till +* we get dynamic cdclk support +* */ + dev_priv->skl_boot_cdclk = dev_priv->max_cdclk_freq; + skl_init_cdclk(dev_priv); + + /* we did have to sanitize */ + return true; +} + /* Adjust CDclk dividers to allow high res or save power if possible */ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0598932..ec10e6a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1152,6 +1152,7 @@ void broxton_ddi_phy_uninit(struct drm_device *dev); void bxt_enable_dc9(struct drm_i915_private *dev_priv); void bxt_disable_dc9(struct drm_i915_private *dev_priv); void skl_init_cdclk(struct drm_i915_private *dev_priv); +int skl_sanitize_cdclk(struct drm_i915_private *dev_priv); void skl_uninit_cdclk(struct drm_i915_private *dev_priv); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3] drm/i915/skl: If needed sanitize bios programmed cdclk
Especially in cases where pre-os does not enable display, cdclk might not be in sane state. During sanitization initialize cdclk with maximum value till we get dynamic cdclk support. v2: Check if BIOS programmed correctly rather than always calling init - Do validation of programmed cdctl and what it is expected - Only do slk_init_cdclk if validation failed else reuse BIOS programmed value v3: Move the validation logic in a separate sanitize function (Ville) Cc: Imre Deak <imre.d...@intel.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_ddi.c | 12 drivers/gpu/drm/i915/intel_display.c | 31 +++ drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index b25e99a..86d43e6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2949,10 +2949,14 @@ void intel_ddi_pll_init(struct drm_device *dev) cdclk_freq = dev_priv->display.get_display_clock_speed(dev); dev_priv->skl_boot_cdclk = cdclk_freq; - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) - DRM_ERROR("LCPLL1 is disabled\n"); - else - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + if (skl_sanitize_cdclk(dev_priv)) + DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n"); + else { + if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) + DRM_ERROR("LCPLL1 is disabled\n"); + else + intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + } } else if (IS_BROXTON(dev)) { broxton_init_cdclk(dev); broxton_ddi_phy_init(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5f37f84..98333d3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5784,6 +5784,37 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) DRM_ERROR("DBuf power enable timeout\n"); } +int skl_sanitize_cdclk(struct drm_i915_private *dev_priv) +{ + uint32_t lcpll1 = I915_READ(LCPLL1_CTL); + uint32_t cdctl = I915_READ(CDCLK_CTL); + int freq = dev_priv->skl_boot_cdclk; + + /* Is PLL enabled and locked ? */ + if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK))) + goto sanitize; + + /* DPLL okay; verify the cdclock +* +* Noticed in some instances that the freq selection is correct but +* decimal part is programmed wrong from BIOS where pre-os does not +* enable display. Verify the same as well. +*/ + if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq))) + /* All well; nothing to sanitize */ + return false; +sanitize: + /* +* As of now initialize with max cdclk till +* we get dynamic cdclk support +* */ + dev_priv->skl_boot_cdclk = 675000; + skl_init_cdclk(dev_priv); + + /* we did have to sanitize */ + return true; +} + /* Adjust CDclk dividers to allow high res or save power if possible */ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0598932..ec10e6a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1152,6 +1152,7 @@ void broxton_ddi_phy_uninit(struct drm_device *dev); void bxt_enable_dc9(struct drm_i915_private *dev_priv); void bxt_disable_dc9(struct drm_i915_private *dev_priv); void skl_init_cdclk(struct drm_i915_private *dev_priv); +int skl_sanitize_cdclk(struct drm_i915_private *dev_priv); void skl_uninit_cdclk(struct drm_i915_private *dev_priv); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2] drm/i915/skl: Init cdclk in the driver rather than relying on pre-os
Reuse what is programmed by pre-os, but in case there is no pre-os initialization, init the cdclk with the max value by default untill dynamic cdclk support comes. v2: Check if BIOS programmed correctly rather than always calling init - Do validation of programmed cdctl and what it is expected - Only do slk_init_cdclk if validation failed else reuse BIOS programmed value Cc: Imre Deak <imre.d...@intel.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_ddi.c | 18 - drivers/gpu/drm/i915/intel_display.c | 39 +++- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 2d3cc82..3ec5618 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2946,11 +2946,19 @@ void intel_ddi_pll_init(struct drm_device *dev) int cdclk_freq; cdclk_freq = dev_priv->display.get_display_clock_speed(dev); - dev_priv->skl_boot_cdclk = cdclk_freq; - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) - DRM_ERROR("LCPLL1 is disabled\n"); - else - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + + /* Invalid CDCLK from BIOS ? */ + if (cdclk_freq < 0) { + /* program to maximum cdclk till we have dynamic cdclk support */ + dev_priv->skl_boot_cdclk = 675000; + skl_init_cdclk(dev_priv); + } else { + dev_priv->skl_boot_cdclk = cdclk_freq; + if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) + DRM_ERROR("LCPLL1 is disabled\n"); + else + intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + } } else if (IS_BROXTON(dev)) { broxton_init_cdclk(dev); broxton_ddi_phy_init(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bbeb6d3..f734410 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6634,12 +6634,15 @@ static int skylake_get_display_clock_speed(struct drm_device *dev) uint32_t lcpll1 = I915_READ(LCPLL1_CTL); uint32_t cdctl = I915_READ(CDCLK_CTL); uint32_t linkrate; + int freq; if (!(lcpll1 & LCPLL_PLL_ENABLE)) return 24000; /* 24MHz is the cd freq with NSSC ref */ - if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) - return 54; + if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) { + freq = 54; + goto verify; + } linkrate = (I915_READ(DPLL_CTRL1) & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; @@ -6649,30 +6652,46 @@ static int skylake_get_display_clock_speed(struct drm_device *dev) /* vco 8640 */ switch (cdctl & CDCLK_FREQ_SEL_MASK) { case CDCLK_FREQ_450_432: - return 432000; + freq = 432000; + break; case CDCLK_FREQ_337_308: - return 308570; + freq = 308570; + break; case CDCLK_FREQ_675_617: - return 617140; + freq = 617140; + break; default: WARN(1, "Unknown cd freq selection\n"); + return -EINVAL; } } else { /* vco 8100 */ switch (cdctl & CDCLK_FREQ_SEL_MASK) { case CDCLK_FREQ_450_432: - return 45; + freq = 45; + break; case CDCLK_FREQ_337_308: - return 337500; + freq = 337500; + break; case CDCLK_FREQ_675_617: - return 675000; + freq = 675000; + break; default: WARN(1, "Unknown cd freq selection\n"); + return -EINVAL; } } - /* error case, do as if DPLL0 isn't enabled */ - return 24000; +verify: + /* +* Noticed in some instances that the freq selection is correct but +* decimal part is programmed wrong from BIOS where pre-os does not +* enable display. Verify the same as well. +*/ + if (cdctl == ((cdctl & CDCLK_
[Intel-gfx] [PATCH] drm/i915/skl: Init cdclk in the driver rather than relying on pre-os
Mostly reuse what is programmed by pre-os, but in case there is no pre-os initialization, init the cdclk with the default value. Cc: Imre Deak <imre.d...@intel.com> Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com> --- drivers/gpu/drm/i915/intel_ddi.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 2d3cc82..675c60d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2947,10 +2947,8 @@ void intel_ddi_pll_init(struct drm_device *dev) cdclk_freq = dev_priv->display.get_display_clock_speed(dev); dev_priv->skl_boot_cdclk = cdclk_freq; - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) - DRM_ERROR("LCPLL1 is disabled\n"); - else - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + + skl_init_cdclk(dev_priv); } else if (IS_BROXTON(dev)) { broxton_init_cdclk(dev); broxton_ddi_phy_init(dev); -- 2.4.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] mfd: Add GPIOLIB dependency if INTEL_SOC_PMIC is to be enabled
This is needed as the CRC PMIC has support for Panel enable/diable as gpio which needs 'gpiod_add_lookup_table' and 'gpiod_remove_lookup_table' from gpiolib. This patch can be squashed with below commit in topic/crc-pmic branch commit 61dd2ca2d44e493b050adbbb75bc50db11c367dd Author: Shobhit Kumar shobhit.ku...@intel.com Date: Fri Jun 26 14:32:05 2015 +0530 mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal On some Intel SoC platforms, the panel enable/disable signals are controlled by CRC PMIC. Add those control as a new GPIO in a lookup table for gpio-crystalcove chip during CRC driver load Cc: Lee Jones lee.jo...@linaro.org Cc: Linus Walleij linus.wall...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6538159..379a420 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -318,6 +318,7 @@ config LPC_SCH config INTEL_SOC_PMIC bool Support for Intel Atom SoC PMIC + depends on GPIOLIB depends on I2C=y select MFD_CORE select REGMAP_I2C -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v3 0/7] Crystalcove (CRC) PMIC based panel and pwm control
On Fri, Jul 10, 2015 at 6:36 PM, Shobhit Kumar ku...@shobhit.info wrote: On Mon, Jun 29, 2015 at 3:48 AM, Paul Gortmaker paul.gortma...@windriver.com wrote: [Re: [Intel-gfx] [v3 0/7] Crystalcove (CRC) PMIC based panel and pwm control] On 26/06/2015 (Fri 20:47) Ville Syrjälä wrote: On Fri, Jun 26, 2015 at 06:31:37PM +0200, Daniel Vetter wrote: On Fri, Jun 26, 2015 at 02:32:03PM +0530, Shobhit Kumar wrote: Hi, Next update of the series reviewed at https://lkml.org/lkml/2015/6/22/155 Major changes are few review comments from Varka and Ville being addressed. Also except for intel-gfx patches, all patches reviesion history is moved out of commit message. Hope this series finally finds its mark. Regards Shobhit Shobhit Kumar (7): gpiolib: Add support for removing registered consumer lookup table mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM pwm: crc: Add Crystalcove (CRC) PWM driver drm/i915: Use the CRC gpio for panel enable/disable drm/i915: Backlight control using CRC PMIC based PWM driver I think we have r-b/acks on all the patches now. Ok if I pull this in through drm-intel.git for 4.3? Or should I make a topic branch with tag and then send out pull requests to everyone? Or will each maintainer merge on their own since it's all only coupled at runtime anyway? Any of these would suit me. I forgot to mention that I had a build failure due to builtin_platform_driver() when I tried this (just changed it to module_platform_driver() to get past it). So I'm not sure if this now depends on some tree which isn't included in -nightly... builtin_platform_register does not yet exist in mainline; as Paul (the other one) said earlier. So you can either open-code what it does for now, or use module_platform_register. If you do the latter, then ensure you (temorarily) also include module.h or you risk additional breakage in the future. Guess its in mainline now. Whats the plan for the merge of these patches ? Do I need to do anything further on these patches ? Daniel can you help in the next steps. Regards Shobhit ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v3 0/7] Crystalcove (CRC) PMIC based panel and pwm control
On Mon, Jun 29, 2015 at 3:48 AM, Paul Gortmaker paul.gortma...@windriver.com wrote: [Re: [Intel-gfx] [v3 0/7] Crystalcove (CRC) PMIC based panel and pwm control] On 26/06/2015 (Fri 20:47) Ville Syrjälä wrote: On Fri, Jun 26, 2015 at 06:31:37PM +0200, Daniel Vetter wrote: On Fri, Jun 26, 2015 at 02:32:03PM +0530, Shobhit Kumar wrote: Hi, Next update of the series reviewed at https://lkml.org/lkml/2015/6/22/155 Major changes are few review comments from Varka and Ville being addressed. Also except for intel-gfx patches, all patches reviesion history is moved out of commit message. Hope this series finally finds its mark. Regards Shobhit Shobhit Kumar (7): gpiolib: Add support for removing registered consumer lookup table mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM pwm: crc: Add Crystalcove (CRC) PWM driver drm/i915: Use the CRC gpio for panel enable/disable drm/i915: Backlight control using CRC PMIC based PWM driver I think we have r-b/acks on all the patches now. Ok if I pull this in through drm-intel.git for 4.3? Or should I make a topic branch with tag and then send out pull requests to everyone? Or will each maintainer merge on their own since it's all only coupled at runtime anyway? Any of these would suit me. I forgot to mention that I had a build failure due to builtin_platform_driver() when I tried this (just changed it to module_platform_driver() to get past it). So I'm not sure if this now depends on some tree which isn't included in -nightly... builtin_platform_register does not yet exist in mainline; as Paul (the other one) said earlier. So you can either open-code what it does for now, or use module_platform_register. If you do the latter, then ensure you (temorarily) also include module.h or you risk additional breakage in the future. Guess its in mainline now. Whats the plan for the merge of these patches ? Regards Shobhit Paul. -- -- Ville Syrjälä Intel OTC ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v3 0/7] Crystalcove (CRC) PMIC based panel and pwm control
On Fri, Jun 26, 2015 at 11:17 PM, Ville Syrjälä ville.syrj...@linux.intel.com wrote: On Fri, Jun 26, 2015 at 06:31:37PM +0200, Daniel Vetter wrote: On Fri, Jun 26, 2015 at 02:32:03PM +0530, Shobhit Kumar wrote: Hi, Next update of the series reviewed at https://lkml.org/lkml/2015/6/22/155 Major changes are few review comments from Varka and Ville being addressed. Also except for intel-gfx patches, all patches reviesion history is moved out of commit message. Hope this series finally finds its mark. Regards Shobhit Shobhit Kumar (7): gpiolib: Add support for removing registered consumer lookup table mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM pwm: crc: Add Crystalcove (CRC) PWM driver drm/i915: Use the CRC gpio for panel enable/disable drm/i915: Backlight control using CRC PMIC based PWM driver I think we have r-b/acks on all the patches now. Ok if I pull this in through drm-intel.git for 4.3? Or should I make a topic branch with tag and then send out pull requests to everyone? Or will each maintainer merge on their own since it's all only coupled at runtime anyway? Any of these would suit me. I forgot to mention that I had a build failure due to builtin_platform_driver() when I tried this (just changed it to module_platform_driver() to get past it). So I'm not sure if this now depends on some tree which isn't included in -nightly... These patches are based on linux-next/master Regards Shobhit ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3 7/7] drm/i915: Backlight control using CRC PMIC based PWM driver
Use the CRC PWM device in intel_panel.c and add new MIPI backlight specififc callbacks v2: Modify to use pwm_config callback v3: Addressed Jani's comments - Renamed all function as pwm_* instead of vlv_* - Call intel_panel_actually_set_backlight in enable function - Return -ENODEV in case pwm_get fails - in case pwm_config error return error cdoe from pwm_config - Cleanup pwm in intel_panel_destroy_backlight v4: Removed unused #defines and initialized backlight with INVALID_PIPE (Ville) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Reviewed-by: Ville Syrjälä ville.syrj...@linux.intel.com Tested-by: Ville Syrjälä ville.syrj...@linux.intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 4 ++ drivers/gpu/drm/i915/intel_dsi.c | 5 ++ drivers/gpu/drm/i915/intel_panel.c | 94 -- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2afb31a..561c17f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -182,6 +182,10 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + + /* PWM chip */ + struct pwm_device *pwm; + struct backlight_device *device; } backlight; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index c4db74a..892b936 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -402,6 +402,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_dsi_port_enable(encoder); } + + intel_panel_enable_backlight(intel_dsi-attached_connector); } static void intel_dsi_pre_enable(struct intel_encoder *encoder) @@ -466,6 +468,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + intel_panel_disable_backlight(intel_dsi-attached_connector); + if (is_vid_mode(intel_dsi)) { /* Send Shutdown command to the panel in LP mode */ for_each_dsi_port(port, intel_dsi-ports) @@ -1132,6 +1136,7 @@ void intel_dsi_init(struct drm_device *dev) } intel_panel_init(intel_connector-panel, fixed_mode, NULL); + intel_panel_setup_backlight(connector, INVALID_PIPE); return; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 7d83527..952fadc 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -32,8 +32,11 @@ #include linux/kernel.h #include linux/moduleparam.h +#include linux/pwm.h #include intel_drv.h +#define CRC_PMIC_PWM_PERIOD_NS 21333 + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -544,6 +547,15 @@ static u32 bxt_get_backlight(struct intel_connector *connector) return I915_READ(BXT_BLC_PWM_DUTY1); } +static u32 pwm_get_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + int duty_ns; + + duty_ns = pwm_get_duty_cycle(panel-backlight.pwm); + return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); +} + static u32 intel_panel_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -632,6 +644,14 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) I915_WRITE(BXT_BLC_PWM_DUTY1, level); } +static void pwm_set_backlight(struct intel_connector *connector, u32 level) +{ + struct intel_panel *panel = connector-panel; + int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + + pwm_config(panel-backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); +} + static void intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) { @@ -769,6 +789,16 @@ static void bxt_disable_backlight(struct intel_connector *connector) I915_WRITE(BXT_BLC_PWM_CTL1, tmp ~BXT_BLC_PWM_ENABLE); } +static void pwm_disable_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + + /* Disable the backlight */ + pwm_config(panel-backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); + usleep_range(2000, 3000); + pwm_disable(panel-backlight.pwm); +} + void intel_panel_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -1002,6 +1032,14 @@ static void bxt_enable_backlight(struct intel_connector *connector) I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl | BXT_BLC_PWM_ENABLE); } +static void pwm_enable_backlight(struct
[Intel-gfx] [v3 4/7] mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM
On some BYT PLatform the PWM is controlled using CRC PMIC. Add a lookup entry for the same to be used by the consumer (Intel GFX) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Tested-by: Ville Syrjälä ville.syrj...@linux.intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- v2: Remove the lookup table on driver unload (Thierry) v3: Correct the subject line (Lee jones) drivers/mfd/intel_soc_pmic_core.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index f3d918e..a00ddd9 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -25,6 +25,7 @@ #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h #include linux/gpio/machine.h +#include linux/pwm.h #include intel_soc_pmic_core.h /* Lookup table for the Panel Enable/Disable line as GPIO signals */ @@ -37,6 +38,11 @@ static struct gpiod_lookup_table panel_gpio_table = { }, }; +/* PWM consumed by the Intel GFX */ +static struct pwm_lookup crc_pwm_lookup[] = { + PWM_LOOKUP(crystal_cove_pwm, 0, :00:02.0, pwm_backlight, 0, PWM_POLARITY_NORMAL), +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -99,6 +105,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, /* Add lookup table binding for Panel Control to the GPIO Chip */ gpiod_add_lookup_table(panel_gpio_table); + /* Add lookup table for crc-pwm */ + pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -121,6 +130,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) /* Remove lookup table for Panel Control from the GPIO Chip */ gpiod_remove_lookup_table(panel_gpio_table); + /* remove crc-pwm lookup table */ + pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + mfd_remove_devices(i2c-dev); return 0; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3 0/7] Crystalcove (CRC) PMIC based panel and pwm control
Hi, Next update of the series reviewed at https://lkml.org/lkml/2015/6/22/155 Major changes are few review comments from Varka and Ville being addressed. Also except for intel-gfx patches, all patches reviesion history is moved out of commit message. Hope this series finally finds its mark. Regards Shobhit Shobhit Kumar (7): gpiolib: Add support for removing registered consumer lookup table mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM pwm: crc: Add Crystalcove (CRC) PWM driver drm/i915: Use the CRC gpio for panel enable/disable drm/i915: Backlight control using CRC PMIC based PWM driver drivers/gpio/gpiolib.c | 13 drivers/gpu/drm/i915/intel_bios.h | 7 ++ drivers/gpu/drm/i915/intel_drv.h | 4 ++ drivers/gpu/drm/i915/intel_dsi.c | 37 +- drivers/gpu/drm/i915/intel_dsi.h | 3 + drivers/gpu/drm/i915/intel_panel.c | 94 ++-- drivers/mfd/intel_soc_pmic_core.c | 29 drivers/mfd/intel_soc_pmic_crc.c | 3 + drivers/pwm/Kconfig| 7 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-crc.c | 143 + include/linux/gpio/machine.h | 1 + 12 files changed, 335 insertions(+), 7 deletions(-) create mode 100644 drivers/pwm/pwm-crc.c -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3 3/7] mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC
Needed for PWM control suuported by the PMIC CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Tested-by: Ville Syrjälä ville.syrj...@linux.intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- v2: Correct the subject line (Lee jones) drivers/mfd/intel_soc_pmic_crc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index 7436075..4a74948 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -109,6 +109,9 @@ static struct mfd_cell crystal_cove_dev[] = { { .name = crystal_cove_pmic, }, + { + .name = crystal_cove_pwm, + }, }; static const struct regmap_config crystal_cove_regmap_config = { -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3 1/7] gpiolib: Add support for removing registered consumer lookup table
In case we unload and load a driver module again that is registering a lookup table, without this it will result in multiple entries. Provide an option to remove the lookup table on driver unload Cc: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Reviewed-by: Alexandre Courbot acour...@nvidia.com Reviewed-by: Linus Walleij linus.wall...@linaro.org Tested-by: Ville Syrjälä ville.syrj...@linux.intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- v2: Ccing maintainers v3: Correct the subject line (Lee jones) drivers/gpio/gpiolib.c | 13 + include/linux/gpio/machine.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 957ede5..9d3ea4e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1675,6 +1675,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table) mutex_unlock(gpio_lookup_lock); } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ + mutex_lock(gpio_lookup_lock); + + list_del(table-list); + + mutex_unlock(gpio_lookup_lock); +} + static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index e270614..c0d712d 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -57,5 +57,6 @@ struct gpiod_lookup_table { } void gpiod_add_lookup_table(struct gpiod_lookup_table *table); +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); #endif /* __LINUX_GPIO_MACHINE_H */ -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3 2/7] mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal
On some Intel SoC platforms, the panel enable/disable signals are controlled by CRC PMIC. Add those control as a new GPIO in a lookup table for gpio-crystalcove chip during CRC driver load CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Acked-by: Linus Walleij linus.wall...@linaro.org Tested-by: Ville Syrjälä ville.syrj...@linux.intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- v2: Make the lookup table static (Thierry) Remove the lookup table during driver remove (Thierry) v3: Correct the subject line (Lee jones) drivers/mfd/intel_soc_pmic_core.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 7b50b6b..f3d918e 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -24,8 +24,19 @@ #include linux/acpi.h #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h +#include linux/gpio/machine.h #include intel_soc_pmic_core.h +/* Lookup table for the Panel Enable/Disable line as GPIO signals */ +static struct gpiod_lookup_table panel_gpio_table = { + /* Intel GFX is consumer */ + .dev_id = :00:02.0, + .table = { + /* Panel EN/DISABLE */ + GPIO_LOOKUP(gpio_crystalcove, 94, panel, GPIO_ACTIVE_HIGH), + }, +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -85,6 +96,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, if (ret) dev_warn(dev, Can't enable IRQ as wake source: %d\n, ret); + /* Add lookup table binding for Panel Control to the GPIO Chip */ + gpiod_add_lookup_table(panel_gpio_table); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -104,6 +118,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) regmap_del_irq_chip(pmic-irq, pmic-irq_chip_data); + /* Remove lookup table for Panel Control from the GPIO Chip */ + gpiod_remove_lookup_table(panel_gpio_table); + mfd_remove_devices(i2c-dev); return 0; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v3 5/7] pwm: crc: Add Crystalcove (CRC) PWM driver
The Crystalcove PMIC provides three PWM signals and this driver exports one of them on the BYT platform which is used to control backlight for DSI panel. This is platform device implementation of the drivers/mfd cell device for CRC PMIC. CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Cc: Paul Bolle pebo...@tiscali.nl Cc: Paul Gortmaker paul.gortma...@windriver.com Tested-by: Ville Syrjälä ville.syrj...@linux.intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- v2: Use the existing config callback with duty_ns and period_ns(Thierry) v3: Correct the subject line (Lee jones) v4: Address comment by Thierry Paul - Commit message update and fixes for few syntax errors - Add PWM_CRC in Kconfig and Makefile sorted alphabetically - Use the PWM_BASE_CLK as 600 for better code readability - Remove the redundant rule of three while calculating pwm level - Use the platform_device in pwm_chip - Use builin_platform_driver v5: Address comments by Varka - Make the bit definition using BIT macro - reorder probe and remove code to directly return from pwmchip_add/remove drivers/pwm/Kconfig | 7 +++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-crc.c | 143 ++ 3 files changed, 151 insertions(+) create mode 100644 drivers/pwm/pwm-crc.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..948d9ab 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -111,6 +111,13 @@ config PWM_CLPS711X To compile this driver as a module, choose M here: the module will be called pwm-clps711x. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + config PWM_EP93XX tristate Cirrus Logic EP93xx PWM support depends on ARCH_EP93XX diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..d186f35 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o +obj-$(CONFIG_PWM_CRC) += pwm-crc.o obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o obj-$(CONFIG_PWM_IMG) += pwm-img.o diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..7101c70 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE BIT(7) +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL 0xFF + +#define PWM_BASE_CLK 600 /* 6 MHz */ +#define PWM_MAX_PERIOD_NS 21333/* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1); + + return 0; +} + +static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 0); +} + +static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + struct device *dev
[Intel-gfx] [v3 6/7] drm/i915: Use the CRC gpio for panel enable/disable
The CRC (Crystal Cove) PMIC, controls the panel enable and disable signals for BYT for dsi panels. This is indicated in the VBT fields. Use that to initialize and use GPIO based control for these signals. v2: Use the newer gpiod interface(Alexandre) v3: Remove the redundant checks and unused code (Ville) v4: Moved PWM vs SoC backlight #defines to intel_bios.h (Jani) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Linus Walleij linus.wall...@linaro.org Reviewed-by: Jani Nikula jani.nik...@intel.com Tested-by: Ville Syrjälä ville.syrj...@linux.intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_bios.h | 7 +++ drivers/gpu/drm/i915/intel_dsi.c | 32 ++-- drivers/gpu/drm/i915/intel_dsi.h | 3 +++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index af0b476..f7ad6a5 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -778,6 +778,13 @@ int intel_parse_bios(struct drm_device *dev); #define MIPI_DSI_UNDEFINED_PANEL_ID0 #define MIPI_DSI_GENERIC_PANEL_ID 1 +/* + * PMIC vs SoC Backlight support specified in pwm_blc + * field in mipi_config block below. +*/ +#define PPS_BLC_PMIC 0 +#define PPS_BLC_SOC1 + struct mipi_config { u16 panel_id; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index b5a5558..c4db74a 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -31,6 +31,7 @@ #include drm/drm_panel.h #include drm/drm_mipi_dsi.h #include linux/slab.h +#include linux/gpio/consumer.h #include i915_drv.h #include intel_drv.h #include intel_dsi.h @@ -415,6 +416,12 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + /* Panel Enable over CRC PMIC */ + if (intel_dsi-gpio_panel) + gpiod_set_value_cansleep(intel_dsi-gpio_panel, 1); + + msleep(intel_dsi-panel_on_delay); + /* Disable DPOunit clock gating, can stall pipe * and we need DPLL REFA always enabled */ tmp = I915_READ(DPLL(pipe)); @@ -432,8 +439,6 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) /* put device in ready state */ intel_dsi_device_ready(encoder); - msleep(intel_dsi-panel_on_delay); - drm_panel_prepare(intel_dsi-panel); for_each_dsi_port(port, intel_dsi-ports) @@ -576,6 +581,10 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder) msleep(intel_dsi-panel_off_delay); msleep(intel_dsi-panel_pwr_cycle_delay); + + /* Panel Disable over CRC PMIC */ + if (intel_dsi-gpio_panel) + gpiod_set_value_cansleep(intel_dsi-gpio_panel, 0); } static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, @@ -955,6 +964,11 @@ static void intel_dsi_encoder_destroy(struct drm_encoder *encoder) /* XXX: Logically this call belongs in the panel driver. */ drm_panel_remove(intel_dsi-panel); } + + /* dispose of the gpios */ + if (intel_dsi-gpio_panel) + gpiod_put(intel_dsi-gpio_panel); + intel_encoder_destroy(encoder); } @@ -1071,6 +1085,20 @@ void intel_dsi_init(struct drm_device *dev) goto err; } + /* +* In case of BYT with CRC PMIC, we need to use GPIO for +* Panel control. +*/ + if (dev_priv-vbt.dsi.config-pwm_blc == PPS_BLC_PMIC) { + intel_dsi-gpio_panel = + gpiod_get(dev-dev, panel, GPIOD_OUT_HIGH); + + if (IS_ERR(intel_dsi-gpio_panel)) { + DRM_ERROR(Failed to own gpio for panel control\n); + intel_dsi-gpio_panel = NULL; + } + } + intel_encoder-type = INTEL_OUTPUT_DSI; intel_encoder-cloneable = 0; drm_connector_init(dev, connector, intel_dsi_connector_funcs, diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 2784ac4..42a6859 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -42,6 +42,9 @@ struct intel_dsi { struct drm_panel *panel; struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS]; + /* GPIO Desc for CRC based Panel control */ + struct gpio_desc *gpio_panel; + struct intel_connector *attached_connector; /* bit mask of ports being driven */ -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v2 7/7] drm/i915: Backlight control using CRC PMIC based PWM driver
On Thu, Jun 25, 2015 at 6:17 PM, Ville Syrjälä ville.syrj...@linux.intel.com wrote: On Thu, Jun 25, 2015 at 05:38:50PM +0530, Shobhit Kumar wrote: On Thu, Jun 25, 2015 at 2:18 PM, Ville Syrjälä ville.syrj...@linux.intel.com wrote: On Mon, Jun 22, 2015 at 04:24:25PM +0530, Shobhit Kumar wrote: Use the CRC PWM device in intel_panel.c and add new MIPI backlight specififc callbacks v2: Modify to use pwm_config callback v3: Addressed Jani's comments - Renamed all function as pwm_* instead of vlv_* - Call intel_panel_actually_set_backlight in enable function - Return -ENODEV in case pwm_get fails - in case pwm_config error return error cdoe from pwm_config - Cleanup pwm in intel_panel_destroy_backlight CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 4 ++ drivers/gpu/drm/i915/intel_dsi.c | 6 +++ drivers/gpu/drm/i915/intel_panel.c | 95 -- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2afb31a..561c17f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -182,6 +182,10 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + + /* PWM chip */ + struct pwm_device *pwm; + struct backlight_device *device; } backlight; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index c4db74a..be8722c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -402,6 +402,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_dsi_port_enable(encoder); } + + intel_panel_enable_backlight(intel_dsi-attached_connector); } static void intel_dsi_pre_enable(struct intel_encoder *encoder) @@ -466,6 +468,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + intel_panel_disable_backlight(intel_dsi-attached_connector); + if (is_vid_mode(intel_dsi)) { /* Send Shutdown command to the panel in LP mode */ for_each_dsi_port(port, intel_dsi-ports) @@ -1132,6 +1136,8 @@ void intel_dsi_init(struct drm_device *dev) } intel_panel_init(intel_connector-panel, fixed_mode, NULL); + intel_panel_setup_backlight(connector, + (intel_encoder-crtc_mask = (1 PIPE_A)) ? PIPE_A : PIPE_B); ^ Whoops. But since the PWM backlight doesn't need the initial pipe for anything you can actually just pass INVALID_PIPE here. You are right, its unused, but I thought passing right value still made sense. Otherwise it makes it look like I am setting up back-light for invalid pipe, when the real meaning is something like DONTCARE_PIPE Well it's not really about the pipe. It's about which set of BLC registers we're supoosed to use when using the BLC built into the display engine. And that's only done so that we take over the hardware state correctly. So INVALID_PIPE is just fine in this case since the backlight control has nothing to do with the pipe. Ok, will update. Regards Shobhit ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v2 7/7] drm/i915: Backlight control using CRC PMIC based PWM driver
On Thu, Jun 25, 2015 at 2:18 PM, Ville Syrjälä ville.syrj...@linux.intel.com wrote: On Mon, Jun 22, 2015 at 04:24:25PM +0530, Shobhit Kumar wrote: Use the CRC PWM device in intel_panel.c and add new MIPI backlight specififc callbacks v2: Modify to use pwm_config callback v3: Addressed Jani's comments - Renamed all function as pwm_* instead of vlv_* - Call intel_panel_actually_set_backlight in enable function - Return -ENODEV in case pwm_get fails - in case pwm_config error return error cdoe from pwm_config - Cleanup pwm in intel_panel_destroy_backlight CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 4 ++ drivers/gpu/drm/i915/intel_dsi.c | 6 +++ drivers/gpu/drm/i915/intel_panel.c | 95 -- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2afb31a..561c17f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -182,6 +182,10 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + + /* PWM chip */ + struct pwm_device *pwm; + struct backlight_device *device; } backlight; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index c4db74a..be8722c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -402,6 +402,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_dsi_port_enable(encoder); } + + intel_panel_enable_backlight(intel_dsi-attached_connector); } static void intel_dsi_pre_enable(struct intel_encoder *encoder) @@ -466,6 +468,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + intel_panel_disable_backlight(intel_dsi-attached_connector); + if (is_vid_mode(intel_dsi)) { /* Send Shutdown command to the panel in LP mode */ for_each_dsi_port(port, intel_dsi-ports) @@ -1132,6 +1136,8 @@ void intel_dsi_init(struct drm_device *dev) } intel_panel_init(intel_connector-panel, fixed_mode, NULL); + intel_panel_setup_backlight(connector, + (intel_encoder-crtc_mask = (1 PIPE_A)) ? PIPE_A : PIPE_B); ^ Whoops. But since the PWM backlight doesn't need the initial pipe for anything you can actually just pass INVALID_PIPE here. You are right, its unused, but I thought passing right value still made sense. Otherwise it makes it look like I am setting up back-light for invalid pipe, when the real meaning is something like DONTCARE_PIPE return; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 7d83527..2aa30db 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -32,8 +32,12 @@ #include linux/kernel.h #include linux/moduleparam.h +#include linux/pwm.h #include intel_drv.h +#define CRC_PMIC_PWM_PERIOD_NS 21333 +#define CRC_PMIC_PWM_STEPS 255 This define appears to be unused. Yeah, missed removing it. + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -544,6 +548,15 @@ static u32 bxt_get_backlight(struct intel_connector *connector) return I915_READ(BXT_BLC_PWM_DUTY1); } +static u32 pwm_get_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + int duty_ns; + + duty_ns = pwm_get_duty_cycle(panel-backlight.pwm); + return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); +} + static u32 intel_panel_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -632,6 +645,14 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) I915_WRITE(BXT_BLC_PWM_DUTY1, level); } +static void pwm_set_backlight(struct intel_connector *connector, u32 level) +{ + struct intel_panel *panel = connector-panel; + int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + + pwm_config(panel-backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); +} + static void intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) { @@ -769,6 +790,16 @@ static void bxt_disable_backlight(struct intel_connector *connector) I915_WRITE(BXT_BLC_PWM_CTL1, tmp ~BXT_BLC_PWM_ENABLE); } +static void pwm_disable_backlight(struct intel_connector *connector) +{ + struct
Re: [Intel-gfx] [v2 4/7] mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM
On Tue, Jun 23, 2015 at 12:49 PM, Lee Jones lee.jo...@linaro.org wrote: On Mon, 22 Jun 2015, Daniel Vetter wrote: On Mon, Jun 22, 2015 at 04:33:22PM +0530, Varka Bhadram wrote: Hi Shobhit Kumar, On 06/22/2015 04:24 PM, Shobhit Kumar wrote: On some BYT PLatform the PWM is controlled using CRC PMIC. Add a lookup entry for the same to be used by the consumer (Intel GFX) v2: Remove the lookup table on driver unload (Thierry) v3: Correct the subject line (Lee jones) This part should only describe what this is about.. Don't put this patch change history over here. Include this change history after ... Signed-off-by: Author email --- CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- Here you add this change history so that after applying this will not be the part of your commit description. This comment is applicable for all of your patches. It's honestly a per-maintainer thing and hard to tell who wants what ... Personally I do want to include the patch changelog in the commit message. The patch change-log should go below the '---'. There are very few (weird ;) ) Maintainers who like to see them in the commit log. To satisfy everybody, for the last two patches for intel-gfx, I will keep the version history as is, for others, I will move it down as suggested. Will push all again as new series after addressing all comments. Regards Shobhit -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [v2 5/7] pwm: crc: Add Crystalcove (CRC) PWM driver
On Mon, Jun 22, 2015 at 4:46 PM, Varka Bhadram varkabhad...@gmail.com wrote: Hi Shobhit Kumar, On 06/22/2015 04:24 PM, Shobhit Kumar wrote: The Crystalcove PMIC provides three PWM signals and this driver exports one of them on the BYT platform which is used to control backlight for DSI panel. This is platform device implementation of the drivers/mfd cell device for CRC PMIC. v2: Use the existing config callback with duty_ns and period_ns(Thierry) v3: Correct the subject line (Lee jones) v4: Address comment by Thierry Paul - Commit message update and fixes for few syntax errors - Add PWM_CRC in Kconfig and Makefile sorted alphabetically - Use the PWM_BASE_CLK as 600 for better code readability - Remove the redundant rule of three while calculating pwm level - Use the platform_device in pwm_chip - Use builin_platform_driver CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Cc: Paul Bolle pebo...@tiscali.nl Cc: Paul Gortmaker paul.gortma...@windriver.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com (...) + +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (1 7) Can't be BIT() macro ? Can be done. +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE0x4E +#define BACKLIGHT_EN 0x51 (...) +static int crystalcove_pwm_probe(struct platform_device *pdev) +{ + struct crystalcove_pwm *pwm; + int retval; + struct device *dev = pdev-dev.parent; + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + + pwm = devm_kzalloc(pdev-dev, sizeof(*pwm), GFP_KERNEL); + if (!pwm) + return -ENOMEM; + + pwm-chip.dev = pdev-dev; + pwm-chip.ops = crc_pwm_ops; + pwm-chip.base = -1; + pwm-chip.npwm = 1; + + /* get the PMIC regmap */ + pwm-regmap = pmic-regmap; + + retval = pwmchip_add(pwm-chip); + if (retval 0) + return retval; + + platform_set_drvdata(pdev, pwm); + If you can change this oder we can simply do something like this: platform_set_drvdata(pdev, pwm); return pwmchip_add(pwm-chip); Okay. seems better. + return 0; +} + +static int crystalcove_pwm_remove(struct platform_device *pdev) +{ + struct crystalcove_pwm *pwm = platform_get_drvdata(pdev); + int retval; + + retval = pwmchip_remove(pwm-chip); + if (retval 0) + return retval; + + dev_dbg(pdev-dev, crc-pwm driver removed\n); This debug message may not be required :-) you can directly do: return pwmchip_remove(pwm-chip); Yeah, will update. Regards Shobhit + + return 0; +} + +static struct platform_driver crystalcove_pwm_driver = { + .probe = crystalcove_pwm_probe, + .remove = crystalcove_pwm_remove, + .driver = { + .name = crystal_cove_pwm, + }, +}; + +builtin_platform_driver(crystalcove_pwm_driver); -- Best regards, Varka Bhadram. ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 1/7] gpiolib: Add support for removing registered consumer lookup table
In case we unload and load a driver module again that is registering a lookup table, without this it will result in multiple entries. Provide an option to remove the lookup table on driver unload v2: Ccing maintainers v3: Correct the subject line (Lee jones) Cc: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Reviewed-by: Alexandre Courbot acour...@nvidia.com Reviewed-by: Linus Walleij linus.wall...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpio/gpiolib.c | 13 + include/linux/gpio/machine.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 957ede5..9d3ea4e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1675,6 +1675,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table) mutex_unlock(gpio_lookup_lock); } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ + mutex_lock(gpio_lookup_lock); + + list_del(table-list); + + mutex_unlock(gpio_lookup_lock); +} + static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index e270614..c0d712d 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -57,5 +57,6 @@ struct gpiod_lookup_table { } void gpiod_add_lookup_table(struct gpiod_lookup_table *table); +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); #endif /* __LINUX_GPIO_MACHINE_H */ -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 2/7] mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal
On some Intel SoC platforms, the panel enable/disable signals are controlled by CRC PMIC. Add those control as a new GPIO in a lookup table for gpio-crystalcove chip during CRC driver load v2: Make the lookup table static (Thierry) Remove the lookup table during driver remove (Thierry) v3: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Acked-by: Linus Walleij linus.wall...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 7b50b6b..f3d918e 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -24,8 +24,19 @@ #include linux/acpi.h #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h +#include linux/gpio/machine.h #include intel_soc_pmic_core.h +/* Lookup table for the Panel Enable/Disable line as GPIO signals */ +static struct gpiod_lookup_table panel_gpio_table = { + /* Intel GFX is consumer */ + .dev_id = :00:02.0, + .table = { + /* Panel EN/DISABLE */ + GPIO_LOOKUP(gpio_crystalcove, 94, panel, GPIO_ACTIVE_HIGH), + }, +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -85,6 +96,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, if (ret) dev_warn(dev, Can't enable IRQ as wake source: %d\n, ret); + /* Add lookup table binding for Panel Control to the GPIO Chip */ + gpiod_add_lookup_table(panel_gpio_table); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -104,6 +118,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) regmap_del_irq_chip(pmic-irq, pmic-irq_chip_data); + /* Remove lookup table for Panel Control from the GPIO Chip */ + gpiod_remove_lookup_table(panel_gpio_table); + mfd_remove_devices(i2c-dev); return 0; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 6/7] drm/i915: Use the CRC gpio for panel enable/disable
The CRC (Crystal Cove) PMIC, controls the panel enable and disable signals for BYT for dsi panels. This is indicated in the VBT fields. Use that to initialize and use GPIO based control for these signals. v2: Use the newer gpiod interface(Alexandre) v3: Remove the redundant checks and unused code (Ville) v4: Moved PWM vs SoC backlight #defines to intel_bios.h (Jani) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Linus Walleij linus.wall...@linaro.org Reviewed-by: Jani Nikula jani.nik...@intel.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_bios.h | 7 +++ drivers/gpu/drm/i915/intel_dsi.c | 32 ++-- drivers/gpu/drm/i915/intel_dsi.h | 3 +++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index af0b476..f7ad6a5 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -778,6 +778,13 @@ int intel_parse_bios(struct drm_device *dev); #define MIPI_DSI_UNDEFINED_PANEL_ID0 #define MIPI_DSI_GENERIC_PANEL_ID 1 +/* + * PMIC vs SoC Backlight support specified in pwm_blc + * field in mipi_config block below. +*/ +#define PPS_BLC_PMIC 0 +#define PPS_BLC_SOC1 + struct mipi_config { u16 panel_id; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index b5a5558..c4db74a 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -31,6 +31,7 @@ #include drm/drm_panel.h #include drm/drm_mipi_dsi.h #include linux/slab.h +#include linux/gpio/consumer.h #include i915_drv.h #include intel_drv.h #include intel_dsi.h @@ -415,6 +416,12 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + /* Panel Enable over CRC PMIC */ + if (intel_dsi-gpio_panel) + gpiod_set_value_cansleep(intel_dsi-gpio_panel, 1); + + msleep(intel_dsi-panel_on_delay); + /* Disable DPOunit clock gating, can stall pipe * and we need DPLL REFA always enabled */ tmp = I915_READ(DPLL(pipe)); @@ -432,8 +439,6 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) /* put device in ready state */ intel_dsi_device_ready(encoder); - msleep(intel_dsi-panel_on_delay); - drm_panel_prepare(intel_dsi-panel); for_each_dsi_port(port, intel_dsi-ports) @@ -576,6 +581,10 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder) msleep(intel_dsi-panel_off_delay); msleep(intel_dsi-panel_pwr_cycle_delay); + + /* Panel Disable over CRC PMIC */ + if (intel_dsi-gpio_panel) + gpiod_set_value_cansleep(intel_dsi-gpio_panel, 0); } static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, @@ -955,6 +964,11 @@ static void intel_dsi_encoder_destroy(struct drm_encoder *encoder) /* XXX: Logically this call belongs in the panel driver. */ drm_panel_remove(intel_dsi-panel); } + + /* dispose of the gpios */ + if (intel_dsi-gpio_panel) + gpiod_put(intel_dsi-gpio_panel); + intel_encoder_destroy(encoder); } @@ -1071,6 +1085,20 @@ void intel_dsi_init(struct drm_device *dev) goto err; } + /* +* In case of BYT with CRC PMIC, we need to use GPIO for +* Panel control. +*/ + if (dev_priv-vbt.dsi.config-pwm_blc == PPS_BLC_PMIC) { + intel_dsi-gpio_panel = + gpiod_get(dev-dev, panel, GPIOD_OUT_HIGH); + + if (IS_ERR(intel_dsi-gpio_panel)) { + DRM_ERROR(Failed to own gpio for panel control\n); + intel_dsi-gpio_panel = NULL; + } + } + intel_encoder-type = INTEL_OUTPUT_DSI; intel_encoder-cloneable = 0; drm_connector_init(dev, connector, intel_dsi_connector_funcs, diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 2784ac4..42a6859 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -42,6 +42,9 @@ struct intel_dsi { struct drm_panel *panel; struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS]; + /* GPIO Desc for CRC based Panel control */ + struct gpio_desc *gpio_panel; + struct intel_connector *attached_connector; /* bit mask of ports being driven */ -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 5/7] pwm: crc: Add Crystalcove (CRC) PWM driver
The Crystalcove PMIC provides three PWM signals and this driver exports one of them on the BYT platform which is used to control backlight for DSI panel. This is platform device implementation of the drivers/mfd cell device for CRC PMIC. v2: Use the existing config callback with duty_ns and period_ns(Thierry) v3: Correct the subject line (Lee jones) v4: Address comment by Thierry Paul - Commit message update and fixes for few syntax errors - Add PWM_CRC in Kconfig and Makefile sorted alphabetically - Use the PWM_BASE_CLK as 600 for better code readability - Remove the redundant rule of three while calculating pwm level - Use the platform_device in pwm_chip - Use builin_platform_driver CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Cc: Paul Bolle pebo...@tiscali.nl Cc: Paul Gortmaker paul.gortma...@windriver.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/pwm/Kconfig | 7 +++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-crc.c | 155 ++ 3 files changed, 163 insertions(+) create mode 100644 drivers/pwm/pwm-crc.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..948d9ab 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -111,6 +111,13 @@ config PWM_CLPS711X To compile this driver as a module, choose M here: the module will be called pwm-clps711x. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + config PWM_EP93XX tristate Cirrus Logic EP93xx PWM support depends on ARCH_EP93XX diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..d186f35 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o +obj-$(CONFIG_PWM_CRC) += pwm-crc.o obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o obj-$(CONFIG_PWM_IMG) += pwm-img.o diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..dcd9782 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (1 7) +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL 0xFF + +#define PWM_BASE_CLK 600 /* 6 MHz */ +#define PWM_MAX_PERIOD_NS 21333/* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1); + + return 0; +} + +static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 0); +} + +static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + struct device *dev = crc_pwm-chip.dev; + int level; + + if (period_ns PWM_MAX_PERIOD_NS) { + dev_err(dev, un-supported period_ns\n); + return -EINVAL; + } + + if (pwm-period
[Intel-gfx] [v2 3/7] mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC
Needed for PWM control suuported by the PMIC v2: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_crc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index 7436075..4a74948 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -109,6 +109,9 @@ static struct mfd_cell crystal_cove_dev[] = { { .name = crystal_cove_pmic, }, + { + .name = crystal_cove_pwm, + }, }; static const struct regmap_config crystal_cove_regmap_config = { -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 7/7] drm/i915: Backlight control using CRC PMIC based PWM driver
Use the CRC PWM device in intel_panel.c and add new MIPI backlight specififc callbacks v2: Modify to use pwm_config callback v3: Addressed Jani's comments - Renamed all function as pwm_* instead of vlv_* - Call intel_panel_actually_set_backlight in enable function - Return -ENODEV in case pwm_get fails - in case pwm_config error return error cdoe from pwm_config - Cleanup pwm in intel_panel_destroy_backlight CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 4 ++ drivers/gpu/drm/i915/intel_dsi.c | 6 +++ drivers/gpu/drm/i915/intel_panel.c | 95 -- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2afb31a..561c17f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -182,6 +182,10 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + + /* PWM chip */ + struct pwm_device *pwm; + struct backlight_device *device; } backlight; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index c4db74a..be8722c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -402,6 +402,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_dsi_port_enable(encoder); } + + intel_panel_enable_backlight(intel_dsi-attached_connector); } static void intel_dsi_pre_enable(struct intel_encoder *encoder) @@ -466,6 +468,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + intel_panel_disable_backlight(intel_dsi-attached_connector); + if (is_vid_mode(intel_dsi)) { /* Send Shutdown command to the panel in LP mode */ for_each_dsi_port(port, intel_dsi-ports) @@ -1132,6 +1136,8 @@ void intel_dsi_init(struct drm_device *dev) } intel_panel_init(intel_connector-panel, fixed_mode, NULL); + intel_panel_setup_backlight(connector, + (intel_encoder-crtc_mask = (1 PIPE_A)) ? PIPE_A : PIPE_B); return; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 7d83527..2aa30db 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -32,8 +32,12 @@ #include linux/kernel.h #include linux/moduleparam.h +#include linux/pwm.h #include intel_drv.h +#define CRC_PMIC_PWM_PERIOD_NS 21333 +#define CRC_PMIC_PWM_STEPS 255 + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -544,6 +548,15 @@ static u32 bxt_get_backlight(struct intel_connector *connector) return I915_READ(BXT_BLC_PWM_DUTY1); } +static u32 pwm_get_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + int duty_ns; + + duty_ns = pwm_get_duty_cycle(panel-backlight.pwm); + return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); +} + static u32 intel_panel_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -632,6 +645,14 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) I915_WRITE(BXT_BLC_PWM_DUTY1, level); } +static void pwm_set_backlight(struct intel_connector *connector, u32 level) +{ + struct intel_panel *panel = connector-panel; + int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + + pwm_config(panel-backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); +} + static void intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) { @@ -769,6 +790,16 @@ static void bxt_disable_backlight(struct intel_connector *connector) I915_WRITE(BXT_BLC_PWM_CTL1, tmp ~BXT_BLC_PWM_ENABLE); } +static void pwm_disable_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + + /* Disable the backlight */ + pwm_config(panel-backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); + usleep_range(2000, 3000); + pwm_disable(panel-backlight.pwm); +} + void intel_panel_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -1002,6 +1033,14 @@ static void bxt_enable_backlight(struct intel_connector *connector) I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl | BXT_BLC_PWM_ENABLE); } +static void pwm_enable_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel
[Intel-gfx] [v2 4/7] mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM
On some BYT PLatform the PWM is controlled using CRC PMIC. Add a lookup entry for the same to be used by the consumer (Intel GFX) v2: Remove the lookup table on driver unload (Thierry) v3: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index f3d918e..a00ddd9 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -25,6 +25,7 @@ #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h #include linux/gpio/machine.h +#include linux/pwm.h #include intel_soc_pmic_core.h /* Lookup table for the Panel Enable/Disable line as GPIO signals */ @@ -37,6 +38,11 @@ static struct gpiod_lookup_table panel_gpio_table = { }, }; +/* PWM consumed by the Intel GFX */ +static struct pwm_lookup crc_pwm_lookup[] = { + PWM_LOOKUP(crystal_cove_pwm, 0, :00:02.0, pwm_backlight, 0, PWM_POLARITY_NORMAL), +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -99,6 +105,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, /* Add lookup table binding for Panel Control to the GPIO Chip */ gpiod_add_lookup_table(panel_gpio_table); + /* Add lookup table for crc-pwm */ + pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -121,6 +130,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) /* Remove lookup table for Panel Control from the GPIO Chip */ gpiod_remove_lookup_table(panel_gpio_table); + /* remove crc-pwm lookup table */ + pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + mfd_remove_devices(i2c-dev); return 0; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [v2 0/7] Crystalcove (CRC) PMIC based panel and pwm control
Hi All, On some of the BYT devices, for DSI panels, the panel enable/disable signals and backlight control are done using the Crystalcove PMIC. This series provides support for the same and has been reviewed earlier on - https://lkml.org/lkml/2015/4/29/301 This series addresses the review comments with one patch from last set already merged as - https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=efb0de55b6a2ec15fc424e660601f22ae2fa487a Basically following are implemented - 1. GPIO control for panel enable/disable with GFX device as consumer 2. New PWM chip driver added for CRC PMIC based backlight control 3. i915 is modified to use the CRC gpio chip and the CRC PWM chip to do backlight control. This is now added in the generic panel backlight control infrastructure All these patches have been tested on AsusT100 and working fine using /sys/class/backlight/intel_backlight interface. Patches were also verified on android-x86 tree for AsusT100. Regards Shobhit Shobhit Kumar (7): gpiolib: Add support for removing registered consumer lookup table mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM pwm: crc: Add Crystalcove (CRC) PWM driver drm/i915: Use the CRC gpio for panel enable/disable drm/i915: Backlight control using CRC PMIC based PWM driver drivers/gpio/gpiolib.c | 13 drivers/gpu/drm/i915/intel_bios.h | 7 ++ drivers/gpu/drm/i915/intel_drv.h | 4 + drivers/gpu/drm/i915/intel_dsi.c | 38 - drivers/gpu/drm/i915/intel_dsi.h | 3 + drivers/gpu/drm/i915/intel_panel.c | 95 +-- drivers/mfd/intel_soc_pmic_core.c | 29 +++ drivers/mfd/intel_soc_pmic_crc.c | 3 + drivers/pwm/Kconfig| 7 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-crc.c | 155 + include/linux/gpio/machine.h | 1 + 12 files changed, 349 insertions(+), 7 deletions(-) create mode 100644 drivers/pwm/pwm-crc.c -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/8] drivers/pwm: Add Crystalcove (CRC) PWM driver
On Sat, Jun 20, 2015 at 11:34 PM, Paul Gortmaker paul.gortma...@windriver.com wrote: [Re: [Intel-gfx] [PATCH 6/8] drivers/pwm: Add Crystalcove (CRC) PWM driver] On 20/06/2015 (Sat 13:23) Paul Bolle wrote: [Added Paul Gortmaker.] Hi Shobhit, On Fri, 2015-06-19 at 12:16 +0530, Shobhit Kumar wrote: So what is the exact big problem with this ? The main problem I have is that it's hard to read a submitter's mind. And, I think, in cases like this we need to know if the submitter just made some silly mistake or that the mismatch (between Kconfig type and code) was intentional. So each time such a mismatch is spotted the submitter ought to be asked about it. (I'd guess that one or two new drivers are submitted _each_ day. And these mismatches are quite common. I'd say I receive answers like: - Oops, yes bool should have been tristate; or - Oops, forgot to clean up after noticing tristate didn't work; or - I just copy-and-pasted a similar driver, the module stuff isn't actually needed at least once a week. Not sure, I don't keep track of this stuff.) Furthermore, it appears that Paul Gortmaker is on a mission to, badly summarized, untangle the module and init code. See for instance https://lkml.org/lkml/2015/5/28/809 and https://lkml.org/lkml/2015/5/31/205 . Now, I don't know whether (other) Paul is bothered by these MODULE_* macros. But Paul did submit a series that adds Yes, I agree that it would be nice to not see these mismatches, regardless of whether we can get away with it or not. builtin_platform_driver(), see https://lkml.org/lkml/2015/5/10/131 . That new macro ensures built-in only code doesn't have to use module_platform_driver(), which your patch also uses. So perhaps Paul can explain some of the non-obvious issues caused by built-in only code using module specific constructs. In https://lkml.org/lkml/2015/5/10/125 I'd written: There are several downsides to this: 1) The code can appear modular to a reader of the code, and they won't know if the code really is modular without checking the Makefile and Kconfig to see if compilation is governed by a bool or tristate. 2) Coders of drivers may be tempted to code up an __exit function that is never used, just in order to satisfy the required three args of the modular registration function. 3) Non-modular code ends up including the module.h which increases CPP overhead that they don't need. 4) It hinders us from performing better separation of the module init code and the generic init code. Okay. Get the idea and the need in terms of clear separation. Its just that there are quite a few built-in drivers using module initialization that I assumed its okay. The nature of linux means that thousands of developers are reading the code every day -- so I think that there is a genuine value in having the code convey a clear message on how it was designed to be used. Only using module related headers/macros for genuinely modular code helps us (albeit in a small way) towards achieving that. Looking at this thread, I see that one of the reasons given for this code's ambiguous module vs. built-in identity was the observation of a similar identity crisis of the related INTEL_SOC_PMIC code. Does that not back up the point above about the value in having the code speak for itself? So IMHO we probably should clarify the PMIC code vs. adding another example that looks just like it. Okay agree. I think there are quite of them lurking in the sources which would need correction. For this PWM driver I will take care as suggested. Regards Shobhit Paul. -- I can anyway shove out these macros to end the discussion. I'd rather convince you than annoy you into doing as I suggested. BTW whether you buy the argument or not, please do treat yourself with ice cream for being able to make such a comment. Will do. Thanks, Paul Bolle ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/8] drivers/pwm: Add Crystalcove (CRC) PWM driver
Hi Paul, On Fri, Jun 19, 2015 at 12:11 AM, Paul Bolle pebo...@tiscali.nl wrote: Hi Shobhit, On Thu, 2015-06-18 at 23:24 +0530, Shobhit Kumar wrote: On Fri, May 1, 2015 at 2:42 AM, Paul Bolle pebo...@tiscali.nl wrote: On Wed, 2015-04-29 at 19:30 +0530, Shobhit Kumar wrote: --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile +obj-$(CONFIG_PWM_CRC)+= pwm-crc.o PWM_CRC is a bool symbol. So pwm-crc.o can never be part of a module. I actually started this as a module but later decided to make it as bool because INTEL_SOC_PMIC on which this depends is itself a bool as well. As does GPIO_CRYSTAL_COVE and that's a tristate. So? Still it is good to keep the module based initialization. Firstly because it causes no harm If I got a dime for every time people used an argument like that I ... I could treat myself to an ice cream. A really big ice cream. Hmm, that doesn't sound too impressive. But still, causes no harm is below the bar for kernel code. Kernel code needs to add value. and even though some of the macros are pre-processed out, gives info about the driver. None of which can't be gotten elsewhere (ie, the commit message, or the file these macro reside in). Causes no harm comment had to be read together with more info about the driver. It causes no harm while providing more info. And as you only said those macros are pre-processed out to really the defaults for built-in drivers. So what is the exact big problem with this ? I can anyway shove out these macros to end the discussion. BTW whether you buy the argument or not, please do treat yourself with ice cream for being able to make such a comment. Secondly there were discussion on why INTEL_SOC_PMIC is bool (note this driver also has module based initialization even when bool). Yes, there's copy and paste going on even in kernel development. There are other examples in the kernel. I just gave the one which is related as well. Regards Shobhit I am guessing because of some tricky module load order dependencies. If ever that becomes a module, this can mostly be unchanged to be loaded as a module. You put in a macro, or any other bit of code, when it's needed, not beforehand, just in case. That's silly. Thanks, Paul Bolle ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/8] drivers/pwm: Add Crystalcove (CRC) PWM driver
On Fri, May 1, 2015 at 2:42 AM, Paul Bolle pebo...@tiscali.nl wrote: On Wed, 2015-04-29 at 19:30 +0530, Shobhit Kumar wrote: --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile +obj-$(CONFIG_PWM_CRC)+= pwm-crc.o PWM_CRC is a bool symbol. So pwm-crc.o can never be part of a module. I actually started this as a module but later decided to make it as bool because INTEL_SOC_PMIC on which this depends is itself a bool as well. Still it is good to keep the module based initialization. Firstly because it causes no harm and even though some of the macros are pre-processed out, gives info about the driver. Secondly there were discussion on why INTEL_SOC_PMIC is bool (note this driver also has module based initialization even when bool). I am guessing because of some tricky module load order dependencies. If ever that becomes a module, this can mostly be unchanged to be loaded as a module. Regards Shobhit (If I'm wrong, and that object file can actually be part of a module, you can stop reading here.) --- /dev/null +++ b/drivers/pwm/pwm-crc.c +#include linux/module.h Perhaps this include is not needed. +static const struct pwm_ops crc_pwm_ops = { + .config = crc_pwm_config, + .enable = crc_pwm_enable, + .disable = crc_pwm_disable, + .owner = THIS_MODULE, For built-in only code THIS_MODULE is basically equivalent to NULL (see include/linux/export.h). So I guess this line can be dropped. +}; +static struct platform_driver crystalcove_pwm_driver = { + .probe = crystalcove_pwm_probe, + .remove = crystalcove_pwm_remove, + .driver = { + .name = crystal_cove_pwm, + }, +}; + +module_platform_driver(crystalcove_pwm_driver); Speaking from memory: for built-in only code this is equivalent to calling platform_driver_register(crystalcove_pwm_driver); from a wrapper, and marking that wrapper with device_initcall(). +MODULE_AUTHOR(Shobhit Kumar shobhit.ku...@intel.com); +MODULE_DESCRIPTION(Intel Crystal Cove PWM Driver); +MODULE_LICENSE(GPL v2); These macros will be effectively preprocessed away for built-in only code. Paul Bolle ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 6/8] pwm: crc: Add Crystalcove (CRC) PWM driver
On Wed, May 20, 2015 at 8:39 PM, Shobhit Kumar ku...@shobhit.info wrote: On Thu, May 7, 2015 at 12:49 PM, Shobhit Kumar ku...@shobhit.info wrote: On Wed, May 6, 2015 at 5:44 PM, Thierry Reding thierry.red...@gmail.com wrote: On Tue, May 05, 2015 at 03:08:36PM +0530, Shobhit Kumar wrote: The Crystalcove PMIC controls PWM signals and this driver exports that You say signal_s_ here, but you only expose a single PWM device. Does the PMIC really control more than one? If it isn't, this should probably become: controls a PWM output and this driver Actually it does support 3 of them but on the platform only one is being used and I exported only that as of now. Probably I should expand a little in the commit message indicating this. will re-post after fixing based on your other comments. Updates pending due to personal leave. Can be expected next week. Folks, really sorry, been busy with lot of unexpected and unavoidable stuff. Working on getting the patches right. Expect them this week. capability as a PWM chip driver. This is platform device implementtaion implementation of the drivers/mfd cell device for CRC PMIC Sentences should end with a full stop. diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..954da3e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -183,6 +183,13 @@ config PWM_LPC32XX To compile this driver as a module, choose M here: the module will be called pwm-lpc32xx. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + This is badly sorted. Please keep the list sorted alphabetically. config PWM_LPSS tristate Intel LPSS PWM support depends on X86 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..3d38fed 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o obj-$(CONFIG_PWM_TWL)+= pwm-twl.o obj-$(CONFIG_PWM_TWL_LED)+= pwm-twl-led.o obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o +obj-$(CONFIG_PWM_CRC)+= pwm-crc.o This too. diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..987f3b4 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,171 @@ +/* + * pwm-crc.c - Intel Crystal Cove PWM Driver I think you can safely remove this line. You already know what file it is when you open it in your editor, and the description is in the MODULE_DESCRIPTION string already. + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/module.h +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (17) Should have spaces around . +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE 0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL0xFF + +#define PWM_BASE_CLK 6000/* 6 MHz */ This number is actually 6 KHz. I think it'd be better if you stuck with one unit here. Or perhaps there's some other reason why you can't use 600 here instead? +#define PWM_MAX_PERIOD_NS21333 /* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct platform_device *pdev; I think I had at some point requested that you get rid of this and use the chip.dev member instead. There's no kerneldoc for it and it isn't (well, almost, see below) used anywhere else, so perhaps you forgot to remove it here? + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1
Re: [Intel-gfx] [PATCH 6/8] pwm: crc: Add Crystalcove (CRC) PWM driver
On Thu, May 7, 2015 at 12:49 PM, Shobhit Kumar ku...@shobhit.info wrote: On Wed, May 6, 2015 at 5:44 PM, Thierry Reding thierry.red...@gmail.com wrote: On Tue, May 05, 2015 at 03:08:36PM +0530, Shobhit Kumar wrote: The Crystalcove PMIC controls PWM signals and this driver exports that You say signal_s_ here, but you only expose a single PWM device. Does the PMIC really control more than one? If it isn't, this should probably become: controls a PWM output and this driver Actually it does support 3 of them but on the platform only one is being used and I exported only that as of now. Probably I should expand a little in the commit message indicating this. will re-post after fixing based on your other comments. Updates pending due to personal leave. Can be expected next week. Regards Shobhit Regards Shobhit capability as a PWM chip driver. This is platform device implementtaion implementation of the drivers/mfd cell device for CRC PMIC Sentences should end with a full stop. diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..954da3e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -183,6 +183,13 @@ config PWM_LPC32XX To compile this driver as a module, choose M here: the module will be called pwm-lpc32xx. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + This is badly sorted. Please keep the list sorted alphabetically. config PWM_LPSS tristate Intel LPSS PWM support depends on X86 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..3d38fed 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o obj-$(CONFIG_PWM_TWL)+= pwm-twl.o obj-$(CONFIG_PWM_TWL_LED)+= pwm-twl-led.o obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o +obj-$(CONFIG_PWM_CRC)+= pwm-crc.o This too. diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..987f3b4 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,171 @@ +/* + * pwm-crc.c - Intel Crystal Cove PWM Driver I think you can safely remove this line. You already know what file it is when you open it in your editor, and the description is in the MODULE_DESCRIPTION string already. + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/module.h +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (17) Should have spaces around . +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE 0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL0xFF + +#define PWM_BASE_CLK 6000/* 6 MHz */ This number is actually 6 KHz. I think it'd be better if you stuck with one unit here. Or perhaps there's some other reason why you can't use 600 here instead? +#define PWM_MAX_PERIOD_NS21333 /* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct platform_device *pdev; I think I had at some point requested that you get rid of this and use the chip.dev member instead. There's no kerneldoc for it and it isn't (well, almost, see below) used anywhere else, so perhaps you forgot to remove it here? + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1); + + return 0; +} + +static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write
Re: [Intel-gfx] [PATCH 6/8] pwm: crc: Add Crystalcove (CRC) PWM driver
On Wed, May 6, 2015 at 5:44 PM, Thierry Reding thierry.red...@gmail.com wrote: On Tue, May 05, 2015 at 03:08:36PM +0530, Shobhit Kumar wrote: The Crystalcove PMIC controls PWM signals and this driver exports that You say signal_s_ here, but you only expose a single PWM device. Does the PMIC really control more than one? If it isn't, this should probably become: controls a PWM output and this driver Actually it does support 3 of them but on the platform only one is being used and I exported only that as of now. Probably I should expand a little in the commit message indicating this. will re-post after fixing based on your other comments. Regards Shobhit capability as a PWM chip driver. This is platform device implementtaion implementation of the drivers/mfd cell device for CRC PMIC Sentences should end with a full stop. diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..954da3e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -183,6 +183,13 @@ config PWM_LPC32XX To compile this driver as a module, choose M here: the module will be called pwm-lpc32xx. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + This is badly sorted. Please keep the list sorted alphabetically. config PWM_LPSS tristate Intel LPSS PWM support depends on X86 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..3d38fed 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o obj-$(CONFIG_PWM_TWL)+= pwm-twl.o obj-$(CONFIG_PWM_TWL_LED)+= pwm-twl-led.o obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o +obj-$(CONFIG_PWM_CRC)+= pwm-crc.o This too. diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..987f3b4 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,171 @@ +/* + * pwm-crc.c - Intel Crystal Cove PWM Driver I think you can safely remove this line. You already know what file it is when you open it in your editor, and the description is in the MODULE_DESCRIPTION string already. + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/module.h +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (17) Should have spaces around . +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE 0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL0xFF + +#define PWM_BASE_CLK 6000/* 6 MHz */ This number is actually 6 KHz. I think it'd be better if you stuck with one unit here. Or perhaps there's some other reason why you can't use 600 here instead? +#define PWM_MAX_PERIOD_NS21333 /* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct platform_device *pdev; I think I had at some point requested that you get rid of this and use the chip.dev member instead. There's no kerneldoc for it and it isn't (well, almost, see below) used anywhere else, so perhaps you forgot to remove it here? + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1); + + return 0; +} + +static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 0); +} + +static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, + int duty_ns, int period_ns
Re: [Intel-gfx] [PATCH 6/8] pwm: crc: Add Crystalcove (CRC) PWM driver
On Wed, May 6, 2015 at 1:10 PM, Paul Bolle pebo...@tiscali.nl wrote: On Tue, 2015-05-05 at 15:08 +0530, Shobhit Kumar wrote: The Crystalcove PMIC controls PWM signals and this driver exports that capability as a PWM chip driver. This is platform device implementtaion of the drivers/mfd cell device for CRC PMIC v2: Use the existing config callback with duty_ns and period_ns(Thierry) v3: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com The same comments can be made as for v2, see http://lkml.kernel.org/r/1430428322.2187.24.camel@x220 . Maybe you didn't receive that message. It could also be that you think my comments were invalid, or too vague, or whatever. Please say so, because then I don't have to bother you again when you send out v4. Not at all, I just missed your comments and realise my mistake later after sending next update. Somehow the mailing list filters that I have setup are not working correctly. I will look into your comments. Regards Shobhit ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/8] gpiolib: Add support for removing registered consumer lookup table
In case we unload and load a driver module again that is registering a lookup table, without this it will result in multiple entries. Provide an option to remove the lookup table on driver unload v2: Ccing maintainers v3: Correct the subject line (Lee jones) Cc: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Reviewed-by: Alexandre Courbot acour...@nvidia.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpio/gpiolib.c | 13 + include/linux/gpio/machine.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 59eaa23..2420af9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1658,6 +1658,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table) mutex_unlock(gpio_lookup_lock); } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ + mutex_lock(gpio_lookup_lock); + + list_del(table-list); + + mutex_unlock(gpio_lookup_lock); +} + static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index e270614..c0d712d 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -57,5 +57,6 @@ struct gpiod_lookup_table { } void gpiod_add_lookup_table(struct gpiod_lookup_table *table); +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); #endif /* __LINUX_GPIO_MACHINE_H */ -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 4/8] mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC
Needed for PWM control suuported by the PMIC v2: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_crc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index 4cc1b32..8839e25 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -109,6 +109,9 @@ static struct mfd_cell crystal_cove_dev[] = { { .name = crystal_cove_pmic, }, + { + .name = crystal_cove_pwm, + }, }; static const struct regmap_config crystal_cove_regmap_config = { -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/8] mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal
On some Intel SoC platforms, the panel enable/disable signals are controlled by CRC PMIC. Add those control as a new GPIO in a lookup table for gpio-crystalcove chip during CRC driver load v2: Make the lookup table static (Thierry) Remove the lookup table during driver remove (Thierry) v3: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 7b50b6b..f3d918e 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -24,8 +24,19 @@ #include linux/acpi.h #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h +#include linux/gpio/machine.h #include intel_soc_pmic_core.h +/* Lookup table for the Panel Enable/Disable line as GPIO signals */ +static struct gpiod_lookup_table panel_gpio_table = { + /* Intel GFX is consumer */ + .dev_id = :00:02.0, + .table = { + /* Panel EN/DISABLE */ + GPIO_LOOKUP(gpio_crystalcove, 94, panel, GPIO_ACTIVE_HIGH), + }, +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -85,6 +96,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, if (ret) dev_warn(dev, Can't enable IRQ as wake source: %d\n, ret); + /* Add lookup table binding for Panel Control to the GPIO Chip */ + gpiod_add_lookup_table(panel_gpio_table); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -104,6 +118,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) regmap_del_irq_chip(pmic-irq, pmic-irq_chip_data); + /* Remove lookup table for Panel Control from the GPIO Chip */ + gpiod_remove_lookup_table(panel_gpio_table); + mfd_remove_devices(i2c-dev); return 0; -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 5/8] mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM
On some BYT PLatform the PWM is controlled using CRC PMIC. Add a lookup entry for the same to be used by the consumer (Intel GFX) v2: Remove the lookup table on driver unload (Thierry) v3: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Acked-by: Lee Jones lee.jo...@linaro.org Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index f3d918e..a00ddd9 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -25,6 +25,7 @@ #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h #include linux/gpio/machine.h +#include linux/pwm.h #include intel_soc_pmic_core.h /* Lookup table for the Panel Enable/Disable line as GPIO signals */ @@ -37,6 +38,11 @@ static struct gpiod_lookup_table panel_gpio_table = { }, }; +/* PWM consumed by the Intel GFX */ +static struct pwm_lookup crc_pwm_lookup[] = { + PWM_LOOKUP(crystal_cove_pwm, 0, :00:02.0, pwm_backlight, 0, PWM_POLARITY_NORMAL), +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -99,6 +105,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, /* Add lookup table binding for Panel Control to the GPIO Chip */ gpiod_add_lookup_table(panel_gpio_table); + /* Add lookup table for crc-pwm */ + pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -121,6 +130,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) /* Remove lookup table for Panel Control from the GPIO Chip */ gpiod_remove_lookup_table(panel_gpio_table); + /* remove crc-pwm lookup table */ + pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + mfd_remove_devices(i2c-dev); return 0; -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 5/8] drivers/mfd: ADD PWM lookup table for CRC PMIC based PWM
On 04/29/2015 07:54 PM, Lee Jones wrote: On Wed, 29 Apr 2015, Shobhit Kumar wrote: On some BYT PLatform the PWM is controlled using CRC PMIC. Add a lookup entry for the same to be used by the consumer (Intel GFX) v2: Remove the lookup table on driver unload (Thierry) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 12 1 file changed, 12 insertions(+) How do you expect this set to be managed? There are some dependencies on the look up table remove functionality in earlier patches, so I think 3/8 can go in only after 1/8. Similarly 5/8 can go only after 2/8. Rest all can be independent. Regards Shobhit Acked-by: Lee Jones lee.jo...@linaro.org diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index f3d918e..a00ddd9 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -25,6 +25,7 @@ #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h #include linux/gpio/machine.h +#include linux/pwm.h #include intel_soc_pmic_core.h /* Lookup table for the Panel Enable/Disable line as GPIO signals */ @@ -37,6 +38,11 @@ static struct gpiod_lookup_table panel_gpio_table = { }, }; +/* PWM consumed by the Intel GFX */ +static struct pwm_lookup crc_pwm_lookup[] = { +PWM_LOOKUP(crystal_cove_pwm, 0, :00:02.0, pwm_backlight, 0, PWM_POLARITY_NORMAL), +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -99,6 +105,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, /* Add lookup table binding for Panel Control to the GPIO Chip */ gpiod_add_lookup_table(panel_gpio_table); +/* Add lookup table for crc-pwm */ +pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -121,6 +130,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) /* Remove lookup table for Panel Control from the GPIO Chip */ gpiod_remove_lookup_table(panel_gpio_table); +/* remove crc-pwm lookup table */ +pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + mfd_remove_devices(i2c-dev); return 0; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/8] pwm: core: Add support to remove registered consumer lookup tables
In case some drivers are unloading, they can remove lookup tables which they would have registered during their load time to avoid redundant entries if loaded again v2: Ccing maintainers v3: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/pwm/core.c | 17 + include/linux/pwm.h | 5 + 2 files changed, 22 insertions(+) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index ba34c7d..d2fe7c8d 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -586,6 +586,23 @@ void pwm_add_table(struct pwm_lookup *table, size_t num) } /** + * pwm_remove_table() - un-register PWM device consumers + * @table: array of consumers to un-register + * @num: number of consumers in table + */ +void pwm_remove_table(struct pwm_lookup *table, size_t num) +{ + mutex_lock(pwm_lookup_lock); + + while (num--) { + list_del(table-list); + table++; + } + + mutex_unlock(pwm_lookup_lock); +} + +/** * pwm_get() - look up and request a PWM device * @dev: device for PWM consumer * @con_id: consumer name diff --git a/include/linux/pwm.h b/include/linux/pwm.h index e90628c..cfe2d8d 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -290,10 +290,15 @@ struct pwm_lookup { #if IS_ENABLED(CONFIG_PWM) void pwm_add_table(struct pwm_lookup *table, size_t num); +void pwm_remove_table(struct pwm_lookup *table, size_t num); #else static inline void pwm_add_table(struct pwm_lookup *table, size_t num) { } + +static inline void pwm_remove_table(struct pwm_lookup *table, size_t num) +{ +} #endif #ifdef CONFIG_PWM_SYSFS -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 6/8] pwm: crc: Add Crystalcove (CRC) PWM driver
The Crystalcove PMIC controls PWM signals and this driver exports that capability as a PWM chip driver. This is platform device implementtaion of the drivers/mfd cell device for CRC PMIC v2: Use the existing config callback with duty_ns and period_ns(Thierry) v3: Correct the subject line (Lee jones) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/pwm/Kconfig | 7 +++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-crc.c | 171 ++ 3 files changed, 179 insertions(+) create mode 100644 drivers/pwm/pwm-crc.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..954da3e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -183,6 +183,13 @@ config PWM_LPC32XX To compile this driver as a module, choose M here: the module will be called pwm-lpc32xx. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + config PWM_LPSS tristate Intel LPSS PWM support depends on X86 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..3d38fed 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o obj-$(CONFIG_PWM_TWL) += pwm-twl.o obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o +obj-$(CONFIG_PWM_CRC) += pwm-crc.o diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..987f3b4 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,171 @@ +/* + * pwm-crc.c - Intel Crystal Cove PWM Driver + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/module.h +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (17) +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL 0xFF + +#define PWM_BASE_CLK 6000/* 6 MHz */ +#define PWM_MAX_PERIOD_NS 21333 /* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct platform_device *pdev; + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1); + + return 0; +} + +static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 0); +} + +static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + struct device *dev = crc_pwm-pdev-dev; + int level, percent; + + if (period_ns PWM_MAX_PERIOD_NS) { + dev_err(dev, un-supported period_ns\n); + return -1; + } + + if (pwm-period != period_ns) { + int clk_div; + + /* changing the clk divisor, need to disable fisrt */ + crc_pwm_disable(c, pwm); + clk_div = PWM_BASE_CLK * period_ns / 100; + + regmap_write(crc_pwm-regmap, PWM0_CLK_DIV, + clk_div | PWM_OUTPUT_ENABLE); + + /* enable back */ + crc_pwm_enable(c, pwm); + } + + if (duty_ns period_ns) { + dev_err(dev, duty cycle cannot be greater than cycle period\n
Re: [Intel-gfx] [PATCH 3/8] drivers/mfd: Add lookup table for Panel Control as GPIO signal
On 04/29/2015 07:57 PM, Lee Jones wrote: On Wed, 29 Apr 2015, Shobhit Kumar wrote: On some Intel SoC platforms, the panel enable/disable signals are controlled by CRC PMIC. Add those control as a new GPIO in a lookup table for gpio-crystalcove chip during CRC driver load v2: Make the lookup table static (Thierry) Remove the lookup table during driver remove (Thierry) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 17 + 1 file changed, 17 insertions(+) I have no idea what this stuff is, but it looks plausible. The CRC PMIC controls the panel enable/disable signal using one of GPIO like lines. It was agreed by Linus Walleij to go this way. The matching crystalcove gpio changes are already merged in Linux next as - http://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=e189ca56d91bbf1d3fe2f88ab6858bf919d42adf This just adds a consumer lookup table for the gpio. Since we do not have a DT or board files, and since this was part of CRC driver, just added the lookup table during CRC driver load itself. Same is done for PWM in a later patch. Regards Shobhit For my own reference: Acked-by: Lee Jones lee.jo...@linaro.org diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 7b50b6b..f3d918e 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -24,8 +24,19 @@ #include linux/acpi.h #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h +#include linux/gpio/machine.h #include intel_soc_pmic_core.h +/* Lookup table for the Panel Enable/Disable line as GPIO signals */ +static struct gpiod_lookup_table panel_gpio_table = { +/* Intel GFX is consumer */ +.dev_id = :00:02.0, +.table = { +/* Panel EN/DISABLE */ +GPIO_LOOKUP(gpio_crystalcove, 94, panel, GPIO_ACTIVE_HIGH), +}, +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -85,6 +96,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, if (ret) dev_warn(dev, Can't enable IRQ as wake source: %d\n, ret); +/* Add lookup table binding for Panel Control to the GPIO Chip */ +gpiod_add_lookup_table(panel_gpio_table); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -104,6 +118,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) regmap_del_irq_chip(pmic-irq, pmic-irq_chip_data); +/* Remove lookup table for Panel Control from the GPIO Chip */ +gpiod_remove_lookup_table(panel_gpio_table); + mfd_remove_devices(i2c-dev); return 0; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 7/8] drm/i915: Use the CRC gpio for panel enable/disable
The CRC (Crystal Cove) PMIC, controls the panel enable and disable signals for BYT for dsi panels. This is indicated in the VBT fields. Use that to initialize and use GPIO based control for these signals. v2: Use the newer gpiod interface(Alexandre) v3: Remove the redundant checks and unused code (Ville) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_dsi.c | 32 ++-- drivers/gpu/drm/i915/intel_dsi.h | 6 ++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 5196642..be55ffa 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -31,6 +31,7 @@ #include drm/drm_panel.h #include drm/drm_mipi_dsi.h #include linux/slab.h +#include linux/gpio/consumer.h #include i915_drv.h #include intel_drv.h #include intel_dsi.h @@ -415,6 +416,12 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + /* Panel Enable over CRC PMIC */ + if (intel_dsi-gpio_panel) + gpiod_set_value_cansleep(intel_dsi-gpio_panel, 1); + + msleep(intel_dsi-panel_on_delay); + /* Disable DPOunit clock gating, can stall pipe * and we need DPLL REFA always enabled */ tmp = I915_READ(DPLL(pipe)); @@ -432,8 +439,6 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) /* put device in ready state */ intel_dsi_device_ready(encoder); - msleep(intel_dsi-panel_on_delay); - drm_panel_prepare(intel_dsi-panel); for_each_dsi_port(port, intel_dsi-ports) @@ -576,6 +581,10 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder) msleep(intel_dsi-panel_off_delay); msleep(intel_dsi-panel_pwr_cycle_delay); + + /* Panel Disable over CRC PMIC */ + if (intel_dsi-gpio_panel) + gpiod_set_value_cansleep(intel_dsi-gpio_panel, 0); } static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, @@ -955,6 +964,11 @@ static void intel_dsi_encoder_destroy(struct drm_encoder *encoder) /* XXX: Logically this call belongs in the panel driver. */ drm_panel_remove(intel_dsi-panel); } + + /* dispose of the gpios */ + if (intel_dsi-gpio_panel) + gpiod_put(intel_dsi-gpio_panel); + intel_encoder_destroy(encoder); } @@ -1071,6 +1085,20 @@ void intel_dsi_init(struct drm_device *dev) goto err; } + /* +* In case of BYT with CRC PMIC, we need to use GPIO for +* Panel control. +*/ + if (dev_priv-vbt.dsi.config-pwm_blc == PPS_BLC_PMIC) { + intel_dsi-gpio_panel = + gpiod_get(dev-dev, panel, GPIOD_OUT_HIGH); + + if (IS_ERR(intel_dsi-gpio_panel)) { + DRM_ERROR(Failed to own gpio for panel control\n); + intel_dsi-gpio_panel = NULL; + } + } + intel_encoder-type = INTEL_OUTPUT_DSI; intel_encoder-cloneable = 0; drm_connector_init(dev, connector, intel_dsi_connector_funcs, diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 2784ac4..bf1bade 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -29,6 +29,9 @@ #include drm/drm_mipi_dsi.h #include intel_drv.h +#define PPS_BLC_PMIC 0 +#define PPS_BLC_SOC1 + /* Dual Link support */ #define DSI_DUAL_LINK_NONE 0 #define DSI_DUAL_LINK_FRONT_BACK 1 @@ -42,6 +45,9 @@ struct intel_dsi { struct drm_panel *panel; struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS]; + /* GPIO Desc for CRC based Panel control */ + struct gpio_desc *gpio_panel; + struct intel_connector *attached_connector; /* bit mask of ports being driven */ -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 8/8] drm/i915: Backlight control using CRC PMIC based PWM driver
Use the CRC PWM device in intel_panel.c and add new MIPI backlight specififc callbacks v2: Modify to use pwm_config callback CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 5 +++ drivers/gpu/drm/i915/intel_dsi.c | 6 +++ drivers/gpu/drm/i915/intel_panel.c | 92 +++--- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 897f17d..b4ebe3b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -182,7 +182,12 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + + /* PWM chip */ + struct pwm_device *pwm; + struct backlight_device *device; + } backlight; void (*backlight_power)(struct intel_connector *, bool enable); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index be55ffa..83c4540 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -402,6 +402,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_dsi_port_enable(encoder); } + + intel_panel_enable_backlight(intel_dsi-attached_connector); } static void intel_dsi_pre_enable(struct intel_encoder *encoder) @@ -466,6 +468,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + intel_panel_disable_backlight(intel_dsi-attached_connector); + if (is_vid_mode(intel_dsi)) { /* Send Shutdown command to the panel in LP mode */ for_each_dsi_port(port, intel_dsi-ports) @@ -1132,6 +1136,8 @@ void intel_dsi_init(struct drm_device *dev) } intel_panel_init(intel_connector-panel, fixed_mode, NULL); + intel_panel_setup_backlight(connector, + (intel_encoder-crtc_mask = (1 PIPE_A)) ? PIPE_A: PIPE_B); return; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 08532d4..5700f6f 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -32,8 +32,12 @@ #include linux/kernel.h #include linux/moduleparam.h +#include linux/pwm.h #include intel_drv.h +#define CRC_PMIC_PWM_PERIOD_NS 21333 +#define CRC_PMIC_PWM_STEPS 255 + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -536,6 +540,15 @@ static u32 vlv_get_backlight(struct intel_connector *connector) return _vlv_get_backlight(dev, pipe); } +static u32 vlv_get_mipi_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + int duty_ns; + + duty_ns = pwm_get_duty_cycle(panel-backlight.pwm); + return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); +} + static u32 intel_panel_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -616,6 +629,14 @@ static void vlv_set_backlight(struct intel_connector *connector, u32 level) I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); } +static void vlv_set_mipi_backlight(struct intel_connector *connector, u32 level) +{ + struct intel_panel *panel = connector-panel; + int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + + pwm_config(panel-backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); +} + static void intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) { @@ -741,6 +762,16 @@ static void vlv_disable_backlight(struct intel_connector *connector) I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp ~BLM_PWM_ENABLE); } +static void vlv_disable_mipi_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + + /* Disable the backlight */ + pwm_config(panel-backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); + usleep_range(2000, 3000); + pwm_disable(panel-backlight.pwm); +} + void intel_panel_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -947,6 +978,16 @@ static void vlv_enable_backlight(struct intel_connector *connector) I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); } +static void vlv_enable_mipi_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + int duty_ns = DIV_ROUND_UP( + panel-backlight.level * CRC_PMIC_PWM_PERIOD_NS, 100); + + pwm_enable(panel-backlight.pwm); + pwm_config(panel-backlight.pwm, duty_ns
[Intel-gfx] [PATCH 4/8] drivers/mfd: Add PWM cell device for Crystalcove PMIC
Needed for PWM control suuported by the PMIC CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_crc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index 4cc1b32..8839e25 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -109,6 +109,9 @@ static struct mfd_cell crystal_cove_dev[] = { { .name = crystal_cove_pmic, }, + { + .name = crystal_cove_pwm, + }, }; static const struct regmap_config crystal_cove_regmap_config = { -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 6/8] drivers/pwm: Add Crystalcove (CRC) PWM driver
The Crystalcove PMIC controls PWM signals and this driver exports that capability as a PWM chip driver. This is platform device implementtaion of the drivers/mfd cell device for CRC PMIC v2: Use the existing config callback with duty_ns and period_ns(Thierry) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/pwm/Kconfig | 7 +++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-crc.c | 171 ++ 3 files changed, 179 insertions(+) create mode 100644 drivers/pwm/pwm-crc.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..954da3e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -183,6 +183,13 @@ config PWM_LPC32XX To compile this driver as a module, choose M here: the module will be called pwm-lpc32xx. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + config PWM_LPSS tristate Intel LPSS PWM support depends on X86 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..3d38fed 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o obj-$(CONFIG_PWM_TWL) += pwm-twl.o obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o +obj-$(CONFIG_PWM_CRC) += pwm-crc.o diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..987f3b4 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,171 @@ +/* + * pwm-crc.c - Intel Crystal Cove PWM Driver + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/module.h +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (17) +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL 0xFF + +#define PWM_BASE_CLK 6000/* 6 MHz */ +#define PWM_MAX_PERIOD_NS 21333 /* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct platform_device *pdev; + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1); + + return 0; +} + +static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 0); +} + +static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + struct device *dev = crc_pwm-pdev-dev; + int level, percent; + + if (period_ns PWM_MAX_PERIOD_NS) { + dev_err(dev, un-supported period_ns\n); + return -1; + } + + if (pwm-period != period_ns) { + int clk_div; + + /* changing the clk divisor, need to disable fisrt */ + crc_pwm_disable(c, pwm); + clk_div = PWM_BASE_CLK * period_ns / 100; + + regmap_write(crc_pwm-regmap, PWM0_CLK_DIV, + clk_div | PWM_OUTPUT_ENABLE); + + /* enable back */ + crc_pwm_enable(c, pwm); + } + + if (duty_ns period_ns) { + dev_err(dev, duty cycle cannot be greater than cycle period\n); + return -1
[Intel-gfx] [PATCH 0/8] Crystalcove (CRC) PMIC based panel and pwm control
Hi All, On some of the BYT devices, for DSI panels, the panel enable/disable signals and backlight control are done using the Crystalcove PMIC. This series provides support for the same and has been reviewed earlier on - http://lists.freedesktop.org/archives/intel-gfx/2015-March/061908.html This series addresses the review comments with two of the patches already merged in linux-next as - http://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=e189ca56d91bbf1d3fe2f88ab6858bf919d42adf http://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=c264f1110d27185f8531602f5fce400a6bbce946 Basically following are implemented - 1. GPIO control for panel enable/disable with GFX device as consumer 2. New PWM chip driver added for CRC PMIC based backlight control 3. i915 is modified to use the CRC gpio chip and the CRC PWM chip to do backlight control. This is now added in the generic panel backlight control infrastructure All these patches have been tested on AsusT100 and working fine using /sys/class/backlight/intel_backlight interface. Patches are also verified on android-x86 tree for AsusT100. Regards Shobhit Shobhit Kumar (8): drivers/gpio/gpiolib: Add support for removing registered consumer lookup table drivers/pwm/core: Add support to remove registered consumer lookup tables drivers/mfd: Add lookup table for Panel Control as GPIO signal drivers/mfd: Add PWM cell device for Crystalcove PMIC drivers/mfd: ADD PWM lookup table for CRC PMIC based PWM drivers/pwm: Add Crystalcove (CRC) PWM driver drm/i915: Use the CRC gpio for panel enable/disable drm/i915: Backlight control using CRC PMIC based PWM driver drivers/gpio/gpiolib.c | 13 +++ drivers/gpu/drm/i915/intel_drv.h | 5 ++ drivers/gpu/drm/i915/intel_dsi.c | 38 - drivers/gpu/drm/i915/intel_dsi.h | 6 ++ drivers/gpu/drm/i915/intel_panel.c | 92 ++-- drivers/mfd/intel_soc_pmic_core.c | 29 +++ drivers/mfd/intel_soc_pmic_crc.c | 3 + drivers/pwm/Kconfig| 7 ++ drivers/pwm/Makefile | 1 + drivers/pwm/core.c | 17 drivers/pwm/pwm-crc.c | 171 + include/linux/gpio/machine.h | 1 + include/linux/pwm.h| 5 ++ 13 files changed, 381 insertions(+), 7 deletions(-) create mode 100644 drivers/pwm/pwm-crc.c -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 3/8] drivers/mfd: Add lookup table for Panel Control as GPIO signal
On some Intel SoC platforms, the panel enable/disable signals are controlled by CRC PMIC. Add those control as a new GPIO in a lookup table for gpio-crystalcove chip during CRC driver load v2: Make the lookup table static (Thierry) Remove the lookup table during driver remove (Thierry) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 7b50b6b..f3d918e 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -24,8 +24,19 @@ #include linux/acpi.h #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h +#include linux/gpio/machine.h #include intel_soc_pmic_core.h +/* Lookup table for the Panel Enable/Disable line as GPIO signals */ +static struct gpiod_lookup_table panel_gpio_table = { + /* Intel GFX is consumer */ + .dev_id = :00:02.0, + .table = { + /* Panel EN/DISABLE */ + GPIO_LOOKUP(gpio_crystalcove, 94, panel, GPIO_ACTIVE_HIGH), + }, +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -85,6 +96,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, if (ret) dev_warn(dev, Can't enable IRQ as wake source: %d\n, ret); + /* Add lookup table binding for Panel Control to the GPIO Chip */ + gpiod_add_lookup_table(panel_gpio_table); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -104,6 +118,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) regmap_del_irq_chip(pmic-irq, pmic-irq_chip_data); + /* Remove lookup table for Panel Control from the GPIO Chip */ + gpiod_remove_lookup_table(panel_gpio_table); + mfd_remove_devices(i2c-dev); return 0; -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/8] drivers/gpio/gpiolib: Add support for removing registered consumer lookup table
In case we unload and load a driver module again that is registering a lookup table, without this it will result in multiple entries. Provide an option to remove the lookup table on driver unload v2: Ccing maintainers Cc: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Reviewed-by: Alexandre Courbot acour...@nvidia.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpio/gpiolib.c | 13 + include/linux/gpio/machine.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 59eaa23..2420af9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1658,6 +1658,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table) mutex_unlock(gpio_lookup_lock); } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ + mutex_lock(gpio_lookup_lock); + + list_del(table-list); + + mutex_unlock(gpio_lookup_lock); +} + static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index e270614..c0d712d 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -57,5 +57,6 @@ struct gpiod_lookup_table { } void gpiod_add_lookup_table(struct gpiod_lookup_table *table); +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); #endif /* __LINUX_GPIO_MACHINE_H */ -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 5/8] drivers/mfd: ADD PWM lookup table for CRC PMIC based PWM
On some BYT PLatform the PWM is controlled using CRC PMIC. Add a lookup entry for the same to be used by the consumer (Intel GFX) v2: Remove the lookup table on driver unload (Thierry) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index f3d918e..a00ddd9 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -25,6 +25,7 @@ #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h #include linux/gpio/machine.h +#include linux/pwm.h #include intel_soc_pmic_core.h /* Lookup table for the Panel Enable/Disable line as GPIO signals */ @@ -37,6 +38,11 @@ static struct gpiod_lookup_table panel_gpio_table = { }, }; +/* PWM consumed by the Intel GFX */ +static struct pwm_lookup crc_pwm_lookup[] = { + PWM_LOOKUP(crystal_cove_pwm, 0, :00:02.0, pwm_backlight, 0, PWM_POLARITY_NORMAL), +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -99,6 +105,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, /* Add lookup table binding for Panel Control to the GPIO Chip */ gpiod_add_lookup_table(panel_gpio_table); + /* Add lookup table for crc-pwm */ + pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -121,6 +130,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) /* Remove lookup table for Panel Control from the GPIO Chip */ gpiod_remove_lookup_table(panel_gpio_table); + /* remove crc-pwm lookup table */ + pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + mfd_remove_devices(i2c-dev); return 0; -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/8] drivers/pwm/core: Add support to remove registered consumer lookup tables
In case some drivers are unloading, they can remove lookup tables which they would have registered during their load time to avoid redundant entries if loaded again v2: Ccing maintainers CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/pwm/core.c | 17 + include/linux/pwm.h | 5 + 2 files changed, 22 insertions(+) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index ba34c7d..d2fe7c8d 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -586,6 +586,23 @@ void pwm_add_table(struct pwm_lookup *table, size_t num) } /** + * pwm_remove_table() - un-register PWM device consumers + * @table: array of consumers to un-register + * @num: number of consumers in table + */ +void pwm_remove_table(struct pwm_lookup *table, size_t num) +{ + mutex_lock(pwm_lookup_lock); + + while (num--) { + list_del(table-list); + table++; + } + + mutex_unlock(pwm_lookup_lock); +} + +/** * pwm_get() - look up and request a PWM device * @dev: device for PWM consumer * @con_id: consumer name diff --git a/include/linux/pwm.h b/include/linux/pwm.h index e90628c..cfe2d8d 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -290,10 +290,15 @@ struct pwm_lookup { #if IS_ENABLED(CONFIG_PWM) void pwm_add_table(struct pwm_lookup *table, size_t num); +void pwm_remove_table(struct pwm_lookup *table, size_t num); #else static inline void pwm_add_table(struct pwm_lookup *table, size_t num) { } + +static inline void pwm_remove_table(struct pwm_lookup *table, size_t num) +{ +} #endif #ifdef CONFIG_PWM_SYSFS -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [RFC v6 6/8] drivers/pwm: Add Crystalcove (CRC) PWM driver
The Crystalcove PMIC controls PWM signals and this driver exports that capability as a PWM chip driver. This is platform device implementtaion of the drivers/mfd cell device for CRC PMIC v2: Use the existing config callback with duty_ns and period_ns(Thierry) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/pwm/Kconfig | 7 +++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-crc.c | 171 ++ 3 files changed, 179 insertions(+) create mode 100644 drivers/pwm/pwm-crc.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b1541f4..954da3e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -183,6 +183,13 @@ config PWM_LPC32XX To compile this driver as a module, choose M here: the module will be called pwm-lpc32xx. +config PWM_CRC + bool Intel Crystalcove (CRC) PWM support + depends on X86 INTEL_SOC_PMIC + help + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM + control. + config PWM_LPSS tristate Intel LPSS PWM support depends on X86 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index ec50eb5..3d38fed 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o obj-$(CONFIG_PWM_TWL) += pwm-twl.o obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o +obj-$(CONFIG_PWM_CRC) += pwm-crc.o diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c new file mode 100644 index 000..987f3b4 --- /dev/null +++ b/drivers/pwm/pwm-crc.c @@ -0,0 +1,171 @@ +/* + * pwm-crc.c - Intel Crystal Cove PWM Driver + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Shobhit Kumar shobhit.ku...@intel.com + */ + +#include linux/module.h +#include linux/platform_device.h +#include linux/regmap.h +#include linux/mfd/intel_soc_pmic.h +#include linux/pwm.h + +#define PWM0_CLK_DIV 0x4B +#define PWM_OUTPUT_ENABLE (17) +#define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ +#define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ +#define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ + +#define PWM0_DUTY_CYCLE0x4E +#define BACKLIGHT_EN 0x51 + +#define PWM_MAX_LEVEL 0xFF + +#define PWM_BASE_CLK 6000/* 6 MHz */ +#define PWM_MAX_PERIOD_NS 21333 /* 46.875KHz */ + +/** + * struct crystalcove_pwm - Crystal Cove PWM controller + * @chip: the abstract pwm_chip structure. + * @regmap: the regmap from the parent device. + */ +struct crystalcove_pwm { + struct pwm_chip chip; + struct platform_device *pdev; + struct regmap *regmap; +}; + +static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) +{ + return container_of(pc, struct crystalcove_pwm, chip); +} + +static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 1); + + return 0; +} + +static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + + regmap_write(crc_pwm-regmap, BACKLIGHT_EN, 0); +} + +static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + struct device *dev = crc_pwm-pdev-dev; + int level, percent; + + if (period_ns PWM_MAX_PERIOD_NS) { + dev_err(dev, un-supported period_ns\n); + return -1; + } + + if (pwm-period != period_ns) { + int clk_div; + + /* changing the clk divisor, need to disable fisrt */ + crc_pwm_disable(c, pwm); + clk_div = PWM_BASE_CLK * period_ns / 100; + + regmap_write(crc_pwm-regmap, PWM0_CLK_DIV, + clk_div | PWM_OUTPUT_ENABLE); + + /* enable back */ + crc_pwm_enable(c, pwm); + } + + if (duty_ns period_ns) { + dev_err(dev, duty cycle cannot be greater than cycle period\n); + return -1
[Intel-gfx] [RFC v6 3/8] drivers/mfd: Add lookup table for Panel Control as GPIO signal
On some Intel SoC platforms, the panel enable/disable signals are controlled by CRC PMIC. Add those control as a new GPIO in a lookup table for gpio-crystalcove chip during CRC driver load v2: Make the lookup table static (Thierry) Remove the lookup table during driver remove (Thierry) CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/mfd/intel_soc_pmic_core.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 7b50b6b..f3d918e 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -24,8 +24,19 @@ #include linux/acpi.h #include linux/regmap.h #include linux/mfd/intel_soc_pmic.h +#include linux/gpio/machine.h #include intel_soc_pmic_core.h +/* Lookup table for the Panel Enable/Disable line as GPIO signals */ +static struct gpiod_lookup_table panel_gpio_table = { + /* Intel GFX is consumer */ + .dev_id = :00:02.0, + .table = { + /* Panel EN/DISABLE */ + GPIO_LOOKUP(gpio_crystalcove, 94, panel, GPIO_ACTIVE_HIGH), + }, +}; + static int intel_soc_pmic_find_gpio_irq(struct device *dev) { struct gpio_desc *desc; @@ -85,6 +96,9 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, if (ret) dev_warn(dev, Can't enable IRQ as wake source: %d\n, ret); + /* Add lookup table binding for Panel Control to the GPIO Chip */ + gpiod_add_lookup_table(panel_gpio_table); + ret = mfd_add_devices(dev, -1, config-cell_dev, config-n_cell_devs, NULL, 0, regmap_irq_get_domain(pmic-irq_chip_data)); @@ -104,6 +118,9 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c) regmap_del_irq_chip(pmic-irq, pmic-irq_chip_data); + /* Remove lookup table for Panel Control from the GPIO Chip */ + gpiod_remove_lookup_table(panel_gpio_table); + mfd_remove_devices(i2c-dev); return 0; -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [RFC v6 8/8] drm/i915: Backlight control using CRC PMIC based PWM driver
Use the CRC PWM device in intel_panel.c and add new MIPI backlight specififc callbacks v2: Modify to use pwm_config callback CC: Samuel Ortiz sa...@linux.intel.com Cc: Linus Walleij linus.wall...@linaro.org Cc: Alexandre Courbot gnu...@gmail.com Cc: Thierry Reding thierry.red...@gmail.com Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 5 +++ drivers/gpu/drm/i915/intel_dsi.c | 6 +++ drivers/gpu/drm/i915/intel_panel.c | 92 +++--- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 897f17d..b4ebe3b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -182,7 +182,12 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + + /* PWM chip */ + struct pwm_device *pwm; + struct backlight_device *device; + } backlight; void (*backlight_power)(struct intel_connector *, bool enable); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index be55ffa..83c4540 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -402,6 +402,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_dsi_port_enable(encoder); } + + intel_panel_enable_backlight(intel_dsi-attached_connector); } static void intel_dsi_pre_enable(struct intel_encoder *encoder) @@ -466,6 +468,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS(\n); + intel_panel_disable_backlight(intel_dsi-attached_connector); + if (is_vid_mode(intel_dsi)) { /* Send Shutdown command to the panel in LP mode */ for_each_dsi_port(port, intel_dsi-ports) @@ -1132,6 +1136,8 @@ void intel_dsi_init(struct drm_device *dev) } intel_panel_init(intel_connector-panel, fixed_mode, NULL); + intel_panel_setup_backlight(connector, + (intel_encoder-crtc_mask = (1 PIPE_A)) ? PIPE_A: PIPE_B); return; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 08532d4..5700f6f 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -32,8 +32,12 @@ #include linux/kernel.h #include linux/moduleparam.h +#include linux/pwm.h #include intel_drv.h +#define CRC_PMIC_PWM_PERIOD_NS 21333 +#define CRC_PMIC_PWM_STEPS 255 + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -536,6 +540,15 @@ static u32 vlv_get_backlight(struct intel_connector *connector) return _vlv_get_backlight(dev, pipe); } +static u32 vlv_get_mipi_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + int duty_ns; + + duty_ns = pwm_get_duty_cycle(panel-backlight.pwm); + return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); +} + static u32 intel_panel_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -616,6 +629,14 @@ static void vlv_set_backlight(struct intel_connector *connector, u32 level) I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); } +static void vlv_set_mipi_backlight(struct intel_connector *connector, u32 level) +{ + struct intel_panel *panel = connector-panel; + int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + + pwm_config(panel-backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); +} + static void intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) { @@ -741,6 +762,16 @@ static void vlv_disable_backlight(struct intel_connector *connector) I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp ~BLM_PWM_ENABLE); } +static void vlv_disable_mipi_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + + /* Disable the backlight */ + pwm_config(panel-backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); + usleep_range(2000, 3000); + pwm_disable(panel-backlight.pwm); +} + void intel_panel_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector-base.dev; @@ -947,6 +978,16 @@ static void vlv_enable_backlight(struct intel_connector *connector) I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); } +static void vlv_enable_mipi_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = connector-panel; + int duty_ns = DIV_ROUND_UP( + panel-backlight.level * CRC_PMIC_PWM_PERIOD_NS, 100); + + pwm_enable(panel-backlight.pwm); + pwm_config(panel-backlight.pwm, duty_ns
[Intel-gfx] [RFC v6 0/8] Crystalcove (CRC) PMIC based panel and pwm control
Hi All, Finally I came back to this and tried to address the pending review comments. Couple of the patches from the older series were merged in linux-next. This series reworks on the remaining and rebases on linux-next. Basically following are implemented - 1. GPIO control for panel enable/disable with GFX device as consumer 2. New PWM chip driver added for CRC PMIC based backlight control 3. i915 is modified to use the CRC gpio chip and the CRC PWM chip to do backlight control. This is now added in intel_panel.c in the generic panel backlight control infrastructure All these patches have been tested on AsusT100 and working fine using /sys/class/backlight/intel_backlight interface. Recently I noticed another device Dell Venue 8 Pro (BYT-CR) which should be using LPSS backlight control. There is already a LPSS PWM chip driver in upstream kernel which should be used in this case. That patch is for another day. Regards Shobhit Shobhit Kumar (8): drivers/gpio/gpiolib: Add support for removing registered consumer lookup table drivers/pwm/core: Add support to remove registered consumer lookup tables drivers/mfd: Add lookup table for Panel Control as GPIO signal drivers/mfd: Add PWM cell device for Crystalcove PMIC drivers/mfd: ADD PWM lookup table for CRC PMIC based PWM drivers/pwm: Add Crystalcove (CRC) PWM driver drm/i915: Use the CRC gpio for panel enable/disable drm/i915: Backlight control using CRC PMIC based PWM driver drivers/gpio/gpiolib.c | 13 +++ drivers/gpu/drm/i915/intel_drv.h | 5 ++ drivers/gpu/drm/i915/intel_dsi.c | 38 - drivers/gpu/drm/i915/intel_dsi.h | 6 ++ drivers/gpu/drm/i915/intel_panel.c | 92 ++-- drivers/mfd/intel_soc_pmic_core.c | 29 +++ drivers/mfd/intel_soc_pmic_crc.c | 3 + drivers/pwm/Kconfig| 7 ++ drivers/pwm/Makefile | 1 + drivers/pwm/core.c | 17 drivers/pwm/pwm-crc.c | 171 + include/linux/gpio/machine.h | 1 + include/linux/pwm.h| 5 ++ 13 files changed, 381 insertions(+), 7 deletions(-) create mode 100644 drivers/pwm/pwm-crc.c -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [RFC v6 2/8] drivers/pwm/core: Add support to remove registered consumer lookup tables
In case some drivers are unloading, they can remove lookup tables which they would have registered during their load time to avoid redundant entries if loaded again Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/pwm/core.c | 17 + include/linux/pwm.h | 5 + 2 files changed, 22 insertions(+) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index ba34c7d..d2fe7c8d 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -586,6 +586,23 @@ void pwm_add_table(struct pwm_lookup *table, size_t num) } /** + * pwm_remove_table() - un-register PWM device consumers + * @table: array of consumers to un-register + * @num: number of consumers in table + */ +void pwm_remove_table(struct pwm_lookup *table, size_t num) +{ + mutex_lock(pwm_lookup_lock); + + while (num--) { + list_del(table-list); + table++; + } + + mutex_unlock(pwm_lookup_lock); +} + +/** * pwm_get() - look up and request a PWM device * @dev: device for PWM consumer * @con_id: consumer name diff --git a/include/linux/pwm.h b/include/linux/pwm.h index e90628c..cfe2d8d 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -290,10 +290,15 @@ struct pwm_lookup { #if IS_ENABLED(CONFIG_PWM) void pwm_add_table(struct pwm_lookup *table, size_t num); +void pwm_remove_table(struct pwm_lookup *table, size_t num); #else static inline void pwm_add_table(struct pwm_lookup *table, size_t num) { } + +static inline void pwm_remove_table(struct pwm_lookup *table, size_t num) +{ +} #endif #ifdef CONFIG_PWM_SYSFS -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [RFC v6 1/8] drivers/gpio/gpiolib: Add support for removing registered consumer lookup table
In case we unload and load a driver module again that is registering a lookup table, without this it will result in multiple entries. Provide an option to remove the lookup table on driver unload Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com --- drivers/gpio/gpiolib.c | 13 + include/linux/gpio/machine.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 59eaa23..2420af9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1658,6 +1658,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table) mutex_unlock(gpio_lookup_lock); } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ + mutex_lock(gpio_lookup_lock); + + list_del(table-list); + + mutex_unlock(gpio_lookup_lock); +} + static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index e270614..c0d712d 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -57,5 +57,6 @@ struct gpiod_lookup_table { } void gpiod_add_lookup_table(struct gpiod_lookup_table *table); +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); #endif /* __LINUX_GPIO_MACHINE_H */ -- 2.1.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx