[RFC 00/12] Add DRM Exynos HDMI on SoCs from Exynos4 family
2013/10/29 Kukjin Kim : > On 10/28/13 06:42, Inki Dae wrote: >> >> Hi Tomasz, >> >> I have merged the re-factoring patch set from Sean Paul. Can you >> re-base your patch set at top of exynos-drm-next? >> > Basically, RFC is not patch for merge. So Tomasz needs to re-submit after > addressing comments from RFC. > There must definitely be your misunderstanding. I have never merged this RFC patch set. For review, shouldn't this RFC patch set be rebased at top of latest exynos-drm-next? :) Thanks, Inki Dae > Thanks, > Kukjin > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" > in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 12/26] drm/exynos: Split manager/display/subdrv
Hi, On Wednesday 23 of October 2013 12:09:06 Sean Paul wrote: > On Wed, Oct 23, 2013 at 11:53 AM, Dave Airlie wrote: > > I think we need to start considering a framework where subdrivers > > just > > add drm objects themselves, then the toplevel node is responsible > > for > > knowing that everything for the current configuration is loaded. > > It would be nice to specify the various pieces in dt, then have > some > type of drm notifier to the toplevel node when everything has been > probed. Doing it in the dt would allow standalone > drm_bridge/drm_panel > drivers to be transparent as far as the device's drm driver is > concerned. > > Sean > > > I realise we may need to make changes to the core drm to allow > > this > > but we should probably start to create a strategy for fixing the > > API > > issues that this throws up. > > > > Note I'm not yet advocating for dynamic addition of nodes once the > > device is in use, or removing them. > >>> > >>> I do wonder if we had some sort of tag in the device tree for any > >>> nodes > >>> involved in the display, and the core drm layer would read that > >>> list, > >>> and when every driver registers tick things off, and when the last > >>> one > >>> joins we get a callback and init the drm layer, we'd of course have > >>> the > >>> basic drm layer setup prior to that so we can add the objects as the > >>> drivers load. It might make development a bit trickier as you'd need > >>> to make sure someone claimed ownership of all the bits for init to > >>> proceed.>> > >> Yeah, that's basically what the strawman looked like in my head. > >> > >> Instead of a property in each node, I was thinking of having a > >> separate gfx pipe nodes that would have dt pointers to the various > >> pieces involved in that pipe. This would allow us to associate > >> standalone entities like bridges and panels with encoders in dt w/o > >> doing it in the drm code. I *think* this should be Ok with the dt > >> guys > >> since it is still describing the hardware, but I think we'd have to > >> make sure it wasn't drm-specific. > > > > I suppose the question is how much dynamic pipeline construction there > > is, > > > > even on things like radeon and i915 we have dynamic clock generator to > > crtc to encoder setups, so I worry about static lists per-pipe, so I > > still think just stating all these devices are needed for display and > > a list of valid interconnections between them, then we can have the > > generic code model drm crtc/encoders/connectors on that list, and > > construct the possible_crtcs /possible_clones etc at that stage. > > I'm, without excuse, hopeless at devicetree, so there are probably > some violations, but something like: > > display-pipelines { > required-elements = <&bridge-a &panel-a &encoder-x &encoder-y > &crtc-x &crtc-y>; > pipe1 { > bridge = <&bridge-a>; > encoder = <&encoder-x>; > crtc = <&crtc-y>; > }; > pipe2 { > encoder = <&encoder-x>; > crtc = <&crtc-x>; > }; > pipe3 { > panel = <&panel-a>; > encoder = <&encoder-y>; > crtc = <&crtc-y>; > }; > }; > > I'm tempted to add connector to the pipe nodes as well, so it's > obvious which connector should be used in cases where multiple > entities in the pipe implement drm_connector. However, I'm not sure if > that would be NACKed by dt people. > > I'm also not sure if there are too many combinations for i915 and > radeon to make this unreasonable. I suppose those devices could just > use required-elements and leave the pipe nodes out. Just to put my two cents in, as one of the people involved into "the device tree movement", I'd say that instead of creating artifical entities, such as display-pipelines and all of the pipeX'es, device tree should represent relations between nodes. According to the generic DT bindings we already have for video-interfaces [1] your example connection layout would look as follows: panel-a { /* Single input port */ port { panel_a: endpoint at 0 { remote-endpoint = <&encoder_y_out>; }; }; }; bridge-a { ports { /* Input port */ port at 0 { bridge_a_in: endpoint at 0 { remote-endpoint = <&encoder_x_out>; }; }; /* * Since it is a bridge, port at 1 should be probably * present here as well... */ }; }; encoder-x { ports { /* Input port */ port at 0 { encoder_x_in0: endpoint at 0 { remote-endpoint = <&crtc_x>; }; encoder_x_in1: endpoint at 1 { remote-endpoin
[PATCH] drm/radeon/audio: fix missing multichannel PCM SAD in some cases
The current code writing SADs to the audio registers seems to assume that there is at most a single SAD per audio format. However, that is not the case. Especially for PCM it is somewhat common for sinks to have two SADs, one for 8-channel and one for 2-channel audio, which may have different supported sample rates (i.e. the sink supports stereo audio at higher sample rates than multichannel audio). Because of this, only the 2-channel SAD may be used if it appears before the 8-channel SAD. Unless other SADs require otherwise, this may cause the ALSA HDA driver to allow stereo playback only. Fix the code to pick the PCM SAD with the highest number of channels, while merging the rate masks of PCM SADs with lower amount of channels into the additional stereo rate mask byte. Technically there are even more cases to handle (multiple non-PCM SADs of the same type, more than two PCM SADs with varying channel counts, etc), but those have not actually been encountered in the field and handling them would be non-trivial. Example affected EDID from Onkyo TX-SR674 specifying 192kHz stereo support and 96kHz 8-channel support (and other 8-channel compressed formats): 00003dcb0101 010380780a0dc9a057479827 12484c0001010101010101010101 010101010101011d8018711c1620582c 2500c48e219e011d007251d01e20 6e285500c48e211e00fc0054 582d5352363734202020202000fd 00313d0f2e08000a202020202020019b 02032f724f8504030f0e07069413121e 1d1615012f097f070f1f071707503707 503f07c0834f66030c00808c 0ad08a20e02d10103e9600c48e21 18011d80d0721c1620102c2580c48e21 9e011d00bc52d01e20b8285540c4 8e211e8c0ad090204031200c4055 00c48e2118a8 Signed-off-by: Anssi Hannula Tested-by: Andre Heider Cc: Rafa? Mi?ecki --- drivers/gpu/drm/radeon/dce6_afmt.c | 20 +++- drivers/gpu/drm/radeon/evergreen_hdmi.c | 20 +++- drivers/gpu/drm/radeon/r600_hdmi.c | 20 +++- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 85a69d2..0a0fcee 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -198,20 +198,30 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder) for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { u32 value = 0; + u8 stereo_freqs = 0; + int max_channels = -1; int j; for (j = 0; j < sad_count; j++) { struct cea_sad *sad = &sads[j]; if (sad->format == eld_reg_to_type[i][1]) { - value = MAX_CHANNELS(sad->channels) | - DESCRIPTOR_BYTE_2(sad->byte2) | - SUPPORTED_FREQUENCIES(sad->freq); + if (sad->channels > max_channels) { + value = MAX_CHANNELS(sad->channels) | + DESCRIPTOR_BYTE_2(sad->byte2) | + SUPPORTED_FREQUENCIES(sad->freq); + max_channels = sad->channels; + } + if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM) - value |= SUPPORTED_FREQUENCIES_STEREO(sad->freq); - break; + stereo_freqs |= sad->freq; + else + break; } } + + value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); + WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value); } diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index f71ce39..2a4837d 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -139,20 +139,30 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder) for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { u32 value = 0; + u8 stereo_freqs = 0; + int max_channels = -1; int j; for (j = 0; j < sad_count; j++) { struct cea_sad *sad = &sads[j]; if (sad->format == eld_reg_to_type[i][1]) { - value = MAX_CHANNELS(sad->channels) | - DESCRIPTOR_BYTE_2(sad->byte2) | - SUPPORTED_FREQUENCIES(sad->freq); + if (sad->channels > max_channels) { + value = MAX_CHANNELS(sad->channels) | + DESCRIPTOR_BYTE_2(sad->byte2) | +
[PATCH -next] drm/tegra: fix return value check
On Mon, Oct 28, 2013 at 04:48:40PM -0600, Stephen Warren wrote: > On 10/28/2013 04:38 PM, Thierry Reding wrote: > > On Mon, Oct 28, 2013 at 03:51:32PM -0600, Stephen Warren wrote: > >> On 10/28/2013 02:53 AM, Thierry Reding wrote: > >>> On Mon, Oct 21, 2013 at 11:34:07AM +0800, Wei Yongjun wrote: > >>>> From: Wei Yongjun > >>>> > >>>> In case of error, the function clk_get_parent() and > >>>> devm_ioremap_resource() returns ERR_PTR() and never returns > >>>> NULL. The NULL test in the return value check should be > >>>> replaced with IS_ERR(). > >>>> > >>>> Signed-off-by: Wei Yongjun > >>>> --- drivers/gpu/drm/tegra/dsi.c | 6 +++--- 1 file changed, 3 > >>>> insertions(+), 3 deletions(-) > >>> > >>> I've applied this, but with the first hunk removed, since > >>> looking at the implementation of clk_get_parent() it can > >>> actually return NULL. In fact it seems like it will never > >>> return ERR_PTR(). > >>> > >>> I've also updated the commit message to reflect that. > >> > >> Hmm. The documentation for clk_get() says: > > > > The patch didn't check the return value clk_get() but > > clk_get_parent(). Here's the implementation: > > > > struct clk *__clk_get_parent(struct clk *clk) { return !clk ? NULL > > : clk->parent; } > > > > Note that clk_get_parent() in simply a locked version of the above. > > That will obviously only return ERR_PTR() if clk->parent happens to > > be set to one such value, which I don't think will ever happen. > > Ah. That looks like a bug in __clk_get_parent() then, since !clk > doesn't sound like the correct error case for it to be checking. > Shouldn't it return IS_ERR(clk) ? clk : clk->parent? Either that, or > clk_get() shouldn't return an error value if the rest of the clock > code doesn NULL checks. Yes, that would seem to be more consistent. Then again, one could argue that if somebody got an invalid (ERR_PTR()) clock from clk_get(), they shouldn't be calling clk_get_parent() on it in the first place. But the same would be true for NULL, so... Looping in Mike. Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/6034dd9b/attachment-0001.pgp>
[Bug 66331] WebGL water demo crashes LLVM
https://bugs.freedesktop.org/show_bug.cgi?id=66331 --- Comment #6 from Grigori Goronzy --- It seems to work fine with current LLVM trunk now. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/e590cf9c/attachment.html>
[Bug 66331] WebGL water demo crashes LLVM
https://bugs.freedesktop.org/show_bug.cgi?id=66331 --- Comment #7 from Dieter N?tzel --- Is a backport possible for stable (3.3)? Couldn't switch all to devel...;-) -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/a471889c/attachment.html>
drm/exynos: change callback argument of sub driver with device
2013/10/28 Sean Paul : > On Mon, Oct 28, 2013 at 9:35 AM, Inki Dae wrote: >> This patch makes callback funtions of each sub driver to be called >> with device object instead of display and manager. >> >> Exynos drm framework doesn't need to pass a manager or a display >> when calling callback function of each sub driver, and each sub >> driver can get its own context from device object. So this patch >> hides sub driver's context from framework. >> > > Inki, > The reason I don't like this patch is that it moves us further away > from a flat drm driver. When I originally wrote the code for these > hooks to accept exynos_drm_manager/exynos_drm_display, it's because > they convert almost 1:1 to drm_crtc/drm_[encoder|connector]. The > drm_crtc_funcs/drm_encoder_funcs/drm_connector_funcs all take > drm_crtc/drm_encoder/drm_connector directly, not a device pointer. > > Another benefit of keeping it as-is is that the managers and displays > need not necessarily be their own device drivers, they could easily be > something like ptn3460 where they just hang off the root drm driver. > I don't think that passing device object into each sub driver makes us futher away from a flat drm driver. And I think I already commented enough before to you about why passing manager and display is not reasonable. I guess the reason you are trying to pass manager and display is that you want to use lvds bridge driver, ptn3460, including tricky codes that make DT binding of ptn3460 to be done in Exynos drm framework, not real device driver. Thanks, Inki Dae > Sean > > >> Signed-off-by: Inki Dae >> Signed-off-by: Kyungmin Park >> --- >> drivers/gpu/drm/exynos/exynos_drm_connector.c | 10 +-- >> drivers/gpu/drm/exynos/exynos_drm_core.c |8 +- >> drivers/gpu/drm/exynos/exynos_drm_crtc.c | 23 ++--- >> drivers/gpu/drm/exynos/exynos_drm_drv.h | 62 +++--- >> drivers/gpu/drm/exynos/exynos_drm_encoder.c | 10 +-- >> drivers/gpu/drm/exynos/exynos_drm_fimd.c | 114 >> - >> drivers/gpu/drm/exynos/exynos_hdmi.c | 64 +++--- >> drivers/gpu/drm/exynos/exynos_mixer.c | 70 +++ >> 8 files changed, 177 insertions(+), 184 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c >> b/drivers/gpu/drm/exynos/exynos_drm_connector.c >> index 9a16dbe..d13f637 100644 >> --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c >> +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c >> @@ -46,7 +46,7 @@ static int exynos_drm_connector_get_modes(struct >> drm_connector *connector) >> * because lcd panel has only one mode. >> */ >> if (display->ops->get_edid) { >> - edid = display->ops->get_edid(display, connector); >> + edid = display->ops->get_edid(display->dev, connector); >> if (IS_ERR_OR_NULL(edid)) { >> ret = PTR_ERR(edid); >> edid = NULL; >> @@ -70,7 +70,7 @@ static int exynos_drm_connector_get_modes(struct >> drm_connector *connector) >> } >> >> if (display->ops->get_panel) >> - panel = display->ops->get_panel(display); >> + panel = display->ops->get_panel(display->dev); >> else { >> drm_mode_destroy(connector->dev, mode); >> return 0; >> @@ -105,7 +105,7 @@ static int exynos_drm_connector_mode_valid(struct >> drm_connector *connector, >> DRM_DEBUG_KMS("%s\n", __FILE__); >> >> if (display->ops->check_mode) >> - if (!display->ops->check_mode(display, mode)) >> + if (!display->ops->check_mode(display->dev, mode)) >> ret = MODE_OK; >> >> return ret; >> @@ -155,7 +155,7 @@ static int exynos_drm_connector_fill_modes(struct >> drm_connector *connector, >> * resolution then get max width and height from that driver. >> */ >> if (display->ops->get_max_resol) >> - display->ops->get_max_resol(display, &width, &height); >> + display->ops->get_max_resol(display->dev, &width, >> &height); >> >> return drm_helper_probe_single_connector_modes(connector, width, >> height); >> @@ -171,7 +171,7 @@ exynos_drm_connector_detect(struct drm_connector >> *connector, bool force) >> enum drm_connector_status status = connector_status_disconnected; >> >> if (display->ops->is_connected) { >> - if (display->ops->is_connected(display)) >> + if (display->ops->is_connected(display->dev)) >> status = connector_status_connected; >> else >> status = connector_status_disconnected; >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c >> b/drivers/gpu/drm/exynos/exynos_drm_core.c >> index 0e11754..d59691d 10
drm/exynos: change callback argument of sub driver with device
Hi, 2013/10/29 Olof Johansson : > On Mon, Oct 28, 2013 at 6:35 AM, Inki Dae wrote: >> This patch makes callback funtions of each sub driver to be called >> with device object instead of display and manager. >> >> Exynos drm framework doesn't need to pass a manager or a display >> when calling callback function of each sub driver, and each sub >> driver can get its own context from device object. So this patch >> hides sub driver's context from framework. > > This is a step backwards. There should be no need to have every driver > have a full struct device associated with it, so removing the > requirement to have a struct device is the right thing to do (and this > patch undoes that). Did you look into Sean patch set? most patch set is great but some part of that patch set makes us to use tricky codes. So below is my question, 1. Where DT binding of a real device should be done in? in real device driver? or don't care wherever? My answer is that DT binding should be done in real device driver. However, now Sean patch set makes some tricky codes to be used in Exynos drm framework. I'm not sure that you had already looked into the ptn3460 lvds bridge driver but in Sean patch set, DT binding of the ptn3460 driver will be done in Exynos drm framework, not real device driver. Is that reasonable to you? And I guess the reason Sean is trying to pass manager and display into sub driver, is for using the ptn3460 driver including some tricky codes. 2. ARM SoC based DRM driver can be perfect single driver? I think most ARM SoC have separated hw resources so DRM driver for ARM couldn't be a perfect single driver. So ARM based DRM driver includes some separated device drivers, and is just used as a single driver. If you don't think so, Could you remove all stuff related to platform device from KMS drivers? If so, Where DT binding of each KMS driver should be done in? So if ARM based DRM driver cannot be a perfect single driver, and we should use DRM driver including separated device drivers then shouldn't we deal with the rule that other frameworks call some driver's callback with device object, and each device driver sets its own context into driver_data, not manager. If there is my missing something, plese give me your comments. > Sticking to the strict driver model on all display IP on SoCs is > making things overly complicated. Sean is clearly moving the Exynos > DRM in the right direction with his restructuring, so please don't > undo his work like this. Especially not without cc:ing him on the > patches. I think we had have discussions enough about this patch with Sean at other email threads, and In the email threads, I told Sean that I will post fixed patch instead of Sean. Anyway, I missed ccing him. Sorry about that. Thanks, Inki Dae > > > -Olof > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 0/7] drm/exynos: move hdmiphy related code to hdmiphy driver
On 28 October 2013 19:10, Inki Dae wrote: > Hi Rahul, > > I have merged the re-factoring patch set from Sean Paul to > exynos-drm-next except eDP related patch set that these need more > reviews. Can you re-base at top of exynos-drm-next? > Ok. I will rebase and post it again. regards, Rahul Sharma. > Thanks, > Inki Dae > > 2013/10/22 Rahul Sharma : >> Currently, exynos hdmiphy operations and configs are kept >> inside the hdmi driver. Hdmiphy related code is very tightly >> coupled with hdmi IP driver. With these patches, hdmiphy >> related stuff is moved to hdmiphy i2c driver for exynos4 and >> exynos5250 socs. hdmi driver, being the phy controller, calls >> exynos hdmiphy interfaces. >> >> This series also removes hdmiphy dummy clock for hdmiphy >> and replace it with Phy PMU Control from the hdmiphy driver. >> >> At the end, support for exynos5420 hdmiphy is added to the >> hdmiphy platform driver. >> >> Drm related paches are based on exynos-drm-next branch at >> git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git >> >> Arch related paches are based on for-next branch at >> http://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git >> >> Rahul Sharma (7): >> drm/exynos: move hdmiphy code to hdmiphy i2c driver >> drm/exynos: remove dummy hdmiphy clock >> drm/exynos: add hdmiphy platform driver for exynos5420 >> drm/exynos: add hdmiphy pmu bit control in hdmiphy drivers >> exynos/drm: fix ddc i2c device probe failure >> ARM: dts: update hdmiphy dt node for exynos5250 >> ARM: dts: update hdmiphy dt node for exynos5420 >> >> .../devicetree/bindings/video/exynos_hdmi.txt |2 + >> .../devicetree/bindings/video/exynos_hdmiphy.txt |8 +- >> arch/arm/boot/dts/exynos5250-smdk5250.dts |9 +- >> arch/arm/boot/dts/exynos5420.dtsi | 14 +- >> drivers/gpu/drm/exynos/Makefile|3 +- >> drivers/gpu/drm/exynos/exynos_ddc.c|5 + >> drivers/gpu/drm/exynos/exynos_hdmi.c | 407 +--- >> drivers/gpu/drm/exynos/exynos_hdmiphy.c| 65 --- >> drivers/gpu/drm/exynos/exynos_hdmiphy.h| 46 ++ >> drivers/gpu/drm/exynos/exynos_hdmiphy_i2c.c| 484 >> >> drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c | 418 + >> drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h | 36 ++ >> drivers/gpu/drm/exynos/regs-hdmiphy.h | 37 ++ >> 13 files changed, 1174 insertions(+), 360 deletions(-) >> delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c >> create mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.h >> create mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy_i2c.c >> create mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c >> create mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h >> create mode 100644 drivers/gpu/drm/exynos/regs-hdmiphy.h >> >> -- >> 1.7.10.4 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" >> in >> the body of a message to majordomo at vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html
drm/exynos: change callback argument of sub driver with device
On Tue, Oct 29, 2013 at 12:56 PM, Inki Dae wrote: > Hi, > > 2013/10/29 Olof Johansson : >> On Mon, Oct 28, 2013 at 6:35 AM, Inki Dae wrote: >>> This patch makes callback funtions of each sub driver to be called >>> with device object instead of display and manager. >>> >>> Exynos drm framework doesn't need to pass a manager or a display >>> when calling callback function of each sub driver, and each sub >>> driver can get its own context from device object. So this patch >>> hides sub driver's context from framework. >> >> This is a step backwards. There should be no need to have every driver >> have a full struct device associated with it, so removing the >> requirement to have a struct device is the right thing to do (and this >> patch undoes that). > > Did you look into Sean patch set? most patch set is great but some > part of that patch set makes us to use tricky codes. > I talked with a lot of people last week at Kernel Summit and I'll send a summary of it really soon, I think we should move exynos in that direction, but I'll just point out below, > So below is my question, > > 1. Where DT binding of a real device should be done in? in real device > driver? or don't care wherever? My answer is that DT binding should be > done in real device driver. However, now Sean patch set makes some > tricky codes to be used in Exynos drm framework. I'm not sure that you > had already looked into the ptn3460 lvds bridge driver but in Sean > patch set, DT binding of the ptn3460 driver will be done in Exynos drm > framework, not real device driver. Is that reasonable to you? And I > guess the reason Sean is trying to pass manager and display into sub > driver, is for using the ptn3460 driver including some tricky codes. There is no need to bind a Linux device to each DT node, having a separate device driver per-DT node isn't a requirement and tying the Linux device model so closely to the DT binding is a bad idea. For something like exynos (also imx, msm etc) we have a very specific set of IP blocks per SoC and a single driver that just enumerates what blocks are required using DT and gets the configuration information for the blocks from DT without binding should be fine. So if you have off-chip blocks that are separable then we would possibly do bindings to DT nodes, but it isn't essential. So I'd like to move away from the 1:1 DT node/driver model as it seriously over complicates things. We have agreed we should possibly add a display virtual node in the DT bindings for a single driver to use as a binding point. > 2. ARM SoC based DRM driver can be perfect single driver? I think most > ARM SoC have separated hw resources so DRM driver for ARM couldn't be > a perfect single driver. So ARM based DRM driver includes some > separated device drivers, and is just used as a single driver. If you > don't think so, Could you remove all stuff related to platform device > from KMS drivers? If so, Where DT binding of each KMS driver should be > done in? So if ARM based DRM driver cannot be a perfect single > driver, and we should use DRM driver including separated device > drivers then shouldn't we deal with the rule that other frameworks > call some driver's callback with device object, and each device driver > sets its own context into driver_data, not manager. > > If there is my missing something, plese give me your comments. > I'll follow up later, but yes a single driver is what we should aim for in cases where the blocks are quite coherent and all from a single source. Dave.
outcome of DRM/KMS DT bindings session
So we had a sessions at kernel summit to discuss the driver model and DT interactions for a display pipeline, we had good attendance from a few sides and I hope to summarise the recommendations below, a) Device Tree bindings We should create a top-level virtual device binding that a top level driver can bind to, like alsa asoc does. We should separate the CDF device tree model from CDF as a starting point and refine it outside of CDF, and produce a set of bindings that cover the current drivers we have, exynos, imx, tegra, msm, armada etc. This set of bindings should not be tied on CDF being merged or anything else. Display pipelines should be modelered in the device tree, but the level of detail required for links between objects may be left up to the SoC developer, esp wrt tightly coupled SoCs. Externally linked devices like bridges and panels should be explicitly linked. b) Driver Model The big thing here is that the device tree description we use should not dictate the driver model we use. This is the biggest thing I learned, so what does it mean? We aren't required to write a device driver per device tree object. We shouldn't be writing device drivers per device tree object. For tightly-coupled SoCs where the blocks come from one vendor and are reused a lot, a top level driver should use the DT as configuration information source for the list of blocks it needs to initialise on the card, not as a list of separate drivers. There may be some external drivers required and the code should deal with this, like how alsa asoc does. To share code between layers we should refactor it into a helper library not a separate driver, the kms/v4l/fbdev can use the library. This should allow us to move forward a bit clearer esp with new drivers and following these recommendations, and I think porting current drivers to a sane model, especially exynos and imx. Now I saw we here but I'm only going to be donating my use of a big stick and review abilities to making this happen, but I'm quite willing to enforce some of these rules going forward as I think it will make life easier. After looking at some of the ordering issues we've had with x86 GPUs (which are really just a tightly coupled SoC) I don't want separate drivers all having their own init, suspend/resume paths in them as I know we'll have to start making special vtable entry points etc to solve some random ordering issues that crop up. Dave.
[Bug 70934] [Regression] Problem with colors (depth?) on DCE5 Barts (HD69xx)
https://bugs.freedesktop.org/show_bug.cgi?id=70934 --- Comment #14 from Rafa? Mi?ecki --- [ 16.732721] [drm] Radeon Display Connectors [ 16.732722] [drm] Connector 0: [ 16.732723] [drm] eDP-1 [ 16.732724] [drm] HPD2 [ 16.732725] [drm] DDC: 0x6460 0x6460 0x6464 0x6464 0x6468 0x6468 0x646c 0x646c [ 16.732726] [drm] Encoders: [ 16.732727] [drm] LCD1: INTERNAL_UNIPHY1 [ 16.732727] [drm] Connector 1: [ 16.732728] [drm] DP-1 [ 16.732729] [drm] HPD3 [ 16.732730] [drm] DDC: 0x6440 0x6440 0x6444 0x6444 0x6448 0x6448 0x644c 0x644c [ 16.732731] [drm] Encoders: [ 16.732731] [drm] DFP1: INTERNAL_UNIPHY2 [ 16.732732] [drm] Connector 2: [ 16.732733] [drm] HDMI-A-1 [ 16.732734] [drm] HPD1 [ 16.732735] [drm] DDC: 0x6430 0x6430 0x6434 0x6434 0x6438 0x6438 0x643c 0x643c [ 16.732735] [drm] Encoders: [ 16.732736] [drm] DFP2: INTERNAL_UNIPHY2 [ 16.732737] [drm] Connector 3: [ 16.732738] [drm] VGA-1 [ 16.732739] [drm] DDC: 0x64d8 0x64d8 0x64dc 0x64dc 0x64e0 0x64e0 0x64e4 0x64e4 [ 16.732739] [drm] Encoders: [ 16.732740] [drm] CRT1: INTERNAL_KLDSCP_DAC1 -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/49db0274/attachment.html>
[Bug 70934] [Regression] Problem with colors (depth?) on DCE5 Barts (HD69xx)
https://bugs.freedesktop.org/show_bug.cgi?id=70934 --- Comment #15 from Rafa? Mi?ecki --- In xrandr my panel is visible as eDP, so I guess it's a eDP-1 with INTERNAL_UNIPHY1 . -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/9792ba4b/attachment-0001.html>
[Bug 63941] Can't control brightness with ATI 5650/Intel Ironlake when switched to radeon
https://bugzilla.kernel.org/show_bug.cgi?id=63941 Jani Nikula changed: What|Removed |Added Component|Video(DRI - Intel) |Video(DRI - non Intel) Assignee|intel-gfx-bugs at lists.freede |drivers_video-dri at kernel-bu |sktop.org |gs.osdl.org --- Comment #3 from Jani Nikula --- (In reply to Nikolay Amiantov from comment #1) > Interesting enough, if unused Intel card is powered up, brightness works > properly. It looks like i915 is in control of the backlight. Either it was designed this way, or there's an additional mux that needs switching for backlight, or something else... I don't really know. Reassigning to non-Intel, maybe the Radeon folks have more clues? -- You are receiving this mail because: You are watching the assignee of the bug.
drm/exynos: vidi: fix build error
2013/10/28 Sean Paul : > On Mon, Oct 28, 2013 at 9:35 AM, Inki Dae wrote: >> This patch fixes build error incurred by the re-factoring patch applying. >> >> The re-factoring patch set from Sean missed to apply the update to vidi >> module so this patch applies the update so that vidi module is also built >> correctly. >> > > Thanks for posting. Sorry about the breakage. I started fixing this as > part of my patch set on Friday. I think it might be better to fix > these as part of the original patch so we preserve bisectability. Do > you want me to continue this and send a revised patch set? > Ok, go ahead. And please know that I requested this fixup to you two times but I cannot get back from you so I posted this patch instead of you. > Sean > > >> Signed-off-by: Inki Dae >> Signed-off-by: Kyungmin Park >> --- >> drivers/gpu/drm/exynos/exynos_drm_vidi.c | 265 >> ++ >> 1 file changed, 119 insertions(+), 146 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c >> b/drivers/gpu/drm/exynos/exynos_drm_vidi.c >> index d734098..669eba5 100644 >> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c >> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c >> @@ -45,7 +45,8 @@ struct vidi_win_data { >> }; >> >> struct vidi_context { >> - struct exynos_drm_subdrvsubdrv; >> + struct device *dev; >> + struct drm_device *drm_dev; >> struct drm_crtc *crtc; >> struct vidi_win_datawin_data[WINDOWS_NR]; >> struct edid *raw_edid; >> @@ -55,6 +56,7 @@ struct vidi_context { >> unsigned intconnected; >> boolvblank_on; >> boolsuspended; >> + int pipe; >> booldirect_vblank; >> struct work_struct work; >> struct mutexlock; >> @@ -137,67 +139,28 @@ static int vidi_check_mode(struct device *dev, struct >> drm_display_mode *mode) >> } >> >> static struct exynos_drm_display_ops vidi_display_ops = { >> - .type = EXYNOS_DISPLAY_TYPE_VIDI, >> .is_connected = vidi_display_is_connected, >> .get_edid = vidi_get_edid, >> .get_panel = vidi_get_panel, >> .check_mode = vidi_check_mode, >> }; >> >> -static void vidi_dpms(void *in_ctx, int mode) >> -{ >> - struct vidi_context *ctx = in_ctx; >> - >> - DRM_DEBUG_KMS("%d\n", mode); >> - >> - mutex_lock(&ctx->lock); >> - >> - switch (mode) { >> - case DRM_MODE_DPMS_ON: >> - /* TODO. */ >> - break; >> - case DRM_MODE_DPMS_STANDBY: >> - case DRM_MODE_DPMS_SUSPEND: >> - case DRM_MODE_DPMS_OFF: >> - /* TODO. */ >> - break; >> - default: >> - DRM_DEBUG_KMS("unspecified mode %d\n", mode); >> - break; >> - } >> - >> - mutex_unlock(&ctx->lock); >> -} >> - >> -static void vidi_apply(void *in_ctx) >> -{ >> - struct vidi_context *ctx = in_ctx; >> - struct exynos_drm_manager *mgr = ctx->subdrv.manager; >> - struct exynos_drm_manager_ops *mgr_ops = mgr->ops; >> - struct vidi_win_data *win_data; >> - int i; >> - >> - for (i = 0; i < WINDOWS_NR; i++) { >> - win_data = &ctx->win_data[i]; >> - if (win_data->enabled && (mgr_ops && mgr_ops->win_commit)) >> - mgr_ops->win_commit(ctx, i); >> - } >> - >> - if (mgr_ops && mgr_ops->commit) >> - mgr_ops->commit(ctx); >> -} >> +static struct exynos_drm_display vidi_display = { >> + .type = EXYNOS_DISPLAY_TYPE_VIDI, >> + .ops = &vidi_display_ops, >> +}; >> >> -static void vidi_commit(void *in_ctx) >> +static void vidi_commit(struct device *dev) >> { >> - struct vidi_context *ctx = in_ctx; >> + struct vidi_context *ctx = get_vidi_context(dev); >> >> if (ctx->suspended) >> return; >> } >> >> -static int vidi_enable_vblank(void *in_ctx) >> +static int vidi_enable_vblank(struct device *dev) >> { >> - struct vidi_context *ctx = in_ctx; >> + struct vidi_context *ctx = get_vidi_context(dev); >> >> if (ctx->suspended) >> return -EPERM; >> @@ -217,9 +180,9 @@ static int vidi_enable_vblank(void *in_ctx) >> return 0; >> } >> >> -static void vidi_disable_vblank(void *in_ctx) >> +static void vidi_disable_vblank(struct device *dev) >> { >> - struct vidi_context *ctx = in_ctx; >> + struct vidi_context *ctx = get_vidi_context(dev); >> >> if (ctx->suspended) >> return; >> @@ -228,9 +191,10 @@ static void vidi_disable_vblank(void *in_ctx) >> ctx->vblank_on = false; >> } >> >> -static void vidi_win_mode_set(void *in_ctx, struct exynos_drm_overlay >> *overlay) >
drm/exynos: change callback argument of sub driver with device
Hi Dave, 2013/10/29 Dave Airlie : > On Tue, Oct 29, 2013 at 12:56 PM, Inki Dae wrote: >> Hi, >> >> 2013/10/29 Olof Johansson : >>> On Mon, Oct 28, 2013 at 6:35 AM, Inki Dae wrote: This patch makes callback funtions of each sub driver to be called with device object instead of display and manager. Exynos drm framework doesn't need to pass a manager or a display when calling callback function of each sub driver, and each sub driver can get its own context from device object. So this patch hides sub driver's context from framework. >>> >>> This is a step backwards. There should be no need to have every driver >>> have a full struct device associated with it, so removing the >>> requirement to have a struct device is the right thing to do (and this >>> patch undoes that). >> >> Did you look into Sean patch set? most patch set is great but some >> part of that patch set makes us to use tricky codes. >> > > I talked with a lot of people last week at Kernel Summit and I'll send > a summary of it really soon, > > I think we should move exynos in that direction, but I'll just point out > below, >> So below is my question, >> >> 1. Where DT binding of a real device should be done in? in real device >> driver? or don't care wherever? My answer is that DT binding should be >> done in real device driver. However, now Sean patch set makes some >> tricky codes to be used in Exynos drm framework. I'm not sure that you >> had already looked into the ptn3460 lvds bridge driver but in Sean >> patch set, DT binding of the ptn3460 driver will be done in Exynos drm >> framework, not real device driver. Is that reasonable to you? And I >> guess the reason Sean is trying to pass manager and display into sub >> driver, is for using the ptn3460 driver including some tricky codes. > > There is no need to bind a Linux device to each DT node, having a separate > device driver per-DT node isn't a requirement and tying the Linux device model > so closely to the DT binding is a bad idea. For something like exynos (also > imx, > msm etc) we have a very specific set of IP blocks per SoC and a single driver > that just enumerates what blocks are required using DT and gets the > configuration > information for the blocks from DT without binding should be fine. > > So if you have off-chip blocks that are separable then we would > possibly do bindings Yes, We have no the off-chip blocks. > to DT nodes, but it isn't essential. So I'd like to move away from the > 1:1 DT node/driver > model as it seriously over complicates things. We have agreed we > should possibly add > a display virtual node in the DT bindings for a single driver to use > as a binding point. Got it and thanks you for comments. The display virtual node seems similar to super node posted by Russell King so just my concern is that the display virtual node can be accepted by device tree people. Anyway, I'll remove this patch. I really wish that the display virtual node can lead us to more perfect world. Thanks, Inki Dae > > >> 2. ARM SoC based DRM driver can be perfect single driver? I think most >> ARM SoC have separated hw resources so DRM driver for ARM couldn't be >> a perfect single driver. So ARM based DRM driver includes some >> separated device drivers, and is just used as a single driver. If you >> don't think so, Could you remove all stuff related to platform device >> from KMS drivers? If so, Where DT binding of each KMS driver should be >> done in? So if ARM based DRM driver cannot be a perfect single >> driver, and we should use DRM driver including separated device >> drivers then shouldn't we deal with the rule that other frameworks >> call some driver's callback with device object, and each device driver >> sets its own context into driver_data, not manager. >> >> If there is my missing something, plese give me your comments. >> > I'll follow up later, but yes a single driver is what we should aim for in > cases where the blocks are quite coherent and all from a single source. > > Dave. > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
drm/exynos: change callback argument of sub driver with device
> >> to DT nodes, but it isn't essential. So I'd like to move away from the >> 1:1 DT node/driver >> model as it seriously over complicates things. We have agreed we >> should possibly add >> a display virtual node in the DT bindings for a single driver to use >> as a binding point. > > Got it and thanks you for comments. The display virtual node seems > similar to super node posted by Russell King so just my concern is > that the display virtual node can be accepted by device tree people. > Anyway, I'll remove this patch. I really wish that the display virtual > node can lead us to more perfect world. Just to confirm, Grant Likely was in the room for the discussion was quite happy to add them. Dave.
[Bug 68503] Graphical glitches in Serious Sam 3 when SB is enabled
https://bugs.freedesktop.org/show_bug.cgi?id=68503 --- Comment #14 from Fabio Pedretti --- Since this is a regression can it be allied before 10.0 branching: http://lists.freedesktop.org/archives/mesa-dev/2013-October/047235.html -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/9c781b99/attachment.html>
[Bug 60659] Backlight control interface with nouveau driver for nVidia Quadro 1000m not works
https://bugzilla.kernel.org/show_bug.cgi?id=60659 --- Comment #9 from Alexey Brodkin --- I have exactly the same laptop - HP Elitebook 8560w with a nVidia Quadro 1000M, NVC1 (GF108) in nouveau slang - and used to suffer from similar issue. But I've just tried Fedora 20 image for Graphics test day (http://fedorapeople.org/groups/qa/201310-Graphics_Test-mini-x86_64.iso) and with "acpi_backlight=vendor" specified I may confirm that in Gnome environment (it's 3.10) backlight controls work properly. Indeed without "acpi_backlight=vendor" (which is a default situation) Gnome shows brightness change animation and "/sys/class/backlight/acpi_video0/brightness" changes properly, but real screen brightness doesn't change. Here's my kernel version information: == Linux localhost 3.11.6-300.fc20.x86_64 #1 SMP Fri Oct 18 22:31:53 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux == Boot command-line (from beginning of dmesg output) is: == Command line: initrd=initrd0.img root=live:CDLABEL=LIVE rootfstype=vfat ro rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0 acpi_backlight=vendor BOOT_IMAGE=vmlinuz0 == So I assume this bug might be closed now as resolved. Let me know if there's a need for some more information/testing. -- You are receiving this mail because: You are watching the assignee of the bug.
[PATCH 1/2] drm: Do not drop root privileges for a fancier younger process
When a second process opens the device and master transferrence is complete, we walk the list of open devices and remove their authentication. This also revokes our root privilege. Instead of simply dropping the authentication, this patch reverts the authenticated state back to its original value. Signed-off-by: Chris Wilson --- drivers/gpu/drm/drm_fops.c | 5 +++-- include/drm/drmP.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index da1940ae9a2d..2f8b41c58d02 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -239,7 +239,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->ioctl_count = 0; /* for compatibility root is always authenticated */ - priv->authenticated = capable(CAP_SYS_ADMIN); + priv->always_authenticated = capable(CAP_SYS_ADMIN); + priv->authenticated = priv->always_authenticated; priv->lock_count = 0; INIT_LIST_HEAD(&priv->lhead); @@ -523,7 +524,7 @@ int drm_release(struct inode *inode, struct file *filp) list_for_each_entry(temp, &dev->filelist, lhead) { if ((temp->master == file_priv->master) && (temp != file_priv)) - temp->authenticated = 0; + temp->authenticated = temp->always_authenticated; } /** diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 490534c990b7..3a90857bd0ee 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -412,6 +412,7 @@ struct drm_prime_file_private { /** File private data */ struct drm_file { + int always_authenticated; int authenticated; struct pid *pid; kuid_t uid; -- 1.8.4.rc3
[PATCH 2/2] drm: Compact booleans within struct drm_file
Replace the sparse array of booleans with a bitfield. Signed-off-by: Chris Wilson --- include/drm/drmP.h | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3a90857bd0ee..02c685f70a72 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -412,8 +412,12 @@ struct drm_prime_file_private { /** File private data */ struct drm_file { - int always_authenticated; - int authenticated; + unsigned always_authenticated :1; + unsigned authenticated :1; + unsigned is_master :1; /* this file private is a master for a minor */ + /* true when the client has asked us to expose stereo 3D mode flags */ + unsigned stereo_allowed :1; + struct pid *pid; kuid_t uid; drm_magic_t magic; @@ -430,13 +434,8 @@ struct drm_file { struct file *filp; void *driver_priv; - int is_master; /* this file private is a master for a minor */ struct drm_master *master; /* master this node is currently associated with N.B. not always minor->master */ - - /* true when the client has asked us to expose stereo 3D mode flags */ - bool stereo_allowed; - /** * fbs - List of framebuffers associated with this file. * -- 1.8.4.rc3
[PATCH 0/4] Add dt support for exynos hdmiphy settings
For various revisions of a chipset if the signal pattern is changed for every revision, then the phy setting need to be updated correspondingly by measuring the signal. For getting correct signals the clock level and data de-emphasis levels needs to be adjusted. Since only these 2 values matter,we can move the same to dt, wherein we can have different dt files for every revision. This is an initial patchset towards achieving the same for exynos 5250 and can be later extended to future chipsets. V2: replaced moving of entire phy config structure with only required and justifiable conf registers. V3: Incorporated Mark Rutland's comments. V4: Rebased and included cros5250-common.dtsi. Shirish S (4): ARM: dts: smdk5250: Add hdmi phy settings ARM: dts: arndale: Add hdmi phy settings ARM: exynos: dts: cros5250: Add hdmi phy settings drm: exynos: hdmi: Add dt support for hdmiphy settings .../devicetree/bindings/video/exynos_hdmi.txt | 34 + arch/arm/boot/dts/cros5250-common.dtsi | 75 +++ arch/arm/boot/dts/exynos5250-arndale.dts | 75 +++ arch/arm/boot/dts/exynos5250-smdk5250.dts | 75 +++ drivers/gpu/drm/exynos/exynos_hdmi.c | 79 +++- 5 files changed, 334 insertions(+), 4 deletions(-) -- 1.7.9.5
[PATCH 1/4] ARM: dts: smdk5250: Add hdmi phy settings
This patch moves the hdmi phy setting to smdk5250 dts,as its more of a per board configuration and also shall be easier for supporting future chipsets. Signed-off-by: Shirish S --- arch/arm/boot/dts/exynos5250-smdk5250.dts | 75 + 1 file changed, 75 insertions(+) diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 2538b32..e1f4e08 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -220,6 +220,81 @@ hdmi { hpd-gpio = <&gpx3 7 0>; + hdmiphy-configs { + /* + * Eye diagram test passed for: + * Data de-emphasis: -0.7dB & Data Level: 880mV + * i.e., 0010 0110 = 0x26 + * and Clock level of 515mV and diff 1030mV + * i.e., 0x66 + */ + nr-configs = <13>; + config0: config0 { + pixel-clock = <2520>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config1: config1 { + pixel-clock = <2700>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config2: config2 { + pixel-clock = <27027000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config3: config3 { + pixel-clock = <3600>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config4: config4 { + pixel-clock = <4000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config5: config5 { + pixel-clock = <6500>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config6: config6 { + pixel-clock = <74176000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config7: config7 { + pixel-clock = <7425>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config8: config8 { + pixel-clock = <8350>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config9: config9 { + pixel-clock = <10650>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config10: config10 { + pixel-clock = <10800>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config11: config11 { + pixel-clock = <14625>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config12: config12 { + pixel-clock = <14850>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + }; }; codec at 1100 { -- 1.7.9.5
[PATCH 4/4] drm: exynos: hdmi: Add dt support for hdmiphy settings
This patch adds dt support to hdmiphy config settings as it is board specific and depends on the signal pattern of board. Signed-off-by: Shirish S --- .../devicetree/bindings/video/exynos_hdmi.txt | 34 + drivers/gpu/drm/exynos/exynos_hdmi.c | 79 +++- 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/video/exynos_hdmi.txt b/Documentation/devicetree/bindings/video/exynos_hdmi.txt index 323983b..c685c90 100644 --- a/Documentation/devicetree/bindings/video/exynos_hdmi.txt +++ b/Documentation/devicetree/bindings/video/exynos_hdmi.txt @@ -13,6 +13,32 @@ Required properties: b) pin number within the gpio controller. c) optional flags and pull up/down. +- hdmiphy-configs: following information about the hdmiphy config settings. +a) "nr-configs" specifies the number of pixel clocks supported. + b) "config: config" specifies the phy configuration settings, + wher 'N' denotes the number of iteration. + "pixel-clock" specifies the pixel clock + "conifig-de-emphasis-level" specifies the 8 bit configuration + of Data De-emphasis levels,below shown is example for + data de-emphasis register at address 0x145D0040. + hdmiphy at 38[16] for bits[3:0] permitted values: + means 760 mVdiff && means 1400 mVdiff + 1LSB corresponds to 20mVdiff + hdmiphy at 38[16] for bits[7:4] permitted values: + 0dB + 0001-0.25dB + 0010-0.7dB + 0011-1.15dB + -7.45dB + "config-clock-level" specifies the 8 bit configuration for + the corresponding clock level, for example if 0x145D005C + is the address of clock level register. + hdmiphy at 38[23] for bits [1:0] permitted values: + 00 means 0 mVdiff && 11 means 60 mVdiff + hdmiphy at 38[23] for bits [7:3] permitted values: + 0 is 790 mVdiff + 1 is 1430 mVdiff + 1LSB corresponds to 20mVdiff Example: hdmi { @@ -20,4 +46,12 @@ Example: reg = <0x1453 0x10>; interrupts = <0 95 0>; hpd-gpio = <&gpx3 7 1>; + hdmiphy-configs { + nr-configs = <1>; + config0: config0 { + pixel-clock = <2520>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + } }; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 32ce9a6..065ac1f 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -197,6 +197,9 @@ struct hdmi_context { struct hdmi_resources res; + struct hdmiphy_config *confs; + int nr_confs; + int hpd_gpio; enum hdmi_type type; @@ -256,7 +259,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = { }, }; -static const struct hdmiphy_config hdmiphy_v14_configs[] = { +static struct hdmiphy_config hdmiphy_v14_configs[] = { { .pixel_clock = 2520, .conf = { @@ -785,8 +788,8 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) confs = hdmiphy_v13_configs; count = ARRAY_SIZE(hdmiphy_v13_configs); } else if (hdata->type == HDMI_TYPE14) { - confs = hdmiphy_v14_configs; - count = ARRAY_SIZE(hdmiphy_v14_configs); + confs = hdata->confs; + count = hdata->nr_confs; } else return -EINVAL; @@ -1415,7 +1418,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) if (hdata->type == HDMI_TYPE13) hdmiphy_data = hdmiphy_v13_configs[i].conf; else - hdmiphy_data = hdmiphy_v14_configs[i].conf; + hdmiphy_data = hdata->confs[i].conf; memcpy(buffer, hdmiphy_data, 32); ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32); @@ -1894,6 +1897,65 @@ fail: return -ENODEV; } +static int drm_hdmi_dt_parse_phy_conf(struct platform_device *pdev, + struct hdmi_context *hdata) +{ + struct device *dev = &pdev->dev; + struct device_node *dev_np = dev->of_node; + struct device_node *phy_c
[PATCH 3/4] ARM: exynos: dts: cros5250: Add hdmi phy settings
This patch moves the hdmi phy setting to arndale dts, as its more of a per board configuration and also shall be easier for supporting future chipsets. Signed-off-by: Shirish S --- arch/arm/boot/dts/cros5250-common.dtsi | 75 1 file changed, 75 insertions(+) diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi index dc259e8b..3cd1779 100644 --- a/arch/arm/boot/dts/cros5250-common.dtsi +++ b/arch/arm/boot/dts/cros5250-common.dtsi @@ -301,6 +301,81 @@ hdmi { hpd-gpio = <&gpx3 7 0>; + hdmiphy-configs { + /* + * Eye diagram test passed for: + * Data de-emphasis: -0.7dB & Data Level: 880mV + * i.e., 0010 0110 = 0x26 + * and Clock level of 515mV and diff 1030mV + * i.e., 0x66 + */ + nr-configs = <13>; + config0: config0 { + pixel-clock = <2520>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config1: config1 { + pixel-clock = <2700>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config2: config2 { + pixel-clock = <27027000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config3: config3 { + pixel-clock = <3600>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config4: config4 { + pixel-clock = <4000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config5: config5 { + pixel-clock = <6500>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config6: config6 { + pixel-clock = <74176000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config7: config7 { + pixel-clock = <7425>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config8: config8 { + pixel-clock = <8350>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config9: config9 { + pixel-clock = <10650>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config10: config10 { + pixel-clock = <10800>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config11: config11 { + pixel-clock = <14625>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config12: config12 { + pixel-clock = <14850>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + }; }; gpio-keys { -- 1.7.9.5
[PATCH 0/3] Add dt support for exynos hdmiphy settings
Ok, i shall rebase. On Mon, Oct 28, 2013 at 7:32 PM, Inki Dae wrote: > Hi Shirish, > > I have merged the re-factoring patch set from Sean Paul to exynos-drm-next. > Can you re-base your patch set at top of exynos-drm-next? > > Thanks, > Inki Dae > > > -Original Message- > > From: Shirish S [mailto:s.shirish at samsung.com] > > Sent: Monday, October 28, 2013 7:39 PM > > To: dri-devel at lists.freedesktop.org; inki.dae at samsung.com; > > devicetree at vger.kernel.org > > Cc: seanpaul at chromium.org; sw0312.kim at samsung.com; mark.rutland at > > arm.com; > > shirish at chromium.org; Shirish S > > Subject: [PATCH 0/3] Add dt support for exynos hdmiphy settings > > > > For various revisions of a chipset if the signal pattern is changed for > > every > > revision, then the phy setting need to be updated correspondingly by > > measuring > > the signal. > > For getting correct signals the clock level and data de-emphasis > > levels needs to be adjusted. > > Since only these 2 values matter,we can move the same to dt, > > wherein we can have different dt files for every revision. > > > > This is an initial patchset towards achieving the same > > for exynos 5250 and can be later extended to future chipsets. > > > > V2: replaced moving of entire phy config structure with only > > required and justifiable conf registers. > > > > V3: Incorporated Mark Rutland's comments. > > > > Shirish S (3): > > ARM: dts: smdk5250: Add hdmi phy settings > > ARM: dts: arndale: Add hdmi phy settings > > drm: exynos: hdmi: Add dt support for hdmiphy settings > > > > .../devicetree/bindings/video/exynos_hdmi.txt | 32 + > > arch/arm/boot/dts/exynos5250-arndale.dts | 68 > ++ > > arch/arm/boot/dts/exynos5250-smdk5250.dts | 68 > ++ > > drivers/gpu/drm/exynos/exynos_hdmi.c | 76 > ++- > > - > > 4 files changed, 240 insertions(+), 4 deletions(-) > > > > -- > > 1.7.9.5 > > -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/a8cea800/attachment-0001.html>
[PATCH v5 0/4] Fix Win8 backlight issue
On 10/28/2013 04:09 PM, Jani Nikula wrote: > On Mon, 28 Oct 2013, Aaron Lu wrote: >> +static int __init video_set_use_native_backlight(const struct dmi_system_id >> *d) >> +{ >> +use_native_backlight = true; >> +return 0; >> +} > > Hi Aaron, it might be beneficial to make use_native_backlight support > three values: force true, force false, and use platform default based on > DMI. Makes sense. I modified the patch a little bit so that if user has specified the cmdline option use_native_backlight=0/1, it will always take effect no matter if the system is in DMI table or not. From: Aaron Lu Subject: [PATCH] ACPI / video: Add systems that should favor native backlight interface Some system's ACPI video backlight control interface is broken and the native backlight control interface should be used by default. This patch sets the use_native_backlight parameter to true for those systems so that video backlight control interface will not be created. To be specific, the ThinkPad T430s/X230, Lenovo Yoga 13 and Dell Inspiron 7520 are added here. Note that the user specified kernel cmdline option will always have the highest priority, i.e. if use_native_backlight=0 is specified and the system is in the DMI table, the video module will not skip register backlight interface for it. Thinkpad T430s: Reported-by: Theodore Tso Reported-and-tested-by: Peter Weber Thinkpad X230: Reported-and-tested-by: Igor Gnatenko Lenovo Yoga 13: Reported-by: Lennart Poettering Reported-and-tested-by: Kevin Smith Dell Inspiron 7520: Reported-by: Rinat Ibragimov Reference: https://bugzilla.kernel.org/show_bug.cgi?id=51231 Signed-off-by: Aaron Lu --- drivers/acpi/video.c | 57 +++- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 38c3a28..41bd4b4 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -89,11 +89,12 @@ static bool use_bios_initial_backlight = 1; module_param(use_bios_initial_backlight, bool, 0644); /* - * For Windows 8 systems: if set ture and the GPU driver has - * registered a backlight interface, skip registering ACPI video's. + * For Windows 8 systems: used to decide if video module + * should skip registering backlight interface of its own. */ -static bool use_native_backlight = false; -module_param(use_native_backlight, bool, 0644); +static int use_native_backlight_param = -1; +module_param_named(use_native_backlight, use_native_backlight_param, int, 0444); +static bool use_native_backlight_dmi = false; static int register_count; static struct mutex video_list_lock; @@ -239,9 +240,17 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, static int acpi_video_switch_brightness(struct acpi_video_device *device, int event); +static bool acpi_video_use_native_backlight(void) +{ + if (use_native_backlight_param != -1) + return !!use_native_backlight_param; + else + return use_native_backlight_dmi; +} + static bool acpi_video_verify_backlight_support(void) { - if (acpi_osi_is_win8() && use_native_backlight && + if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && backlight_device_registered(BACKLIGHT_RAW)) return false; return acpi_video_backlight_support(); @@ -412,6 +421,12 @@ static int video_ignore_initial_backlight(const struct dmi_system_id *d) return 0; } +static int __init video_set_use_native_backlight(const struct dmi_system_id *d) +{ + use_native_backlight_dmi = true; + return 0; +} + static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -512,6 +527,38 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G1 Notebook PC"), }, }, + { +.callback = video_set_use_native_backlight, +.ident = "ThinkPad T430s", +.matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"), + }, + }, + { +.callback = video_set_use_native_backlight, +.ident = "ThinkPad X230", +.matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + }, + }, + { +.callback = video_set_use_native_backlight, +.ident = "Lenovo Yoga 13", +.matches = { +DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), + }, + }, + { +.callback = video_set_use_native_backlight, +.ident = "Dell Inspiron 7520", +.matches = { +DMI_MATCH(DMI_SYS_V
[PATCH 3/3] drm: exynos: hdmi: Add dt support for hdmiphy settings
On Tue, Oct 29, 2013 at 4:08 AM, Mark Rutland wrote: > On Mon, Oct 28, 2013 at 10:15:00AM +, Shirish S wrote: >> Hi Mark, >> Firstly thanks for reviewing. > > Hi, > > Please could you refrain from replying in HTML and use plaintext, it's rather > difficult to respond sensibly. > Sorry for your troubles,hope with this reply its fine. >> >> >> On Mon, Oct 28, 2013 at 12:20 PM, Mark Rutland >> wrote: >> >> Hi, >> >> On Mon, Oct 28, 2013 at 06:24:22AM +, Shirish S wrote: >> > This patch adds dt support to hdmiphy config settings >> > as it is board specific and depends on the signal pattern >> > of board. >> > >> > Signed-off-by: Shirish S >> > --- >> > .../devicetree/bindings/video/exynos_hdmi.txt | 29 >> > arch/arm/boot/dts/exynos5250-arndale.dts |6 +- >> > drivers/gpu/drm/exynos/exynos_hdmi.c | 70 >> ++-- >> > 3 files changed, 98 insertions(+), 7 deletions(-) >> > >> > diff --git a/Documentation/devicetree/bindings/video/exynos_hdmi.txt b/ >> Documentation/devicetree/bindings/video/exynos_hdmi.txt >> > index 323983b..770f92d 100644 >> > --- a/Documentation/devicetree/bindings/video/exynos_hdmi.txt >> > +++ b/Documentation/devicetree/bindings/video/exynos_hdmi.txt >> > @@ -13,6 +13,27 @@ Required properties: >> > b) pin number within the gpio controller. >> > c) optional flags and pull up/down. >> > >> > +- hdmiphy-confs: following information about the hdmiphy conf >> settings. >> >> Judging by the other patches, this is a node, not a property. >> >> >> Yes its a node. > > My point was that the documentation should reflect this. > Its property and not a node, i had misunderstood the concepts. >> >> > +a) "nr-confs" specifies the number of pixel clocks supported. >> >> Why is this needed? Someone will get it wrong eventually and it can be >> figured >> out currently by counting the child nodes, testing if they have the >> appropriate >> properties. >> >> >> Actually i need to get the array size also from dt, hence this is approach i >> have taken > > While this approach works now for perfect DTs, as I pointed out it is encoding > redundant information and could be broken by future changes. Please fix this. > Hope you have had a look at my next patch set (v4), this property is now more or less optional, i mean if the user enters wrong number of configs it shall not be considered and driver shall use the predefined table provided in the driver. >> >> > + b) "confX: confX" specifies the phy configuration settings, >> >> This is confusing. What is X? >> >> >> I am trying to generalize, here X means any numerical, and the programmer >> needs >> to >> make sure conf0:conf0, wherein X is 0.I shall provide the values permitted >> for >> X in my next patch set. > > Please be explicit with your definitions. Experience shows that people will > get > this wrong. > Is the way i have documented in patch set v4 still wrong, or its clear? >> >> The label is irrelevant -- none of this patch looks for phandles pointing >> at >> configurations, nor is the precise name of the label important. >> >> This is a node, not a property. >> >> >> Ideally every conf a combination of pixel clock and new >> values for data and clock level. > > This answers neither of my concerns. > The fact that its a property and not a node,and contains pairs of pixel clock and config values should answer your concerns. Please note: in this case(exynos5250) the config values seem to same for all the pixel clocks, however in the next chipset (exynos5420) the values vary across pixel clocks, that is the reason why i need to keep these config values attached to pixel clocks. >> >> > + "clock-frequency" specifies the pixel clock >> >> Is this a frequency to configure the pixel clock with, or the >> pre-determined >> frequency of a clock that we will select? >> >> >> No, as the explanation suggests its the pixel clock itself. > > That doesn't answer my question. Is this the frequency that the pixel clock is > fixed at in hardware, or is this a value to configure the pixel clock with? > This the frequency that the pixel clock is fixed at in hardware also note that i have changed the name from clock-frequency to pixel-clock. >> >> > + "con-de-emphasis-level" specifies the configuration >> > + of Data De-emphasis levels. >> >> Please explain _why_ we need this configuration. >> >> >> Our chipset to undergo HDMI compliance test and noticed that the HDMI >> Compliance Test id 7-10 was failing >> for eye diagram test. Hence on further analysis, it was found that altering >> the >> data de-emphasis levels and clock >> level are required to pass the test.And also these values may vary for >> variuos >> board revisons, this is the purpose of this whole
[PATCH 2/4] ARM: dts: arndale: Add hdmi phy settings
This patch moves the hdmi phy setting to arndale dts, as its more of a per board configuration and also shall be easier for supporting future chipsets. Signed-off-by: Shirish S --- arch/arm/boot/dts/exynos5250-arndale.dts | 75 ++ 1 file changed, 75 insertions(+) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index cee55fa..c771ba3 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -475,6 +475,81 @@ vdd_osc-supply = <&ldo10_reg>; vdd_pll-supply = <&ldo8_reg>; vdd-supply = <&ldo8_reg>; + hdmiphy-configs { + /* + * Eye diagram test passed for: + * Data de-emphasis: -0.7dB & Data Level: 880mV + * i.e., 0010 0110 = 0x26 + * and Clock level of 515mV and diff 1030mV + * i.e., 0x66 + */ + nr-configs = <13>; + config0: config0 { + pixel-clock = <2520>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config1: config1 { + pixel-clock = <2700>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config2: config2 { + pixel-clock = <27027000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config3: config3 { + pixel-clock = <3600>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config4: config4 { + pixel-clock = <4000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config5: config5 { + pixel-clock = <6500>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config6: config6 { + pixel-clock = <74176000>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config7: config7 { + pixel-clock = <7425>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config8: config8 { + pixel-clock = <8350>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config9: config9 { + pixel-clock = <10650>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config10: config10 { + pixel-clock = <10800>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config11: config11 { + pixel-clock = <14625>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + config12: config12 { + pixel-clock = <14850>; + config-de-emphasis-level = /bits/ 8 <0x26>; + config-clock-level = /bits/ 8 < 0x66>; + }; + }; }; regulators { -- 1.7.9.5
Build failure: shmobile drm driver references backlight symbols
My build system picked up on this failure: drivers/built-in.o: In function `shmob_drm_backlight_init': fmc-chardev.c:(.text+0x9f2d0): undefined reference to `backlight_device_register' drivers/built-in.o: In function `shmob_drm_backlight_exit': fmc-chardev.c:(.text+0x9f370): undefined reference to `backlight_device_unregister' which is cuased by drivers/gpu/drm/shmobile/shmob_drm_backlight.c being built without the backlight dependency being enabled. It looks like the backlight dependency is a hard requirement, so needs ot be added to the Kconfig entry for this driver in some way.
[PULL] drm-intel-fixes
On Mon, Oct 28, 2013 at 08:49:45AM +0100, Daniel Vetter wrote: > Hi Dave, > > Please do _not_ pull this. The pipe bpp readout stuff this crucially > relies on is only partially backported from -next to -fixes and apparently > missing bits on Haswell. Ok, updated pull request. I wanted to wait a bit for an ivb 3 pipe regression fix, but my brain was too fuzzy thus far to write a correct patch ... So I guess that one will go through the merge window with a cc: stable. On top of the edp bpp fix from Jani just a no-lvds quirk. The two patches from Ville are both from -next and provide infrastructure for Jani's fix. I could have done a more minimal port, but I'd like to avoid divergent code for backports as much as possible. Cheers, Daniel The following changes since commit 959f58544b7f20c92d5eb43d1232c96c15c01bfb: Linux 3.12-rc7 (2013-10-27 16:12:03 -0700) are available in the git repository at: git://people.freedesktop.org/~danvet/drm-intel tags/drm-intel-fixes-2013-10-29 for you to fetch changes up to 645378d85ee524e429aa4cf52806047b56cdc596: drm/i915: No LVDS hardware on Intel D410PT and D425KT (2013-10-28 17:48:30 +0100) Jani Nikula (1): drm/i915/dp: workaround BIOS eDP bpp clamping issue Rob Pearce (1): drm/i915: No LVDS hardware on Intel D410PT and D425KT Ville Syrj?l? (2): drm/i915: Add support for pipe_bpp readout drm/i915: Add HSW CRT output readout support > > Thanks, Daniel > > On Fri, Oct 25, 2013 at 12:50:12PM +0200, Daniel Vetter wrote: > > Hi Dave, > > > > Just the edp bpp fix from Jani plus the pipe bpp readout code from Ville > > to make it work. There's a 3 pipe ivb regression fix pending from me, but > > Ville's review convinced me that my first stab is broken. > > > > Cheers, Daniel > > > > > > The following changes since commit 828c79087cec61eaf4c76bb32c222fbe35ac3930: > > > > drm/i915: Disable GGTT PTEs on GEN6+ suspend (2013-10-18 15:44:47 +0200) > > > > are available in the git repository at: > > > > git://people.freedesktop.org/~danvet/drm-intel > > tags/drm-intel-fixes-2013-10-25 > > > > for you to fetch changes up to 52e1e223456e3aa747e9932f95948381f04b3b26: > > > > drm/i915/dp: workaround BIOS eDP bpp clamping issue (2013-10-21 > > 09:57:02 +0200) > > > > > > Jani Nikula (1): > > drm/i915/dp: workaround BIOS eDP bpp clamping issue > > > > Ville Syrj?l? (1): > > drm/i915: Add support for pipe_bpp readout > > > > drivers/gpu/drm/i915/intel_ddi.c | 17 + > > drivers/gpu/drm/i915/intel_display.c | 36 > > > > drivers/gpu/drm/i915/intel_dp.c | 20 > > 3 files changed, 73 insertions(+) > > > > -- > > Daniel Vetter > > Software Engineer, Intel Corporation > > +41 (0) 79 365 57 48 - http://blog.ffwll.ch > > -- > Daniel Vetter > Software Engineer, Intel Corporation > +41 (0) 79 365 57 48 - http://blog.ffwll.ch -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH] drm: delete unconsumed pending event list in drm_events_release
When there are unconsumed pending events, the events are destroyed by calling destroy callback, but the events list are remained, because there is no list_del(). It is possible that the page flip request is handled after drm_events_release() is called and before drm_fb_release(). In this case a drm_pending_event is remained not freed. So exynos driver checks again to remove it in its post close routine. But the file_priv->event_list contains undeleted ones, this can make oops for accessing invalid memory. Change-Id: I2eaad659d5b514d5df68a2323083dbd38ada1b5f Signed-off-by: YoungJun Cho Signed-off-by: Kyungmin Park --- drivers/gpu/drm/drm_fops.c |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 3f84277..3c860b7 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -379,8 +379,10 @@ static void drm_events_release(struct drm_file *file_priv) } /* Remove unconsumed events */ - list_for_each_entry_safe(e, et, &file_priv->event_list, link) + list_for_each_entry_safe(e, et, &file_priv->event_list, link) { + list_del(&e->link); e->destroy(e); + } spin_unlock_irqrestore(&dev->event_lock, flags); } -- 1.7.9.5
drm/exynos: change callback argument of sub driver with device
2013/10/28 Sean Paul : > Hi Inki, > I noticed that you merged "drm/exynos: change callback argument of sub > driver with device" to your tree without posting it to me, or > dri-devel, first. I think it would have been prudent to send for > review/comments considering that: > > a) we don't agree on this, and were in discussion about it last week, and > b) it essentially reverts my "Pass exynos_drm_manager in..." patch, > and changes key elements of my "Split manager/display/subdrv" patch, > Don't worry about that. I have already removed my patch: it was really my mistake. And it doesn't need to discuss that issue anymore. I understood enough. :) > Lastly, I was working on fixing the vidi errors in the patchset, > instead of just on top. For bisect reasons, this is probably > desirable. I had already commented about that, and my patch has already be removed from exynos-drm-next. Please re-post that fixup. :) Thanks, Inki Dae > > Sean > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
drm/exynos: change callback argument of sub driver with device
On Oct 29, 2013 8:16 AM, "Inki Dae" wrote: > > 2013/10/28 Sean Paul : > > Hi Inki, > > I noticed that you merged "drm/exynos: change callback argument of sub > > driver with device" to your tree without posting it to me, or > > dri-devel, first. I think it would have been prudent to send for > > review/comments considering that: > > > > a) we don't agree on this, and were in discussion about it last week, and > > b) it essentially reverts my "Pass exynos_drm_manager in..." patch, > > and changes key elements of my "Split manager/display/subdrv" patch, > > > > Don't worry about that. I have already removed my patch: it was really > my mistake. And it doesn't need to discuss that issue anymore. I > understood enough. :) > Hi InKi, I sent this yesterday before your patches were posted to dri-devel, I guess it got lost in the ether. Sean > > Lastly, I was working on fixing the vidi errors in the patchset, > > instead of just on top. For bisect reasons, this is probably > > desirable. > > I had already commented about that, and my patch has already be > removed from exynos-drm-next. Please re-post that fixup. :) > > Thanks, > Inki Dae > > > > > Sean > > ___ > > dri-devel mailing list > > dri-devel at lists.freedesktop.org > > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/1473fae1/attachment.html>
[PULL] drm-intel-fixes
On Tue, Oct 29, 2013 at 11:29:29AM +0100, Daniel Vetter wrote: > On Mon, Oct 28, 2013 at 08:49:45AM +0100, Daniel Vetter wrote: > > Hi Dave, > > > > Please do _not_ pull this. The pipe bpp readout stuff this crucially > > relies on is only partially backported from -next to -fixes and apparently > > missing bits on Haswell. > > Ok, updated pull request. I wanted to wait a bit for an ivb 3 pipe > regression fix, but my brain was too fuzzy thus far to write a correct > patch ... So I guess that one will go through the merge window with a cc: > stable. > > On top of the edp bpp fix from Jani just a no-lvds quirk. The two patches > from Ville are both from -next and provide infrastructure for Jani's fix. > I could have done a more minimal port, but I'd like to avoid divergent > code for backports as much as possible. Ok, clue came back in the nick of time, so I've figured I'll smash the 3 pipe fix (tested&reviewed) into the pull request, too. I like my kernel release free of known regressions ;-) Cheers, Daniel The following changes since commit 959f58544b7f20c92d5eb43d1232c96c15c01bfb: Linux 3.12-rc7 (2013-10-27 16:12:03 -0700) are available in the git repository at: git://people.freedesktop.org/~danvet/drm-intel tags/drm-intel-fixes-2013-10-29 for you to fetch changes up to 1fbc0d789d12fec313c91912fc11733fdfbab863: drm/i915: Fix the PPT fdi lane bifurcate state handling on ivb (2013-10-29 13:52:56 +0100) Daniel Vetter (1): drm/i915: Fix the PPT fdi lane bifurcate state handling on ivb Jani Nikula (1): drm/i915/dp: workaround BIOS eDP bpp clamping issue Rob Pearce (1): drm/i915: No LVDS hardware on Intel D410PT and D425KT Ville Syrj?l? (2): drm/i915: Add support for pipe_bpp readout drm/i915: Add HSW CRT output readout support -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH] drm/nouveau/agp: add a quirk list to limit agp modes
On Sun, Oct 27, 2013 at 11:01 PM, Robert Hancock wrote: > On 10/27/2013 09:54 AM, Ilia Mirkin wrote: >> >> Certain combinations of hardware can't actually support the maximum >> detected speed. Add a quirk list that lists pairs of hostbridge/chip pci >> ids and the mode that they should work with. >> >> See https://bugs.freedesktop.org/show_bug.cgi?id=20341 > > > It seems like this quirk is likely too specific. This almost certainly > affects more than 5600 Ultra cards and probably not just NV cards either. It > probably affects more VIA chipsets than this too. > > Given the amount of breakage that seems to exist with VIA AGP chipsets, I > would think that being much more aggressive and forcing AGP mode to 2X > maximum at the AGP driver level for all VIA chipsets doesn't seem like it > would be a bad idea. The tricky part with AGP in general is that lowering the mode does not always improve stability. There are a lot of cases where the only stable mode is the one set up by the bios and lowering it causes more instability. Alex > >> >> Reported-by: Jason Detring >> Signed-off-by: Ilia Mirkin >> --- >> >> I didn't go as far as subdevice matching... IMO that's overkill for now. >> >> drivers/gpu/drm/nouveau/nouveau_agp.c | 44 >> +++ >> 1 file changed, 39 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c >> b/drivers/gpu/drm/nouveau/nouveau_agp.c >> index 6e7a55f..2953c4e 100644 >> --- a/drivers/gpu/drm/nouveau/nouveau_agp.c >> +++ b/drivers/gpu/drm/nouveau/nouveau_agp.c >> @@ -11,10 +11,28 @@ MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable >> AGP)"); >> static int nouveau_agpmode = -1; >> module_param_named(agpmode, nouveau_agpmode, int, 0400); >> >> +struct nouveau_agpmode_quirk { >> + u16 hostbridge_vendor; >> + u16 hostbridge_device; >> + u16 chip_vendor; >> + u16 chip_device; >> + int mode; >> +}; >> + >> +static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = { >> + /* VIA Apollo PRO133x / GeForce FX 5600 Ultra, max agpmode 2, fdo >> #20341 */ >> + { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, >> + >> + {}, >> +}; >> + >> static unsigned long >> -get_agp_mode(struct nouveau_drm *drm, unsigned long mode) >> +get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info) >> { >> struct nouveau_device *device = nv_device(drm->device); >> + struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list; >> + int agpmode = nouveau_agpmode; >> + unsigned long mode = info->mode; >> >> /* >> * FW seems to be broken on nv18, it makes the card lock up >> @@ -24,11 +42,27 @@ get_agp_mode(struct nouveau_drm *drm, unsigned long >> mode) >> mode &= ~PCI_AGP_COMMAND_FW; >> >> /* >> +* Go through the quirks list and adjust the agpmode accordingly. >> +*/ >> + while (agpmode == -1 && quirk->hostbridge_vendor) { >> + if (info->id_vendor == quirk->hostbridge_vendor && >> + info->id_device == quirk->hostbridge_device && >> + device->pdev->vendor == quirk->chip_vendor && >> + device->pdev->device == quirk->chip_device) { >> + agpmode = quirk->mode; >> + nv_info(device, "Forcing agp mode to %dX. Use >> agpmode to override.\n", >> + agpmode); >> + break; >> + } >> + ++quirk; >> + } >> + >> + /* >> * AGP mode set in the command line. >> */ >> - if (nouveau_agpmode > 0) { >> + if (agpmode > 0) { >> bool agpv3 = mode & 0x8; >> - int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode; >> + int rate = agpv3 ? agpmode / 4 : agpmode; >> >> mode = (mode & ~0x7) | (rate & 0x7); >> } >> @@ -90,7 +124,7 @@ nouveau_agp_reset(struct nouveau_drm *drm) >> if (ret) >> return; >> >> - mode.mode = get_agp_mode(drm, info.mode); >> + mode.mode = get_agp_mode(drm, &info); >> mode.mode &= ~PCI_AGP_COMMAND_FW; >> >> ret = drm_agp_enable(dev, mode); >> @@ -139,7 +173,7 @@ nouveau_agp_init(struct nouveau_drm *drm) >> } >> >> /* see agp.h for the AGPSTAT_* modes available */ >> - mode.mode = get_agp_mode(drm, info.mode); >> + mode.mode = get_agp_mode(drm, &info); >> >> ret = drm_agp_enable(dev, mode); >> if (ret) { >> > > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 63941] Can't control brightness with ATI 5650/Intel Ironlake when switched to radeon
https://bugzilla.kernel.org/show_bug.cgi?id=63941 Alex Deucher changed: What|Removed |Added CC||alexdeucher at gmail.com --- Comment #4 from Alex Deucher --- The radeon driver should add a backlight control if the platform utilizes the GPU's backlight controller. If there is no radeon backlight interface, the platform uses some OEM specific backlight control (probably Intel or ACPI). I suspect you will have to use the intel backlight control to control the backlight. -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 63941] Can't control brightness with ATI 5650/Intel Ironlake when switched to radeon
https://bugzilla.kernel.org/show_bug.cgi?id=63941 --- Comment #5 from Nikolay Amiantov --- Is there any way to trace ACPI calls and Intel card state (enabled or not) on Windows? It works there, so maybe I can get some information. 29.10.2013 17:32 ???: > https://bugzilla.kernel.org/show_bug.cgi?id=63941 > > Alex Deucher changed: > >What|Removed |Added > > > CC||alexdeucher at gmail.com > > --- Comment #4 from Alex Deucher --- > The radeon driver should add a backlight control if the platform utilizes > the > GPU's backlight controller. If there is no radeon backlight interface, the > platform uses some OEM specific backlight control (probably Intel or > ACPI). I > suspect you will have to use the intel backlight control to control the > backlight. > > -- > You are receiving this mail because: > You are on the CC list for the bug. > You reported the bug. > -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 63941] Can't control brightness with ATI 5650/Intel Ironlake when switched to radeon
https://bugzilla.kernel.org/show_bug.cgi?id=63941 --- Comment #6 from Nikolay Amiantov --- Comment on attachment 112661 --> https://bugzilla.kernel.org/attachment.cgi?id=112661 attachment-21199-0.html Replied from GMail and this happened, sorry. -- You are receiving this mail because: You are watching the assignee of the bug.
[PATCH] drm/ttm: Make NO_EVICT bos available to shrinkers pending destruction
On Thu, Oct 10, 2013 at 8:22 PM, Thomas Hellstrom wrote: > NO_EVICT bos that are not idle when all references are dropped are put on > the delayed destroy list. However, since they are not on LRU lists, they > are not available to shrinkers at that point, and buffers on the delayed > destroy list are not checked very often for idle. > > So when these buffers are put on the delayed destroy list, clear the > NO_EVICT flag and put them on the right LRU list. This way they are > immediately available for eviction or shrinkers and will not cause false > OOMS. > > Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz > --- > drivers/gpu/drm/ttm/ttm_bo.c | 14 +- > 1 file changed, 13 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c > index f1a857e..6c1a38f 100644 > --- a/drivers/gpu/drm/ttm/ttm_bo.c > +++ b/drivers/gpu/drm/ttm/ttm_bo.c > @@ -429,8 +429,20 @@ static void ttm_bo_cleanup_refs_or_queue(struct > ttm_buffer_object *bo) > sync_obj = driver->sync_obj_ref(bo->sync_obj); > spin_unlock(&bdev->fence_lock); > > - if (!ret) > + if (!ret) { > + > + /* > +* Make NO_EVICT bos immediately available to > +* shrinkers, now that they are queued for > +* destruction. > +*/ > + if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) { > + bo->mem.placement &= ~TTM_PL_FLAG_NO_EVICT; > + ttm_bo_add_to_lru(bo); > + } > + > ww_mutex_unlock(&bo->resv->lock); > + } > > kref_get(&bo->list_kref); > list_add_tail(&bo->ddestroy, &bdev->ddestroy); > -- > 1.7.10.4 > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/ttm: Allow vm fault retries
On Thu, Oct 10, 2013 at 8:22 PM, Thomas Hellstrom wrote: > Make use of the FAULT_FLAG_ALLOW_RETRY flag to allow dropping the > mmap_sem while waiting for bo idle. > > FAULT_FLAG_ALLOW_RETRY appears to be primarily designed for disk waits > but should work just as fine for GPU waits.. > > Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Tho somebody else should also take a look at this. > --- > drivers/gpu/drm/ttm/ttm_bo_vm.c | 62 > +++ > 1 file changed, 50 insertions(+), 12 deletions(-) > > diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c > index 1006c15..c03514b 100644 > --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c > +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c > @@ -41,6 +41,51 @@ > > #define TTM_BO_VM_NUM_PREFAULT 16 > > +static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, > + struct vm_area_struct *vma, > + struct vm_fault *vmf) > +{ > + struct ttm_bo_device *bdev = bo->bdev; > + int ret = 0; > + > + spin_lock(&bdev->fence_lock); > + if (likely(!test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags))) > + goto out_unlock; > + > + /* > +* Quick non-stalling check for idle. > +*/ > + ret = ttm_bo_wait(bo, false, false, true); > + if (likely(ret == 0)) > + goto out_unlock; > + > + /* > +* If possible, avoid waiting for GPU with mmap_sem > +* held. > +*/ > + if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) { > + ret = VM_FAULT_RETRY; > + if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) > + goto out_unlock; > + > + up_read(&vma->vm_mm->mmap_sem); > + (void) ttm_bo_wait(bo, false, true, false); > + goto out_unlock; > + } > + > + /* > +* Ordinary wait. > +*/ > + ret = ttm_bo_wait(bo, false, true, false); > + if (unlikely(ret != 0)) > + ret = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS : > + VM_FAULT_NOPAGE; > + > +out_unlock: > + spin_unlock(&bdev->fence_lock); > + return ret; > +} > + > static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) > { > struct ttm_buffer_object *bo = (struct ttm_buffer_object *) > @@ -91,18 +136,11 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, > struct vm_fault *vmf) > * Wait for buffer data in transit, due to a pipelined > * move. > */ > - > - spin_lock(&bdev->fence_lock); > - if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) { > - ret = ttm_bo_wait(bo, false, true, false); > - spin_unlock(&bdev->fence_lock); > - if (unlikely(ret != 0)) { > - retval = (ret != -ERESTARTSYS) ? > - VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; > - goto out_unlock; > - } > - } else > - spin_unlock(&bdev->fence_lock); > + ret = ttm_bo_vm_fault_idle(bo, vma, vmf); > + if (unlikely(ret != 0)) { > + retval = ret; > + goto out_unlock; > + } > > ret = ttm_mem_io_lock(man, true); > if (unlikely(ret != 0)) { > -- > 1.7.10.4 > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 63941] Can't control brightness with ATI 5650/Intel Ironlake when switched to radeon
https://bugzilla.kernel.org/show_bug.cgi?id=63941 Jani Nikula changed: What|Removed |Added Attachment #112661|0 |1 is obsolete|| -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 70934] [Regression] Problem with colors (depth?) on DCE5 Barts (HD69xx)
https://bugs.freedesktop.org/show_bug.cgi?id=70934 --- Comment #16 from Alex Deucher --- Does forcing the bpc to 8 fix the issue? If so, can you narrow down which particular table(s) are causing the problem? -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131029/7f7d7fab/attachment.html>
[PATCH 3/6] drm: restore crtc origin if mode_set_base fails
Signed-off-by: Ilija Hadzic --- drivers/gpu/drm/drm_crtc_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index b06a6c4..65f3658 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -814,6 +814,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ret = crtc_funcs->mode_set_base(set->crtc, set->x, set->y, save_set.fb); if (ret != 0) { + set->crtc->x = save_set.x; + set->crtc->y = save_set.y; set->crtc->fb = save_set.fb; goto fail; } -- 1.8.2.1
[PATCH 1/6] drm: remove redundant if statement
Signed-off-by: Ilija Hadzic --- drivers/gpu/drm/drm_crtc_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index dbcd687..d0ac595 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -814,8 +814,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) set->crtc->y = set->y; old_fb = set->crtc->fb; - if (set->crtc->fb != set->fb) - set->crtc->fb = set->fb; + set->crtc->fb = set->fb; ret = crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); if (ret != 0) { -- 1.8.2.1
fix for CRTC mutex corruption
The following patch series fixes the mutex corruption problem due to bit-copying of drm_crtc structure that happens when drm_crtc_helper_set_config function takes the error-recovery path. The patch series is the alternative solution for the patch that was proposed and NACK-ed two weeks ago [1]. The actual fix is implemented in patch #6; preceding 5 patches are necessary prerequisites. A couple of my own remarks: 1) Someone (including myself) may be tempted to eliminate the bit-copy for encoder and connector structures as well. I would, however, prefer to leave that improvement for a different patch series. The primary reason is that this patch series addresses an acute (and serious) problem (mutex corruption), while doing the equivalent rework for connector and encoder structure would be only for the sake of improving the code quality. 2) The problem exists in old (stable at ...) kernels and my original intention (in the patch that was NACK-ed [1]) was to make the fix simple enough to be eligible for stable at This patch series is now probably more complex than what stable at ... may be willing to accept. So the question in my mind is what we should do with the old kernels. 3) This patch series does not include the fix for incidental finding described in earlier discussions about this problem [2] because it's not the part of the fix that this patch series is targeting, so I'd leave it for later. regards, Ilija [1] http://lists.freedesktop.org/archives/dri-devel/2013-October/047479.html [2] http://lists.freedesktop.org/archives/dri-devel/2013-October/047557.html
[PATCH 4/6] drm: fix error recovery path in drm_crtc_helper_set_mode
There is no need to save or restore hwmode field, because by the time this function sets this field, it cannot fail any more. However, we should save old enabled field because if the function fails, we want to return with unchanged CRTC. Signed-off-by: Ilija Hadzic --- drivers/gpu/drm/drm_crtc_helper.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 65f3658..9e536b1 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -405,22 +405,25 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; - struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; + struct drm_display_mode *adjusted_mode, saved_mode; struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_encoder_helper_funcs *encoder_funcs; int saved_x, saved_y; + bool saved_enabled; struct drm_encoder *encoder; bool ret = true; + saved_enabled = crtc->enabled; crtc->enabled = drm_helper_crtc_in_use(crtc); if (!crtc->enabled) return true; adjusted_mode = drm_mode_duplicate(dev, mode); - if (!adjusted_mode) + if (!adjusted_mode) { + crtc->enabled = saved_enabled; return false; + } - saved_hwmode = crtc->hwmode; saved_mode = crtc->mode; saved_x = crtc->x; saved_y = crtc->y; @@ -539,7 +542,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, done: drm_mode_destroy(dev, adjusted_mode); if (!ret) { - crtc->hwmode = saved_hwmode; + crtc->enabled = saved_enabled; crtc->mode = saved_mode; crtc->x = saved_x; crtc->y = saved_y; -- 1.8.2.1
[PATCH 2/6] drm: eliminate old_fb from drm_crtc_helper_set_config
Old framebuffer is stored in save_set.fb and it is the same value that is later stored in old_fb. This makes old_fb redundant so we can replace it with save_set.fb. Signed-off-by: Ilija Hadzic --- drivers/gpu/drm/drm_crtc_helper.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d0ac595..b06a6c4 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -595,7 +595,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) struct drm_device *dev; struct drm_crtc *save_crtcs, *new_crtc, *crtc; struct drm_encoder *save_encoders, *new_encoder, *encoder; - struct drm_framebuffer *old_fb = NULL; bool mode_changed = false; /* if true do a full mode set */ bool fb_changed = false; /* if true and !mode_changed just do a flip */ struct drm_connector *save_connectors, *connector; @@ -790,14 +789,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); - old_fb = set->crtc->fb; set->crtc->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, set->y, - old_fb)) { + save_set.fb)) { DRM_ERROR("failed to set mode on [CRTC:%d]\n", set->crtc->base.id); - set->crtc->fb = old_fb; + set->crtc->fb = save_set.fb; ret = -EINVAL; goto fail; } @@ -812,13 +810,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } else if (fb_changed) { set->crtc->x = set->x; set->crtc->y = set->y; - - old_fb = set->crtc->fb; set->crtc->fb = set->fb; ret = crtc_funcs->mode_set_base(set->crtc, - set->x, set->y, old_fb); + set->x, set->y, save_set.fb); if (ret != 0) { - set->crtc->fb = old_fb; + set->crtc->fb = save_set.fb; goto fail; } } -- 1.8.2.1
[PATCH 5/6] drm: do not set crtc enabled field twice
There is no need to set crtc->enabled field in drm_crtc_helper_set_config. This is already done (and properly restored in case of failure) in drm_crtc_helper_set_mode that is called by drm_crtc_helper_set_config. Doing it at only one place makes restoration in case of failure easier. Signed-off-by: Ilija Hadzic --- drivers/gpu/drm/drm_crtc_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 9e536b1..a1322af 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -787,8 +787,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) mode_changed = true; if (mode_changed) { - set->crtc->enabled = drm_helper_crtc_in_use(set->crtc); - if (set->crtc->enabled) { + if (drm_helper_crtc_in_use(set->crtc)) { DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); -- 1.8.2.1
[PATCH 6/6] drm: eliminate bit-copy restoration of crtc
Bit-copying restoration of CRTC structure in failure-recovery path of drm_crtc_helper_set_config function evokes a subtle and rare, but very dangerous, corruption of CRTC mutex structure. Namely, if drm_crtc_helper_set_config takes the path under 'fail:' label *and* some other process has attempted to grab the crtc mutex (and got blocked), restoring the CRTC structure by bit-copying it will overwrite the CRTC mutex state and the waiters list pointer within the mutex structure. Consequently the blocked process will never be scheduled. This patch fixes the issue by eliminating the bit-copy restoration. The elimination is possible because previous patches have cleaned up the resoration path so that only the fields touched by the drm_crtc_helper_set_config function are saved and restored if necessary. Signed-off-by: Ilija Hadzic --- drivers/gpu/drm/drm_crtc_helper.c | 33 - 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a1322af..d171032 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -596,7 +596,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) int drm_crtc_helper_set_config(struct drm_mode_set *set) { struct drm_device *dev; - struct drm_crtc *save_crtcs, *new_crtc, *crtc; + struct drm_crtc *new_crtc; struct drm_encoder *save_encoders, *new_encoder, *encoder; bool mode_changed = false; /* if true do a full mode set */ bool fb_changed = false; /* if true and !mode_changed just do a flip */ @@ -633,38 +633,28 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) dev = set->crtc->dev; - /* Allocate space for the backup of all (non-pointer) crtc, encoder and -* connector data. */ - save_crtcs = kzalloc(dev->mode_config.num_crtc * -sizeof(struct drm_crtc), GFP_KERNEL); - if (!save_crtcs) - return -ENOMEM; - + /* +* Allocate space for the backup of all (non-pointer) encoder and +* connector data. +*/ save_encoders = kzalloc(dev->mode_config.num_encoder * sizeof(struct drm_encoder), GFP_KERNEL); - if (!save_encoders) { - kfree(save_crtcs); + if (!save_encoders) return -ENOMEM; - } save_connectors = kzalloc(dev->mode_config.num_connector * sizeof(struct drm_connector), GFP_KERNEL); if (!save_connectors) { - kfree(save_crtcs); kfree(save_encoders); return -ENOMEM; } - /* Copy data. Note that driver private data is not affected. + /* +* Copy data. Note that driver private data is not affected. * Should anything bad happen only the expected state is * restored, not the drivers personal bookkeeping. */ count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - save_crtcs[count++] = *crtc; - } - - count = 0; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { save_encoders[count++] = *encoder; } @@ -825,17 +815,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) kfree(save_connectors); kfree(save_encoders); - kfree(save_crtcs); return 0; fail: /* Restore all previous data. */ count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - *crtc = save_crtcs[count++]; - } - - count = 0; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { *encoder = save_encoders[count++]; } @@ -853,7 +837,6 @@ fail: kfree(save_connectors); kfree(save_encoders); - kfree(save_crtcs); return ret; } EXPORT_SYMBOL(drm_crtc_helper_set_config); -- 1.8.2.1
[PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver
This patchset refactors parts of the exynos driver to move it closer to a proper drm driver (rather than just implementing a drm layer on top of the hardware drivers). The hope is to get to a point where the dp/hdmi drivers can implement drm_connector/drm_encoder directly, and fimd/mixer can directly implement drm_crtc. The notable changes in this set: - drm_encoder funcs no longer route through the crtc - DP driver has been moved from video into the drm driver - fimd no longer implements encoder callbacks - exynos_drm_hdmi is removed in favor of generic manager/display handling At a glance, differences between v1 and v2: - Passing manager/display in callbacks instead of ctx - Tacked on some dpms patches on the end to handle suspend/resume through the dpms path At a glance, differences between v2 and v3: - Fixed vidi issues - Moved exynos_drm_hdmi.c removal to the right place - Added the exynos_drm_connector removal patches on the end Sean Daniel Kurtz (1): drm/exynos: hdmi: remove the i2c drivers and use devtree Sean Paul (30): drm/exynos: Merge overlay_ops into manager_ops drm/exynos: Add an initialize function to manager and display drm/exynos: Use manager_op initialize in fimd drm/exynos: hdmi: Implement initialize op for hdmi drm/exynos: Pass exynos_drm_manager in manager ops instead of dev drm/exynos: Remove apply manager callback drm/exynos: Remove dpms link between encoder/connector drm/exynos: Rename display_op power_on to dpms drm/exynos: Don't keep dpms state in encoder drm/exynos: Use unsigned long for possible_crtcs drm/exynos: Split manager/display/subdrv drm/exynos: Remove exynos_drm_hdmi shim drm/exynos: Use drm_mode_copy to copy modes drm/exynos: Disable unused crtc planes from crtc drm/exynos: Add mode_set manager operation drm/exynos: Implement mode_fixup manager operation drm/exynos: Use mode_set to configure fimd drm/exynos: Remove unused/useless fimd_context members drm/exynos: Move dp driver from video/ to drm/ drm/exynos: Move display implementation into dp ARM: dts: Move display-timings node from fimd to dp drm/exynos: Implement dpms display callback in DP drm/exynos: Clean up FIMD power on/off routines drm/exynos: Consolidate suspend/resume in drm_drv drm/exynos: Add create_connector callback drm/exynos: Implement drm_connector in hdmi directly drm/exynos: Implement drm_connector directly in dp driver drm/exynos: Implement drm_connector directly in vidi driver drm/exynos: Move lvds bridge discovery into DP driver drm/exynos: Remove the exynos_drm_connector shim St?phane Marchesin (1): drm/exynos: Remove useless slab.h include .../devicetree/bindings/video/exynos_dp.txt| 17 + .../devicetree/bindings/video/samsung-fimd.txt |2 + arch/arm/boot/dts/exynos5250-arndale.dts |7 +- arch/arm/boot/dts/exynos5250-smdk5250.dts |7 +- arch/arm/boot/dts/exynos5250-snow.dts |7 +- arch/arm/boot/dts/exynos5420-smdk5420.dts |7 +- drivers/gpu/drm/exynos/Kconfig |7 + drivers/gpu/drm/exynos/Makefile|7 +- drivers/gpu/drm/exynos/exynos_ddc.c| 63 - drivers/gpu/drm/exynos/exynos_dp_core.c| 1399 drivers/gpu/drm/exynos/exynos_dp_core.h| 220 +++ drivers/gpu/drm/exynos/exynos_dp_reg.c | 1245 + drivers/gpu/drm/exynos/exynos_dp_reg.h | 366 + drivers/gpu/drm/exynos/exynos_drm_connector.c | 304 - drivers/gpu/drm/exynos/exynos_drm_connector.h | 24 - drivers/gpu/drm/exynos/exynos_drm_core.c | 233 ++-- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 139 +- drivers/gpu/drm/exynos/exynos_drm_crtc.h | 20 +- drivers/gpu/drm/exynos/exynos_drm_drv.c| 155 ++- drivers/gpu/drm/exynos/exynos_drm_drv.h| 154 ++- drivers/gpu/drm/exynos/exynos_drm_encoder.c| 357 + drivers/gpu/drm/exynos/exynos_drm_encoder.h| 18 +- drivers/gpu/drm/exynos/exynos_drm_fb.c |4 +- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 875 ++-- drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 439 -- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 67 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 17 +- drivers/gpu/drm/exynos/exynos_drm_plane.h |2 +- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 434 +++--- drivers/gpu/drm/exynos/exynos_hdmi.c | 360 ++--- drivers/gpu/drm/exynos/exynos_hdmi.h | 23 - drivers/gpu/drm/exynos/exynos_hdmiphy.c| 65 - drivers/gpu/drm/exynos/exynos_mixer.c | 280 ++-- drivers/gpu/drm/exynos/exynos_mixer.h | 20 + drivers/video/exynos/Kconfig |7 - drive
[PATCH v3 01/32] drm/exynos: Remove useless slab.h include
From: St?phane Marchesin Signed-off-by: St?phane Marchesin Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/video/exynos/exynos_dp_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 12bbede..089ae22 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include -- 1.8.4
[PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops
This patch merges overlay_ops into manager_ops. In all cases, overlay_ops is implemented in the same place as manager ops, it doesn't serve a functional purpose, and doesn't make things more clear. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_drv.h | 29 +-- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 26 +- drivers/gpu/drm/exynos/exynos_drm_fimd.c| 363 ++-- drivers/gpu/drm/exynos/exynos_drm_hdmi.c| 36 ++- drivers/gpu/drm/exynos/exynos_drm_vidi.c| 29 +-- drivers/gpu/drm/exynos/exynos_mixer.c | 2 - 6 files changed, 229 insertions(+), 256 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index eaa1966..6f31839 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -54,22 +54,6 @@ enum exynos_drm_output_type { }; /* - * Exynos drm overlay ops structure. - * - * @mode_set: copy drm overlay info to hw specific overlay info. - * @commit: apply hardware specific overlay data to registers. - * @enable: enable hardware specific overlay. - * @disable: disable hardware specific overlay. - */ -struct exynos_drm_overlay_ops { - void (*mode_set)(struct device *subdrv_dev, -struct exynos_drm_overlay *overlay); - void (*commit)(struct device *subdrv_dev, int zpos); - void (*enable)(struct device *subdrv_dev, int zpos); - void (*disable)(struct device *subdrv_dev, int zpos); -}; - -/* * Exynos drm common overlay structure. * * @fb_x: offset x on a framebuffer to be displayed. @@ -169,6 +153,10 @@ struct exynos_drm_display_ops { * @disable_vblank: specific driver callback for disabling vblank interrupt. * @wait_for_vblank: wait for vblank interrupt to make sure that * hardware overlay is updated. + * @win_mode_set: copy drm overlay info to hw specific overlay info. + * @win_commit: apply hardware specific overlay data to registers. + * @win_enable: enable hardware specific overlay. + * @win_disable: disable hardware specific overlay. */ struct exynos_drm_manager_ops { void (*dpms)(struct device *subdrv_dev, int mode); @@ -184,6 +172,11 @@ struct exynos_drm_manager_ops { int (*enable_vblank)(struct device *subdrv_dev); void (*disable_vblank)(struct device *subdrv_dev); void (*wait_for_vblank)(struct device *subdrv_dev); + void (*win_mode_set)(struct device *subdrv_dev, + struct exynos_drm_overlay *overlay); + void (*win_commit)(struct device *subdrv_dev, int zpos); + void (*win_enable)(struct device *subdrv_dev, int zpos); + void (*win_disable)(struct device *subdrv_dev, int zpos); }; /* @@ -195,9 +188,6 @@ struct exynos_drm_manager_ops { * @ops: pointer to callbacks for exynos drm specific framebuffer. * these callbacks should be set by specific drivers such fimd * or hdmi driver and are used to control hardware global registers. - * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer. - * these callbacks should be set by specific drivers such fimd - * or hdmi driver and are used to control hardware overlay reigsters. * @display: pointer to callbacks for exynos drm specific framebuffer. * these callbacks should be set by specific drivers such fimd * or hdmi driver and are used to control display devices such as @@ -207,7 +197,6 @@ struct exynos_drm_manager { struct device *dev; int pipe; struct exynos_drm_manager_ops *ops; - struct exynos_drm_overlay_ops *overlay_ops; struct exynos_drm_display_ops *display_ops; }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 06f1b2a..c255341 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -133,7 +133,7 @@ static void disable_plane_to_crtc(struct drm_device *dev, * * plane->funcs->disable_plane call checks * if encoder->crtc is same as plane->crtc and if same -* then overlay_ops->disable callback will be called +* then manager_ops->win_disable callback will be called * to diasble current hw overlay so plane->crtc should * have new_crtc because new_crtc was set to * encoder->crtc in advance. @@ -442,51 +442,51 @@ void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data) { struct exynos_drm_manager *manager = to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; + struct exynos_drm_manager_ops *manager_ops = manager->ops; struct exynos_drm_overlay *overlay = data; - if (overlay
[PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd
This patch implements the intitialize manager op in fimd. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_fimd.c | 19 +++ 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index f271f22..90fcd6f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -106,6 +106,7 @@ struct fimd_win_data { struct fimd_context { struct exynos_drm_subdrvsubdrv; + struct drm_device *drm_dev; int irq; struct drm_crtc *crtc; struct clk *bus_clk; @@ -490,6 +491,16 @@ static void fimd_win_disable(struct device *dev, int zpos) win_data->enabled = false; } +static int fimd_mgr_initialize(struct device *subdrv_dev, + struct drm_device *drm_dev) +{ + struct fimd_context *ctx = get_fimd_context(subdrv_dev); + + ctx->drm_dev = drm_dev; + + return 0; +} + static void fimd_dpms(struct device *subdrv_dev, int mode) { struct fimd_context *ctx = get_fimd_context(subdrv_dev); @@ -660,6 +671,7 @@ static void fimd_wait_for_vblank(struct device *dev) } static struct exynos_drm_manager_ops fimd_manager_ops = { + .initialize = fimd_mgr_initialize, .dpms = fimd_dpms, .apply = fimd_apply, .commit = fimd_commit, @@ -681,7 +693,6 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) { struct fimd_context *ctx = (struct fimd_context *)dev_id; struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct drm_device *drm_dev = subdrv->drm_dev; struct exynos_drm_manager *manager = subdrv->manager; u32 val; @@ -692,11 +703,11 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); /* check the crtc is detached already from encoder */ - if (manager->pipe < 0) + if (manager->pipe < 0 || !ctx->drm_dev) goto out; - drm_handle_vblank(drm_dev, manager->pipe); - exynos_drm_crtc_finish_pageflip(drm_dev, manager->pipe); + drm_handle_vblank(ctx->drm_dev, manager->pipe); + exynos_drm_crtc_finish_pageflip(ctx->drm_dev, manager->pipe); /* set wait vsync event to zero and wake up queue. */ if (atomic_read(&ctx->wait_vsync_event)) { -- 1.8.4
[PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi
This patch implements the initialize callback in the hdmi and mixer manager. This allows us to get rid of drm_dev in the drm_hdmi level and track it in the mixer and hdmi drivers. This is one of the things holding back the complete removal of the drm_hdmi layer. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 35 ++-- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 3 ++- drivers/gpu/drm/exynos/exynos_hdmi.c | 18 drivers/gpu/drm/exynos/exynos_mixer.c| 35 +++- 4 files changed, 66 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index a1ef3c9..aebcc0e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -97,6 +97,18 @@ void exynos_mixer_ops_register(struct exynos_mixer_ops *ops) mixer_ops = ops; } +static int drm_hdmi_display_initialize(struct device *dev, + struct drm_device *drm_dev) +{ + struct drm_hdmi_context *ctx = to_context(dev); + + if (hdmi_ops && hdmi_ops->initialize) + return hdmi_ops->initialize(ctx->hdmi_ctx->ctx, drm_dev); + + return 0; +} + + static bool drm_hdmi_is_connected(struct device *dev) { struct drm_hdmi_context *ctx = to_context(dev); @@ -153,6 +165,7 @@ static int drm_hdmi_power_on(struct device *dev, int mode) static struct exynos_drm_display_ops drm_hdmi_display_ops = { .type = EXYNOS_DISPLAY_TYPE_HDMI, + .initialize = drm_hdmi_display_initialize, .is_connected = drm_hdmi_is_connected, .get_edid = drm_hdmi_get_edid, .check_mode = drm_hdmi_check_mode, @@ -257,6 +270,21 @@ static void drm_hdmi_commit(struct device *subdrv_dev) hdmi_ops->commit(ctx->hdmi_ctx->ctx); } +static int drm_hdmi_mgr_initialize(struct device *subdrv_dev, + struct drm_device *drm_dev) +{ + struct drm_hdmi_context *ctx = to_context(subdrv_dev); + int ret = 0; + + if (mixer_ops && mixer_ops->initialize) + ret = mixer_ops->initialize(ctx->mixer_ctx->ctx, drm_dev); + + if (mixer_ops->iommu_on) + mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true); + + return ret; +} + static void drm_hdmi_dpms(struct device *subdrv_dev, int mode) { struct drm_hdmi_context *ctx = to_context(subdrv_dev); @@ -326,6 +354,7 @@ static void drm_mixer_win_disable(struct device *subdrv_dev, int zpos) } static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { + .initialize = drm_hdmi_mgr_initialize, .dpms = drm_hdmi_dpms, .apply = drm_hdmi_apply, .enable_vblank = drm_hdmi_enable_vblank, @@ -372,12 +401,6 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev, ctx->hdmi_ctx = hdmi_ctx; ctx->mixer_ctx = mixer_ctx; - ctx->hdmi_ctx->drm_dev = drm_dev; - ctx->mixer_ctx->drm_dev = drm_dev; - - if (mixer_ops->iommu_on) - mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true); - return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index 724cab1..cf7b1da 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -23,12 +23,12 @@ * this context should be hdmi_context or mixer_context. */ struct exynos_drm_hdmi_context { - struct drm_device *drm_dev; void*ctx; }; struct exynos_hdmi_ops { /* display */ + int (*initialize)(void *ctx, struct drm_device *drm_dev); bool (*is_connected)(void *ctx); struct edid *(*get_edid)(void *ctx, struct drm_connector *connector); @@ -45,6 +45,7 @@ struct exynos_hdmi_ops { struct exynos_mixer_ops { /* manager */ + int (*initialize)(void *ctx, struct drm_device *drm_dev); int (*iommu_on)(void *ctx, bool enable); int (*enable_vblank)(void *ctx, int pipe); void (*disable_vblank)(void *ctx); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index fcfa23a..00704e9 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -741,6 +741,15 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, } } +static int hdmi_initialize(void *ctx, struct drm_device *drm_dev) +{ + struct hdmi_context *hdata = ctx; + + hdata->drm_dev = drm_dev; + + return 0; +} + static bool hdmi_is_connected(void *ctx) { struct hdmi_context *hdata = ctx; @@ -1746,6 +1755,7 @@ static void hdmi_dpms(void *ctx, int mode) static struct exynos_hdmi_ops hdmi_ops = { /* display */ + .initialize = hdmi_initialize, .is_connected = hdmi_is_connected, .get_edid = hdmi_get_edid, .che
[PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
This patch changes the manager ops callbacks from accepting the subdrv device pointer to taking a pointer to the manager. This will allow us to move closer to decoupling manager/display from subdrv, and subsequently decoupling the crtc/plane from the encoder. Signed-off-by: Sean Paul --- Changes in v2: - Instead of passing context, pass manager - Properly assign ctx->dev in fimd driver Changes in v3: - Added vidi implementation drivers/gpu/drm/exynos/exynos_drm_connector.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_drv.h | 35 drivers/gpu/drm/exynos/exynos_drm_encoder.c | 27 +++--- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 114 ++ drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 72 drivers/gpu/drm/exynos/exynos_drm_vidi.c | 83 ++- 6 files changed, 180 insertions(+), 153 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index e082efb..23b69d8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -198,7 +198,7 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector, * resolution then get max width and height from that driver. */ if (ops && ops->get_max_resol) - ops->get_max_resol(manager->dev, &width, &height); + ops->get_max_resol(manager, &width, &height); return drm_helper_probe_single_connector_modes(connector, width, height); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 09bfe60..8eb8b83 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -161,27 +161,28 @@ struct exynos_drm_display_ops { * @win_enable: enable hardware specific overlay. * @win_disable: disable hardware specific overlay. */ +struct exynos_drm_manager; struct exynos_drm_manager_ops { - int (*initialize)(struct device *subdrv_dev, - struct drm_device *drm_dev); - void (*dpms)(struct device *subdrv_dev, int mode); - void (*apply)(struct device *subdrv_dev); - void (*mode_fixup)(struct device *subdrv_dev, + int (*initialize)(struct exynos_drm_manager *mgr, + struct drm_device *drm_dev); + void (*dpms)(struct exynos_drm_manager *mgr, int mode); + void (*apply)(struct exynos_drm_manager *mgr); + void (*mode_fixup)(struct exynos_drm_manager *mgr, struct drm_connector *connector, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); - void (*mode_set)(struct device *subdrv_dev, void *mode); - void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, - unsigned int *height); - void (*commit)(struct device *subdrv_dev); - int (*enable_vblank)(struct device *subdrv_dev); - void (*disable_vblank)(struct device *subdrv_dev); - void (*wait_for_vblank)(struct device *subdrv_dev); - void (*win_mode_set)(struct device *subdrv_dev, + void (*mode_set)(struct exynos_drm_manager *mgr, void *mode); + void (*get_max_resol)(struct exynos_drm_manager *mgr, + unsigned int *width, unsigned int *height); + void (*commit)(struct exynos_drm_manager *mgr); + int (*enable_vblank)(struct exynos_drm_manager *mgr); + void (*disable_vblank)(struct exynos_drm_manager *mgr); + void (*wait_for_vblank)(struct exynos_drm_manager *mgr); + void (*win_mode_set)(struct exynos_drm_manager *mgr, struct exynos_drm_overlay *overlay); - void (*win_commit)(struct device *subdrv_dev, int zpos); - void (*win_enable)(struct device *subdrv_dev, int zpos); - void (*win_disable)(struct device *subdrv_dev, int zpos); + void (*win_commit)(struct exynos_drm_manager *mgr, int zpos); + void (*win_enable)(struct exynos_drm_manager *mgr, int zpos); + void (*win_disable)(struct exynos_drm_manager *mgr, int zpos); }; /* @@ -197,12 +198,14 @@ struct exynos_drm_manager_ops { * these callbacks should be set by specific drivers such fimd * or hdmi driver and are used to control display devices such as * analog tv, digital tv and lcd panel and also get timing data for them. + * @ctx: A pointer to the manager's implementation specific context */ struct exynos_drm_manager { struct device *dev; int pipe; struct exynos_drm_manager_ops *ops; struct exynos_drm_display_ops *display_ops; + void *ctx; }; struct exynos_drm_g2d_private { diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/e
[PATCH v3 07/32] drm/exynos: Remove apply manager callback
This patch removes the apply() manager callback in favor of putting the relevant commits in the individual drivers. This will mitigate some of the difference between the suspend/resume path and the dpms path Signed-off-by: Sean Paul --- Changes in v2: - This was previously in another patch, but moved since it warrants its own Changes in v3: - Removed apply() from vidi drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 -- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 6 -- drivers/gpu/drm/exynos/exynos_drm_fimd.c| 22 +- drivers/gpu/drm/exynos/exynos_drm_hdmi.c| 17 - drivers/gpu/drm/exynos/exynos_drm_vidi.c| 1 - drivers/gpu/drm/exynos/exynos_hdmi.c| 1 + drivers/gpu/drm/exynos/exynos_mixer.c | 2 ++ 7 files changed, 8 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 8eb8b83..bff432a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -146,7 +146,6 @@ struct exynos_drm_display_ops { * * @initialize: initializes the manager with drm_dev * @dpms: control device power. - * @apply: set timing, vblank and overlay data to registers. * @mode_fixup: fix mode data comparing to hw specific display mode. * @mode_set: convert drm_display_mode to hw specific display mode and * would be called by encoder->mode_set(). @@ -166,7 +165,6 @@ struct exynos_drm_manager_ops { int (*initialize)(struct exynos_drm_manager *mgr, struct drm_device *drm_dev); void (*dpms)(struct exynos_drm_manager *mgr, int mode); - void (*apply)(struct exynos_drm_manager *mgr); void (*mode_fixup)(struct exynos_drm_manager *mgr, struct drm_connector *connector, const struct drm_display_mode *mode, diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index ec627fa..19ee84d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -57,8 +57,6 @@ static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_manager_ops *manager_ops = manager->ops; struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); DRM_DEBUG_KMS("encoder dpms: %d\n", mode); @@ -72,10 +70,6 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - if (manager_ops && manager_ops->apply) - if (!exynos_encoder->updated) - manager_ops->apply(manager); - exynos_drm_connector_power(encoder, mode); exynos_encoder->dpms = mode; break; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 2769eb3..f0ac1d5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -672,7 +672,6 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr) static struct exynos_drm_manager_ops fimd_manager_ops = { .initialize = fimd_mgr_initialize, .dpms = fimd_dpms, - .apply = fimd_apply, .commit = fimd_commit, .enable_vblank = fimd_enable_vblank, .disable_vblank = fimd_disable_vblank, @@ -883,6 +882,8 @@ static int fimd_activate(struct exynos_drm_manager *mgr, bool enable) fimd_enable_vblank(mgr); fimd_window_resume(dev); + + fimd_apply(mgr); } else { fimd_window_suspend(dev); @@ -1037,23 +1038,10 @@ static int fimd_resume(struct device *dev) * of pm runtime would still be 1 so in this case, fimd driver * should be on directly not drawing on pm runtime interface. */ - if (!pm_runtime_suspended(dev)) { - int ret; + if (pm_runtime_suspended(dev)) + return 0; - ret = fimd_activate(mgr, true); - if (ret < 0) - return ret; - - /* -* in case of dpms on(standby), fimd_apply function will -* be called by encoder's dpms callback to update fimd's -* registers but in case of sleep wakeup, it's not. -* so fimd_apply function should be called at here. -*/ - fimd_apply(mgr); - } - - return 0; + return fimd_activate(mgr, true); } #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm
[PATCH v3 08/32] drm/exynos: Remove dpms link between encoder/connector
This patch removes the call from encoder dpms into connector dpms (which will then call back into encoder dpms through the helper function). The callback is likely to keep connector->dpms in the right state when initiating dpms from crtc or encoder, but this isn't the right way to do it. This patch is the first step towards rationalizing power management in the exynos drm driver. Signed-off-by: Sean Paul --- Changes in v2: - Split out the apply change into a new patch Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_connector.c | 42 ++ drivers/gpu/drm/exynos/exynos_drm_connector.h | 4 --- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 50 +++ 3 files changed, 8 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 23b69d8..ca270e2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -26,7 +26,6 @@ struct exynos_drm_connector { struct drm_connectordrm_connector; uint32_tencoder_id; struct exynos_drm_manager *manager; - uint32_tdpms; }; static int exynos_drm_connector_get_modes(struct drm_connector *connector) @@ -119,7 +118,8 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector, return ret; } -struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector) +static struct drm_encoder *exynos_drm_best_encoder( + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct exynos_drm_connector *exynos_connector = @@ -146,41 +146,6 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = { .best_encoder = exynos_drm_best_encoder, }; -void exynos_drm_display_power(struct drm_connector *connector, int mode) -{ - struct drm_encoder *encoder = exynos_drm_best_encoder(connector); - struct exynos_drm_connector *exynos_connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_display_ops *display_ops = manager->display_ops; - - exynos_connector = to_exynos_connector(connector); - - if (exynos_connector->dpms == mode) { - DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); - return; - } - - if (display_ops && display_ops->power_on) - display_ops->power_on(manager->dev, mode); - - exynos_connector->dpms = mode; -} - -static void exynos_drm_connector_dpms(struct drm_connector *connector, - int mode) -{ - /* -* in case that drm_crtc_helper_set_mode() is called, -* encoder/crtc->funcs->dpms() will be just returned -* because they already were DRM_MODE_DPMS_ON so only -* exynos_drm_display_power() will be called. -*/ - drm_helper_connector_dpms(connector, mode); - - exynos_drm_display_power(connector, mode); - -} - static int exynos_drm_connector_fill_modes(struct drm_connector *connector, unsigned int max_width, unsigned int max_height) { @@ -236,7 +201,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector) } static struct drm_connector_funcs exynos_connector_funcs = { - .dpms = exynos_drm_connector_dpms, + .dpms = drm_helper_connector_dpms, .fill_modes = exynos_drm_connector_fill_modes, .detect = exynos_drm_connector_detect, .destroy= exynos_drm_connector_destroy, @@ -281,7 +246,6 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, exynos_connector->encoder_id = encoder->base.id; exynos_connector->manager = manager; - exynos_connector->dpms = DRM_MODE_DPMS_OFF; connector->dpms = DRM_MODE_DPMS_OFF; connector->encoder = encoder; diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h index 547c6b5..4eb20d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.h +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.h @@ -17,8 +17,4 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, struct drm_encoder *encoder); -struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector); - -void exynos_drm_display_power(struct drm_connector *connector, int mode); - #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 19ee84d..df4b2852 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -29,35 +29,19 @@ * @manager: specific encoder has its own manager to control a hardware * appropriately and we can access a har
[PATCH v3 11/32] drm/exynos: Use unsigned long for possible_crtcs
Change all instances of possible_crtcs in the exynos drm driver to be unsigned long. This matches the type used in the drm layer. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_encoder.h | 2 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_plane.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index bb82ef7..617748e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -84,7 +84,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) for (nr = 0; nr < MAX_PLANE; nr++) { struct drm_plane *plane; - unsigned int possible_crtcs = (1 << MAX_CRTC) - 1; + unsigned long possible_crtcs = (1 << MAX_CRTC) - 1; plane = exynos_plane_init(dev, possible_crtcs, false); if (!plane) diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index a823d53..efe4e60 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -249,7 +249,7 @@ void exynos_drm_encoder_setup(struct drm_device *dev) struct drm_encoder * exynos_drm_encoder_create(struct drm_device *dev, struct exynos_drm_manager *manager, - unsigned int possible_crtcs) + unsigned long possible_crtcs) { struct drm_encoder *encoder; struct exynos_drm_encoder *exynos_encoder; diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h index 89e2fb0..0f3e5e2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h @@ -19,7 +19,7 @@ struct exynos_drm_manager; void exynos_drm_encoder_setup(struct drm_device *dev); struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, struct exynos_drm_manager *mgr, - unsigned int possible_crtcs); + unsigned long possible_crtcs); struct exynos_drm_manager * exynos_drm_get_manager(struct drm_encoder *encoder); void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index fcb0652..cff3aed 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -259,7 +259,7 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane) } struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned int possible_crtcs, bool priv) + unsigned long possible_crtcs, bool priv) { struct exynos_plane *exynos_plane; int err; diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 8831245..84d464c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -17,4 +17,4 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, void exynos_plane_commit(struct drm_plane *plane); void exynos_plane_dpms(struct drm_plane *plane, int mode); struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned int possible_crtcs, bool priv); + unsigned long possible_crtcs, bool priv); -- 1.8.4
[PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree
From: Daniel Kurtz The i2c client was previously being passed into the hdmi driver via a dedicated i2c driver, and then a global variable. This patch removes all of that and just uses the device tree to get the i2c_client. This patch also properly references the client so we don't lose it before we're done with it. Signed-off-by: Daniel Kurtz Signed-off-by: Sean Paul --- Changes in v2: - Change include to linux/i2c.h instead of linux/of_i2c.h Changes in v3: None drivers/gpu/drm/exynos/Makefile | 1 - drivers/gpu/drm/exynos/exynos_ddc.c | 63 drivers/gpu/drm/exynos/exynos_hdmi.c| 59 ++ drivers/gpu/drm/exynos/exynos_hdmi.h| 23 drivers/gpu/drm/exynos/exynos_hdmiphy.c | 65 - 5 files changed, 27 insertions(+), 184 deletions(-) delete mode 100644 drivers/gpu/drm/exynos/exynos_ddc.c delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.h delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 639b49e..819961a 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -12,7 +12,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)+= exynos_drm_fimd.o exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)+= exynos_hdmi.o exynos_mixer.o \ - exynos_ddc.o exynos_hdmiphy.o \ exynos_drm_hdmi.o exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)+= exynos_drm_vidi.o exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o diff --git a/drivers/gpu/drm/exynos/exynos_ddc.c b/drivers/gpu/drm/exynos/exynos_ddc.c deleted file mode 100644 index 6a8c84e..000 --- a/drivers/gpu/drm/exynos/exynos_ddc.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Seung-Woo Kim - * Inki Dae - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include - -#include -#include -#include - -#include "exynos_drm_drv.h" -#include "exynos_hdmi.h" - -static int s5p_ddc_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - hdmi_attach_ddc_client(client); - - dev_info(&client->adapter->dev, - "attached %s into i2c adapter successfully\n", - client->name); - - return 0; -} - -static int s5p_ddc_remove(struct i2c_client *client) -{ - dev_info(&client->adapter->dev, - "detached %s from i2c adapter successfully\n", - client->name); - - return 0; -} - -static struct of_device_id hdmiddc_match_types[] = { - { - .compatible = "samsung,exynos5-hdmiddc", - }, { - .compatible = "samsung,exynos4210-hdmiddc", - }, { - /* end node */ - } -}; - -struct i2c_driver ddc_driver = { - .driver = { - .name = "exynos-hdmiddc", - .owner = THIS_MODULE, - .of_match_table = hdmiddc_match_types, - }, - .probe = s5p_ddc_probe, - .remove = s5p_ddc_remove, - .command= NULL, -}; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index d35ab2a..e106309 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -40,8 +41,6 @@ #include "exynos_drm_drv.h" #include "exynos_drm_hdmi.h" -#include "exynos_hdmi.h" - #include #include @@ -1849,20 +1848,6 @@ fail: return -ENODEV; } -static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy; - -void hdmi_attach_ddc_client(struct i2c_client *ddc) -{ - if (ddc) - hdmi_ddc = ddc; -} - -void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy) -{ - if (hdmiphy) - hdmi_hdmiphy = hdmiphy; -} - static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata (struct device *dev) { @@ -1907,6 +1892,7 @@ static int hdmi_probe(struct platform_device *pdev) struct s5p_hdmi_platform_data *pdata; struct resource *res; const struct of_device_id *match; + struct device_node *ddc_node, *phy_node; int ret; if (!dev->of_node) @@ -1957,21 +1943,30 @@ static int hdmi_probe(struct platform_device *pdev) } /* DDC i2c driver */ - if (i2c_add_driver(&ddc_driver)) { - DRM_ERROR("failed to register ddc i2c driver\n"); -
[PATCH v3 14/32] drm/exynos: Remove exynos_drm_hdmi shim
This patch trims exynos_drm_hdmi out of the driver. The reason it existed in the first place was to make up for the mixture of display/overlay/manager ops being spread across hdmi and mixer. With that code now rationalized, mixer and hdmi map directly to exynos_drm_crtc and exynos_drm_encoder, respectively. Since there is a 1:1 mapping, we no longer need this layer. Signed-off-by: Sean Paul --- Changes in v2: - hdmi/mixer ops now take display/manager instead of context Changes in v3: - Moved removal of exynos_drm_hdmi.c file here drivers/gpu/drm/exynos/Makefile | 3 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 13 - drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 416 --- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 69 - drivers/gpu/drm/exynos/exynos_hdmi.c | 162 +++- drivers/gpu/drm/exynos/exynos_mixer.c| 204 --- drivers/gpu/drm/exynos/exynos_mixer.h| 20 ++ 7 files changed, 222 insertions(+), 665 deletions(-) delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.h create mode 100644 drivers/gpu/drm/exynos/exynos_mixer.h diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 819961a..afbe499 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -11,8 +11,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)+= exynos_drm_fimd.o -exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)+= exynos_hdmi.o exynos_mixer.o \ - exynos_drm_hdmi.o +exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)+= exynos_hdmi.o exynos_mixer.o exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)+= exynos_drm_vidi.o exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 250903c..4b265bf 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -329,13 +329,6 @@ static int __init exynos_drm_init(void) ret = platform_driver_register(&mixer_driver); if (ret < 0) goto out_mixer; - ret = platform_driver_register(&exynos_drm_common_hdmi_driver); - if (ret < 0) - goto out_common_hdmi; - - ret = exynos_platform_device_hdmi_register(); - if (ret < 0) - goto out_common_hdmi_dev; #endif #ifdef CONFIG_DRM_EXYNOS_VIDI @@ -428,10 +421,6 @@ out_vidi: #endif #ifdef CONFIG_DRM_EXYNOS_HDMI - exynos_platform_device_hdmi_unregister(); -out_common_hdmi_dev: - platform_driver_unregister(&exynos_drm_common_hdmi_driver); -out_common_hdmi: platform_driver_unregister(&mixer_driver); out_mixer: platform_driver_unregister(&hdmi_driver); @@ -473,8 +462,6 @@ static void __exit exynos_drm_exit(void) #endif #ifdef CONFIG_DRM_EXYNOS_HDMI - exynos_platform_device_hdmi_unregister(); - platform_driver_unregister(&exynos_drm_common_hdmi_driver); platform_driver_unregister(&mixer_driver); platform_driver_unregister(&hdmi_driver); #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c deleted file mode 100644 index b0b09b2..000 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Inki Dae - * Seung-Woo Kim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include - -#include -#include -#include -#include - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_hdmi.h" - -/* platform device pointer for common drm hdmi device. */ -static struct platform_device *exynos_drm_hdmi_pdev; - -/* Common hdmi subdrv needs to access the hdmi and mixer though context. -* These should be initialied by the repective drivers */ -static struct exynos_drm_hdmi_context *hdmi_ctx; -static struct exynos_drm_hdmi_context *mixer_ctx; - -/* these callback points shoud be set by specific drivers. */ -static struct exynos_hdmi_ops *hdmi_ops; -static struct exynos_mixer_ops *mixer_ops; - -struct drm_hdmi_context { - struct exynos_drm_hdmi_context *hdmi_ctx; - struct exynos_drm_hdmi_context *mixer_ctx; - - boolenabled[MIXER_WIN_NR]; -}; - -int exynos_platform_device_hdmi_register(void) -{ - struct platform_device *pdev; - - if (exynos_drm_hdmi_pdev) - return -EEXIST; - - pdev = pl
[PATCH v3 22/32] drm/exynos: Move display implementation into dp
This patch moves the exynos_drm_display implementation from fimd into the dp driver. This will allow for tighter integration of the dp driver into the exynos drm driver. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None .../devicetree/bindings/video/exynos_dp.txt| 17 +++ .../devicetree/bindings/video/samsung-fimd.txt | 2 + drivers/gpu/drm/exynos/exynos_dp_core.c| 137 - drivers/gpu/drm/exynos/exynos_dp_core.h| 5 + drivers/gpu/drm/exynos/exynos_drm_drv.c| 14 +++ drivers/gpu/drm/exynos/exynos_drm_drv.h| 1 + drivers/gpu/drm/exynos/exynos_drm_fimd.c | 78 +++- 7 files changed, 156 insertions(+), 98 deletions(-) diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 84f10c1..a073e15 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -45,6 +45,8 @@ Required properties for dp-controller: -samsung,lane-count: number of lanes supported by the panel. LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4 + - display-timings: timings for the connected panel as described by + Documentation/devicetree/bindings/video/display-timing.txt Optional properties for dp-controller: -interlaced: @@ -83,4 +85,19 @@ Board Specific portion: samsung,color-depth = <1>; samsung,link-rate = <0x0a>; samsung,lane-count = <4>; + + display-timings { + native-mode = <&lcd_timing>; + lcd_timing: 1366x768 { + clock-frequency = <70589280>; + hactive = <1366>; + vactive = <768>; + hfront-porch = <40>; + hback-porch = <40>; + hsync-len = <32>; + vback-porch = <10>; + vfront-porch = <12>; + vsync-len = <6>; + }; + }; }; diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt index 778838a..fa465c3 100644 --- a/Documentation/devicetree/bindings/video/samsung-fimd.txt +++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt @@ -39,6 +39,8 @@ Required properties: Optional Properties: - samsung,power-domain: a phandle to FIMD power domain node. +- samsung,invert-vden: video enable signal is inverted +- samsung,invert_vclk: video clock signal is inverted Example: diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 089ae22..13ea8b7 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -18,9 +18,12 @@ #include #include #include +#include +#include -#include +#include +#include "exynos_drm_drv.h" #include "exynos_dp_core.h" static int exynos_dp_init_dp(struct exynos_dp_device *dp) @@ -893,6 +896,35 @@ static void exynos_dp_hotplug(struct work_struct *work) dev_err(dp->dev, "unable to config video\n"); } +static bool exynos_dp_display_is_connected(struct exynos_drm_display *display) +{ + return true; +} + +static void *exynos_dp_get_panel(struct exynos_drm_display *display) +{ + struct exynos_dp_device *dp = display->ctx; + + return &dp->panel; +} + +static int exynos_dp_check_mode(struct exynos_drm_display *display, + struct drm_display_mode *mode) +{ + return 0; +} + +static struct exynos_drm_display_ops exynos_dp_display_ops = { + .is_connected = exynos_dp_display_is_connected, + .get_panel = exynos_dp_get_panel, + .check_mode = exynos_dp_check_mode, +}; + +static struct exynos_drm_display exynos_dp_display = { + .type = EXYNOS_DISPLAY_TYPE_LCD, + .ops = &exynos_dp_display_ops, +}; + #ifdef CONFIG_OF static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) { @@ -1000,6 +1032,19 @@ err: return ret; } +static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) +{ + int ret; + + ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm, + OF_USE_NATIVE_MODE); + if (ret) { + DRM_ERROR("failed: of_get_videomode() : %d\n", ret); + return ret; + } + return 0; +} + static void exynos_dp_phy_init(struct exynos_dp_device *dp) { u32 reg; @@ -1028,6 +1073,11 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) return -EINVAL; } +static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) +{ + return -EINVAL; +} + static void exynos_dp_phy_init
[PATCH v3 23/32] ARM: dts: Move display-timings node from fimd to dp
This patch moves the display-timings node from fimd to dp to reflect the device tree bindings change. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None arch/arm/boot/dts/exynos5250-arndale.dts | 7 --- arch/arm/boot/dts/exynos5250-smdk5250.dts | 7 --- arch/arm/boot/dts/exynos5250-snow.dts | 7 --- arch/arm/boot/dts/exynos5420-smdk5420.dts | 7 --- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index cee55fa..4583de4 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -517,10 +517,7 @@ samsung,link-rate = <0x0a>; samsung,lane-count = <4>; status = "okay"; - }; - fimd: fimd at 1440 { - status = "okay"; display-timings { native-mode = <&timing0>; timing0: timing at 0 { @@ -538,6 +535,10 @@ }; }; + fimd: fimd at 1440 { + status = "okay"; + }; + usb_hub_bus { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 2538b32..df1001d 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -261,10 +261,7 @@ pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>; status = "okay"; - }; - fimd at 1440 { - status = "okay"; display-timings { native-mode = <&timing0>; timing0: timing at 0 { @@ -282,6 +279,10 @@ }; }; + fimd at 1440 { + status = "okay"; + }; + fixed-rate-clocks { xxti { compatible = "samsung,clock-xxti"; diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index 86e8db5..395dbf7 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -223,10 +223,7 @@ pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>; status = "okay"; - }; - fimd: fimd at 1440 { - status = "okay"; display-timings { native-mode = <&lcd_timing>; lcd_timing: 1366x768 { @@ -243,6 +240,10 @@ }; }; + fimd: fimd at 1440 { + status = "okay"; + }; + fixed-rate-clocks { xxti { compatible = "samsung,clock-xxti"; diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index bafba25..763797c 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -41,10 +41,7 @@ samsung,link-rate = <0x0a>; samsung,lane-count = <4>; status = "okay"; - }; - fimd at 1440 { - status = "okay"; display-timings { native-mode = <&timing0>; timing0: timing at 0 { @@ -61,4 +58,8 @@ }; }; + fimd at 1440 { + status = "okay"; + }; + }; -- 1.8.4
[PATCH v3 24/32] drm/exynos: Implement dpms display callback in DP
This patch implements the dpms display callback for the DP driver. Signed-off-by: Sean Paul --- Changes in v2: - Added to the patchset Changes in v3: None drivers/gpu/drm/exynos/exynos_dp_core.c | 173 drivers/gpu/drm/exynos/exynos_dp_core.h | 1 + 2 files changed, 85 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 13ea8b7..476d3b0 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -914,10 +914,82 @@ static int exynos_dp_check_mode(struct exynos_drm_display *display, return 0; } +static void exynos_dp_phy_init(struct exynos_dp_device *dp) +{ + struct exynos_dp_platdata *pdata = dp->dev->platform_data; + u32 reg; + + if (dp->phy_addr) { + reg = readl(dp->phy_addr); + reg |= dp->enable_mask; + writel(reg, dp->phy_addr); + } + + if (pdata && pdata->phy_init) + pdata->phy_init(); +} + +static void exynos_dp_phy_exit(struct exynos_dp_device *dp) +{ + struct exynos_dp_platdata *pdata = dp->dev->platform_data; + u32 reg; + + if (dp->phy_addr) { + reg = readl(dp->phy_addr); + reg &= ~(dp->enable_mask); + writel(reg, dp->phy_addr); + } + + if (pdata && pdata->phy_exit) + pdata->phy_exit(); +} + +static void exynos_dp_poweron(struct exynos_dp_device *dp) +{ + if (dp->dpms_mode == DRM_MODE_DPMS_ON) + return; + + clk_prepare_enable(dp->clock); + exynos_dp_phy_init(dp); + exynos_dp_init_dp(dp); + enable_irq(dp->irq); +} + +static void exynos_dp_poweroff(struct exynos_dp_device *dp) +{ + if (dp->dpms_mode != DRM_MODE_DPMS_ON) + return; + + disable_irq(dp->irq); + flush_work(&dp->hotplug_work); + exynos_dp_phy_exit(dp); + clk_disable_unprepare(dp->clock); +} + +static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) +{ + struct exynos_dp_device *dp = display->ctx; + + switch (mode) { + case DRM_MODE_DPMS_ON: + exynos_dp_poweron(dp); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + exynos_dp_poweroff(dp); + break; + default: + break; + }; + dp->dpms_mode = mode; +} + static struct exynos_drm_display_ops exynos_dp_display_ops = { .is_connected = exynos_dp_display_is_connected, .get_panel = exynos_dp_get_panel, .check_mode = exynos_dp_check_mode, + .dpms = exynos_dp_dpms, }; static struct exynos_drm_display exynos_dp_display = { @@ -1044,24 +1116,6 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) } return 0; } - -static void exynos_dp_phy_init(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = __raw_readl(dp->phy_addr); - reg |= dp->enable_mask; - __raw_writel(reg, dp->phy_addr); -} - -static void exynos_dp_phy_exit(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = __raw_readl(dp->phy_addr); - reg &= ~(dp->enable_mask); - __raw_writel(reg, dp->phy_addr); -} #else static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) { @@ -1089,46 +1143,6 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp) } #endif /* CONFIG_OF */ -void exynos_dp_poweron(struct exynos_dp_device *dp) -{ - struct device *dev = dp->dev; - struct exynos_dp_platdata *pdata = dev->platform_data; - - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_init(dp); - } else { - if (pdata->phy_init) - pdata->phy_init(); - } - - clk_prepare_enable(dp->clock); - - exynos_dp_init_dp(dp); - - enable_irq(dp->irq); -} - -void exynos_dp_poweroff(struct exynos_dp_device *dp) -{ - struct device *dev = dp->dev; - struct exynos_dp_platdata *pdata = dev->platform_data; - - disable_irq(dp->irq); - - flush_work(&dp->hotplug_work); - - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_exit(dp); - } else { - if (pdata->phy_exit) - pdata->phy_exit(); - } - - clk_disable_unprepare(dp->clock); -} - static int exynos_dp_probe(struct platform_device *pdev) { struct resource *res; @@ -1145,6 +1159,7 @@ static int exynos_dp_probe(struct platform_device *pdev) } dp->dev = &pdev->dev; + dp->dpms_mode = DRM_MODE_DPMS_OFF; if (pdev->dev.of_node) { pdata = exynos_dp_dt_parse_pdata(&pdev->dev); @@ -1190,26 +1205,17 @@ static int exynos_dp_probe(struct platform_device *pdev) dp->video_info =
[PATCH v3 03/32] drm/exynos: Add an initialize function to manager and display
This patch adds an initialize function to the manager and display operations. This allows them to keep track of drm_device in their local context, as well as adds an initialization hook right after the encoder is created. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_drv.h | 5 + drivers/gpu/drm/exynos/exynos_drm_encoder.c | 21 + 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 6f31839..09bfe60 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -123,6 +123,7 @@ struct exynos_drm_overlay { * - this structure is common to analog tv, digital tv and lcd panel. * * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. + * @initialize: initializes the display with drm_dev * @is_connected: check for that display is connected or not. * @get_edid: get edid modes from display driver. * @get_panel: get panel object from display driver. @@ -131,6 +132,7 @@ struct exynos_drm_overlay { */ struct exynos_drm_display_ops { enum exynos_drm_output_type type; + int (*initialize)(struct device *dev, struct drm_device *drm_dev); bool (*is_connected)(struct device *dev); struct edid *(*get_edid)(struct device *dev, struct drm_connector *connector); @@ -142,6 +144,7 @@ struct exynos_drm_display_ops { /* * Exynos drm manager ops * + * @initialize: initializes the manager with drm_dev * @dpms: control device power. * @apply: set timing, vblank and overlay data to registers. * @mode_fixup: fix mode data comparing to hw specific display mode. @@ -159,6 +162,8 @@ struct exynos_drm_display_ops { * @win_disable: disable hardware specific overlay. */ struct exynos_drm_manager_ops { + int (*initialize)(struct device *subdrv_dev, + struct drm_device *drm_dev); void (*dpms)(struct device *subdrv_dev, int mode); void (*apply)(struct device *subdrv_dev); void (*mode_fixup)(struct device *subdrv_dev, diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index c255341..a9eb2b0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -316,6 +316,7 @@ exynos_drm_encoder_create(struct drm_device *dev, { struct drm_encoder *encoder; struct exynos_drm_encoder *exynos_encoder; + int ret; if (!manager || !possible_crtcs) return NULL; @@ -339,9 +340,29 @@ exynos_drm_encoder_create(struct drm_device *dev, drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs); + if (manager->ops && manager->ops->initialize) { + ret = manager->ops->initialize(manager->dev, dev); + if (ret) { + DRM_ERROR("Manager initialize failed %d\n", ret); + goto error; + } + } + + if (manager->display_ops && manager->display_ops->initialize) { + ret = manager->display_ops->initialize(manager->dev, dev); + if (ret) { + DRM_ERROR("Display initialize failed %d\n", ret); + goto error; + } + } + DRM_DEBUG_KMS("encoder has been created\n"); return encoder; + +error: + exynos_drm_encoder_destroy(&exynos_encoder->drm_encoder); + return NULL; } struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder) -- 1.8.4
[PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
This patch splits display and manager from subdrv. The result is that crtc functions can directly call into manager callbacks and encoder functions can directly call into display callbacks. This will allow us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp with common code. Signed-off-by: Sean Paul --- Changes in v2: - Pass display into display_ops instead of context Changes in v3: - Changed vidi args to exynos_drm_display instead of void - Moved exynos_drm_hdmi.c removal into next patch drivers/gpu/drm/exynos/exynos_drm_connector.c | 50 ++--- drivers/gpu/drm/exynos/exynos_drm_core.c | 181 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 115 +--- drivers/gpu/drm/exynos/exynos_drm_crtc.h | 20 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 29 +-- drivers/gpu/drm/exynos/exynos_drm_drv.h | 106 +++ drivers/gpu/drm/exynos/exynos_drm_encoder.c | 258 -- drivers/gpu/drm/exynos/exynos_drm_encoder.h | 18 +- drivers/gpu/drm/exynos/exynos_drm_fb.c| 4 +- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 161 drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 211 + drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 2 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 15 +- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 129 ++--- 14 files changed, 615 insertions(+), 684 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index ca270e2..9a16dbe 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -23,26 +23,20 @@ drm_connector) struct exynos_drm_connector { - struct drm_connectordrm_connector; - uint32_tencoder_id; - struct exynos_drm_manager *manager; + struct drm_connectordrm_connector; + uint32_tencoder_id; + struct exynos_drm_display *display; }; static int exynos_drm_connector_get_modes(struct drm_connector *connector) { struct exynos_drm_connector *exynos_connector = to_exynos_connector(connector); - struct exynos_drm_manager *manager = exynos_connector->manager; - struct exynos_drm_display_ops *display_ops = manager->display_ops; + struct exynos_drm_display *display = exynos_connector->display; struct edid *edid = NULL; unsigned int count = 0; int ret; - if (!display_ops) { - DRM_DEBUG_KMS("display_ops is null.\n"); - return 0; - } - /* * if get_edid() exists then get_edid() callback of hdmi side * is called to get edid data through i2c interface else @@ -51,8 +45,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) * P.S. in case of lcd panel, count is always 1 if success * because lcd panel has only one mode. */ - if (display_ops->get_edid) { - edid = display_ops->get_edid(manager->dev, connector); + if (display->ops->get_edid) { + edid = display->ops->get_edid(display, connector); if (IS_ERR_OR_NULL(edid)) { ret = PTR_ERR(edid); edid = NULL; @@ -75,8 +69,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) return 0; } - if (display_ops->get_panel) - panel = display_ops->get_panel(manager->dev); + if (display->ops->get_panel) + panel = display->ops->get_panel(display); else { drm_mode_destroy(connector->dev, mode); return 0; @@ -105,14 +99,13 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector, { struct exynos_drm_connector *exynos_connector = to_exynos_connector(connector); - struct exynos_drm_manager *manager = exynos_connector->manager; - struct exynos_drm_display_ops *display_ops = manager->display_ops; + struct exynos_drm_display *display = exynos_connector->display; int ret = MODE_BAD; DRM_DEBUG_KMS("%s\n", __FILE__); - if (display_ops && display_ops->check_mode) - if (!display_ops->check_mode(manager->dev, mode)) + if (display->ops->check_mode) + if (!display->ops->check_mode(display, mode)) ret = MODE_OK; return ret; @@ -151,8 +144,7 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector, { struct exynos_drm_connector *exynos_connector = to_exynos_connector(connector); - struct ex
[PATCH v3 15/32] drm/exynos: Use drm_mode_copy to copy modes
This patch changes the manual copying of mode to adjusted_mode in mode_fixup to use drm_mode_copy instead of handling things manually. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_hdmi.c | 10 +- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 9e12fb7..2c127b9 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -846,21 +846,13 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display, mode_ok = hdmi_check_mode(display, m); if (mode_ok == 0) { - struct drm_mode_object base; - struct list_head head; - DRM_INFO("desired mode doesn't exist so\n"); DRM_INFO("use the most suitable mode among modes.\n"); DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n", m->hdisplay, m->vdisplay, m->vrefresh); - /* preserve display mode header while copying. */ - head = adjusted_mode->head; - base = adjusted_mode->base; - memcpy(adjusted_mode, m, sizeof(*m)); - adjusted_mode->head = head; - adjusted_mode->base = base; + drm_mode_copy(adjusted_mode, m); break; } } -- 1.8.4
[PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver
This patch implements drm_connector directly in the vidi driver, this will allow us to move away from the exynos_drm_connector layer. Signed-off-by: Sean Paul --- Changes in v3: - Added to the patchset drivers/gpu/drm/exynos/exynos_drm_vidi.c | 163 --- 1 file changed, 107 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 7d79b6c..5104431 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -29,6 +29,8 @@ #define WINDOWS_NR 3 #define get_vidi_mgr(dev) platform_get_drvdata(to_platform_device(dev)) +#define ctx_from_connector(c) container_of(c, struct vidi_context, \ + connector) struct vidi_win_data { unsigned intoffset_x; @@ -47,6 +49,8 @@ struct vidi_win_data { struct vidi_context { struct drm_device *drm_dev; struct drm_crtc *crtc; + struct drm_encoder *encoder; + struct drm_connectorconnector; struct vidi_win_datawin_data[WINDOWS_NR]; struct edid *raw_edid; unsigned intclkdiv; @@ -86,62 +90,6 @@ static const char fake_edid_info[] = { 0x00, 0x00, 0x00, 0x06 }; -static bool vidi_display_is_connected(struct exynos_drm_display *display) -{ - struct vidi_context *ctx = display->ctx; - - /* -* connection request would come from user side -* to do hotplug through specific ioctl. -*/ - return ctx->connected ? true : false; -} - -static struct edid *vidi_get_edid(struct exynos_drm_display *display, - struct drm_connector *connector) -{ - struct vidi_context *ctx = display->ctx; - struct edid *edid; - int edid_len; - - /* -* the edid data comes from user side and it would be set -* to ctx->raw_edid through specific ioctl. -*/ - if (!ctx->raw_edid) { - DRM_DEBUG_KMS("raw_edid is null.\n"); - return ERR_PTR(-EFAULT); - } - - edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; - edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); - if (!edid) { - DRM_DEBUG_KMS("failed to allocate edid\n"); - return ERR_PTR(-ENOMEM); - } - - return edid; -} - -static int vidi_check_mode(struct exynos_drm_display *display, - struct drm_display_mode *mode) -{ - /* TODO. */ - - return 0; -} - -static struct exynos_drm_display_ops vidi_display_ops = { - .is_connected = vidi_display_is_connected, - .get_edid = vidi_get_edid, - .check_mode = vidi_check_mode, -}; - -static struct exynos_drm_display vidi_display = { - .type = EXYNOS_DISPLAY_TYPE_VIDI, - .ops = &vidi_display_ops, -}; - static void vidi_apply(struct exynos_drm_manager *mgr) { struct vidi_context *ctx = mgr->ctx; @@ -536,6 +484,109 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, return 0; } +static enum drm_connector_status vidi_detect(struct drm_connector *connector, + bool force) +{ + struct vidi_context *ctx = ctx_from_connector(connector); + + /* +* connection request would come from user side +* to do hotplug through specific ioctl. +*/ + return ctx->connected ? connector_status_connected : + connector_status_disconnected; +} + +static void vidi_connector_destroy(struct drm_connector *connector) +{ +} + +static struct drm_connector_funcs vidi_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = vidi_detect, + .destroy = vidi_connector_destroy, +}; + +static int vidi_get_modes(struct drm_connector *connector) +{ + struct vidi_context *ctx = ctx_from_connector(connector); + struct edid *edid; + int edid_len; + + /* +* the edid data comes from user side and it would be set +* to ctx->raw_edid through specific ioctl. +*/ + if (!ctx->raw_edid) { + DRM_DEBUG_KMS("raw_edid is null.\n"); + return -EFAULT; + } + + edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; + edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); + if (!edid) { + DRM_DEBUG_KMS("failed to allocate edid\n"); + return -ENOMEM; + } + + drm_mode_connector_update_edid_property(connector, edid); + + return drm_add_edid_modes(connector, edid); +} + +static int vidi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + return MODE_OK; +} + +static struct drm_encoder *vidi_best_encoder(struct
[PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver
This patch implements drm_connector directly in the dp driver, this will allow us to move away from the exynos_drm_connector layer. Signed-off-by: Sean Paul --- Changes in v3: - Added to the patchset drivers/gpu/drm/exynos/exynos_dp_core.c | 99 ++--- drivers/gpu/drm/exynos/exynos_dp_core.h | 4 ++ 2 files changed, 94 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 476d3b0..139ea15 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -22,10 +22,15 @@ #include #include +#include +#include #include "exynos_drm_drv.h" #include "exynos_dp_core.h" +#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ + connector) + static int exynos_dp_init_dp(struct exynos_dp_device *dp) { exynos_dp_reset(dp); @@ -896,21 +901,98 @@ static void exynos_dp_hotplug(struct work_struct *work) dev_err(dp->dev, "unable to config video\n"); } -static bool exynos_dp_display_is_connected(struct exynos_drm_display *display) +static enum drm_connector_status exynos_dp_detect( + struct drm_connector *connector, bool force) { - return true; + return connector_status_connected; } -static void *exynos_dp_get_panel(struct exynos_drm_display *display) +static void exynos_dp_connector_destroy(struct drm_connector *connector) { - struct exynos_dp_device *dp = display->ctx; +} + +static struct drm_connector_funcs exynos_dp_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = exynos_dp_detect, + .destroy = exynos_dp_connector_destroy, +}; + +static int exynos_dp_get_modes(struct drm_connector *connector) +{ + struct exynos_dp_device *dp = ctx_from_connector(connector); + struct drm_display_mode *mode; + + mode = drm_mode_create(connector->dev); + if (!mode) { + DRM_ERROR("failed to create a new display mode.\n"); + return 0; + } - return &dp->panel; + drm_display_mode_from_videomode(&dp->panel.vm, mode); + mode->width_mm = dp->panel.width_mm; + mode->height_mm = dp->panel.height_mm; + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(mode); + drm_mode_probed_add(connector, mode); + + return 1; } -static int exynos_dp_check_mode(struct exynos_drm_display *display, +static int exynos_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + return MODE_OK; +} + +static struct drm_encoder *exynos_dp_best_encoder( + struct drm_connector *connector) +{ + struct exynos_dp_device *dp = ctx_from_connector(connector); + + return dp->encoder; +} + +static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { + .get_modes = exynos_dp_get_modes, + .mode_valid = exynos_dp_mode_valid, + .best_encoder = exynos_dp_best_encoder, +}; + +static int exynos_dp_initialize(struct exynos_drm_display *display, + struct drm_device *drm_dev) +{ + struct exynos_dp_device *dp = display->ctx; + + dp->drm_dev = drm_dev; + + return 0; +} + +static int exynos_dp_create_connector(struct exynos_drm_display *display, + struct drm_encoder *encoder) +{ + struct exynos_dp_device *dp = display->ctx; + struct drm_connector *connector = &dp->connector; + int ret; + + dp->encoder = encoder; + connector->polled = DRM_CONNECTOR_POLL_HPD; + + ret = drm_connector_init(dp->drm_dev, connector, + &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); + if (ret) { + DRM_ERROR("Failed to initialize connector with drm\n"); + return ret; + } + + drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); + drm_sysfs_connector_add(connector); + drm_mode_connector_attach_encoder(connector, encoder); + return 0; } @@ -986,9 +1068,8 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) } static struct exynos_drm_display_ops exynos_dp_display_ops = { - .is_connected = exynos_dp_display_is_connected, - .get_panel = exynos_dp_get_panel, - .check_mode = exynos_dp_check_mode, + .initialize = exynos_dp_initialize, + .create_connector = exynos_dp_create_connector, .dpms = exynos_dp_dpms, }; diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h index 0c67c19..da3fa7e 100644 --- a/drivers/gpu/drm/exynos/ex
[PATCH v3 09/32] drm/exynos: Rename display_op power_on to dpms
This patch renames the display_op power_on to dpms to accurately reflect what the function does. The side-effect of this patch is that the new hdmi dpms callback is now invoked twice in the dpms path. This is safe and will be dealt with when the exynos_drm shim goes away. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: - Changed vidi to dpms as well drivers/gpu/drm/exynos/exynos_drm_drv.h | 4 ++-- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 4 ++-- drivers/gpu/drm/exynos/exynos_drm_fimd.c| 8 drivers/gpu/drm/exynos/exynos_drm_hdmi.c| 8 drivers/gpu/drm/exynos/exynos_drm_hdmi.h| 3 +-- drivers/gpu/drm/exynos/exynos_drm_vidi.c| 8 drivers/gpu/drm/exynos/exynos_hdmi.c| 2 +- 7 files changed, 10 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index bff432a..e31c088 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -128,7 +128,7 @@ struct exynos_drm_overlay { * @get_edid: get edid modes from display driver. * @get_panel: get panel object from display driver. * @check_mode: check if mode is valid or not. - * @power_on: display device on or off. + * @dpms: display device on or off. */ struct exynos_drm_display_ops { enum exynos_drm_output_type type; @@ -138,7 +138,7 @@ struct exynos_drm_display_ops { struct drm_connector *connector); void *(*get_panel)(struct device *dev); int (*check_mode)(struct device *dev, struct drm_display_mode *mode); - int (*power_on)(struct device *dev, int mode); + int (*dpms)(struct device *dev, int mode); }; /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index df4b2852..5bf1e1e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -50,8 +50,8 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) return; } - if (display_ops && display_ops->power_on) - display_ops->power_on(manager->ctx, mode); + if (display_ops && display_ops->dpms) + display_ops->dpms(manager->ctx, mode); exynos_encoder->dpms = mode; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index f0ac1d5..b980b05 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -169,19 +169,11 @@ static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode) return 0; } -static int fimd_display_power_on(struct device *dev, int mode) -{ - /* TODO */ - - return 0; -} - static struct exynos_drm_display_ops fimd_display_ops = { .type = EXYNOS_DISPLAY_TYPE_LCD, .is_connected = fimd_display_is_connected, .get_panel = fimd_get_panel, .check_mode = fimd_check_mode, - .power_on = fimd_display_power_on, }; static void fimd_win_mode_set(struct exynos_drm_manager *mgr, diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index c5de00a..f9a9324 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -159,12 +159,12 @@ static int drm_hdmi_check_mode(struct device *dev, return drm_hdmi_check_mode_ctx(ctx, mode); } -static int drm_hdmi_power_on(struct device *dev, int mode) +static int drm_hdmi_display_dpms(struct device *dev, int mode) { struct drm_hdmi_context *ctx = to_context(dev); - if (hdmi_ops && hdmi_ops->power_on) - return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode); + if (hdmi_ops && hdmi_ops->dpms) + hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode); return 0; } @@ -175,7 +175,7 @@ static struct exynos_drm_display_ops drm_hdmi_display_ops = { .is_connected = drm_hdmi_is_connected, .get_edid = drm_hdmi_get_edid, .check_mode = drm_hdmi_check_mode, - .power_on = drm_hdmi_power_on, + .dpms = drm_hdmi_display_dpms, }; static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr) diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index cf7b1da..923239b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -33,14 +33,13 @@ struct exynos_hdmi_ops { struct edid *(*get_edid)(void *ctx, struct drm_connector *connector); int (*check_mode)(void *ctx, struct drm_display_mode *mode); - int (*power_on)(void *ctx, int mode); + void (*dpms)(void *ctx, int mode); /* manager */ void (*mode_set)(void *ctx, struct drm_display_mode *mode); void (*get_max_resol)(void *ctx, unsigned int *width,
[PATCH v3 10/32] drm/exynos: Don't keep dpms state in encoder
This patch removes the dpms state tracking in encoder. This state is at best confusing and at worst incorrect since the display drivers can turn on and off without propagating the value. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_encoder.c | 17 - 1 file changed, 17 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 5bf1e1e..a823d53 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -28,32 +28,22 @@ * @drm_encoder: encoder object. * @manager: specific encoder has its own manager to control a hardware * appropriately and we can access a hardware drawing on this manager. - * @dpms: store the encoder dpms value. */ struct exynos_drm_encoder { struct drm_crtc *old_crtc; struct drm_encoder drm_encoder; struct exynos_drm_manager *manager; - int dpms; }; static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) { struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); struct exynos_drm_display_ops *display_ops = manager->display_ops; DRM_DEBUG_KMS("encoder dpms: %d\n", mode); - if (exynos_encoder->dpms == mode) { - DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); - return; - } - if (display_ops && display_ops->dpms) display_ops->dpms(manager->ctx, mode); - - exynos_encoder->dpms = mode; } static bool @@ -157,12 +147,6 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder) if (manager_ops && manager_ops->commit) manager_ops->commit(manager); - - /* -* In case of setcrtc, there is no way to update encoder's dpms -* so update it here. -*/ - exynos_encoder->dpms = DRM_MODE_DPMS_ON; } void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb) @@ -281,7 +265,6 @@ exynos_drm_encoder_create(struct drm_device *dev, if (!exynos_encoder) return NULL; - exynos_encoder->dpms = DRM_MODE_DPMS_OFF; exynos_encoder->manager = manager; encoder = &exynos_encoder->drm_encoder; encoder->possible_crtcs = possible_crtcs; -- 1.8.4
[PATCH v3 16/32] drm/exynos: Disable unused crtc planes from crtc
This patch moves the code which disables unused crtc planes from the encoder to the crtc. Since there is a 1:1 encoder/crtc mapping in exynos, the only valid crtc change the pre-existing code could catch is disconnecting an active crtc from the encoder. Thus it is functionally equivalent to just disable all planes attached to a crtc when the crtc is disabled. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_crtc.c| 13 +- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 65 ++--- 2 files changed, 15 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 347d62d..d019385 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -176,10 +176,19 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, static void exynos_drm_crtc_disable(struct drm_crtc *crtc) { - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct drm_plane *plane; + int ret; - exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF); exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + + list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) { + if (plane->crtc != crtc) + continue; + + ret = plane->funcs->disable_plane(plane); + if (ret) + DRM_ERROR("Failed to disable plane %d\n", ret); + } } static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index d4ae664..bfa2f17 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -29,7 +29,6 @@ * @display: the display structure that maps to this encoder */ struct exynos_drm_encoder { - struct drm_crtc *old_crtc; struct drm_encoder drm_encoder; struct exynos_drm_display *display; }; @@ -67,71 +66,15 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, return true; } -static void disable_plane_to_crtc(struct drm_device *dev, - struct drm_crtc *old_crtc, - struct drm_crtc *new_crtc) -{ - struct drm_plane *plane; - - /* -* if old_crtc isn't same as encoder->crtc then it means that -* user changed crtc id to another one so the plane to old_crtc -* should be disabled and plane->crtc should be set to new_crtc -* (encoder->crtc) -*/ - list_for_each_entry(plane, &dev->mode_config.plane_list, head) { - if (plane->crtc == old_crtc) { - /* -* do not change below call order. -* -* plane->funcs->disable_plane call checks -* if encoder->crtc is same as plane->crtc and if same -* then manager_ops->win_disable callback will be called -* to diasble current hw overlay so plane->crtc should -* have new_crtc because new_crtc was set to -* encoder->crtc in advance. -*/ - plane->crtc = new_crtc; - plane->funcs->disable_plane(plane); - } - } -} - static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct drm_device *dev = encoder->dev; - struct drm_connector *connector; - struct exynos_drm_display *display; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - struct exynos_drm_encoder *exynos_encoder; - - exynos_encoder = to_exynos_encoder(encoder); - - if (exynos_encoder->old_crtc != encoder->crtc && - exynos_encoder->old_crtc) { - - /* -* disable a plane to old crtc and change -* crtc of the plane to new one. -*/ - disable_plane_to_crtc(dev, - exynos_encoder->old_crtc, - encoder->crtc); - } - - display = exynos_encoder->display; - - if (display->ops->mode_set) - display->ops->mode_set(display, -
[PATCH v3 17/32] drm/exynos: Add mode_set manager operation
This patch adds a mode_set callback to the manager operations which sets the crtc's current mode to the manager driver. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 drivers/gpu/drm/exynos/exynos_drm_drv.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index d019385..a5cb104 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -115,6 +115,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_framebuffer *old_fb) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct exynos_drm_manager *manager = exynos_crtc->manager; struct drm_plane *plane = exynos_crtc->plane; unsigned int crtc_w; unsigned int crtc_h; @@ -129,6 +130,9 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, crtc_w = crtc->fb->width - x; crtc_h = crtc->fb->height - y; + if (manager->ops->mode_set) + manager->ops->mode_set(manager, &crtc->mode); + ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h, x, y, crtc_w, crtc_h); if (ret) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index dc730e5..c58a4c7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -184,6 +184,7 @@ struct exynos_drm_display { * @initialize: initializes the manager with drm_dev * @remove: cleans up the manager for removal * @dpms: control device power. + * @mode_set: set the given mode to the manager * @commit: set current hw specific display mode to hw. * @enable_vblank: specific driver callback for enabling vblank interrupt. * @disable_vblank: specific driver callback for disabling vblank interrupt. @@ -200,6 +201,8 @@ struct exynos_drm_manager_ops { struct drm_device *drm_dev, int pipe); void (*remove)(struct exynos_drm_manager *mgr); void (*dpms)(struct exynos_drm_manager *mgr, int mode); + void (*mode_set)(struct exynos_drm_manager *mgr, + const struct drm_display_mode *mode); void (*commit)(struct exynos_drm_manager *mgr); int (*enable_vblank)(struct exynos_drm_manager *mgr); void (*disable_vblank)(struct exynos_drm_manager *mgr); -- 1.8.4
[PATCH v3 18/32] drm/exynos: Implement mode_fixup manager operation
This patch adds a new manager callback for mode_fixup and pipes it through exynos_drm_crtc. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 ++- drivers/gpu/drm/exynos/exynos_drm_drv.h | 4 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index a5cb104..100a561 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -105,7 +105,12 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - /* drm framework doesn't check NULL */ + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct exynos_drm_manager *manager = exynos_crtc->manager; + + if (manager->ops->mode_fixup) + return manager->ops->mode_fixup(manager, mode, adjusted_mode); + return true; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index c58a4c7..97bdfcc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -184,6 +184,7 @@ struct exynos_drm_display { * @initialize: initializes the manager with drm_dev * @remove: cleans up the manager for removal * @dpms: control device power. + * @mode_fixup: fix mode data before applying it * @mode_set: set the given mode to the manager * @commit: set current hw specific display mode to hw. * @enable_vblank: specific driver callback for enabling vblank interrupt. @@ -201,6 +202,9 @@ struct exynos_drm_manager_ops { struct drm_device *drm_dev, int pipe); void (*remove)(struct exynos_drm_manager *mgr); void (*dpms)(struct exynos_drm_manager *mgr, int mode); + bool (*mode_fixup)(struct exynos_drm_manager *mgr, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); void (*mode_set)(struct exynos_drm_manager *mgr, const struct drm_display_mode *mode); void (*commit)(struct exynos_drm_manager *mgr); -- 1.8.4
[PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd
This patch uses the mode passed into mode_set to configure fimd instead of directly using the panel from context. This will allow us to move the exynos_drm_display implementation from fimd into the DP driver where it belongs. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_fimd.c | 159 ++- 1 file changed, 91 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index d2b8ccb..f69d6e5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -104,6 +104,20 @@ struct fimd_win_data { boolresume; }; +struct fimd_mode_data { + unsignedvtotal; + unsignedvdisplay; + unsignedvsync_len; + unsignedvbpd; + unsignedvfpd; + unsignedhtotal; + unsignedhdisplay; + unsignedhsync_len; + unsignedhbpd; + unsignedhfpd; + u32 clkdiv; +}; + struct fimd_context { struct device *dev; struct drm_device *drm_dev; @@ -112,8 +126,8 @@ struct fimd_context { struct clk *bus_clk; struct clk *lcd_clk; void __iomem*regs; + struct fimd_mode_data mode; struct fimd_win_datawin_data[WINDOWS_NR]; - unsigned intclkdiv; unsigned intdefault_win; unsigned long irq_flags; u32 vidcon0; @@ -560,11 +574,56 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) mutex_unlock(&ctx->lock); } +static u32 fimd_calc_clkdiv(struct fimd_context *ctx, + const struct drm_display_mode *mode) +{ + unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh; + u32 clkdiv; + + /* Find the clock divider value that gets us closest to ideal_clk */ + clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk); + + return (clkdiv < 0x100) ? clkdiv : 0xff; +} + +static bool fimd_mode_fixup(struct exynos_drm_manager *mgr, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + if (adjusted_mode->vrefresh == 0) + adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE; + + return true; +} + +static void fimd_mode_set(struct exynos_drm_manager *mgr, + const struct drm_display_mode *in_mode) +{ + struct fimd_context *ctx = mgr->ctx; + struct fimd_mode_data *mode = &ctx->mode; + int hblank, vblank; + + vblank = in_mode->crtc_vblank_end - in_mode->crtc_vblank_start; + mode->vtotal = in_mode->crtc_vtotal; + mode->vdisplay = in_mode->crtc_vdisplay; + mode->vsync_len = in_mode->crtc_vsync_end - in_mode->crtc_vsync_start; + mode->vbpd = (vblank - mode->vsync_len) / 2; + mode->vfpd = vblank - mode->vsync_len - mode->vbpd; + + hblank = in_mode->crtc_hblank_end - in_mode->crtc_hblank_start; + mode->htotal = in_mode->crtc_htotal; + mode->hdisplay = in_mode->crtc_hdisplay; + mode->hsync_len = in_mode->crtc_hsync_end - in_mode->crtc_hsync_start; + mode->hbpd = (hblank - mode->hsync_len) / 2; + mode->hfpd = hblank - mode->hsync_len - mode->hbpd; + + mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode); +} + static void fimd_commit(struct exynos_drm_manager *mgr) { struct fimd_context *ctx = mgr->ctx; - struct exynos_drm_panel_info *panel = &ctx->panel; - struct videomode *vm = &panel->vm; + struct fimd_mode_data *mode = &ctx->mode; struct fimd_driver_data *driver_data; u32 val; @@ -572,26 +631,30 @@ static void fimd_commit(struct exynos_drm_manager *mgr) if (ctx->suspended) return; + /* nothing to do if we haven't set the mode yet */ + if (mode->htotal == 0 || mode->vtotal == 0) + return; + /* setup polarity values from machine code. */ writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); /* setup vertical timing values. */ - val = VIDTCON0_VBPD(vm->vback_porch - 1) | - VIDTCON0_VFPD(vm->vfront_porch - 1) | - VIDTCON0_VSPW(vm->vsync_len - 1); + val = VIDTCON0_VBPD(mode->vbpd - 1) | + VIDTCON0_VFPD(mode->vfpd - 1) | + VIDTCON0_VSPW(mode->vsync_len - 1); writel(val, ctx->regs + driver_data->timing_base + VIDTCON0); /* setup horizontal timing values. */ - val = VIDTCON1_HBPD(vm->hback_porch - 1) | - VIDTCON1_HFPD(vm->hfront_porch - 1) | -
[PATCH v3 20/32] drm/exynos: Remove unused/useless fimd_context members
This patch removes a few fimd_context members which are either entirely unused or unneeded. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_fimd.c | 13 + 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index f69d6e5..61124ca 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -121,8 +121,6 @@ struct fimd_mode_data { struct fimd_context { struct device *dev; struct drm_device *drm_dev; - int irq; - struct drm_crtc *crtc; struct clk *bus_clk; struct clk *lcd_clk; void __iomem*regs; @@ -134,7 +132,6 @@ struct fimd_context { u32 vidcon1; boolsuspended; int pipe; - struct mutexlock; wait_queue_head_t wait_vsync_queue; atomic_twait_vsync_event; @@ -547,8 +544,6 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) DRM_DEBUG_KMS("%d\n", mode); - mutex_lock(&ctx->lock); - switch (mode) { case DRM_MODE_DPMS_ON: /* @@ -570,8 +565,6 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) DRM_DEBUG_KMS("unspecified mode %d\n", mode); break; } - - mutex_unlock(&ctx->lock); } static u32 fimd_calc_clkdiv(struct fimd_context *ctx, @@ -964,9 +957,7 @@ static int fimd_probe(struct platform_device *pdev) return -ENXIO; } - ctx->irq = res->start; - - ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler, + ret = devm_request_irq(dev, res->start, fimd_irq_handler, 0, "drm_fimd", ctx); if (ret) { dev_err(dev, "irq request failed.\n"); @@ -977,8 +968,6 @@ static int fimd_probe(struct platform_device *pdev) DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue); atomic_set(&ctx->wait_vsync_event, 0); - mutex_init(&ctx->lock); - platform_set_drvdata(pdev, &fimd_manager); fimd_manager.ctx = ctx; -- 1.8.4
[PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
This patch moves the code from video/ to drm/ Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: None drivers/gpu/drm/exynos/Kconfig |7 + drivers/gpu/drm/exynos/Makefile |1 + drivers/gpu/drm/exynos/exynos_dp_core.c | 1213 ++ drivers/gpu/drm/exynos/exynos_dp_core.h | 210 ++ drivers/gpu/drm/exynos/exynos_dp_reg.c | 1245 +++ drivers/gpu/drm/exynos/exynos_dp_reg.h | 366 + drivers/video/exynos/Kconfig|7 - drivers/video/exynos/Makefile |1 - drivers/video/exynos/exynos_dp_core.c | 1213 -- drivers/video/exynos/exynos_dp_core.h | 210 -- drivers/video/exynos/exynos_dp_reg.c| 1245 --- drivers/video/exynos/exynos_dp_reg.h| 366 - 12 files changed, 3042 insertions(+), 3042 deletions(-) create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h delete mode 100644 drivers/video/exynos/exynos_dp_core.c delete mode 100644 drivers/video/exynos/exynos_dp_core.h delete mode 100644 drivers/video/exynos/exynos_dp_reg.c delete mode 100644 drivers/video/exynos/exynos_dp_reg.h diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 45b6ef5..3ace74f 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -30,6 +30,13 @@ config DRM_EXYNOS_FIMD help Choose this option if you want to use Exynos FIMD for DRM. +config DRM_EXYNOS_DP + bool "EXYNOS DRM DP driver support" + depends on ARCH_EXYNOS + default n + help + This enables support for DP device. + config DRM_EXYNOS_HDMI bool "Exynos DRM HDMI" depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index afbe499..fc8555c 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -11,6 +11,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)+= exynos_drm_fimd.o +exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)+= exynos_hdmi.o exynos_mixer.o exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)+= exynos_drm_vidi.o exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c new file mode 100644 index 000..089ae22 --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -0,0 +1,1213 @@ +/* + * Samsung SoC DP (Display Port) interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "exynos_dp_core.h" + +static int exynos_dp_init_dp(struct exynos_dp_device *dp) +{ + exynos_dp_reset(dp); + + exynos_dp_swreset(dp); + + exynos_dp_init_analog_param(dp); + exynos_dp_init_interrupt(dp); + + /* SW defined function Normal operation */ + exynos_dp_enable_sw_function(dp); + + exynos_dp_config_interrupt(dp); + exynos_dp_init_analog_func(dp); + + exynos_dp_init_hpd(dp); + exynos_dp_init_aux(dp); + + return 0; +} + +static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) +{ + int timeout_loop = 0; + + while (exynos_dp_get_plug_in_status(dp) != 0) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "failed to get hpd plug status\n"); + return -ETIMEDOUT; + } + usleep_range(10, 11); + } + + return 0; +} + +static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) +{ + int i; + unsigned char sum = 0; + + for (i = 0; i < EDID_BLOCK_LENGTH; i++) + sum = sum + edid_data[i]; + + return sum; +} + +static int exynos_dp_read_edid(struct exynos_dp_device *dp) +{ + unsigned char edid[EDID_BLOCK_LENGTH * 2]; + unsigned int extend_block = 0; + unsigned char sum; + unsigned char test_vector; + int retval; + + /* +* EDID device address is 0x50. +* However, if necessary, you must have set upper addre
[PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines
This patch separates the fimd_activate function into poweron/poweroff functions to be more consistent with the other drivers in exynos drm. It also properly cleans up after failures in poweron. The functions have also been shuffled around such that they are all in the same spot in the file and poweron/poweroff can be called from the dpms function. Signed-off-by: Sean Paul --- Changes in v2: - Added to the patchset Changes in v3: None drivers/gpu/drm/exynos/exynos_drm_fimd.c | 247 +-- 1 file changed, 135 insertions(+), 112 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index c6a05f6..ba12916 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -324,6 +324,12 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos) win_data = &ctx->win_data[win]; + /* If suspended, enable this on resume */ + if (ctx->suspended) { + win_data->resume = true; + return; + } + /* * SHADOWCON/PRTCON register is used for enabling timing. * @@ -505,35 +511,6 @@ static void fimd_mgr_remove(struct exynos_drm_manager *mgr) drm_iommu_detach_device(ctx->drm_dev, ctx->dev); } -static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) -{ - struct fimd_context *ctx = mgr->ctx; - - DRM_DEBUG_KMS("%d\n", mode); - - switch (mode) { - case DRM_MODE_DPMS_ON: - /* -* enable fimd hardware only if suspended status. -* -* P.S. fimd_dpms function would be called at booting time so -* clk_enable could be called double time. -*/ - if (ctx->suspended) - pm_runtime_get_sync(ctx->dev); - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - if (!ctx->suspended) - pm_runtime_put_sync(ctx->dev); - break; - default: - DRM_DEBUG_KMS("unspecified mode %d\n", mode); - break; - } -} - static u32 fimd_calc_clkdiv(struct fimd_context *ctx, const struct drm_display_mode *mode) { @@ -726,6 +703,130 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr) DRM_DEBUG_KMS("vblank wait timed out.\n"); } +static void fimd_window_suspend(struct exynos_drm_manager *mgr) +{ + struct fimd_context *ctx = mgr->ctx; + struct fimd_win_data *win_data; + int i; + + for (i = 0; i < WINDOWS_NR; i++) { + win_data = &ctx->win_data[i]; + win_data->resume = win_data->enabled; + if (win_data->enabled) + fimd_win_disable(mgr, i); + } + fimd_wait_for_vblank(mgr); +} + +static void fimd_window_resume(struct exynos_drm_manager *mgr) +{ + struct fimd_context *ctx = mgr->ctx; + struct fimd_win_data *win_data; + int i; + + for (i = 0; i < WINDOWS_NR; i++) { + win_data = &ctx->win_data[i]; + win_data->enabled = win_data->resume; + win_data->resume = false; + } +} + +static int fimd_poweron(struct exynos_drm_manager *mgr) +{ + struct fimd_context *ctx = mgr->ctx; + int ret; + + if (!ctx->suspended) + return 0; + + ctx->suspended = false; + + ret = clk_prepare_enable(ctx->bus_clk); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret); + goto bus_clk_err; + } + + ret = clk_prepare_enable(ctx->lcd_clk); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret); + goto lcd_clk_err; + } + + /* if vblank was enabled status, enable it again. */ + if (test_and_clear_bit(0, &ctx->irq_flags)) { + ret = fimd_enable_vblank(mgr); + if (ret) { + DRM_ERROR("Failed to re-enable vblank [%d]\n", ret); + goto enable_vblank_err; + } + } + + fimd_window_resume(mgr); + + fimd_apply(mgr); + + return 0; + +enable_vblank_err: + clk_disable_unprepare(ctx->lcd_clk); +lcd_clk_err: + clk_disable_unprepare(ctx->bus_clk); +bus_clk_err: + ctx->suspended = true; + return ret; +} + +static int fimd_poweroff(struct exynos_drm_manager *mgr) +{ + struct fimd_context *ctx = mgr->ctx; + + if (ctx->suspended) + return 0; + + /* +* We need to make sure that all windows are disabled before we +* suspend that connector. Otherwise we might try to scan from +* a destroyed buffer later. +*/ + fimd_window_suspend(mgr); + + clk_disable_unprepare(
[PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv
This patch removes all of the suspend/resume logic from the individual drivers and consolidates it in drm_drv. This consolidation reduces the number of functions which enable/disable the hardware to just one -- the dpms callback. This ensures that we always power up/down in a consistent manner. Signed-off-by: Sean Paul --- Changes in v2: - Added to the patchset Changes in v3: - Made appropriate changes to vidi as well (removed pm_ops) drivers/gpu/drm/exynos/exynos_drm_drv.c | 97 + drivers/gpu/drm/exynos/exynos_drm_fimd.c | 91 --- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 119 +-- drivers/gpu/drm/exynos/exynos_hdmi.c | 82 + drivers/gpu/drm/exynos/exynos_mixer.c| 75 --- 5 files changed, 176 insertions(+), 288 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 03caa3a..91d6863 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -11,6 +11,7 @@ * option) any later version. */ +#include #include #include @@ -51,6 +52,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) return -ENOMEM; INIT_LIST_HEAD(&private->pageflip_event_list); + dev_set_drvdata(dev->dev, dev); dev->dev_private = (void *)private; /* @@ -155,6 +157,41 @@ static int exynos_drm_unload(struct drm_device *dev) return 0; } +static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state) +{ + struct drm_connector *connector; + + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + int old_dpms = connector->dpms; + + if (connector->funcs->dpms) + connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF); + + /* Set the old mode back to the connector for resume */ + connector->dpms = old_dpms; + } + drm_modeset_unlock_all(dev); + + return 0; +} + +static int exynos_drm_resume(struct drm_device *dev) +{ + struct drm_connector *connector; + + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->funcs->dpms) + connector->funcs->dpms(connector, connector->dpms); + } + + drm_helper_resume_force_mode(dev); + drm_modeset_unlock_all(dev); + + return 0; +} + static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) { struct drm_exynos_file_private *file_priv; @@ -262,6 +299,8 @@ static struct drm_driver exynos_drm_driver = { DRIVER_GEM | DRIVER_PRIME, .load = exynos_drm_load, .unload = exynos_drm_unload, + .suspend= exynos_drm_suspend, + .resume = exynos_drm_resume, .open = exynos_drm_open, .preclose = exynos_drm_preclose, .lastclose = exynos_drm_lastclose, @@ -293,6 +332,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) { pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + return drm_platform_init(&exynos_drm_driver, pdev); } @@ -303,12 +345,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int exynos_drm_sys_suspend(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + pm_message_t message; + + if (pm_runtime_suspended(dev)) + return 0; + + message.event = PM_EVENT_SUSPEND; + return exynos_drm_suspend(drm_dev, message); +} + +static int exynos_drm_sys_resume(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + + if (pm_runtime_suspended(dev)) + return 0; + + return exynos_drm_resume(drm_dev); +} +#endif + +#ifdef CONFIG_PM_RUNTIME +static int exynos_drm_runtime_suspend(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + pm_message_t message; + + if (pm_runtime_suspended(dev)) + return 0; + + message.event = PM_EVENT_SUSPEND; + return exynos_drm_suspend(drm_dev, message); +} + +static int exynos_drm_runtime_resume(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + + if (!pm_runtime_suspended(dev)) + return 0; + + return exynos_drm_resume(drm_dev); +} +#endif + +static const struct dev_pm_ops exynos_drm_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume) + SET_RUNTIME_PM_OPS(exynos_drm_runt
[PATCH v3 27/32] drm/exynos: Add create_connector callback
This creates a new display hook called create_connector. The purpose is to allow the display driver to create its own drm_connector instead of using the exynos_drm_connector. This moves things closer to completely removing the exynos_drm_connector abstraction. Signed-off-by: Sean Paul --- Changes in v2: None Changes in v3: - Added to the patchset drivers/gpu/drm/exynos/exynos_drm_core.c | 3 +++ drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index e76098d..1a60f5a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c @@ -87,6 +87,9 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev, return 0; } + if (display->ops->create_connector) + return display->ops->create_connector(display, encoder); + /* * create and initialize a connector for this sub driver and * attach the encoder created above to the connector. diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index f3e18d1..db6a3b2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -139,6 +139,8 @@ struct exynos_drm_display; struct exynos_drm_display_ops { int (*initialize)(struct exynos_drm_display *display, struct drm_device *drm_dev); + int (*create_connector)(struct exynos_drm_display *display, + struct drm_encoder *encoder); void (*remove)(struct exynos_drm_display *display); bool (*is_connected)(struct exynos_drm_display *display); void (*get_max_resol)(struct exynos_drm_display *display, -- 1.8.4
[PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly
This patch implements drm_connector in the hdmi driver directly, instead of using exynos_drm_connector. Signed-off-by: Sean Paul --- Changes in v3: - Added to the patchset drivers/gpu/drm/exynos/exynos_hdmi.c | 126 +++ 1 file changed, 85 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index c6561fe..b063610 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -43,9 +43,8 @@ #include #include -#define MAX_WIDTH 1920 -#define MAX_HEIGHT 1080 #define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev)) +#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector) /* AVI header and aspect ratio */ #define HDMI_AVI_VERSION 0x02 @@ -180,6 +179,8 @@ struct hdmi_conf_regs { struct hdmi_context { struct device *dev; struct drm_device *drm_dev; + struct drm_connectorconnector; + struct drm_encoder *encoder; boolhpd; boolpowered; booldvi_mode; @@ -738,42 +739,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, } } -static int hdmi_initialize(struct exynos_drm_display *display, - struct drm_device *drm_dev) +static enum drm_connector_status hdmi_detect(struct drm_connector *connector, + bool force) { - struct hdmi_context *hdata = display->ctx; + struct hdmi_context *hdata = ctx_from_connector(connector); - hdata->drm_dev = drm_dev; - - return 0; + return hdata->hpd ? connector_status_connected : + connector_status_disconnected; } -static bool hdmi_is_connected(struct exynos_drm_display *display) +static void hdmi_connector_destroy(struct drm_connector *connector) { - struct hdmi_context *hdata = display->ctx; - - return hdata->hpd; } -static struct edid *hdmi_get_edid(struct exynos_drm_display *display, - struct drm_connector *connector) +static struct drm_connector_funcs hdmi_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = hdmi_detect, + .destroy = hdmi_connector_destroy, +}; + +static int hdmi_get_modes(struct drm_connector *connector) { - struct edid *raw_edid; - struct hdmi_context *hdata = display->ctx; + struct hdmi_context *hdata = ctx_from_connector(connector); + struct edid *edid; if (!hdata->ddc_port) - return ERR_PTR(-ENODEV); + return -ENODEV; - raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); - if (!raw_edid) - return ERR_PTR(-ENODEV); + edid = drm_get_edid(connector, hdata->ddc_port->adapter); + if (!edid) + return -ENODEV; - hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); + hdata->dvi_mode = !drm_detect_hdmi_monitor(edid); DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), - raw_edid->width_cm, raw_edid->height_cm); + edid->width_cm, edid->height_cm); + + drm_mode_connector_update_edid_property(connector, edid); - return raw_edid; + return drm_add_edid_modes(connector, edid); } static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) @@ -798,10 +803,10 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) return -EINVAL; } -static int hdmi_check_mode(struct exynos_drm_display *display, +static int hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct hdmi_context *hdata = display->ctx; + struct hdmi_context *hdata = ctx_from_connector(connector); int ret; DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n", @@ -811,11 +816,60 @@ static int hdmi_check_mode(struct exynos_drm_display *display, ret = mixer_check_mode(mode); if (ret) - return ret; + return MODE_BAD; ret = hdmi_find_phy_conf(hdata, mode->clock * 1000); if (ret < 0) + return MODE_BAD; + + return MODE_OK; +} + +static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector) +{ + struct hdmi_context *hdata = ctx_from_connector(connector); + + return hdata->encoder; +} + +static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = { + .get_modes = hdmi_get_modes, + .mode_valid = hdmi_mode_valid, + .best_encoder = hdmi_best_encoder, +}; + +static int hdmi_create_connector(struct exynos_drm_display
[PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver
This patch moves the lvds bridge discovery and connector pre-emption code from exynos common code into the dp driver (since the bridge is only applicable for dp). Signed-off-by: Sean Paul --- Changes in v3: - Added to the patchset drivers/gpu/drm/exynos/exynos_dp_core.c | 41 drivers/gpu/drm/exynos/exynos_drm_core.c | 41 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 139ea15..32ba791 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "exynos_drm_drv.h" #include "exynos_dp_core.h" @@ -31,6 +32,11 @@ #define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ connector) +struct bridge_init { + struct i2c_client *client; + struct device_node *node; +}; + static int exynos_dp_init_dp(struct exynos_dp_device *dp) { exynos_dp_reset(dp); @@ -972,6 +978,35 @@ static int exynos_dp_initialize(struct exynos_drm_display *display, return 0; } +static bool find_bridge(const char *compat, struct bridge_init *bridge) +{ + bridge->client = NULL; + bridge->node = of_find_compatible_node(NULL, NULL, compat); + if (!bridge->node) + return false; + + bridge->client = of_find_i2c_device_by_node(bridge->node); + if (!bridge->client) + return false; + + return true; +} + +/* returns the number of bridges attached */ +static int exynos_drm_attach_lcd_bridge(struct drm_device *dev, + struct drm_encoder *encoder) +{ + struct bridge_init bridge; + int ret; + + if (find_bridge("nxp,ptn3460", &bridge)) { + ret = ptn3460_init(dev, encoder, bridge.client, bridge.node); + if (!ret) + return 1; + } + return 0; +} + static int exynos_dp_create_connector(struct exynos_drm_display *display, struct drm_encoder *encoder) { @@ -980,6 +1015,12 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, int ret; dp->encoder = encoder; + + /* Pre-empt DP connector creation if there's a bridge */ + ret = exynos_drm_attach_lcd_bridge(dp->drm_dev, encoder); + if (ret) + return 0; + connector->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(dp->drm_dev, connector, diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index 1a60f5a..2446352 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c @@ -14,7 +14,6 @@ #include #include -#include #include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" #include "exynos_drm_encoder.h" @@ -25,40 +24,6 @@ static LIST_HEAD(exynos_drm_subdrv_list); static LIST_HEAD(exynos_drm_manager_list); static LIST_HEAD(exynos_drm_display_list); -struct bridge_init { - struct i2c_client *client; - struct device_node *node; -}; - -static bool find_bridge(const char *compat, struct bridge_init *bridge) -{ - bridge->client = NULL; - bridge->node = of_find_compatible_node(NULL, NULL, compat); - if (!bridge->node) - return false; - - bridge->client = of_find_i2c_device_by_node(bridge->node); - if (!bridge->client) - return false; - - return true; -} - -/* returns the number of bridges attached */ -static int exynos_drm_attach_lcd_bridge(struct drm_device *dev, - struct drm_encoder *encoder) -{ - struct bridge_init bridge; - int ret; - - if (find_bridge("nxp,ptn3460", &bridge)) { - ret = ptn3460_init(dev, encoder, bridge.client, bridge.node); - if (!ret) - return 1; - } - return 0; -} - static int exynos_drm_create_enc_conn(struct drm_device *dev, struct exynos_drm_display *display) { @@ -81,12 +46,6 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev, } display->encoder = encoder; - if (display->type == EXYNOS_DISPLAY_TYPE_LCD) { - ret = exynos_drm_attach_lcd_bridge(dev, encoder); - if (ret) - return 0; - } - if (display->ops->create_connector) return display->ops->create_connector(display, encoder); -- 1.8.4
[PATCH v3 32/32] drm/exynos: Remove the exynos_drm_connector shim
This path removes the exynos_drm_connector code since it was just passing hooks through display_ops. The individual device drivers are now responsible for implementing drm_connector directly. Signed-off-by: Sean Paul --- Changes in v3: - Added to the patchset drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/exynos_drm_connector.c | 258 -- drivers/gpu/drm/exynos/exynos_drm_connector.h | 20 -- drivers/gpu/drm/exynos/exynos_drm_core.c | 18 +- drivers/gpu/drm/exynos/exynos_drm_drv.h | 11 -- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 1 - 6 files changed, 4 insertions(+), 306 deletions(-) delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.h diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index fc8555c..b1839e8 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -3,7 +3,7 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos -exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ +exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \ exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ exynos_drm_plane.o diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c deleted file mode 100644 index 9a16dbe..000 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include - -#include -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" -#include "exynos_drm_connector.h" - -#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ - drm_connector) - -struct exynos_drm_connector { - struct drm_connectordrm_connector; - uint32_tencoder_id; - struct exynos_drm_display *display; -}; - -static int exynos_drm_connector_get_modes(struct drm_connector *connector) -{ - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - struct exynos_drm_display *display = exynos_connector->display; - struct edid *edid = NULL; - unsigned int count = 0; - int ret; - - /* -* if get_edid() exists then get_edid() callback of hdmi side -* is called to get edid data through i2c interface else -* get timing from the FIMD driver(display controller). -* -* P.S. in case of lcd panel, count is always 1 if success -* because lcd panel has only one mode. -*/ - if (display->ops->get_edid) { - edid = display->ops->get_edid(display, connector); - if (IS_ERR_OR_NULL(edid)) { - ret = PTR_ERR(edid); - edid = NULL; - DRM_ERROR("Panel operation get_edid failed %d\n", ret); - goto out; - } - - count = drm_add_edid_modes(connector, edid); - if (!count) { - DRM_ERROR("Add edid modes failed %d\n", count); - goto out; - } - - drm_mode_connector_update_edid_property(connector, edid); - } else { - struct exynos_drm_panel_info *panel; - struct drm_display_mode *mode = drm_mode_create(connector->dev); - if (!mode) { - DRM_ERROR("failed to create a new display mode.\n"); - return 0; - } - - if (display->ops->get_panel) - panel = display->ops->get_panel(display); - else { - drm_mode_destroy(connector->dev, mode); - return 0; - } - - drm_display_mode_from_videomode(&panel->vm, mode); - mode->width_mm = panel->width_mm; - mode->height_mm = panel->height_mm; - connector->display_info.width_mm = mode->width_mm; - connector->display_info.height_mm = mode->height_mm; - - mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; - drm_mode_set_name(mode); - drm_mode_probed_add(connector, mode); - - count = 1; -
Build failure: shmobile drm driver references backlight symbols
Hi Russell, On Tuesday 29 October 2013 10:04:13 Russell King - ARM Linux wrote: > My build system picked up on this failure: > > drivers/built-in.o: In function `shmob_drm_backlight_init': > fmc-chardev.c:(.text+0x9f2d0): undefined reference to > `backlight_device_register' drivers/built-in.o: In function > `shmob_drm_backlight_exit': > fmc-chardev.c:(.text+0x9f370): undefined reference to > `backlight_device_unregister' > > which is cuased by drivers/gpu/drm/shmobile/shmob_drm_backlight.c being > built without the backlight dependency being enabled. It looks like > the backlight dependency is a hard requirement, so needs ot be added > to the Kconfig entry for this driver in some way. Thank you for the report. I'll send a fix. -- Regards, Laurent Pinchart
[PATCH] drm: shmobile: Add dependency on BACKLIGHT_CLASS_DEVICE
From: Laurent Pinchart The driver registers a backlight device and thus requires BACKLIGHT_CLASS_DEVICE to be selected to avoid compilation breakages. Cc: stable at vger.kernel.org Reported-by: Russell King Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/shmobile/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/shmobile/Kconfig b/drivers/gpu/drm/shmobile/Kconfig index ca498d1..5240690 100644 --- a/drivers/gpu/drm/shmobile/Kconfig +++ b/drivers/gpu/drm/shmobile/Kconfig @@ -1,6 +1,7 @@ config DRM_SHMOBILE tristate "DRM Support for SH Mobile" depends on DRM && (ARM || SUPERH) + select BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER -- Regards, Laurent Pinchart
[PATCH 00/14] drm: Some more vblank timestampi changes
So I took another look at the vblank timestamping code, and got a bit excited. The result is this patchset. Summary of changes: - kill crtc->hwmode dependency - eliminate a bunch of 64bit math - fix timestamps for stereo and interlaced modes (on i915 at least) - move the "early vbl irq" hack into radeon code - add a similar hack to i915, but make it as finely targeted as possibly to minimize the chance of accidentally applying it in the wrong place The s/clock/crtc_clock change could use some radeon people to verify whether changing radeon_atom_get_tv_timings() is enough to make crtc_clock always populated. This series applies on top of Mario's "Vblank timestamping improvements/fixes for Linux drm." series. Ville Syrj?l? (14): drm: Pass the display mode to drm_calc_timestamping_constants() drm: Pass the display mode to drm_calc_vbltimestamp_from_scanoutpos() drm/i915: Kill hwmode save/restore drm/i915: Call drm_calc_timestamping_constants() earlier drm: Improve drm_calc_timestamping_constants() documentation drm: Simplify the math in drm_calc_timestamping_constants() drm/radeon: Populate crtc_clock in radeon_atom_get_tv_timings() drm: Use crtc_clock in drm_calc_timestamping_constants() drm: Change {pixel,line,frame}dur_ns from s64 to int drm/i915: Fix scanoutpos calculations for interlaced modes drm: Fix vblank timestamping constants for interlaced modes drm: Pass 'flags' from the caller to .get_scanout_position() drm/radeon: Move the early vblank IRQ fixup to radeon_get_crtc_scanoutpos() drm/i915: Add a kludge for DSL incrementing too late and ISR not working drivers/gpu/drm/drm_crtc_helper.c| 2 +- drivers/gpu/drm/drm_irq.c| 109 --- drivers/gpu/drm/i915/i915_irq.c | 91 ++ drivers/gpu/drm/i915/intel_display.c | 29 drivers/gpu/drm/radeon/radeon_atombios.c | 6 +- drivers/gpu/drm/radeon/radeon_display.c | 29 +++- drivers/gpu/drm/radeon/radeon_kms.c | 2 +- drivers/gpu/drm/radeon/radeon_mode.h | 1 + drivers/gpu/drm/radeon/radeon_pm.c | 2 +- include/drm/drmP.h | 8 ++- include/drm/drm_crtc.h | 2 +- 11 files changed, 143 insertions(+), 138 deletions(-)
[PATCH 01/14] drm: Pass the display mode to drm_calc_timestamping_constants()
From: Ville Syrj?l? We don't really use hwmode anymore in i915, so eliminating its use from the core code seems prudent. Just pass the appropriate mode to drm_calc_timestamping_constants(). Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_crtc_helper.c| 2 +- drivers/gpu/drm/drm_irq.c| 17 + drivers/gpu/drm/i915/intel_display.c | 3 ++- include/drm/drmP.h | 3 ++- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index dbcd687..fce1cff 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -533,7 +533,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, * are later needed by vblank and swap-completion * timestamping. They are derived from true hwmode. */ - drm_calc_timestamping_constants(crtc); + drm_calc_timestamping_constants(crtc, &crtc->hwmode); /* FIXME: add subpixel order */ done: diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 2250724..679417d 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -445,20 +445,22 @@ int drm_control(struct drm_device *dev, void *data, * adjustments into account. * * @crtc drm_crtc whose timestamp constants should be updated. + * @mode display mode containing the scanout timings * */ -void drm_calc_timestamping_constants(struct drm_crtc *crtc) +void drm_calc_timestamping_constants(struct drm_crtc *crtc, +const struct drm_display_mode *mode) { s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; u64 dotclock; /* Dot clock in Hz: */ - dotclock = (u64) crtc->hwmode.clock * 1000; + dotclock = (u64) mode->clock * 1000; /* Fields of interlaced scanout modes are only halve a frame duration. * Double the dotclock to get halve the frame-/line-/pixelduration. */ - if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE) + if (mode->flags & DRM_MODE_FLAG_INTERLACE) dotclock *= 2; /* Valid dotclock? */ @@ -469,10 +471,9 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc) * nanoseconds: */ pixeldur_ns = (s64) div64_u64(10, dotclock); - linedur_ns = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal * + linedur_ns = (s64) div64_u64(((u64) mode->crtc_htotal * 10), dotclock); - frame_size = crtc->hwmode.crtc_htotal * - crtc->hwmode.crtc_vtotal; + frame_size = mode->crtc_htotal * mode->crtc_vtotal; framedur_ns = (s64) div64_u64((u64) frame_size * 10, dotclock); } else @@ -484,8 +485,8 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc) crtc->framedur_ns = framedur_ns; DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", - crtc->base.id, crtc->hwmode.crtc_htotal, - crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay); + crtc->base.id, mode->crtc_htotal, + mode->crtc_vtotal, mode->crtc_vdisplay); DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", crtc->base.id, (int) dotclock/1000, (int) framedur_ns, (int) linedur_ns, (int) pixeldur_ns); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0c2e83c..7ea20b2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9364,7 +9364,8 @@ static int __intel_set_mode(struct drm_crtc *crtc, * are later needed by vblank and swap-completion * timestamping. They are derived from true hwmode. */ - drm_calc_timestamping_constants(crtc); + drm_calc_timestamping_constants(crtc, + &pipe_config->adjusted_mode); } /* FIXME: add subpixel order */ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8d4e10d..99f49ea 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1419,7 +1419,8 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, struct timeval *vblank_time, unsigned flags, struct drm_crtc *refcrtc); -extern void drm_calc_timestamping_constants(struct drm_crtc *crtc); +extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, + const struct drm_display_mode *mode); extern bool drm_mode_parse_command_line_for_connector(const char *mode
[PATCH 02/14] drm: Pass the display mode to drm_calc_vbltimestamp_from_scanoutpos()
From: Ville Syrj?l? Rather than using crtc->hwmode, just pass the relevant mode to drm_calc_vbltimestamp_from_scanoutpos(). This removes the last hwmode usage from core drm. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 6 +++--- drivers/gpu/drm/i915/i915_irq.c | 3 ++- drivers/gpu/drm/radeon/radeon_kms.c | 2 +- include/drm/drmP.h | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 679417d..7702614 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -522,6 +522,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * 0 = Default. * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. * @refcrtc: drm_crtc* of crtc which defines scanout timing. + * @mode: mode which defines the scanout timings * * Returns negative value on error, failure or if not supported in current * video mode: @@ -541,11 +542,11 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, int *max_error, struct timeval *vblank_time, unsigned flags, - struct drm_crtc *refcrtc) + const struct drm_crtc *refcrtc, + const struct drm_display_mode *mode) { ktime_t stime, etime, mono_time_offset; struct timeval tv_etime; - struct drm_display_mode *mode; int vbl_status, vtotal, vdisplay; int vpos, hpos, i; s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; @@ -562,7 +563,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, return -EIO; } - mode = &refcrtc->hwmode; vtotal = mode->crtc_vtotal; vdisplay = mode->crtc_vdisplay; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5a60d89..2b19989 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -790,7 +790,8 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, vblank_time, flags, -crtc); +crtc, + &to_intel_crtc(crtc)->config.adjusted_mode); } static bool intel_hpd_irq_event(struct drm_device *dev, diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index d6b3676..80896a1 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -670,7 +670,7 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, vblank_time, flags, -drmcrtc); +drmcrtc, &drmcrtc->hwmode); } #define KMS_INVALID_IOCTL(name) \ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 99f49ea..14d4046 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1418,7 +1418,8 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, int *max_error, struct timeval *vblank_time, unsigned flags, -struct drm_crtc *refcrtc); +const struct drm_crtc *refcrtc, +const struct drm_display_mode *mode); extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode); -- 1.8.1.5
[PATCH 03/14] drm/i915: Kill hwmode save/restore
From: Ville Syrj?l? drm core no longer uses crtc->hwmode, and neither does i915, so we can totally ignore it in i915. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/i915/intel_display.c | 13 +++-- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7ea20b2..2b35b29 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9283,21 +9283,19 @@ static int __intel_set_mode(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_display_mode *saved_mode, *saved_hwmode; + struct drm_display_mode *saved_mode; struct intel_crtc_config *pipe_config = NULL; struct intel_crtc *intel_crtc; unsigned disable_pipes, prepare_pipes, modeset_pipes; int ret = 0; - saved_mode = kcalloc(2, sizeof(*saved_mode), GFP_KERNEL); + saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL); if (!saved_mode) return -ENOMEM; - saved_hwmode = saved_mode + 1; intel_modeset_affected_pipes(crtc, &modeset_pipes, &prepare_pipes, &disable_pipes); - *saved_hwmode = crtc->hwmode; *saved_mode = crtc->mode; /* Hack: Because we don't (yet) support global modeset on multiple @@ -9357,9 +9355,6 @@ static int __intel_set_mode(struct drm_crtc *crtc, dev_priv->display.crtc_enable(&intel_crtc->base); if (modeset_pipes) { - /* Store real post-adjustment hardware mode. */ - crtc->hwmode = pipe_config->adjusted_mode; - /* Calculate and store various constants which * are later needed by vblank and swap-completion * timestamping. They are derived from true hwmode. @@ -9370,10 +9365,8 @@ static int __intel_set_mode(struct drm_crtc *crtc, /* FIXME: add subpixel order */ done: - if (ret && crtc->enabled) { - crtc->hwmode = *saved_hwmode; + if (ret && crtc->enabled) crtc->mode = *saved_mode; - } out: kfree(pipe_config); -- 1.8.1.5
[PATCH 04/14] drm/i915: Call drm_calc_timestamping_constants() earlier
From: Ville Syrj?l? Update the pixel/line/frame duration information when we switch to the new pipe config. This will keep the timestamping constants in better sync with the real hardware state. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/i915/intel_display.c | 17 - 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2b35b29..1b8ed0e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9331,6 +9331,14 @@ static int __intel_set_mode(struct drm_crtc *crtc, /* mode_set/enable/disable functions rely on a correct pipe * config. */ to_intel_crtc(crtc)->config = *pipe_config; + + /* +* Calculate and store various constants which +* are later needed by vblank and swap-completion +* timestamping. They are derived from true hwmode. +*/ + drm_calc_timestamping_constants(crtc, + &pipe_config->adjusted_mode); } /* Only after disabling all output pipelines that will be changed can we @@ -9354,15 +9362,6 @@ static int __intel_set_mode(struct drm_crtc *crtc, for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) dev_priv->display.crtc_enable(&intel_crtc->base); - if (modeset_pipes) { - /* Calculate and store various constants which -* are later needed by vblank and swap-completion -* timestamping. They are derived from true hwmode. -*/ - drm_calc_timestamping_constants(crtc, - &pipe_config->adjusted_mode); - } - /* FIXME: add subpixel order */ done: if (ret && crtc->enabled) -- 1.8.1.5
[PATCH 06/14] drm: Simplify the math in drm_calc_timestamping_constants()
From: Ville Syrj?l? drm_calc_timestamping_constants() makes the math more complex than necessary. - multipying the dotclock by 1000 is pointless, just makes all the numbers bigger - div64_u64() is also pointless, div_u64 is enough - pixeldur_ns doesn't need any 64bit math Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 26 +++--- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 48bf91f..d6ef034 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -451,10 +451,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) { s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; - u64 dotclock; - - /* Dot clock in Hz: */ - dotclock = (u64) mode->clock * 1000; + int dotclock = mode->clock; /* Fields of interlaced scanout modes are only halve a frame duration. * Double the dotclock to get halve the frame-/line-/pixelduration. @@ -464,17 +461,16 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, /* Valid dotclock? */ if (dotclock > 0) { - int frame_size; - /* Convert scanline length in pixels and video dot clock to -* line duration, frame duration and pixel duration in -* nanoseconds: + int frame_size = mode->crtc_htotal * mode->crtc_vtotal; + + /* +* Convert scanline length in pixels and video +* dot clock to line duration, frame duration +* and pixel duration in nanoseconds: */ - pixeldur_ns = (s64) div64_u64(10, dotclock); - linedur_ns = (s64) div64_u64(((u64) mode->crtc_htotal * - 10), dotclock); - frame_size = mode->crtc_htotal * mode->crtc_vtotal; - framedur_ns = (s64) div64_u64((u64) frame_size * 10, - dotclock); + pixeldur_ns = 100 / dotclock; + linedur_ns = div_u64((u64) mode->crtc_htotal * 100, dotclock); + framedur_ns = div_u64((u64) frame_size * 100, dotclock); } else DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", crtc->base.id); @@ -487,7 +483,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, crtc->base.id, mode->crtc_htotal, mode->crtc_vtotal, mode->crtc_vdisplay); DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", - crtc->base.id, (int) dotclock/1000, (int) framedur_ns, + crtc->base.id, dotclock, (int) framedur_ns, (int) linedur_ns, (int) pixeldur_ns); } EXPORT_SYMBOL(drm_calc_timestamping_constants); -- 1.8.1.5
[PATCH 07/14] drm/radeon: Populate crtc_clock in radeon_atom_get_tv_timings()
From: Ville Syrj?l? crtc_clock is now supposed to be the actual pixel clock corresponding to the other crtc_ timing values. Populate crtc_clock appropriately in radeon_atom_get_tv_timings(). This was the only obvious place where we frob with the crtc_ timigns directly instead of calling drm_mode_set_crtcinfo() which would also update crtc_clock. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/radeon/radeon_atombios.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index f79ee18..229ef65 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1809,7 +1809,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, if (misc & ATOM_DOUBLE_CLOCK_MODE) mode->flags |= DRM_MODE_FLAG_DBLSCAN; - mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; + mode->crtc_clock = mode->clock = + le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; if (index == 1) { /* PAL timings appear to have wrong values for totals */ @@ -1852,7 +1853,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, if (misc & ATOM_DOUBLE_CLOCK_MODE) mode->flags |= DRM_MODE_FLAG_DBLSCAN; - mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10; + mode->crtc_clock = mode->clock = + le16_to_cpu(dtd_timings->usPixClk) * 10; break; } return true; -- 1.8.1.5
[PATCH 08/14] drm: Use crtc_clock in drm_calc_timestamping_constants()
From: Ville Syrj?l? drm_calc_timestamping_constants() computes the pixel/line/frame durations based on the crtc_ timing values. The corresponding pixel clock is in mode->crtc_clock, so we need to use that instead of mode->clock. This should fix drm_calc_timestamping_constants() for frame packing stereo modes. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index d6ef034..77be2fb 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -451,7 +451,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) { s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; - int dotclock = mode->clock; + int dotclock = mode->crtc_clock; /* Fields of interlaced scanout modes are only halve a frame duration. * Double the dotclock to get halve the frame-/line-/pixelduration. -- 1.8.1.5
[PATCH 09/14] drm: Change {pixel,line,frame}dur_ns from s64 to int
From: Ville Syrj?l? Using s64 for the timestamping constants is wasteful. Signed 32bit integers get us a range of over +-2 seconds. Presuming that no-one wants to a vrefresh rate less than 0.5, we can switch to using int for the timestamping constants. We save a few bytes in drm_crtc and avoid a bunch of 64bit math. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 18 +- include/drm/drm_crtc.h| 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 77be2fb..b21a226 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -450,7 +450,7 @@ int drm_control(struct drm_device *dev, void *data, void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) { - s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; + int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; int dotclock = mode->crtc_clock; /* Fields of interlaced scanout modes are only halve a frame duration. @@ -483,8 +483,8 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, crtc->base.id, mode->crtc_htotal, mode->crtc_vtotal, mode->crtc_vdisplay); DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", - crtc->base.id, dotclock, (int) framedur_ns, - (int) linedur_ns, (int) pixeldur_ns); + crtc->base.id, dotclock, framedur_ns, + linedur_ns, pixeldur_ns); } EXPORT_SYMBOL(drm_calc_timestamping_constants); @@ -544,7 +544,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, struct timeval tv_etime; int vbl_status, vtotal, vdisplay; int vpos, hpos, i; - s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; + int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; bool invbl; if (crtc < 0 || crtc >= dev->num_crtcs) { @@ -605,18 +605,18 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); /* Accept result with < max_error nsecs timing uncertainty. */ - if (duration_ns <= (s64) *max_error) + if (duration_ns <= *max_error) break; } /* Noisy system timing? */ if (i == DRM_TIMESTAMP_MAXRETRIES) { DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n", - crtc, (int) duration_ns/1000, *max_error/1000, i); + crtc, duration_ns/1000, *max_error/1000, i); } /* Return upper bound of timestamp precision error. */ - *max_error = (int) duration_ns; + *max_error = duration_ns; /* Check if in vblank area: * vpos is >=0 in video scanout area, but negative @@ -629,7 +629,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, * since start of scanout at first display scanline. delta_ns * can be negative if start of scanout hasn't happened yet. */ - delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns; + delta_ns = vpos * linedur_ns + hpos * pixeldur_ns; /* Is vpos outside nominal vblank area, but less than * 1/100 of a frame height away from start of vblank? @@ -667,7 +667,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, crtc, (int)vbl_status, hpos, vpos, (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, - (int)duration_ns/1000, i); + duration_ns/1000, i); vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; if (invbl) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d3a91ad..d94c25f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -447,7 +447,7 @@ struct drm_crtc { uint16_t *gamma_store; /* Constants needed for precise vblank and swap timestamping. */ - s64 framedur_ns, linedur_ns, pixeldur_ns; + int framedur_ns, linedur_ns, pixeldur_ns; /* if you are using the helper */ void *helper_private; -- 1.8.1.5
[PATCH 10/14] drm/i915: Fix scanoutpos calculations for interlaced modes
From: Ville Syrj?l? The scanline counter counts lines in the current field, not the entire frame. But the crtc_ timings are the values for the entire frame. Divide the vertical timings by 2 to make them match the scanline counter. The rounding was carefully chosen to make it do the right thing wrt. the observed scanline counter and ISR vblank bit behaviour. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/i915/i915_irq.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2b19989..f6b3206 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -680,6 +680,12 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, vbl_start = mode->crtc_vblank_start; vbl_end = mode->crtc_vblank_end; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + vbl_start = DIV_ROUND_UP(vbl_start, 2); + vbl_end /= 2; + vtotal /= 2; + } + ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; /* Lock uncore.lock, as we will do multiple timing critical raw -- 1.8.1.5
[PATCH 12/14] drm: Pass 'flags' from the caller to .get_scanout_position()
From: Ville Syrj?l? Preparation for moving the early vblank IRQ logic into radeon_get_crtc_scanoutpos(). Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 3 ++- drivers/gpu/drm/radeon/radeon_display.c | 7 --- drivers/gpu/drm/radeon/radeon_mode.h| 1 + drivers/gpu/drm/radeon/radeon_pm.c | 2 +- include/drm/drmP.h | 2 ++ 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index b5c4d42..b39255f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -585,7 +585,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, /* Get vertical and horizontal scanout position vpos, hpos, * and bounding timestamps stime, etime, pre/post query. */ - vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, + vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos, &hpos, &stime, &etime); /* Get correction for CLOCK_MONOTONIC -> CLOCK_REALTIME if diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f6b3206..70daf3c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -657,7 +657,8 @@ static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe) } static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, -int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) + unsigned int flags, int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index ccd8751..3581570 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -305,7 +305,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) * to complete in this vblank? */ if (update_pending && - (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, + (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0, &vpos, &hpos, NULL, NULL)) && ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || (vpos < 0 && !ASIC_IS_AVIVO(rdev { @@ -1544,6 +1544,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * * \param dev Device to query. * \param crtc Crtc to query. + * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). * \param *vpos Location where vertical scanout position should be stored. * \param *hpos Location where horizontal scanout position should go. * \param *stime Target location for timestamp taken immediately before @@ -1565,8 +1566,8 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * unknown small number of scanlines wrt. real scanout position. * */ -int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime) +int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, + int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) { u32 stat_crtc = 0, vbl = 0, position = 0; int vbl_start, vbl_end, vtotal, ret = 0; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 3bfa910..c4016dc 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -758,6 +758,7 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 98bf63b..a394049 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -1468,7 +1468,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev) */ for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { if (rdev->pm.active_crtcs & (1 << crtc)) { - vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos, NULL, NULL); + vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, cr
[PATCH 05/14] drm: Improve drm_calc_timestamping_constants() documentation
From: Ville Syrj?l? Move the long blurp to into the body of the comment, leaving only a short summary line at the top. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 7702614..48bf91f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -436,17 +436,16 @@ int drm_control(struct drm_device *dev, void *data, } /** - * drm_calc_timestamping_constants - Calculate and - * store various constants which are later needed by - * vblank and swap-completion timestamping, e.g, by - * drm_calc_vbltimestamp_from_scanoutpos(). - * They are derived from crtc's true scanout timing, - * so they take things like panel scaling or other - * adjustments into account. + * drm_calc_timestamping_constants - Calculate vblank timestamp constants * * @crtc drm_crtc whose timestamp constants should be updated. * @mode display mode containing the scanout timings * + * Calculate and store various constants which are later + * needed by vblank and swap-completion timestamping, e.g, + * by drm_calc_vbltimestamp_from_scanoutpos(). They are + * derived from crtc's true scanout timing, so they take + * things like panel scaling or other adjustments into account. */ void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) -- 1.8.1.5
[PATCH 11/14] drm: Fix vblank timestamping constants for interlaced modes
From: Ville Syrj?l? We're currently miscalculating the line and pixel durations for interlaced modes. crtc_htotal and crtc_vtotal are the full frame timings, and so is crtc_clock, so we can compute the line and pixel durations from those w/o any extra adjustments. But we actually want framedur_ns to be the field, not frame, duration, so we must divide it by two. This should make the scanout based vblank timestamp corrections work correctly with interlaced modes, at least for i915. It all depends whether we keep the field or frame timings in the display mode crtc_ timings. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index b21a226..b5c4d42 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -453,12 +453,6 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; int dotclock = mode->crtc_clock; - /* Fields of interlaced scanout modes are only halve a frame duration. -* Double the dotclock to get halve the frame-/line-/pixelduration. -*/ - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - dotclock *= 2; - /* Valid dotclock? */ if (dotclock > 0) { int frame_size = mode->crtc_htotal * mode->crtc_vtotal; @@ -471,6 +465,12 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, pixeldur_ns = 100 / dotclock; linedur_ns = div_u64((u64) mode->crtc_htotal * 100, dotclock); framedur_ns = div_u64((u64) frame_size * 100, dotclock); + + /* +* Fields of interlaced scanout modes are only halve a frame duration. +*/ + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + framedur_ns /= 2; } else DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", crtc->base.id); -- 1.8.1.5
[PATCH 14/14] drm/i915: Add a kludge for DSL incrementing too late and ISR not working
From: Ville Syrj?l? On pre-PCH platforms ISR doesn't seem to be an actual ISR, at least as far as display interrupts are concerned. Instead it sort of looks like some ISR bits just directly reflect the corresponding bit from PIPESTAT. The bit appears in the ISR only if the PIPESTAT interrupt is enabled. So in that sense it sort of looks a bit like the south interrupt scheme on PCH platforms. So it goes something a bit like this: PIPESTAT.status & PIPESTAT.enable -> ISR -> IMR -> IIR -> IER -> actual interrupt In any case that means the intel_pipe_in_vblank_locked() doesn't actually work for pre-PCH platforms. As a last resort, add a similar kludge as radeon has that fixes things up if we got called from the vblank interrupt, but the scanline counter value indicates that we're not quite there yet. We know that the scanline counter increments at hsync but is otherwise accurate, so we can limit the kludge to the line just prior to vblank start, instead of the relative distance that radeon uses. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/i915/i915_irq.c | 79 - 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 70daf3c..b93f39c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -603,36 +603,15 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) #define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__)) #define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__)) -static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe) +static bool ilk_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t status; - int reg; - if (IS_VALLEYVIEW(dev)) { - status = pipe == PIPE_A ? - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT : - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - - reg = VLV_ISR; - } else if (IS_GEN2(dev)) { - status = pipe == PIPE_A ? - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT : - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - - reg = ISR; - } else if (INTEL_INFO(dev)->gen < 5) { - status = pipe == PIPE_A ? - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT : - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - - reg = ISR; - } else if (INTEL_INFO(dev)->gen < 7) { + if (INTEL_INFO(dev)->gen < 7) { status = pipe == PIPE_A ? DE_PIPEA_VBLANK : DE_PIPEB_VBLANK; - - reg = DEISR; } else { switch (pipe) { default: @@ -646,14 +625,9 @@ static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe) status = DE_PIPEC_VBLANK_IVB; break; } - - reg = DEISR; } - if (IS_GEN2(dev)) - return __raw_i915_read16(dev_priv, reg) & status; - else - return __raw_i915_read32(dev_priv, reg) & status; + return __raw_i915_read32(dev_priv, DEISR) & status; } static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, @@ -710,17 +684,42 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, else position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; - /* -* The scanline counter increments at the leading edge -* of hsync, ie. it completely misses the active portion -* of the line. Fix up the counter at both edges of vblank -* to get a more accurate picture whether we're in vblank -* or not. -*/ - in_vbl = intel_pipe_in_vblank_locked(dev, pipe); - if ((in_vbl && position == vbl_start - 1) || - (!in_vbl && position == vbl_end - 1)) - position = (position + 1) % vtotal; + if (HAS_PCH_SPLIT(dev)) { + /* +* The scanline counter increments at the leading edge +* of hsync, ie. it completely misses the active portion +* of the line. Fix up the counter at both edges of vblank +* to get a more accurate picture whether we're in vblank +* or not. +*/ + in_vbl = ilk_pipe_in_vblank_locked(dev, pipe); + if ((in_vbl && position == vbl_start - 1) || + (!in_vbl && position == vbl_end - 1)) + position = (posit
[PATCH 13/14] drm/radeon: Move the early vblank IRQ fixup to radeon_get_crtc_scanoutpos()
From: Ville Syrj?l? i915 doesn't need this kludge for most platforms. Although we do appear to need something similar on certain platforms, but we can be more accurate when we apply the adjustment since we know exactly why the scanline counter doesn't always quite match the vblank status. Also the current code doesn't handle interlaced modes correctly, and we already deal with interlaced modes in i915 code. So let's just move the current code to radeon_get_crtc_scanoutpos() since that's why it was added. For i915 we'll add a more finely targeted variant. Signed-off-by: Ville Syrj?l? --- drivers/gpu/drm/drm_irq.c | 25 ++--- drivers/gpu/drm/radeon/radeon_display.c | 22 ++ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index b39255f..a1cc1a3 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -542,7 +542,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, { ktime_t stime, etime, mono_time_offset; struct timeval tv_etime; - int vbl_status, vtotal, vdisplay; + int vbl_status; int vpos, hpos, i; int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; bool invbl; @@ -558,9 +558,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, return -EIO; } - vtotal = mode->crtc_vtotal; - vdisplay = mode->crtc_vdisplay; - /* Durations of frames, lines, pixels in nanoseconds. */ framedur_ns = refcrtc->framedur_ns; linedur_ns = refcrtc->linedur_ns; @@ -569,7 +566,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, /* If mode timing undefined, just return as no-op: * Happens during initial modesetting of a crtc. */ - if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) { + if (framedur_ns == 0) { DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); return -EAGAIN; } @@ -631,24 +628,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, */ delta_ns = vpos * linedur_ns + hpos * pixeldur_ns; - /* Is vpos outside nominal vblank area, but less than -* 1/100 of a frame height away from start of vblank? -* If so, assume this isn't a massively delayed vblank -* interrupt, but a vblank interrupt that fired a few -* microseconds before true start of vblank. Compensate -* by adding a full frame duration to the final timestamp. -* Happens, e.g., on ATI R500, R600. -* -* We only do this if DRM_CALLED_FROM_VBLIRQ. -*/ - if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl && - ((vdisplay - vpos) < vtotal / 100)) { - delta_ns = delta_ns - framedur_ns; - - /* Signal this correction as "applied". */ - vbl_status |= 0x8; - } - if (!drm_timestamp_monotonic) etime = ktime_sub(etime, mono_time_offset); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 3581570..9d02fa7 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1709,5 +1709,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl if (in_vbl) ret |= DRM_SCANOUTPOS_INVBL; + /* Is vpos outside nominal vblank area, but less than +* 1/100 of a frame height away from start of vblank? +* If so, assume this isn't a massively delayed vblank +* interrupt, but a vblank interrupt that fired a few +* microseconds before true start of vblank. Compensate +* by adding a full frame duration to the final timestamp. +* Happens, e.g., on ATI R500, R600. +* +* We only do this if DRM_CALLED_FROM_VBLIRQ. +*/ + if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { + vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; + vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + + if (vbl_start - *vpos < vtotal / 100) { + vpos -= vtotal; + + /* Signal this correction as "applied". */ + ret |= 0x8; + } + } + return ret; } -- 1.8.1.5