[PATCH 0/8] tilcdc-panel: Backlight and GPIO devicetree support
On 07/11/2014 09:18 AM, Ezequiel Garcia wrote: > Hello all, > > This patchset adds the required changes to support an optional backlight > and GPIO for the tilcdc panel driver. > > There was some code to support a backlight, but it was somewhat broken > and undocumented. I've followed the nice implementation in panel-simple > and added a similar one here. > > The enable GPIO is required to turn on and off devices with such capability. > Also here, I've followed panel-simple which looks correct. > > In addition to this there are very minor cosmetic cleanups and a larger > error path fix in tilcdc's DRM driver .load error path. > > This patchset applies on top of drm-next branch which contains the latest > tilcdc pushed by Guido. > > If at all possible, I'd like to get this merged for v3.17. If a pull request > is needed, don't hesitate to ask and I'll prepare one. > > Comments and tests welcome! > All of the changes seem to make sense and I tested on AM335x-EVM both with and without the addition "backlight = " in the dts for the panel node. I see no issues in either case, continued to work as before. Tested against 3.16-rc6 with this patchset and the earlier patchset from Guido applied. Also tested on BeagleBone Black even though it doesn't have a panel, just to make sure nothing changed there. For the series: Tested-by: Darren Etheridge > Ezequiel Garcia (8): >drm/tilcdc: Fix the error path in tilcdc_load() >drm/tilcdc: panel: Add missing of_node_put >drm/tilcdc: panel: Remove unused variable >drm/tilcdc: panel: Spurious whitespace removal >drm/tilcdc: panel: Use devm_kzalloc to simplify the error path >drm/tilcdc: panel: Fix backlight devicetree support >drm/tilcdc: panel: Set return value explicitly >drm/tilcdc: panel: Add support for enable GPIO > > .../devicetree/bindings/drm/tilcdc/panel.txt | 7 ++ > drivers/gpu/drm/tilcdc/tilcdc_drv.c| 60 +++--- > drivers/gpu/drm/tilcdc/tilcdc_panel.c | 74 > +- > 3 files changed, 114 insertions(+), 27 deletions(-) >
[PATCH RFA 2/2] drm/i2c: tda998x: add component support
On 07/24/2014 09:57 AM, Russell King wrote: > Add component helper support to the tda998x driver. This permits the > TDA998x to be declared as a separate device in device tree, and bound > at the appropriate moment with a co-operating card driver. > > The existing slave_encoder interfaces are kept while there are existing > users of it in order to prevent regressions. > > Signed-off-by: Russell King > --- > RFA = request for acks, but tested-by's are also welcome, particularly > for tilcdc hardware. > Works fine on BeagleBone Black (tilcdc + tda998x) Tested against 3.16-rc6, using unmodified tilcdc driver, unmodified dts. Version details: Linux am335x-evm 3.16.0-rc6-2-gf8a096f-dirty #40 SMP Thu Jul 24 13:49:42 CDT 2014 armv7l GNU/Linux Tried modetest with a variety of modes, all looked correct. Tested as both built-in and modules. Tested-by: Darren Etheridge
[PATCH RFA 1/2] drm/i2c: tda998x: allow re-use of tda998x support code
On 07/24/2014 09:57 AM, Russell King wrote: > Re-jig the TDA998x code so that we separate the functionality from the > drm slave encoder implementation. In several places, this is pretty > clearly the correct thing to do, because we can avoid repetitively > having to convert from the drm_encoder to the TDA998x private > structure, particularly with the driver internal functions. > > The main motivation behind this change is to allow the code to be > re-used with a standard drm_encoder and drm_connector implementation > based on the component helpers, rather than the slave_encoder system. > The addition of this will be in the following patch. > > We keep the slave_encoder interface as there are existing users of > this; we need to give them time to convert and test. > > Signed-off-by: Russell King > --- > RFA = request for acks, but tested-by's would also be great, > particularly from the tilcdc folk. > Works fine on BeagleBone Black (tilcdc + tda998x) Tested against 3.16-rc6, using unmodified tilcdc driver, unmodified dts. Version details: Linux am335x-evm 3.16.0-rc6-2-gf8a096f-dirty #40 SMP Thu Jul 24 13:49:42 CDT 2014 armv7l GNU/Linux Tried modetest with a variety of modes, all looked correct. Tested as both built-in and modules. Tested-by: Darren Etheridge
[PATCH/RESEND 0/9] drm: tilcdc driver fixes
On 07/01/2014 06:39 PM, Guido Mart?nez wrote: > On Fri, Jun 27, 2014 at 05:08:51PM -0500, Darren Etheridge wrote: >> [snip] >> >> Otherwise I think this is a good and useful patch series. > It that a Tested-by tag? :) Sure - I would prefer that the WARN_ON was silenced when the tilcdc module is removed, but the series adds improvements over what is there now. I have tested it across a few variants of AM335x boards and attached display hardware in both module form and built-in to the kernel, therefore: Tested-by: Darren Etheridge > > Thanks! > Guido > >> >> Darren >> >>> The first 7 patches are bug fixes which and should probably be applied >>> in the stable trees. The last two are clean-ups. >>> >>> >>> Resending this since I got no replies. >>> >>> >>> Guido Mart?nez (9): >>>drm/i2c: tda998x: move drm_i2c_encoder_destroy call >>>drm/tilcdc: panel: fix dangling sysfs connector node >>>drm/tilcdc: slave: fix dangling sysfs connector node >>>drm/tilcdc: tfp410: fix dangling sysfs connector node >>>drm/tilcdc: panel: fix leak when unloading the module >>>drm/tilcdc: fix release order on exit >>>drm/tilcdc: fix double kfree >>>drm/tilcdc: remove submodule destroy calls >>>drm/tilcdc: replace late_initcall with module_init >>> >>> drivers/gpu/drm/i2c/tda998x_drv.c | 2 +- >>> drivers/gpu/drm/tilcdc/Module.symvers | 0 >>> drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 + >>> drivers/gpu/drm/tilcdc/tilcdc_drv.h| 1 - >>> drivers/gpu/drm/tilcdc/tilcdc_panel.c | 39 >>> +- >>> drivers/gpu/drm/tilcdc/tilcdc_slave.c | 27 +-- >>> drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 35 +++--- >>> 7 files changed, 59 insertions(+), 60 deletions(-) >>> create mode 100644 drivers/gpu/drm/tilcdc/Module.symvers >>> >
[PATCH/RESEND 0/9] drm: tilcdc driver fixes
Guido, On 06/17/2014 09:17 AM, Guido Mart?nez wrote: > The tilcdc driver could be compiled as a module, but was severely broken > and could not be used as such. This patchset attempts to fix the issues > preventing a proper load/unload of the module. > > Issues included dangling sysfs nodes, dangling devices, memory leaks and > a double kfree. > > It now seems to be working ok. We have tested this by loading and > unloading the driver repeteadly, with both panel and slave connectors > and found no flaws. > > There is still one warning left on tilcdc_crtc_destroy, caused by > destroying the connector while still in an ON status. We don't know why > this happens or why it's an issue, so we did not fix it. > Yes I see what you mean, it triggers the WARN_ON in tilcdc_crtc_destroy because DRM_MODE_DPMS_ON is still set. This WARN_ON does make some sense because DPMS_OFF would have the effect of turning off clocks and putting the monitor to sleep which seems logical considering we have torn down the display. Adding a tilcdc_crtc_dpms(DPMS_OFF) right before the WARN_ON confirms this, but it seems strange that this hasn't happened automatically (+ Russell doesn't need to do it in his Armada driver) - so I suspect there is a better way. Otherwise I think this is a good and useful patch series. Darren > The first 7 patches are bug fixes which and should probably be applied > in the stable trees. The last two are clean-ups. > > > Resending this since I got no replies. > > > Guido Mart?nez (9): >drm/i2c: tda998x: move drm_i2c_encoder_destroy call >drm/tilcdc: panel: fix dangling sysfs connector node >drm/tilcdc: slave: fix dangling sysfs connector node >drm/tilcdc: tfp410: fix dangling sysfs connector node >drm/tilcdc: panel: fix leak when unloading the module >drm/tilcdc: fix release order on exit >drm/tilcdc: fix double kfree >drm/tilcdc: remove submodule destroy calls >drm/tilcdc: replace late_initcall with module_init > > drivers/gpu/drm/i2c/tda998x_drv.c | 2 +- > drivers/gpu/drm/tilcdc/Module.symvers | 0 > drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 + > drivers/gpu/drm/tilcdc/tilcdc_drv.h| 1 - > drivers/gpu/drm/tilcdc/tilcdc_panel.c | 39 > +- > drivers/gpu/drm/tilcdc/tilcdc_slave.c | 27 +-- > drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 35 +++--- > 7 files changed, 59 insertions(+), 60 deletions(-) > create mode 100644 drivers/gpu/drm/tilcdc/Module.symvers >
[PATCH/RESEND 8/9] drm/tilcdc: remove submodule destroy calls
Guido, On 06/17/2014 09:17 AM, Guido Mart?nez wrote: > The TI tilcdc driver is designed with a notion of submodules. Currently, > at unload time, these submodules are iterated and destroyed. > > Now that the tilcdc remove order is fixed, this can be handled perfectly I am not sure I understand the first part of the above sentence - did something change with tilcdc ordering? I think you a referring to previous patches in your series which really mean tilcdc can actually unload now. So really the method this patch uses could always have been used, it just wasn't for some reason? I have tested all of the other patches in your series and all looks good on BeagleBone Black and AM335xEVM, I tested as both built-ins and modules and can load/unload on BeagleBone Black with HDMI enabled correctly. I want to play around a bit more with this particular patch, to try and understand how it differs from Rob's original intent with his module registration/deregistration scheme. I prefer your method, but do we loose anything that Rob's originally had in mind? Darren > by the kernel using the device infrastructure, since each submodule > is a kernel driver itself, and they are only destroy()'ed at unload > time. Therefore we move the destroy() functionality to each submodule's > remove(). > > Also, remove some checks in the unloading process since the new code > guarantees the resources are allocated and need a release. > > Signed-off-by: Guido Mart?nez > --- > drivers/gpu/drm/tilcdc/Module.symvers | 0 > drivers/gpu/drm/tilcdc/tilcdc_drv.c| 6 -- > drivers/gpu/drm/tilcdc/tilcdc_drv.h| 1 - > drivers/gpu/drm/tilcdc/tilcdc_panel.c | 36 > +- > drivers/gpu/drm/tilcdc/tilcdc_slave.c | 26 +--- > drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 34 > 6 files changed, 50 insertions(+), 53 deletions(-) > create mode 100644 drivers/gpu/drm/tilcdc/Module.symvers > > diff --git a/drivers/gpu/drm/tilcdc/Module.symvers > b/drivers/gpu/drm/tilcdc/Module.symvers > new file mode 100644 > index 000..e69de29 > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c > b/drivers/gpu/drm/tilcdc/tilcdc_drv.c > index 006a30e..2c860c4 100644 > --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c > +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c > @@ -120,7 +120,6 @@ static int cpufreq_transition(struct notifier_block *nb, > static int tilcdc_unload(struct drm_device *dev) > { > struct tilcdc_drm_private *priv = dev->dev_private; > - struct tilcdc_module *mod, *cur; > > drm_fbdev_cma_fini(priv->fbdev); > drm_kms_helper_poll_fini(dev); > @@ -149,11 +148,6 @@ static int tilcdc_unload(struct drm_device *dev) > > pm_runtime_disable(dev->dev); > > - list_for_each_entry_safe(mod, cur, &module_list, list) { > - DBG("destroying module: %s", mod->name); > - mod->funcs->destroy(mod); > - } > - > kfree(priv); > > return 0; > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h > b/drivers/gpu/drm/tilcdc/tilcdc_drv.h > index 0938036..7596c14 100644 > --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h > +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h > @@ -98,7 +98,6 @@ struct tilcdc_module; > struct tilcdc_module_ops { > /* create appropriate encoders/connectors: */ > int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev); > - void (*destroy)(struct tilcdc_module *mod); > #ifdef CONFIG_DEBUG_FS > /* create debugfs nodes (can be NULL): */ > int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor); > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c > b/drivers/gpu/drm/tilcdc/tilcdc_panel.c > index b085dcc..2f6efae 100644 > --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c > +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c > @@ -282,21 +282,8 @@ static int panel_modeset_init(struct tilcdc_module *mod, > struct drm_device *dev) > return 0; > } > > -static void panel_destroy(struct tilcdc_module *mod) > -{ > - struct panel_module *panel_mod = to_panel_module(mod); > - > - if (panel_mod->timings) > - display_timings_release(panel_mod->timings); > - > - tilcdc_module_cleanup(mod); > - kfree(panel_mod->info); > - kfree(panel_mod); > -} > - > static const struct tilcdc_module_ops panel_module_ops = { > .modeset_init = panel_modeset_init, > - .destroy = panel_destroy, > }; > > /* > @@ -372,6 +359,7 @@ static int panel_probe(struct platform_device *pdev) > return -ENOMEM; > > mod = &panel_mod->base; > + pdev->dev.platform_data = mod; > > tilcdc_module_init(mod, "panel", &panel_module_ops); > > @@ -379,17 +367,16 @@ static int panel_probe(struct platform_device *pdev) > if (IS_ERR(pinctrl)) > dev_warn(&pdev->dev, "pins are not configured\n"); > > - > panel_mod->timings = of_get_display_timings(node); > if (!panel_mod->tim
[PATCH/RESEND 9/9] drm/tilcdc: replace late_initcall with module_init
On 06/17/2014 09:17 AM, Guido Mart?nez wrote: > Use module_init instead of late_initcall, as is the norm for modular > drivers. > > module_init was used until 6e8de0bd6a51fdeebd5d975c4fcc426f730b339b > ("drm/tilcdc: add encoder slave (v2)") changed it to a late_initcall, > but it does not explain why. Tests show it's working properly with > module_init. > If I recall, the late_initcall stuff was done to try and make sure the tda998x/i2c subsystem came up before tilcdc. However it didn't always work so we added commit: 39de6194131c155901f96686a063212656d80c2e to try and ensure the ordering. This might be why changing back to module_init is fine (and I agree with your assessment from my testing). > Signed-off-by: Guido Mart?nez > --- > drivers/gpu/drm/tilcdc/tilcdc_drv.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c > b/drivers/gpu/drm/tilcdc/tilcdc_drv.c > index 2c860c4..6be623b 100644 > --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c > +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c > @@ -629,7 +629,7 @@ static void __exit tilcdc_drm_fini(void) > tilcdc_tfp410_fini(); > } > > -late_initcall(tilcdc_drm_init); > +module_init(tilcdc_drm_init); > module_exit(tilcdc_drm_fini); > > MODULE_AUTHOR("Rob Clark
[PATCH/RESEND 0/9] drm: tilcdc driver fixes
Guido, Thanks and sorry I missed this the first time around. I'll give it a try on a few of my AM335x based boards when I have access to them again on Monday. Darren On 06/17/2014 09:17 AM, Guido Mart?nez wrote: > The tilcdc driver could be compiled as a module, but was severely broken > and could not be used as such. This patchset attempts to fix the issues > preventing a proper load/unload of the module. > > Issues included dangling sysfs nodes, dangling devices, memory leaks and > a double kfree. > > It now seems to be working ok. We have tested this by loading and > unloading the driver repeteadly, with both panel and slave connectors > and found no flaws. > > There is still one warning left on tilcdc_crtc_destroy, caused by > destroying the connector while still in an ON status. We don't know why > this happens or why it's an issue, so we did not fix it. > > The first 7 patches are bug fixes which and should probably be applied > in the stable trees. The last two are clean-ups. > > > Resending this since I got no replies. > > > Guido Mart?nez (9): >drm/i2c: tda998x: move drm_i2c_encoder_destroy call >drm/tilcdc: panel: fix dangling sysfs connector node >drm/tilcdc: slave: fix dangling sysfs connector node >drm/tilcdc: tfp410: fix dangling sysfs connector node >drm/tilcdc: panel: fix leak when unloading the module >drm/tilcdc: fix release order on exit >drm/tilcdc: fix double kfree >drm/tilcdc: remove submodule destroy calls >drm/tilcdc: replace late_initcall with module_init > > drivers/gpu/drm/i2c/tda998x_drv.c | 2 +- > drivers/gpu/drm/tilcdc/Module.symvers | 0 > drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 + > drivers/gpu/drm/tilcdc/tilcdc_drv.h| 1 - > drivers/gpu/drm/tilcdc/tilcdc_panel.c | 39 > +- > drivers/gpu/drm/tilcdc/tilcdc_slave.c | 27 +-- > drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 35 +++--- > 7 files changed, 59 insertions(+), 60 deletions(-) > create mode 100644 drivers/gpu/drm/tilcdc/Module.symvers >
[PATCH] drm/tilcdc increase allowable supported resolution
Rob Clark wrote on Thu [2014-Apr-24 16:51:04 -0400]: > On Mon, Mar 3, 2014 at 2:08 PM, Felipe Balbi wrote: > > From: Darren Etheridge > > > > 1680x1050 appears to also be within the bandwidth capabilities > > of the device and memory infrastructure. > > For this one, is 1680x1050 possible on all devices w/ tilcdc (like 1st > gen beaglebone (white), etc)? If not, maybe better to keep the > default conservative and override the default in devicetree.. > Fair point Rob, I didn't test BeagleBone White at that resolution, only BeagleBone Black. I'll redo this patch as a BBB specific dts change given we already have a max-bandwidth DT binding in place for tilcdc. Thanks for reviewing it. Darren > BR, > -R > > > Signed-off-by: Darren Etheridge > > --- > > drivers/gpu/drm/tilcdc/tilcdc_drv.h | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h > > b/drivers/gpu/drm/tilcdc/tilcdc_drv.h > > index 5bb64e3..b47ec24 100644 > > --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h > > +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h > > @@ -43,7 +43,7 @@ > > * with optimized DDR & EMIF settings tweaked 1920x1080 at 24 appears to > > * be supportable > > */ > > -#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) > > +#define TILCDC_DEFAULT_MAX_BANDWIDTH (1680*1050*60) > > > > > > struct tilcdc_drm_private { > > -- > > 1.9.0 > >
[PATCH v3 07/24] drm/i2c: tda998x: set the video mode from the adjusted value
Jean-Francois Moine wrote on Tue [2014-Jan-28 18:12:18 +0100]: > On Thu, 23 Jan 2014 17:29:07 -0600 > Darren Etheridge wrote: > > > > @@ -896,9 +897,9 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, > > >* TDA19988 requires high-active sync at input stage, > > >* so invert low-active sync provided by master encoder here > > >*/ > > > - if (mode->flags & DRM_MODE_FLAG_NHSYNC) > > > + if (adj_mode->flags & DRM_MODE_FLAG_NHSYNC) > > > reg_set(priv, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL); > > > - if (mode->flags & DRM_MODE_FLAG_NVSYNC) > > > + if (adj_mode->flags & DRM_MODE_FLAG_NVSYNC) > > > reg_set(priv, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL); > > > > > > > Using the adj_mode->flags breaks a workaround I had done on BeagleBone Black > > (tilcdc + tda998x) to resolve an issue with out of spec syncs from the > > tlcdc. I invert the HSYNC in adj_mode->flags but don't want the tda998x to > > really know that I am doing that so I use adj_mode in the tilcdc driver, and > > mode here in the tda998x driver. The theory being adj_mode contains > > whatever > > workarounds I need to do for the driving device and mode has the pristine > > values that I want to send to the monitor. I would need to look if there > > is a > > different way to solve this as I am guessing you are actually using > > adj_mode in > > the manner it was intended. > > No. In fact, I just wanted the function to use only one mode. > > Looking at the other drivers, it seems that they don't touch the > adjusted_mode, so, for the Cubox, mode and adjusted_mode have same > values. > > I will do an other patch so that you will not have to touch the tilcdc > driver. > Thanks, that would certainly be the easiest path to avoid the regression given the other drivers that use tda998x don't currently use adj_mode. However I don't disagree with your reasoning, it would make sense to only use values from one of the strctures and not a mix and match. Anybody looking at only the tda998x driver would be confused :) I'll work on finding a different solution for this. > -- > Ken ar c'henta? | ** Breizh ha Linux atav! ** > Jef | http://moinejf.free.fr/
[PATCH v3 07/24] drm/i2c: tda998x: set the video mode from the adjusted value
Jean-Francois Moine wrote on Sun [2014-Jan-19 19:58:40 +0100]: > This patch uses always the adjusted video mode instead of a mix of > original and adjusted mode. > > Signed-off-by: Jean-Francois Moine > --- > drivers/gpu/drm/i2c/tda998x_drv.c | 66 > +++ > 1 file changed, 33 insertions(+), 33 deletions(-) > > diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c > b/drivers/gpu/drm/i2c/tda998x_drv.c > index b688801..5d82301 100644 > --- a/drivers/gpu/drm/i2c/tda998x_drv.c > +++ b/drivers/gpu/drm/i2c/tda998x_drv.c > @@ -773,7 +773,7 @@ tda998x_encoder_mode_valid(struct drm_encoder *encoder, > static void > tda998x_encoder_mode_set(struct drm_encoder *encoder, > struct drm_display_mode *mode, > - struct drm_display_mode *adjusted_mode) > + struct drm_display_mode *adj_mode) > { > struct tda998x_priv *priv = to_tda998x_priv(encoder); > uint16_t ref_pix, ref_line, n_pix, n_line; > @@ -802,13 +802,13 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, >* So we add +1 to all horizontal and vertical register values, >* plus an additional +3 for REFPIX as we are using RGB input only. >*/ > - n_pix= mode->htotal; > - n_line = mode->vtotal; > + n_pix= adj_mode->htotal; > + n_line = adj_mode->vtotal; > > - hs_pix_e = mode->hsync_end - mode->hdisplay; > - hs_pix_s = mode->hsync_start - mode->hdisplay; > - de_pix_e = mode->htotal; > - de_pix_s = mode->htotal - mode->hdisplay; > + hs_pix_e = adj_mode->hsync_end - adj_mode->hdisplay; > + hs_pix_s = adj_mode->hsync_start - adj_mode->hdisplay; > + de_pix_e = adj_mode->htotal; > + de_pix_s = adj_mode->htotal - adj_mode->hdisplay; > ref_pix = 3 + hs_pix_s; > > /* > @@ -816,37 +816,38 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, >* those to adjust the position of the rising VS edge by adding >* HSKEW to ref_pix. >*/ > - if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW) > - ref_pix += adjusted_mode->hskew; > + if (adj_mode->flags & DRM_MODE_FLAG_HSKEW) > + ref_pix += adj_mode->hskew; > > - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) { > - ref_line = 1 + mode->vsync_start - mode->vdisplay; > - vwin1_line_s = mode->vtotal - mode->vdisplay - 1; > - vwin1_line_e = vwin1_line_s + mode->vdisplay; > + if ((adj_mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) { > + ref_line = 1 + adj_mode->vsync_start - adj_mode->vdisplay; > + vwin1_line_s = adj_mode->vtotal - adj_mode->vdisplay - 1; > + vwin1_line_e = vwin1_line_s + adj_mode->vdisplay; > vs1_pix_s= vs1_pix_e = hs_pix_s; > - vs1_line_s = mode->vsync_start - mode->vdisplay; > + vs1_line_s = adj_mode->vsync_start - adj_mode->vdisplay; > vs1_line_e = vs1_line_s + > -mode->vsync_end - mode->vsync_start; > +adj_mode->vsync_end - adj_mode->vsync_start; > vwin2_line_s = vwin2_line_e = 0; > vs2_pix_s= vs2_pix_e = 0; > vs2_line_s = vs2_line_e = 0; > } else { > - ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2; > - vwin1_line_s = (mode->vtotal - mode->vdisplay)/2; > - vwin1_line_e = vwin1_line_s + mode->vdisplay/2; > + ref_line = 1 + (adj_mode->vsync_start - > + adj_mode->vdisplay)/2; > + vwin1_line_s = (adj_mode->vtotal - adj_mode->vdisplay)/2; > + vwin1_line_e = vwin1_line_s + adj_mode->vdisplay/2; > vs1_pix_s= vs1_pix_e = hs_pix_s; > - vs1_line_s = (mode->vsync_start - mode->vdisplay)/2; > + vs1_line_s = (adj_mode->vsync_start - adj_mode->vdisplay)/2; > vs1_line_e = vs1_line_s + > -(mode->vsync_end - mode->vsync_start)/2; > - vwin2_line_s = vwin1_line_s + mode->vtotal/2; > - vwin2_line_e = vwin2_line_s + mode->vdisplay/2; > - vs2_pix_s= vs2_pix_e = hs_pix_s + mode->htotal/2; > - vs2_line_s = vs1_line_s + mode->vtotal/2 ; > +(adj_mode->vsync_end - adj_mode->vsync_start)/2; > + vwin2_line_s = vwin1_line_s + adj_mode->vtotal/2; > + vwin2_line_e = vwin2_line_s + adj_mode->vdisplay/2; > + vs2_pix_s= vs2_pix_e = hs_pix_s + adj_mode->htotal/2; > + vs2_line_s = vs1_line_s + adj_mode->vtotal/2 ; > vs2_line_e = vs2_line_s + > -(mode->vsync_end - mode->vsync_start)/2; > +(adj_mode->vsync_end - adj_mode->vsync_start)/2; > } > > -
[PATCH 0/8] Several NXP TDA998x patches
Sebastian Hesselbarth wrote on Tue [2013-Aug-06 00:20:10 +0200]: > This patch set picks up several patches sent during the past months > related with NXP TDA998x HDMI transmitter driver. The patches have > been tested on Marvell Dove (Armada DRM) on several HDMI modes with > audio playing on S/PDIF. I have also quickly tested on Beaglebone > Black (tilcdc) for one DVI mode. > > As I squashed some patches and fixed some audio issues, it would > be great to have a formal Tested-by or Acked-by from Russell and > Darren for the whole patch set. > Sebastian, Looks good to me, I tried this series with all the known "problem" modes on the BeagleBone Black and they are working correctly now. I should just state for the record that I have so far tested DVI mode (no audio) and only boot time mode setting but this is all we have been using from the original mainline NXP/tilcdc drm drivers anyway. So for the series: Tested-by: Darren Etheridge Darren
Re: [PATCH 0/8] Several NXP TDA998x patches
Sebastian Hesselbarth wrote on Tue [2013-Aug-06 00:20:10 +0200]: > This patch set picks up several patches sent during the past months > related with NXP TDA998x HDMI transmitter driver. The patches have > been tested on Marvell Dove (Armada DRM) on several HDMI modes with > audio playing on S/PDIF. I have also quickly tested on Beaglebone > Black (tilcdc) for one DVI mode. > > As I squashed some patches and fixed some audio issues, it would > be great to have a formal Tested-by or Acked-by from Russell and > Darren for the whole patch set. > Sebastian, Looks good to me, I tried this series with all the known "problem" modes on the BeagleBone Black and they are working correctly now. I should just state for the record that I have so far tested DVI mode (no audio) and only boot time mode setting but this is all we have been using from the original mainline NXP/tilcdc drm drivers anyway. So for the series: Tested-by: Darren Etheridge Darren ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/2] drm/tilcdc drm/i2c/tda998x workaround for sync issues on TI SoC
Sebastian Hesselbarth wrote on Wed [2013-Jul-31 22:21:20 +0200]: > Darren, > > I now fully understand the issues of AM335x's LCD controller and your > fix for it. I suggest to clarify the comments you added to tilcdc to > allow others to understand it more quickly. > Sebastian, Thanks for looking at my proposed changes, you understand this sync stuff very well so I appreciate your input that this is actually an acceptable workaround. > Actually, the LCD controller always aligns vsync to the second edge > of hsync, which will never give VESA-compliant sync. The (elegant) > workaround you are proposing is to align both rising edges, so at > least TDA998x can sync on those with some hskew added. Lucky you that > it ignores hsync length but only looks for rising HS/VS edges ;) Yes we definitely got lucky with this one, good thing the NXP supported that reference pixel position, as I was out of options from the lcd controller side of things to adjust the horizontal position. > > Should we prepare a new patch set comprising the following patches? > > Russell King: > drm/i2c: nxp-tda998x: fix EDID reading on TDA19988 devices > drm/i2c: nxp-tda998x: ensure VIP output mux is properly set > drm/i2c: nxp-tda998x: fix npix/nline programming > drm/i2c: nxp-tda998x: prepare for video input configuration > drm/i2c: nxp-tda998x: add video and audio input configuration > > Sebastian Hesselbarth: > drm/i2c: tda998x: fix sync generation and calculation > > Darren Etheridge: > drm/i2c/tda998x prepare for tilcdc sync workaround > drm/tilcdc fixup mode to workaound sync for tda998x > > Or do we keep them separated and possibly resend them if David cannot > find them anymore? I vote we submit a complete series that we can all test, there were quite a lot of versions of things in flight at the same time so I am sure David would appreciate a consolidated version. The only thing I have not tested is audio support, but as the original driver did not have that anyway I don't consider it blocking if it is working for CuBox. Darren
Re: [PATCH 0/2] drm/tilcdc drm/i2c/tda998x workaround for sync issues on TI SoC
Sebastian Hesselbarth wrote on Wed [2013-Jul-31 22:21:20 +0200]: > Darren, > > I now fully understand the issues of AM335x's LCD controller and your > fix for it. I suggest to clarify the comments you added to tilcdc to > allow others to understand it more quickly. > Sebastian, Thanks for looking at my proposed changes, you understand this sync stuff very well so I appreciate your input that this is actually an acceptable workaround. > Actually, the LCD controller always aligns vsync to the second edge > of hsync, which will never give VESA-compliant sync. The (elegant) > workaround you are proposing is to align both rising edges, so at > least TDA998x can sync on those with some hskew added. Lucky you that > it ignores hsync length but only looks for rising HS/VS edges ;) Yes we definitely got lucky with this one, good thing the NXP supported that reference pixel position, as I was out of options from the lcd controller side of things to adjust the horizontal position. > > Should we prepare a new patch set comprising the following patches? > > Russell King: > drm/i2c: nxp-tda998x: fix EDID reading on TDA19988 devices > drm/i2c: nxp-tda998x: ensure VIP output mux is properly set > drm/i2c: nxp-tda998x: fix npix/nline programming > drm/i2c: nxp-tda998x: prepare for video input configuration > drm/i2c: nxp-tda998x: add video and audio input configuration > > Sebastian Hesselbarth: > drm/i2c: tda998x: fix sync generation and calculation > > Darren Etheridge: > drm/i2c/tda998x prepare for tilcdc sync workaround > drm/tilcdc fixup mode to workaound sync for tda998x > > Or do we keep them separated and possibly resend them if David cannot > find them anymore? I vote we submit a complete series that we can all test, there were quite a lot of versions of things in flight at the same time so I am sure David would appreciate a consolidated version. The only thing I have not tested is audio support, but as the original driver did not have that anyway I don't consider it blocking if it is working for CuBox. Darren ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/2] drm/tilcdc fixup mode to workaound sync for tda998x
Add a fixup function that will flip the hsync priority and add a hskew value that is used to shift the tda998x to the right by a variable number of pixels depending on the mode. This works around an issue with the sync timings that tilcdc is outputing. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c |7 ++- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 21 - 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 6118651..1c10bf1 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -377,7 +377,12 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, else tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); - if (mode->flags & DRM_MODE_FLAG_NHSYNC) + /* +* use value from adjusted_mode here as this might have been +* changed as part of the fixup for NXP TDA998x to solve the +* issue where tilcdc timings are not VESA compliant +*/ + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); else tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index dfffaf0..d5197a3 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -73,13 +73,32 @@ static void slave_encoder_prepare(struct drm_encoder *encoder) tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info); } +static bool slave_encoder_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + adjusted_mode->hskew = mode->hsync_end - mode->hsync_start; + adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW; + + if (mode->flags & DRM_MODE_FLAG_NHSYNC) { + adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; + } else { + adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC; + } + + return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode); +} + + static const struct drm_encoder_funcs slave_encoder_funcs = { .destroy= slave_encoder_destroy, }; static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { .dpms = drm_i2c_encoder_dpms, - .mode_fixup = drm_i2c_encoder_mode_fixup, + .mode_fixup = slave_encoder_fixup, .prepare= slave_encoder_prepare, .commit = drm_i2c_encoder_commit, .mode_set = drm_i2c_encoder_mode_set, -- 1.7.0.4
[PATCH 1/2] drm/i2c/tda998x prepare for tilcdc sync workaround
Add necessary support for flipping the hsync signal and shifting the display to the right by a certain number of pixels. Changes only take effect if adjusted_mode is changed in fixup function. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/i2c/tda998x_drv.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index e384b59..ad870e6 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -778,6 +778,16 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, n_line = mode->vtotal; ref_pix = 3 + mode->hsync_start - mode->hdisplay; + + /* +* handle issue on TILCDC where it is outputing +* non-VESA compliant sync signals the workaround +* forces us to invert the HSYNC, so need to adjust display to +* the left by hskew pixels, provided by the tilcdc driver +*/ + if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW) + ref_pix += adjusted_mode->hskew; + de_pix_s = mode->htotal - mode->hdisplay; de_pix_e = de_pix_s + mode->hdisplay; hs_pix_s = mode->hsync_start - mode->hdisplay; -- 1.7.0.4
[PATCH 0/2] drm/tilcdc drm/i2c/tda998x workaround for sync issues on TI SoC
Russell King and Sebastian Hasselbarth had proposed some very good changes for the tda998x HDMI encoder driver. But when those changes were tested on BeagleBone Black against the tilcdc driver many modes would no longer display correctly. After analyzing the sync signals from the TI lcd contoller to the nxp it is apparent that the hsync/vsync's are not rising at the same time as per the VESA spec and this is causing the HDMI encoder to get messed up and failing to lock correctly. This series of patches should be applied on top of: Russell King's rmk's Dove DRM/TDA19988 Cubox driver series Sebastian Hasselbarth's drm/i2c: tda998x: fix sync generation and calculation I have done as much of the change as I can in the tilcdc driver but there is a small unavoidable change in the tda998x driver. However I have been careful not to break anything from the Dove drivers perspective. It would be great if somebody can test on Cubox and confirm that. This patch set inverts the hsync signal coming from the tilcdc so the NXP is kept happy and then shifts the output to the right to compensate for the sync timing issues. Display modes from the NXP have been verified using a HDMI analyzer and are reporting correct timings at the output stage. Hopefully this will allow the dove/tda driver changes to progress now that were blocked as per this discussion: http://lists.freedesktop.org/archives/dri-devel/2013-July/040900.html Darren Etheridge (2): drm/i2c/tda998x prepare for tilcdc sync workaround drm/tilcdc fixup mode to workaound sync for tda998x drivers/gpu/drm/i2c/tda998x_drv.c | 10 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c |7 ++- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 21 - 3 files changed, 36 insertions(+), 2 deletions(-)
[PATCH 2/2] drm/tilcdc fixup mode to workaound sync for tda998x
Add a fixup function that will flip the hsync priority and add a hskew value that is used to shift the tda998x to the right by a variable number of pixels depending on the mode. This works around an issue with the sync timings that tilcdc is outputing. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c |7 ++- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 21 - 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 6118651..1c10bf1 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -377,7 +377,12 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, else tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); - if (mode->flags & DRM_MODE_FLAG_NHSYNC) + /* +* use value from adjusted_mode here as this might have been +* changed as part of the fixup for NXP TDA998x to solve the +* issue where tilcdc timings are not VESA compliant +*/ + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); else tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index dfffaf0..d5197a3 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -73,13 +73,32 @@ static void slave_encoder_prepare(struct drm_encoder *encoder) tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info); } +static bool slave_encoder_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + adjusted_mode->hskew = mode->hsync_end - mode->hsync_start; + adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW; + + if (mode->flags & DRM_MODE_FLAG_NHSYNC) { + adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; + } else { + adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC; + } + + return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode); +} + + static const struct drm_encoder_funcs slave_encoder_funcs = { .destroy= slave_encoder_destroy, }; static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { .dpms = drm_i2c_encoder_dpms, - .mode_fixup = drm_i2c_encoder_mode_fixup, + .mode_fixup = slave_encoder_fixup, .prepare= slave_encoder_prepare, .commit = drm_i2c_encoder_commit, .mode_set = drm_i2c_encoder_mode_set, -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm/i2c/tda998x prepare for tilcdc sync workaround
Add necessary support for flipping the hsync signal and shifting the display to the right by a certain number of pixels. Changes only take effect if adjusted_mode is changed in fixup function. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/i2c/tda998x_drv.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index e384b59..ad870e6 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -778,6 +778,16 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, n_line = mode->vtotal; ref_pix = 3 + mode->hsync_start - mode->hdisplay; + + /* +* handle issue on TILCDC where it is outputing +* non-VESA compliant sync signals the workaround +* forces us to invert the HSYNC, so need to adjust display to +* the left by hskew pixels, provided by the tilcdc driver +*/ + if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW) + ref_pix += adjusted_mode->hskew; + de_pix_s = mode->htotal - mode->hdisplay; de_pix_e = de_pix_s + mode->hdisplay; hs_pix_s = mode->hsync_start - mode->hdisplay; -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/2] drm/tilcdc drm/i2c/tda998x workaround for sync issues on TI SoC
Russell King and Sebastian Hasselbarth had proposed some very good changes for the tda998x HDMI encoder driver. But when those changes were tested on BeagleBone Black against the tilcdc driver many modes would no longer display correctly. After analyzing the sync signals from the TI lcd contoller to the nxp it is apparent that the hsync/vsync's are not rising at the same time as per the VESA spec and this is causing the HDMI encoder to get messed up and failing to lock correctly. This series of patches should be applied on top of: Russell King's rmk's Dove DRM/TDA19988 Cubox driver series Sebastian Hasselbarth's drm/i2c: tda998x: fix sync generation and calculation I have done as much of the change as I can in the tilcdc driver but there is a small unavoidable change in the tda998x driver. However I have been careful not to break anything from the Dove drivers perspective. It would be great if somebody can test on Cubox and confirm that. This patch set inverts the hsync signal coming from the tilcdc so the NXP is kept happy and then shifts the output to the right to compensate for the sync timing issues. Display modes from the NXP have been verified using a HDMI analyzer and are reporting correct timings at the output stage. Hopefully this will allow the dove/tda driver changes to progress now that were blocked as per this discussion: http://lists.freedesktop.org/archives/dri-devel/2013-July/040900.html Darren Etheridge (2): drm/i2c/tda998x prepare for tilcdc sync workaround drm/tilcdc fixup mode to workaound sync for tda998x drivers/gpu/drm/i2c/tda998x_drv.c | 10 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c |7 ++- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 21 - 3 files changed, 36 insertions(+), 2 deletions(-) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH V2 0/7] drm/tilcdc: bug fixes, mode selection improvements
Rob Clark wrote on Wed [2013-Jun-26 11:42:44 -0400]: > On Fri, Jun 21, 2013 at 2:52 PM, Darren Etheridge > wrote: > > The series of patches that follow are intended to address issues that > > have been found in the tilcdc drm driver. The patchset enables support > > for screen resolutions with horizontal resolutions greater than 1024 > > pixels. The patchset also addresses a limitation where certain > > monitor timings would overflow LCD controller timing registers causing > > either no monitor signal or a very corrupted display. This patchset > > will stop monitor modes from being reported as valid if the lcd > > controller cannot support them. > > > > V2: > > Fix typos in commit messages > > Add a patch that enables runtime modesetting to work correctly > > Fix an issue where the slave encoder can initialize before the i2c > > subsystem, resulting in no displays being configured. > > > for the series: > Acked-by: Rob Clark > > the i2c/slave race thing.. well, isn't pretty.. but right now I don't > see a better way. I guess at some point we need to revisit how the > encoder-slave stuff gets loaded in drm > Thanks Rob. Yes I agree with your assessment, I looked at using the module list as a way to indicate if a given module is deferred or not but this had its own difficulties. This patch was the easiest way to defer the probing at the earliest possible point for both the slave module and the main tilcdc driver. Reordering the drivers/Makefile was the other suggestion that was given. By moving the Makefile drm entry to a point after the i2c entry the order that the initilization happens is changed. This certainly appeared to work when I tried it. However I was really concerned that this would have horrible side effects for drivers that I had no knowledge about and no way of testing. So my provided solution while not elegant its impact is at least localized to the tilcdc driver. Darren
Re: [PATCH V2 0/7] drm/tilcdc: bug fixes, mode selection improvements
Rob Clark wrote on Wed [2013-Jun-26 11:42:44 -0400]: > On Fri, Jun 21, 2013 at 2:52 PM, Darren Etheridge wrote: > > The series of patches that follow are intended to address issues that > > have been found in the tilcdc drm driver. The patchset enables support > > for screen resolutions with horizontal resolutions greater than 1024 > > pixels. The patchset also addresses a limitation where certain > > monitor timings would overflow LCD controller timing registers causing > > either no monitor signal or a very corrupted display. This patchset > > will stop monitor modes from being reported as valid if the lcd > > controller cannot support them. > > > > V2: > > Fix typos in commit messages > > Add a patch that enables runtime modesetting to work correctly > > Fix an issue where the slave encoder can initialize before the i2c > > subsystem, resulting in no displays being configured. > > > for the series: > Acked-by: Rob Clark > > the i2c/slave race thing.. well, isn't pretty.. but right now I don't > see a better way. I guess at some point we need to revisit how the > encoder-slave stuff gets loaded in drm > Thanks Rob. Yes I agree with your assessment, I looked at using the module list as a way to indicate if a given module is deferred or not but this had its own difficulties. This patch was the easiest way to defer the probing at the earliest possible point for both the slave module and the main tilcdc driver. Reordering the drivers/Makefile was the other suggestion that was given. By moving the Makefile drm entry to a point after the i2c entry the order that the initilization happens is changed. This certainly appeared to work when I tried it. However I was really concerned that this would have horrible side effects for drivers that I had no knowledge about and no way of testing. So my provided solution while not elegant its impact is at least localized to the tilcdc driver. Darren ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH V2 7/7] drm/tilcdc: Clear bits of register we're going to set.
From: Pantelis Antoniou Bits weren't cleared so resolution changes didn't work. Signed-off-by: Pantelis Antoniou Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 6118651..eb06f70 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -299,6 +299,8 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, * a value of 0 as 1 */ if (priv->rev == 2) { + /* clear bits we're going to set */ + reg &= ~0x7833; reg |= ((hfp-1) & 0x300) >> 8; reg |= ((hbp-1) & 0x300) >> 4; reg |= ((hsw-1) & 0x3c0) << 21; -- 1.7.0.4
[PATCH V2 6/7] drm/tilcdc fixing i2c/slave initialization race
In certain senarios drm will initialize before i2c this means that i2c slave devices like the nxp tda998x will fail to be probed. This patch detects this condition then defers the probe of the slave device and the tilcdc main driver. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 10 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.h |2 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 53 ++--- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 1e8f273..40b71da 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -26,6 +26,7 @@ #include "drm_fb_helper.h" static LIST_HEAD(module_list); +static bool slave_probing; void tilcdc_module_init(struct tilcdc_module *mod, const char *name, const struct tilcdc_module_ops *funcs) @@ -41,6 +42,11 @@ void tilcdc_module_cleanup(struct tilcdc_module *mod) list_del(&mod->list); } +void tilcdc_slave_probedefer(bool defered) +{ + slave_probing = defered; +} + static struct of_device_id tilcdc_of_match[]; static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev, @@ -580,6 +586,10 @@ static int tilcdc_pdev_probe(struct platform_device *pdev) return -ENXIO; } + /* defer probing if slave is in deferred probing */ + if (slave_probing == true) + return -EPROBE_DEFER; + return drm_platform_init(&tilcdc_driver, pdev); } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 66df316..0938036 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -117,7 +117,7 @@ struct tilcdc_module { void tilcdc_module_init(struct tilcdc_module *mod, const char *name, const struct tilcdc_module_ops *funcs); void tilcdc_module_cleanup(struct tilcdc_module *mod); - +void tilcdc_slave_probedefer(bool defered); /* Panel config that needs to be set in the crtc, but is not coming from * the mode timings. The display module is expected to call diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index 8bf4fd1..dfffaf0 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -298,6 +298,7 @@ static int slave_probe(struct platform_device *pdev) struct tilcdc_module *mod; struct pinctrl *pinctrl; uint32_t i2c_phandle; + struct i2c_adapter *slavei2c; int ret = -EINVAL; /* bail out early if no DT data: */ @@ -306,44 +307,48 @@ static int slave_probe(struct platform_device *pdev) return -ENXIO; } - slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); - if (!slave_mod) - return -ENOMEM; - - mod = &slave_mod->base; - - tilcdc_module_init(mod, "slave", &slave_module_ops); - - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, "pins are not configured\n"); - + /* Bail out early if i2c not specified */ if (of_property_read_u32(node, "i2c", &i2c_phandle)) { dev_err(&pdev->dev, "could not get i2c bus phandle\n"); - goto fail; + return ret; } - mod->preferred_bpp = slave_info.bpp; - i2c_node = of_find_node_by_phandle(i2c_phandle); if (!i2c_node) { dev_err(&pdev->dev, "could not get i2c bus node\n"); - goto fail; + return ret; } - slave_mod->i2c = of_find_i2c_adapter_by_node(i2c_node); - if (!slave_mod->i2c) { + /* but defer the probe if it can't be initialized it might come later */ + slavei2c = of_find_i2c_adapter_by_node(i2c_node); + of_node_put(i2c_node); + + if (!slavei2c) { + ret = -EPROBE_DEFER; + tilcdc_slave_probedefer(true); dev_err(&pdev->dev, "could not get i2c\n"); - goto fail; + return ret; } - of_node_put(i2c_node); + slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); + if (!slave_mod) + return -ENOMEM; - return 0; + mod = &slave_mod->base; -fail: - slave_destroy(mod); - return ret; + mod->preferred_bpp = slave_info.bpp; + + slave_mod->i2c = slavei2c; + + tilcdc_module_init(mod, "slave", &slave_module_ops); + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_warn(&pdev->dev, "pins are not configured\n"); + + tilcdc_slave_probedefer(false); + + return 0; } static int slave_remove(struct platform_device *pdev) -- 1.7.0.4
[PATCH V2 5/7] drm/tilcdc: whitespace fixes and tidyup
keeping checkpatch happy. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 16 ++-- 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 283e0a6..6118651 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -42,7 +42,8 @@ struct tilcdc_crtc { static void unref_worker(struct work_struct *work) { - struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work); + struct tilcdc_crtc *tilcdc_crtc = + container_of(work, struct tilcdc_crtc, work); struct drm_device *dev = tilcdc_crtc->base.dev; struct drm_framebuffer *fb; @@ -55,10 +56,12 @@ static void unref_worker(struct work_struct *work) static void set_scanout(struct drm_crtc *crtc, int n) { static const uint32_t base_reg[] = { - LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG, + LCDC_DMA_FB_BASE_ADDR_0_REG, + LCDC_DMA_FB_BASE_ADDR_1_REG, }; static const uint32_t ceil_reg[] = { - LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG, + LCDC_DMA_FB_CEILING_ADDR_0_REG, + LCDC_DMA_FB_CEILING_ADDR_1_REG, }; static const uint32_t stat[] = { LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1, @@ -194,7 +197,8 @@ static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode) tilcdc_crtc->frame_done = false; stop(crtc); - /* if necessary wait for framedone irq which will still come + /* +* if necessary wait for framedone irq which will still come * before putting things to sleep.. */ if (priv->rev == 2) { @@ -504,7 +508,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) * configured from the DT */ if (mode->clock > priv->max_pixelclock) { - DBG("Pruning mode, pixel clock too high"); + DBG("Pruning mode: pixel clock too high"); return MODE_CLOCK_HIGH; } @@ -519,7 +523,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); if (bandwidth > priv->max_bandwidth) { - DBG("Pruning mode, exceeds defined bandwidth limit"); + DBG("Pruning mode: exceeds defined bandwidth limit"); return MODE_BAD; } -- 1.7.0.4
[PATCH V2 4/7] drm/tilcdc: adding more guards to prevent selection of invalid modes
The tilcdc has a number of limitations for the allowed sizes of the various adjustable timing parameter. Some modes are outside of these timings. This commit will prune modes that report timings that will overflow the allowed sizes in the tilcdc. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 46 ++ 1 files changed, 46 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 4455a41..283e0a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -442,7 +442,12 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = crtc->dev->dev_private; unsigned int bandwidth; + uint32_t hbp, hfp, hsw, vbp, vfp, vsw; + /* +* check to see if the width is within the range that +* the LCD Controller physically supports +*/ if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) return MODE_VIRTUAL_X; @@ -453,6 +458,47 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + DBG("Processing mode %dx%d@%d with pixel clock %d", + mode->hdisplay, mode->vdisplay, + drm_mode_vrefresh(mode), mode->clock); + + hbp = mode->htotal - mode->hsync_end; + hfp = mode->hsync_start - mode->hdisplay; + hsw = mode->hsync_end - mode->hsync_start; + vbp = mode->vtotal - mode->vsync_end; + vfp = mode->vsync_start - mode->vdisplay; + vsw = mode->vsync_end - mode->vsync_start; + + if ((hbp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Back Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hfp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Front Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hsw-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Sync Width out of range"); + return MODE_HSYNC_WIDE; + } + + if (vbp & ~0xff) { + DBG("Pruning mode: Vertical Back Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if (vfp & ~0xff) { + DBG("Pruning mode: Vertical Front Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if ((vsw-1) & ~0x3f) { + DBG("Pruning mode: Vertical Sync Width out of range"); + return MODE_VSYNC_WIDE; + } + /* * some devices have a maximum allowed pixel clock * configured from the DT -- 1.7.0.4
[PATCH V2 3/7] drm/tilcdc: fixing off by one errors found on analyzer
When hooking up to an HDMI analyzer noticed some timings were off by one. Referring to the hardware technical reference manual for the lcd controller some of the timing registers use 0 to represent 1. This patch addresses that issue. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 19 --- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 05f2b14..4455a41 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -289,17 +289,22 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); + + /* +* subtract one from hfp, hbp, hsw because the hardware uses +* a value of 0 as 1 +*/ if (priv->rev == 2) { - reg |= (hfp & 0x300) >> 8; - reg |= (hbp & 0x300) >> 4; - reg |= (hsw & 0x3c0) << 21; + reg |= ((hfp-1) & 0x300) >> 8; + reg |= ((hbp-1) & 0x300) >> 4; + reg |= ((hsw-1) & 0x3c0) << 21; } tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg); reg = (((mode->hdisplay >> 4) - 1) << 4) | - ((hbp & 0xff) << 24) | - ((hfp & 0xff) << 16) | - ((hsw & 0x3f) << 10); + (((hbp-1) & 0xff) << 24) | + (((hfp-1) & 0xff) << 16) | + (((hsw-1) & 0x3f) << 10); if (priv->rev == 2) reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg); @@ -307,7 +312,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = ((mode->vdisplay - 1) & 0x3ff) | ((vbp & 0xff) << 24) | ((vfp & 0xff) << 16) | - ((vsw & 0x3f) << 10); + (((vsw-1) & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); /* -- 1.7.0.4
[PATCH V2 2/7] drm/tilcdc: adding some more devicetree config
Adding support for max-pixelclock and max-width device tree entries. As some devices that use the tilcdc hardware module have restrictions on the allowed/tested values. Also update DT bindings document to reflect new parameters. Signed-off-by: Darren Etheridge --- .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 +++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 23 ++- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 - drivers/gpu/drm/tilcdc/tilcdc_drv.h| 22 +++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt index e5f1301..fff10da 100644 --- a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt +++ b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt @@ -10,6 +10,14 @@ Recommended properties: services interrupts for this device. - ti,hwmods: Name of the hwmod associated to the LCDC +Optional properties: + - max-bandwidth: The maximum pixels per second that the memory + interface / lcd controller combination can sustain + - max-width: The maximum horizontal pixel width supported by + the lcd controller. + - max-pixelclock: The maximum pixel clock that can be supported + by the lcd controller in KHz. + Example: fb: fb at 4830e000 { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 84fdf25..05f2b14 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -448,10 +448,29 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + /* +* some devices have a maximum allowed pixel clock +* configured from the DT +*/ + if (mode->clock > priv->max_pixelclock) { + DBG("Pruning mode, pixel clock too high"); + return MODE_CLOCK_HIGH; + } + + /* +* some devices further limit the max horizontal resolution +* configured from the DT +*/ + if (mode->hdisplay > priv->max_width) + return MODE_BAD_WIDTH; + /* filter out modes that would require too much memory bandwidth: */ - bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); - if (bandwidth > priv->max_bandwidth) + bandwidth = mode->hdisplay * mode->vdisplay * + drm_mode_vrefresh(mode); + if (bandwidth > priv->max_bandwidth) { + DBG("Pruning mode, exceeds defined bandwidth limit"); return MODE_BAD; + } return MODE_OK; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index f2a6528..1e8f273 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -212,7 +212,20 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) #endif if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth)) - priv->max_bandwidth = 1280 * 1024 * 60; + priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH; + + DBG("Maximum Bandwidth Value %d", priv->max_bandwidth); + + if (of_property_read_u32(node, "ti,max-width", &priv->max_width)) + priv->max_width = TILCDC_DEFAULT_MAX_WIDTH; + + DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width); + + if (of_property_read_u32(node, "ti,max-pixelclock", + &priv->max_pixelclock)) + priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK; + + DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock); pm_runtime_enable(dev->dev); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 0906843..66df316 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -34,6 +34,18 @@ #include #include +/* Defaulting to pixel clock defined on AM335x */ +#define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000 +/* Defaulting to max width as defined on AM335x */ +#define TILCDC_DEFAULT_MAX_WIDTH 2048 +/* + * This may need some tweaking, but want to allow at least 1280x1024 at 60 + * with optimized DDR & EMIF settings tweaked 1920x1080 at 24 appears to + * be supportable + */ +#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) + + struct tilcdc_drm_private { void __iomem *mmio; @@ -43,6 +55,16 @@ struct tilcdc_drm_private { /* don't attempt resolutions w/ higher W * H * Hz: */ uint32_t max_bandwidth; + /* +* Pixel Clock will be restricted to some value
[PATCH V2 1/7] drm/tilcdc: support pixel widths greater than 1024
TI LCD controller version 2 has an extended eleventh bit that enables horizontal resolutions greater than 1024 pixels to be specified (upto 2048). This patch adds support for setting this bit on LCDC V2. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 +++ drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 5dd3c7d..84fdf25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -310,6 +310,21 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, ((vsw & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); + /* +* be sure to set Bit 10 for the V2 LCDC controller, +* otherwise limited to 1024 pixels width, stopping +* 1920x1080 being suppoted. +*/ + if (priv->rev == 2) { + if ((mode->vdisplay - 1) & 0x400) { + tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } else { + tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } + } + /* Configure display type: */ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h index 17fd1b4..1bf5e25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h @@ -80,6 +80,7 @@ #define LCDC_INVERT_PIXEL_CLOCK BIT(22) #define LCDC_INVERT_HSYNCBIT(21) #define LCDC_INVERT_VSYNCBIT(20) +#define LCDC_LPP_B10 BIT(26) /* LCDC Block */ #define LCDC_PID_REG 0x0 -- 1.7.0.4
[PATCH V2 0/7] drm/tilcdc: bug fixes, mode selection improvements
The series of patches that follow are intended to address issues that have been found in the tilcdc drm driver. The patchset enables support for screen resolutions with horizontal resolutions greater than 1024 pixels. The patchset also addresses a limitation where certain monitor timings would overflow LCD controller timing registers causing either no monitor signal or a very corrupted display. This patchset will stop monitor modes from being reported as valid if the lcd controller cannot support them. V2: Fix typos in commit messages Add a patch that enables runtime modesetting to work correctly Fix an issue where the slave encoder can initialize before the i2c subsystem, resulting in no displays being configured. Applies cleanly on drm-next. Darren Etheridge (6): drm/tilcdc: support pixel widths greater than 1024 drm/tilcdc: adding some more devicetree config drm/tilcdc: fixing off by one errors found on analyzer drm/tilcdc: adding more guards to prevent selection of invalid modes drm/tilcdc: whitespace fixes and tidyup drm/tilcdc fixing i2c/slave initialization race Pantelis Antoniou (1): drm/tilcdc: Clear bits of register we're going to set. .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 117 +-- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 25 - drivers/gpu/drm/tilcdc/tilcdc_drv.h| 24 - drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 53 + 6 files changed, 189 insertions(+), 39 deletions(-)
[PATCH V2 7/7] drm/tilcdc: Clear bits of register we're going to set.
From: Pantelis Antoniou Bits weren't cleared so resolution changes didn't work. Signed-off-by: Pantelis Antoniou Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 6118651..eb06f70 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -299,6 +299,8 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, * a value of 0 as 1 */ if (priv->rev == 2) { + /* clear bits we're going to set */ + reg &= ~0x7833; reg |= ((hfp-1) & 0x300) >> 8; reg |= ((hbp-1) & 0x300) >> 4; reg |= ((hsw-1) & 0x3c0) << 21; -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH V2 6/7] drm/tilcdc fixing i2c/slave initialization race
In certain senarios drm will initialize before i2c this means that i2c slave devices like the nxp tda998x will fail to be probed. This patch detects this condition then defers the probe of the slave device and the tilcdc main driver. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 10 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.h |2 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 53 ++--- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 1e8f273..40b71da 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -26,6 +26,7 @@ #include "drm_fb_helper.h" static LIST_HEAD(module_list); +static bool slave_probing; void tilcdc_module_init(struct tilcdc_module *mod, const char *name, const struct tilcdc_module_ops *funcs) @@ -41,6 +42,11 @@ void tilcdc_module_cleanup(struct tilcdc_module *mod) list_del(&mod->list); } +void tilcdc_slave_probedefer(bool defered) +{ + slave_probing = defered; +} + static struct of_device_id tilcdc_of_match[]; static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev, @@ -580,6 +586,10 @@ static int tilcdc_pdev_probe(struct platform_device *pdev) return -ENXIO; } + /* defer probing if slave is in deferred probing */ + if (slave_probing == true) + return -EPROBE_DEFER; + return drm_platform_init(&tilcdc_driver, pdev); } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 66df316..0938036 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -117,7 +117,7 @@ struct tilcdc_module { void tilcdc_module_init(struct tilcdc_module *mod, const char *name, const struct tilcdc_module_ops *funcs); void tilcdc_module_cleanup(struct tilcdc_module *mod); - +void tilcdc_slave_probedefer(bool defered); /* Panel config that needs to be set in the crtc, but is not coming from * the mode timings. The display module is expected to call diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index 8bf4fd1..dfffaf0 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -298,6 +298,7 @@ static int slave_probe(struct platform_device *pdev) struct tilcdc_module *mod; struct pinctrl *pinctrl; uint32_t i2c_phandle; + struct i2c_adapter *slavei2c; int ret = -EINVAL; /* bail out early if no DT data: */ @@ -306,44 +307,48 @@ static int slave_probe(struct platform_device *pdev) return -ENXIO; } - slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); - if (!slave_mod) - return -ENOMEM; - - mod = &slave_mod->base; - - tilcdc_module_init(mod, "slave", &slave_module_ops); - - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, "pins are not configured\n"); - + /* Bail out early if i2c not specified */ if (of_property_read_u32(node, "i2c", &i2c_phandle)) { dev_err(&pdev->dev, "could not get i2c bus phandle\n"); - goto fail; + return ret; } - mod->preferred_bpp = slave_info.bpp; - i2c_node = of_find_node_by_phandle(i2c_phandle); if (!i2c_node) { dev_err(&pdev->dev, "could not get i2c bus node\n"); - goto fail; + return ret; } - slave_mod->i2c = of_find_i2c_adapter_by_node(i2c_node); - if (!slave_mod->i2c) { + /* but defer the probe if it can't be initialized it might come later */ + slavei2c = of_find_i2c_adapter_by_node(i2c_node); + of_node_put(i2c_node); + + if (!slavei2c) { + ret = -EPROBE_DEFER; + tilcdc_slave_probedefer(true); dev_err(&pdev->dev, "could not get i2c\n"); - goto fail; + return ret; } - of_node_put(i2c_node); + slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); + if (!slave_mod) + return -ENOMEM; - return 0; + mod = &slave_mod->base; -fail: - slave_destroy(mod); - return ret; + mod->preferred_bpp = slave_info.bpp; + + slave_mod->i2c = slavei2c; + + tilcdc_module_init(mod, "slave", &slave_module_ops); + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_warn(&pdev->dev, "pins are not configured\n"); + + tilcdc_slave_probedefer(false);
[PATCH V2 5/7] drm/tilcdc: whitespace fixes and tidyup
keeping checkpatch happy. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 16 ++-- 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 283e0a6..6118651 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -42,7 +42,8 @@ struct tilcdc_crtc { static void unref_worker(struct work_struct *work) { - struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work); + struct tilcdc_crtc *tilcdc_crtc = + container_of(work, struct tilcdc_crtc, work); struct drm_device *dev = tilcdc_crtc->base.dev; struct drm_framebuffer *fb; @@ -55,10 +56,12 @@ static void unref_worker(struct work_struct *work) static void set_scanout(struct drm_crtc *crtc, int n) { static const uint32_t base_reg[] = { - LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG, + LCDC_DMA_FB_BASE_ADDR_0_REG, + LCDC_DMA_FB_BASE_ADDR_1_REG, }; static const uint32_t ceil_reg[] = { - LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG, + LCDC_DMA_FB_CEILING_ADDR_0_REG, + LCDC_DMA_FB_CEILING_ADDR_1_REG, }; static const uint32_t stat[] = { LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1, @@ -194,7 +197,8 @@ static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode) tilcdc_crtc->frame_done = false; stop(crtc); - /* if necessary wait for framedone irq which will still come + /* +* if necessary wait for framedone irq which will still come * before putting things to sleep.. */ if (priv->rev == 2) { @@ -504,7 +508,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) * configured from the DT */ if (mode->clock > priv->max_pixelclock) { - DBG("Pruning mode, pixel clock too high"); + DBG("Pruning mode: pixel clock too high"); return MODE_CLOCK_HIGH; } @@ -519,7 +523,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); if (bandwidth > priv->max_bandwidth) { - DBG("Pruning mode, exceeds defined bandwidth limit"); + DBG("Pruning mode: exceeds defined bandwidth limit"); return MODE_BAD; } -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH V2 3/7] drm/tilcdc: fixing off by one errors found on analyzer
When hooking up to an HDMI analyzer noticed some timings were off by one. Referring to the hardware technical reference manual for the lcd controller some of the timing registers use 0 to represent 1. This patch addresses that issue. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 19 --- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 05f2b14..4455a41 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -289,17 +289,22 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); + + /* +* subtract one from hfp, hbp, hsw because the hardware uses +* a value of 0 as 1 +*/ if (priv->rev == 2) { - reg |= (hfp & 0x300) >> 8; - reg |= (hbp & 0x300) >> 4; - reg |= (hsw & 0x3c0) << 21; + reg |= ((hfp-1) & 0x300) >> 8; + reg |= ((hbp-1) & 0x300) >> 4; + reg |= ((hsw-1) & 0x3c0) << 21; } tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg); reg = (((mode->hdisplay >> 4) - 1) << 4) | - ((hbp & 0xff) << 24) | - ((hfp & 0xff) << 16) | - ((hsw & 0x3f) << 10); + (((hbp-1) & 0xff) << 24) | + (((hfp-1) & 0xff) << 16) | + (((hsw-1) & 0x3f) << 10); if (priv->rev == 2) reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg); @@ -307,7 +312,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = ((mode->vdisplay - 1) & 0x3ff) | ((vbp & 0xff) << 24) | ((vfp & 0xff) << 16) | - ((vsw & 0x3f) << 10); + (((vsw-1) & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); /* -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH V2 4/7] drm/tilcdc: adding more guards to prevent selection of invalid modes
The tilcdc has a number of limitations for the allowed sizes of the various adjustable timing parameter. Some modes are outside of these timings. This commit will prune modes that report timings that will overflow the allowed sizes in the tilcdc. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 46 ++ 1 files changed, 46 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 4455a41..283e0a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -442,7 +442,12 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = crtc->dev->dev_private; unsigned int bandwidth; + uint32_t hbp, hfp, hsw, vbp, vfp, vsw; + /* +* check to see if the width is within the range that +* the LCD Controller physically supports +*/ if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) return MODE_VIRTUAL_X; @@ -453,6 +458,47 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + DBG("Processing mode %dx%d@%d with pixel clock %d", + mode->hdisplay, mode->vdisplay, + drm_mode_vrefresh(mode), mode->clock); + + hbp = mode->htotal - mode->hsync_end; + hfp = mode->hsync_start - mode->hdisplay; + hsw = mode->hsync_end - mode->hsync_start; + vbp = mode->vtotal - mode->vsync_end; + vfp = mode->vsync_start - mode->vdisplay; + vsw = mode->vsync_end - mode->vsync_start; + + if ((hbp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Back Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hfp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Front Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hsw-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Sync Width out of range"); + return MODE_HSYNC_WIDE; + } + + if (vbp & ~0xff) { + DBG("Pruning mode: Vertical Back Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if (vfp & ~0xff) { + DBG("Pruning mode: Vertical Front Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if ((vsw-1) & ~0x3f) { + DBG("Pruning mode: Vertical Sync Width out of range"); + return MODE_VSYNC_WIDE; + } + /* * some devices have a maximum allowed pixel clock * configured from the DT -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH V2 2/7] drm/tilcdc: adding some more devicetree config
Adding support for max-pixelclock and max-width device tree entries. As some devices that use the tilcdc hardware module have restrictions on the allowed/tested values. Also update DT bindings document to reflect new parameters. Signed-off-by: Darren Etheridge --- .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 +++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 23 ++- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 - drivers/gpu/drm/tilcdc/tilcdc_drv.h| 22 +++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt index e5f1301..fff10da 100644 --- a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt +++ b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt @@ -10,6 +10,14 @@ Recommended properties: services interrupts for this device. - ti,hwmods: Name of the hwmod associated to the LCDC +Optional properties: + - max-bandwidth: The maximum pixels per second that the memory + interface / lcd controller combination can sustain + - max-width: The maximum horizontal pixel width supported by + the lcd controller. + - max-pixelclock: The maximum pixel clock that can be supported + by the lcd controller in KHz. + Example: fb: fb@4830e000 { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 84fdf25..05f2b14 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -448,10 +448,29 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + /* +* some devices have a maximum allowed pixel clock +* configured from the DT +*/ + if (mode->clock > priv->max_pixelclock) { + DBG("Pruning mode, pixel clock too high"); + return MODE_CLOCK_HIGH; + } + + /* +* some devices further limit the max horizontal resolution +* configured from the DT +*/ + if (mode->hdisplay > priv->max_width) + return MODE_BAD_WIDTH; + /* filter out modes that would require too much memory bandwidth: */ - bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); - if (bandwidth > priv->max_bandwidth) + bandwidth = mode->hdisplay * mode->vdisplay * + drm_mode_vrefresh(mode); + if (bandwidth > priv->max_bandwidth) { + DBG("Pruning mode, exceeds defined bandwidth limit"); return MODE_BAD; + } return MODE_OK; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index f2a6528..1e8f273 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -212,7 +212,20 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) #endif if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth)) - priv->max_bandwidth = 1280 * 1024 * 60; + priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH; + + DBG("Maximum Bandwidth Value %d", priv->max_bandwidth); + + if (of_property_read_u32(node, "ti,max-width", &priv->max_width)) + priv->max_width = TILCDC_DEFAULT_MAX_WIDTH; + + DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width); + + if (of_property_read_u32(node, "ti,max-pixelclock", + &priv->max_pixelclock)) + priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK; + + DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock); pm_runtime_enable(dev->dev); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 0906843..66df316 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -34,6 +34,18 @@ #include #include +/* Defaulting to pixel clock defined on AM335x */ +#define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000 +/* Defaulting to max width as defined on AM335x */ +#define TILCDC_DEFAULT_MAX_WIDTH 2048 +/* + * This may need some tweaking, but want to allow at least 1280x1024@60 + * with optimized DDR & EMIF settings tweaked 1920x1080@24 appears to + * be supportable + */ +#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) + + struct tilcdc_drm_private { void __iomem *mmio; @@ -43,6 +55,16 @@ struct tilcdc_drm_private { /* don't attempt resolutions w/ higher W * H * Hz: */ uint32_t max_bandwidth; + /* +* Pixel Clock will be restricted to some value
[PATCH V2 1/7] drm/tilcdc: support pixel widths greater than 1024
TI LCD controller version 2 has an extended eleventh bit that enables horizontal resolutions greater than 1024 pixels to be specified (upto 2048). This patch adds support for setting this bit on LCDC V2. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 +++ drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 5dd3c7d..84fdf25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -310,6 +310,21 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, ((vsw & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); + /* +* be sure to set Bit 10 for the V2 LCDC controller, +* otherwise limited to 1024 pixels width, stopping +* 1920x1080 being suppoted. +*/ + if (priv->rev == 2) { + if ((mode->vdisplay - 1) & 0x400) { + tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } else { + tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } + } + /* Configure display type: */ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h index 17fd1b4..1bf5e25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h @@ -80,6 +80,7 @@ #define LCDC_INVERT_PIXEL_CLOCK BIT(22) #define LCDC_INVERT_HSYNCBIT(21) #define LCDC_INVERT_VSYNCBIT(20) +#define LCDC_LPP_B10 BIT(26) /* LCDC Block */ #define LCDC_PID_REG 0x0 -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH V2 0/7] drm/tilcdc: bug fixes, mode selection improvements
The series of patches that follow are intended to address issues that have been found in the tilcdc drm driver. The patchset enables support for screen resolutions with horizontal resolutions greater than 1024 pixels. The patchset also addresses a limitation where certain monitor timings would overflow LCD controller timing registers causing either no monitor signal or a very corrupted display. This patchset will stop monitor modes from being reported as valid if the lcd controller cannot support them. V2: Fix typos in commit messages Add a patch that enables runtime modesetting to work correctly Fix an issue where the slave encoder can initialize before the i2c subsystem, resulting in no displays being configured. Applies cleanly on drm-next. Darren Etheridge (6): drm/tilcdc: support pixel widths greater than 1024 drm/tilcdc: adding some more devicetree config drm/tilcdc: fixing off by one errors found on analyzer drm/tilcdc: adding more guards to prevent selection of invalid modes drm/tilcdc: whitespace fixes and tidyup drm/tilcdc fixing i2c/slave initialization race Pantelis Antoniou (1): drm/tilcdc: Clear bits of register we're going to set. .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 117 +-- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 25 - drivers/gpu/drm/tilcdc/tilcdc_drv.h| 24 - drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 53 + 6 files changed, 189 insertions(+), 39 deletions(-) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/5] drm/tilcdc: support pixel widths greater than 1024
TI LCD controller version 2 has an extended eleventh bit that enables horizontal resolutions greater than 1024 pixels to be specified (upto 2048). This patch adds support for setting this bit on LCDC V2. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 +++ drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 5dd3c7d..84fdf25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -310,6 +310,21 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, ((vsw & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); + /* +* be sure to set Bit 10 for the V2 LCDC controller, +* otherwise limited to 1024 pixels width, stopping +* 1920x1080 being suppoted. +*/ + if (priv->rev == 2) { + if ((mode->vdisplay - 1) & 0x400) { + tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } else { + tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } + } + /* Configure display type: */ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h index 17fd1b4..1bf5e25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h @@ -80,6 +80,7 @@ #define LCDC_INVERT_PIXEL_CLOCK BIT(22) #define LCDC_INVERT_HSYNCBIT(21) #define LCDC_INVERT_VSYNCBIT(20) +#define LCDC_LPP_B10 BIT(26) /* LCDC Block */ #define LCDC_PID_REG 0x0 -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/5] drm/tilcdc: whitespace fixes and tidyup
keeping checkpatch happy. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 16 ++-- 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 283e0a6..6118651 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -42,7 +42,8 @@ struct tilcdc_crtc { static void unref_worker(struct work_struct *work) { - struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work); + struct tilcdc_crtc *tilcdc_crtc = + container_of(work, struct tilcdc_crtc, work); struct drm_device *dev = tilcdc_crtc->base.dev; struct drm_framebuffer *fb; @@ -55,10 +56,12 @@ static void unref_worker(struct work_struct *work) static void set_scanout(struct drm_crtc *crtc, int n) { static const uint32_t base_reg[] = { - LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG, + LCDC_DMA_FB_BASE_ADDR_0_REG, + LCDC_DMA_FB_BASE_ADDR_1_REG, }; static const uint32_t ceil_reg[] = { - LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG, + LCDC_DMA_FB_CEILING_ADDR_0_REG, + LCDC_DMA_FB_CEILING_ADDR_1_REG, }; static const uint32_t stat[] = { LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1, @@ -194,7 +197,8 @@ static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode) tilcdc_crtc->frame_done = false; stop(crtc); - /* if necessary wait for framedone irq which will still come + /* +* if necessary wait for framedone irq which will still come * before putting things to sleep.. */ if (priv->rev == 2) { @@ -504,7 +508,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) * configured from the DT */ if (mode->clock > priv->max_pixelclock) { - DBG("Pruning mode, pixel clock too high"); + DBG("Pruning mode: pixel clock too high"); return MODE_CLOCK_HIGH; } @@ -519,7 +523,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); if (bandwidth > priv->max_bandwidth) { - DBG("Pruning mode, exceeds defined bandwidth limit"); + DBG("Pruning mode: exceeds defined bandwidth limit"); return MODE_BAD; } -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/5] drm/tilcdc: adding more guards to present selection of invalid modes
The tilcdc has a number of limitations for the allowed sizes of the various adjustable timing parameter. Some modes are outside of these timings. This commit will prune modes that report timings that will overflow the allowed sizes in the tilcdc. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 46 ++ 1 files changed, 46 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 4455a41..283e0a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -442,7 +442,12 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = crtc->dev->dev_private; unsigned int bandwidth; + uint32_t hbp, hfp, hsw, vbp, vfp, vsw; + /* +* check to see if the width is within the range that +* the LCD Controller physically supports +*/ if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) return MODE_VIRTUAL_X; @@ -453,6 +458,47 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + DBG("Processing mode %dx%d@%d with pixel clock %d", + mode->hdisplay, mode->vdisplay, + drm_mode_vrefresh(mode), mode->clock); + + hbp = mode->htotal - mode->hsync_end; + hfp = mode->hsync_start - mode->hdisplay; + hsw = mode->hsync_end - mode->hsync_start; + vbp = mode->vtotal - mode->vsync_end; + vfp = mode->vsync_start - mode->vdisplay; + vsw = mode->vsync_end - mode->vsync_start; + + if ((hbp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Back Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hfp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Front Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hsw-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Sync Width out of range"); + return MODE_HSYNC_WIDE; + } + + if (vbp & ~0xff) { + DBG("Pruning mode: Vertical Back Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if (vfp & ~0xff) { + DBG("Pruning mode: Vertical Front Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if ((vsw-1) & ~0x3f) { + DBG("Pruning mode: Vertical Sync Width out of range"); + return MODE_VSYNC_WIDE; + } + /* * some devices have a maximum allowed pixel clock * configured from the DT -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/5] drm/tilcdc: fixing off by one errors found on analyzer
When hooking up to an HDMI analyzer noticed some timings were off by one. Referring to the hardware technical reference manual for the lcd controller some of the timing registers use 0 to represent 1. This patch addresses that issue. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 19 --- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 05f2b14..4455a41 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -289,17 +289,22 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); + + /* +* subtract one from hfp, hbp, hsw because the hardware uses +* a value of 0 as 1 +*/ if (priv->rev == 2) { - reg |= (hfp & 0x300) >> 8; - reg |= (hbp & 0x300) >> 4; - reg |= (hsw & 0x3c0) << 21; + reg |= ((hfp-1) & 0x300) >> 8; + reg |= ((hbp-1) & 0x300) >> 4; + reg |= ((hsw-1) & 0x3c0) << 21; } tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg); reg = (((mode->hdisplay >> 4) - 1) << 4) | - ((hbp & 0xff) << 24) | - ((hfp & 0xff) << 16) | - ((hsw & 0x3f) << 10); + (((hbp-1) & 0xff) << 24) | + (((hfp-1) & 0xff) << 16) | + (((hsw-1) & 0x3f) << 10); if (priv->rev == 2) reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg); @@ -307,7 +312,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = ((mode->vdisplay - 1) & 0x3ff) | ((vbp & 0xff) << 24) | ((vfp & 0xff) << 16) | - ((vsw & 0x3f) << 10); + (((vsw-1) & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); /* -- 1.7.0.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/5] drm/tilcdc: bug fixes, mode selection improvements
The series of patches that follow are intended to address issues that have been found in the tilcdc drm driver. The patchset enables support for screen resolutions with horizontal resolutions greater than 1024 pixels. The patchset also addresses a limitation where certain monitor timings would overflow LCD controller timing registers causing either no monitor signal or a very corrupted display. This patchset will stop monitor modes from being reported as valid if the lcd controller cannot support them. Applies cleanly on 3.10rc4. Darren Etheridge (5): drm/tilcdc: support pixel widths greater than 1024 drm/tilcdc: adding some more devicetree config drm/tilcdc: fixing off by one errors found on analyzer drm/tilcdc: adding more guards to present selection of invalid modes drm/tilcdc: whitespace fixes and tidyup .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 115 +--- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 +++- drivers/gpu/drm/tilcdc/tilcdc_drv.h| 22 drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + 5 files changed, 147 insertions(+), 14 deletions(-) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/5] drm/tilcdc: adding some more devicetree config
Adding support for max-pixelclock and max-width device tree entries. As some devices that use the tilcdc hardware module have restrictions on the allowed/tested values. Also update DT bindings document to reflect new parameters. Signed-off-by: Darren Etheridge --- .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 +++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 23 ++- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 - drivers/gpu/drm/tilcdc/tilcdc_drv.h| 22 +++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt index e5f1301..fff10da 100644 --- a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt +++ b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt @@ -10,6 +10,14 @@ Recommended properties: services interrupts for this device. - ti,hwmods: Name of the hwmod associated to the LCDC +Optional properties: + - max-bandwidth: The maximum pixels per second that the memory + interface / lcd controller combination can sustain + - max-width: The maximum horizontal pixel width supported by + the lcd controller. + - max-pixelclock: The maximum pixel clock that can be supported + by the lcd controller in KHz. + Example: fb: fb@4830e000 { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 84fdf25..05f2b14 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -448,10 +448,29 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + /* +* some devices have a maximum allowed pixel clock +* configured from the DT +*/ + if (mode->clock > priv->max_pixelclock) { + DBG("Pruning mode, pixel clock too high"); + return MODE_CLOCK_HIGH; + } + + /* +* some devices further limit the max horizontal resolution +* configured from the DT +*/ + if (mode->hdisplay > priv->max_width) + return MODE_BAD_WIDTH; + /* filter out modes that would require too much memory bandwidth: */ - bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); - if (bandwidth > priv->max_bandwidth) + bandwidth = mode->hdisplay * mode->vdisplay * + drm_mode_vrefresh(mode); + if (bandwidth > priv->max_bandwidth) { + DBG("Pruning mode, exceeds defined bandwidth limit"); return MODE_BAD; + } return MODE_OK; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 2b5461b..b40fa91 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -210,7 +210,20 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) #endif if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth)) - priv->max_bandwidth = 1280 * 1024 * 60; + priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH; + + DBG("Maximum Bandwidth Value %d", priv->max_bandwidth); + + if (of_property_read_u32(node, "ti,max-width", &priv->max_width)) + priv->max_width = TILCDC_DEFAULT_MAX_WIDTH; + + DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width); + + if (of_property_read_u32(node, "ti,max-pixelclock", + &priv->max_pixelclock)) + priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK; + + DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock); pm_runtime_enable(dev->dev); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 8242b5a..edb89a5 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -34,6 +34,18 @@ #include #include +/* Defaulting to pixel clock defined on AM335x */ +#define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000 +/* Defaulting to max width as defined on AM335x */ +#define TILCDC_DEFAULT_MAX_WIDTH 2048 +/* + * This may need some tweaking, but want to allow at least 1280x1024@60 + * with optimized DDR & EMIF settings tweaked 1920x1080@24 appears to + * be supportable + */ +#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) + + struct tilcdc_drm_private { void __iomem *mmio; @@ -43,6 +55,16 @@ struct tilcdc_drm_private { /* don't attempt resolutions w/ higher W * H * Hz: */ uint32_t max_bandwidth; + /* +* Pixel Clock will be restricted to some value
[PATCH 5/5] drm/tilcdc: whitespace fixes and tidyup
keeping checkpatch happy. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 16 ++-- 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 283e0a6..6118651 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -42,7 +42,8 @@ struct tilcdc_crtc { static void unref_worker(struct work_struct *work) { - struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work); + struct tilcdc_crtc *tilcdc_crtc = + container_of(work, struct tilcdc_crtc, work); struct drm_device *dev = tilcdc_crtc->base.dev; struct drm_framebuffer *fb; @@ -55,10 +56,12 @@ static void unref_worker(struct work_struct *work) static void set_scanout(struct drm_crtc *crtc, int n) { static const uint32_t base_reg[] = { - LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG, + LCDC_DMA_FB_BASE_ADDR_0_REG, + LCDC_DMA_FB_BASE_ADDR_1_REG, }; static const uint32_t ceil_reg[] = { - LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG, + LCDC_DMA_FB_CEILING_ADDR_0_REG, + LCDC_DMA_FB_CEILING_ADDR_1_REG, }; static const uint32_t stat[] = { LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1, @@ -194,7 +197,8 @@ static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode) tilcdc_crtc->frame_done = false; stop(crtc); - /* if necessary wait for framedone irq which will still come + /* +* if necessary wait for framedone irq which will still come * before putting things to sleep.. */ if (priv->rev == 2) { @@ -504,7 +508,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) * configured from the DT */ if (mode->clock > priv->max_pixelclock) { - DBG("Pruning mode, pixel clock too high"); + DBG("Pruning mode: pixel clock too high"); return MODE_CLOCK_HIGH; } @@ -519,7 +523,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); if (bandwidth > priv->max_bandwidth) { - DBG("Pruning mode, exceeds defined bandwidth limit"); + DBG("Pruning mode: exceeds defined bandwidth limit"); return MODE_BAD; } -- 1.7.0.4
[PATCH 4/5] drm/tilcdc: adding more guards to present selection of invalid modes
The tilcdc has a number of limitations for the allowed sizes of the various adjustable timing parameter. Some modes are outside of these timings. This commit will prune modes that report timings that will overflow the allowed sizes in the tilcdc. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 46 ++ 1 files changed, 46 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 4455a41..283e0a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -442,7 +442,12 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = crtc->dev->dev_private; unsigned int bandwidth; + uint32_t hbp, hfp, hsw, vbp, vfp, vsw; + /* +* check to see if the width is within the range that +* the LCD Controller physically supports +*/ if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) return MODE_VIRTUAL_X; @@ -453,6 +458,47 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + DBG("Processing mode %dx%d@%d with pixel clock %d", + mode->hdisplay, mode->vdisplay, + drm_mode_vrefresh(mode), mode->clock); + + hbp = mode->htotal - mode->hsync_end; + hfp = mode->hsync_start - mode->hdisplay; + hsw = mode->hsync_end - mode->hsync_start; + vbp = mode->vtotal - mode->vsync_end; + vfp = mode->vsync_start - mode->vdisplay; + vsw = mode->vsync_end - mode->vsync_start; + + if ((hbp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Back Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hfp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Front Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hsw-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Sync Width out of range"); + return MODE_HSYNC_WIDE; + } + + if (vbp & ~0xff) { + DBG("Pruning mode: Vertical Back Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if (vfp & ~0xff) { + DBG("Pruning mode: Vertical Front Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if ((vsw-1) & ~0x3f) { + DBG("Pruning mode: Vertical Sync Width out of range"); + return MODE_VSYNC_WIDE; + } + /* * some devices have a maximum allowed pixel clock * configured from the DT -- 1.7.0.4
[PATCH 3/5] drm/tilcdc: fixing off by one errors found on analyzer
When hooking up to an HDMI analyzer noticed some timings were off by one. Referring to the hardware technical reference manual for the lcd controller some of the timing registers use 0 to represent 1. This patch addresses that issue. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 19 --- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 05f2b14..4455a41 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -289,17 +289,22 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); + + /* +* subtract one from hfp, hbp, hsw because the hardware uses +* a value of 0 as 1 +*/ if (priv->rev == 2) { - reg |= (hfp & 0x300) >> 8; - reg |= (hbp & 0x300) >> 4; - reg |= (hsw & 0x3c0) << 21; + reg |= ((hfp-1) & 0x300) >> 8; + reg |= ((hbp-1) & 0x300) >> 4; + reg |= ((hsw-1) & 0x3c0) << 21; } tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg); reg = (((mode->hdisplay >> 4) - 1) << 4) | - ((hbp & 0xff) << 24) | - ((hfp & 0xff) << 16) | - ((hsw & 0x3f) << 10); + (((hbp-1) & 0xff) << 24) | + (((hfp-1) & 0xff) << 16) | + (((hsw-1) & 0x3f) << 10); if (priv->rev == 2) reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg); @@ -307,7 +312,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = ((mode->vdisplay - 1) & 0x3ff) | ((vbp & 0xff) << 24) | ((vfp & 0xff) << 16) | - ((vsw & 0x3f) << 10); + (((vsw-1) & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); /* -- 1.7.0.4
[PATCH 2/5] drm/tilcdc: adding some more devicetree config
Adding support for max-pixelclock and max-width device tree entries. As some devices that use the tilcdc hardware module have restrictions on the allowed/tested values. Also update DT bindings document to reflect new parameters. Signed-off-by: Darren Etheridge --- .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 +++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 23 ++- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 - drivers/gpu/drm/tilcdc/tilcdc_drv.h| 22 +++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt index e5f1301..fff10da 100644 --- a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt +++ b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt @@ -10,6 +10,14 @@ Recommended properties: services interrupts for this device. - ti,hwmods: Name of the hwmod associated to the LCDC +Optional properties: + - max-bandwidth: The maximum pixels per second that the memory + interface / lcd controller combination can sustain + - max-width: The maximum horizontal pixel width supported by + the lcd controller. + - max-pixelclock: The maximum pixel clock that can be supported + by the lcd controller in KHz. + Example: fb: fb at 4830e000 { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 84fdf25..05f2b14 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -448,10 +448,29 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y; + /* +* some devices have a maximum allowed pixel clock +* configured from the DT +*/ + if (mode->clock > priv->max_pixelclock) { + DBG("Pruning mode, pixel clock too high"); + return MODE_CLOCK_HIGH; + } + + /* +* some devices further limit the max horizontal resolution +* configured from the DT +*/ + if (mode->hdisplay > priv->max_width) + return MODE_BAD_WIDTH; + /* filter out modes that would require too much memory bandwidth: */ - bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); - if (bandwidth > priv->max_bandwidth) + bandwidth = mode->hdisplay * mode->vdisplay * + drm_mode_vrefresh(mode); + if (bandwidth > priv->max_bandwidth) { + DBG("Pruning mode, exceeds defined bandwidth limit"); return MODE_BAD; + } return MODE_OK; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 2b5461b..b40fa91 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -210,7 +210,20 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) #endif if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth)) - priv->max_bandwidth = 1280 * 1024 * 60; + priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH; + + DBG("Maximum Bandwidth Value %d", priv->max_bandwidth); + + if (of_property_read_u32(node, "ti,max-width", &priv->max_width)) + priv->max_width = TILCDC_DEFAULT_MAX_WIDTH; + + DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width); + + if (of_property_read_u32(node, "ti,max-pixelclock", + &priv->max_pixelclock)) + priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK; + + DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock); pm_runtime_enable(dev->dev); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 8242b5a..edb89a5 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -34,6 +34,18 @@ #include #include +/* Defaulting to pixel clock defined on AM335x */ +#define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000 +/* Defaulting to max width as defined on AM335x */ +#define TILCDC_DEFAULT_MAX_WIDTH 2048 +/* + * This may need some tweaking, but want to allow at least 1280x1024 at 60 + * with optimized DDR & EMIF settings tweaked 1920x1080 at 24 appears to + * be supportable + */ +#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) + + struct tilcdc_drm_private { void __iomem *mmio; @@ -43,6 +55,16 @@ struct tilcdc_drm_private { /* don't attempt resolutions w/ higher W * H * Hz: */ uint32_t max_bandwidth; + /* +* Pixel Clock will be restricted to some value
[PATCH 1/5] drm/tilcdc: support pixel widths greater than 1024
TI LCD controller version 2 has an extended eleventh bit that enables horizontal resolutions greater than 1024 pixels to be specified (upto 2048). This patch adds support for setting this bit on LCDC V2. Signed-off-by: Darren Etheridge --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 +++ drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 5dd3c7d..84fdf25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -310,6 +310,21 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, ((vsw & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); + /* +* be sure to set Bit 10 for the V2 LCDC controller, +* otherwise limited to 1024 pixels width, stopping +* 1920x1080 being suppoted. +*/ + if (priv->rev == 2) { + if ((mode->vdisplay - 1) & 0x400) { + tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } else { + tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } + } + /* Configure display type: */ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h index 17fd1b4..1bf5e25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h @@ -80,6 +80,7 @@ #define LCDC_INVERT_PIXEL_CLOCK BIT(22) #define LCDC_INVERT_HSYNCBIT(21) #define LCDC_INVERT_VSYNCBIT(20) +#define LCDC_LPP_B10 BIT(26) /* LCDC Block */ #define LCDC_PID_REG 0x0 -- 1.7.0.4
[PATCH 0/5] drm/tilcdc: bug fixes, mode selection improvements
The series of patches that follow are intended to address issues that have been found in the tilcdc drm driver. The patchset enables support for screen resolutions with horizontal resolutions greater than 1024 pixels. The patchset also addresses a limitation where certain monitor timings would overflow LCD controller timing registers causing either no monitor signal or a very corrupted display. This patchset will stop monitor modes from being reported as valid if the lcd controller cannot support them. Applies cleanly on 3.10rc4. Darren Etheridge (5): drm/tilcdc: support pixel widths greater than 1024 drm/tilcdc: adding some more devicetree config drm/tilcdc: fixing off by one errors found on analyzer drm/tilcdc: adding more guards to present selection of invalid modes drm/tilcdc: whitespace fixes and tidyup .../devicetree/bindings/drm/tilcdc/tilcdc.txt |8 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 115 +--- drivers/gpu/drm/tilcdc/tilcdc_drv.c| 15 +++- drivers/gpu/drm/tilcdc/tilcdc_drv.h| 22 drivers/gpu/drm/tilcdc/tilcdc_regs.h |1 + 5 files changed, 147 insertions(+), 14 deletions(-)