Re: [PATCH v2 0/4] gpio: fix an incorrect lockdep warning
On 2016-09-18 21:45, Bartosz Golaszewski wrote: > 2016-09-18 21:43 GMT+02:00 Bartosz Golaszewski : >> 2016-09-18 10:52 GMT+02:00 Peter Rosin : >>> On 2016-09-16 19:58, Wolfram Sang wrote: >>>> >>>> Same here. And if it prevents us from false positive lockdep reports, I >>>> am all for fixing it. >>> >>> Except it doesn't, when I think some more about it... >>> >>> If you have two gpio-expanders on the same depth but on different i2c >>> branches you still end up with a splat if one is used to control a mux >>> to reach the other. >>> >>> The only way to solve it for good, that I see, is to have every instance >>> of the gpio-expander mutex in its own class. That might lead to many >>> lockdep classes but then again, how many gpio expanders could there be >>> in a system? A dozen or two seems extreme, so maybe that is the correct >>> approach anyway? >> >> Wouldn't it be enough to have a separate class for every base (as in: >> not having any parent adapters) i2c adapter? >> > > Eeek -ESENTTOOEARLY > > Of course not - since we could have two branches deeper on the tree > with the same problem. > > Nevermind my last e-mail. Right, but you have a point, we can avoid some lockdep classes if we work at it. We could recognize that no gpio-expander can be involved with muxing for a gpio-expander sitting on a root i2c adapter. That much is trivially obvious. That means that we could treat all gpio-expanders sitting directly on a root i2c-adapter as we always have, just like v1 (and v2, implicitly) do, but instead of putting all other gpio-exanders in one lockdep class (as in v1) or in one lockdep class per depth (as in v2), we put all other gpio-mutexes in a lockdep class of their own. Then we do not get any extra lockdep classes unless there are i2c muxes, which is better. But only i2c-mux-gpio can cause the recursion. I think the theoretical minimal number of lockdep classes is to create a new lockdep class for every i2c-mux-gpio instance. gpio-expanders needing a mutex could walk up the adapter tree looking for a i2c-mux-gpio and getting the lockdep class from there. If the root i2c adapter is reached, use some default lockdep class. That would consolidate muxes from different gpio-expander drivers into the one lockdep class. I don't know if that is a big no-no? I guess that can be handled too with more code, but it is starting to get messy... Or, do what the i2c-mux code is doing and use an rt_mutex instead of an ordinary mutex. That way you are very sure to not get any lockdep splat ... at all. Ok, sorry, that was not a serious suggestion, but it would be a tad bit simpler to implement... Cheers, Peter
Re: [PATCH v2 0/4] gpio: fix an incorrect lockdep warning
On 2016-09-19 11:03, Peter Zijlstra wrote: > On Mon, Sep 19, 2016 at 10:48:44AM +0200, Peter Rosin wrote: >> On 2016-09-19 10:14, Peter Zijlstra wrote: >>> On Mon, Sep 19, 2016 at 10:01:49AM +0200, Peter Rosin wrote: >>>> Or, do what the i2c-mux code is doing and use an rt_mutex instead >>>> of an ordinary mutex. That way you are very sure to not get any >>>> lockdep splat ... at all. Ok, sorry, that was not a serious >>>> suggestion, but it would be a tad bit simpler to implement... >>> >>> So I find it weird that people use rt_mutex as a locking primitive, >>> since its only that one lock that then does PI and all the other locks >>> that are related still create inversions. >> >> So, someone took the bait :-) >> >> Yes, I too find it weird, and would like to get rid of it. It's just >> odd. It's been some years since the start though, waaay before me >> entering kernel space. >> >> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=194684e596af4b >> >> >> But it's hard to argue with the numbers given in the discussion: >> >> http://linux-i2c.vger.kernel.narkive.com/nokldJcc/patch-1-1-i2c-prevent-priority-inversion-on-top-of-bus-lock >> >> Has anything happened to the regular mutex implementation that might >> have changed the picture? *crosses fingers* > > Use the -RT kernel and all locks will end up as rt_mutex. Avoiding > inversion on one specific lock, while there are then a gazillion other > than can equally create inversion doesn't make sense to me. So, are we willing to risk a regression and ask any victims of that fallout to switch to the -RT kernel? -RT is still not completely mainline, right? Is the part with the mutex->rt_mutex conversion in mainline? In other words, is it just a config option that we can ask victims to use, or will they have to defer to patches? I guess the relatively freshly introduced rt_mutex "mux_lock" in include/linux/i2c.h can be safely converted to an ordinary mutex since the only reason I went with rt_mutex was that "bus_lock" was an rt_mutex and they are grabbed in similar circumstances. I can certainly send a patch. However, the i2c muxing suffers from the issue we were originally discussing, potentially causing false positive lockdep reports when you build complex hierarchies with additional dependencies between branches coming from client devices in the hierarchy (such as i2c-muxes controlled by i2c-gpio-expanders). One pretty simple problematic case is: .---. .. | | ||-- i2c2 | |-- i2c0 --|mux0| .. | l | ||-- i2c3 --|gpio| | i | '' '' | n | .--' | u | .. .. | x | ||-- i2c4 --|dev0| | |-- i2c1 --|mux1| '' | | ||-- i2c5 '---' '' Accesses to dev0 will: 1. lock i2c1:mux_lock (depth 0) 2. switch mux1 to i2c4 using gpio a lock i2c0:mux_lock (depth 0) b switch mux0 to i2c3 using whatever c access gpio d unlock i2c0:mux_lock 3. access dev0 4. unlock i2c1:mux_lock 2a will cause a lockdep splat if i2c0:mux_lock is in the same lockdep class & subclass as i2c1:mux_lock. So, lockdep needs separate lockdep classes depending on the i2c root adapter (subclasses are needed to handle deeper trees, so they are off limits). Great fun. How do I go about creating a new lockdep class for every i2c root adapter instance? Cheers, Peter
Re: [PATCH v2 0/4] gpio: fix an incorrect lockdep warning
On 2016-09-20 12:07, Bartosz Golaszewski wrote: > 2016-09-20 10:48 GMT+02:00 Peter Rosin : >> >> One pretty simple problematic case is: >> >> .---. .. >> | | ||-- i2c2 >> | |-- i2c0 --|mux0| .. >> | l | ||-- i2c3 --|gpio| >> | i | '' '' >> | n | .--' >> | u | .. .. >> | x | ||-- i2c4 --|dev0| >> | |-- i2c1 --|mux1| '' >> | | ||-- i2c5 >> '---' '' >> >> Accesses to dev0 will: >> >> 1. lock i2c1:mux_lock (depth 0) >> 2. switch mux1 to i2c4 using gpio >> a lock i2c0:mux_lock (depth 0) >> b switch mux0 to i2c3 using whatever >> c access gpio >> d unlock i2c0:mux_lock >> 3. access dev0 >> 4. unlock i2c1:mux_lock >> >> 2a will cause a lockdep splat if i2c0:mux_lock is in the same >> lockdep class & subclass as i2c1:mux_lock. So, lockdep needs >> separate lockdep classes depending on the i2c root adapter >> (subclasses are needed to handle deeper trees, so they are off >> limits). Great fun. How do I go about creating a new lockdep >> class for every i2c root adapter instance? >> > > I feel like it's just wrong to set an arbitrary limit on the number of > i2c branches - and this is what the result of this approach would be. What arbitrary limit would that be? The number of lockdep classes can't be *that* limited? Or? I mean one lockdep class per root adapter and one subclass within that class per mux level doesn't sound too bad. How many root adapters do we need to design for? > One solution that comes to mind is to have a separate, global set of > lock classes solely for gpio expanders. I think you mentioned earlier > that it's the only thing that can cause this kind of lockdep false > positives. No, that's not true, so if I said that, it was simply wrong. E.g. I think the new mlxcpld i2c mux can mux another i2c adapter and will cause the same problem without involving any gpio expander. [OT: Wolfram, are you still following this? Are you picking up the mlxcpld mux driver, or did my ack fly by without you noticing?] Oh, and the there is a pinctrl-based i2c mux that also suffers as there are pinctrl chips that are i2c clients. And even though I don't really know the pinctrl demux, it will probably also cause interesting nesting if an i2c based pinctrl is used as demuxer. If that's relevant, probably isn't... >We could potentially have a limited set of lock classes and > every expander that would need one would request it using some kind of > API ensuring that every instance gets a separate class. But this > sounds like a big hack too I'm afraid... And regmap would need to be > aware of that as well. > > Anyways, we're past rc7 already and 4.9 will be the next LTS kernel. > We have real hardware here that runs on mainline linux and is > suffering from this issue. Are there any objections against merging > this series now and continuing the work on improving the solution for > 4.10? No, I have no objection. It's not wrong per se, it's just not complete. Cheers, Peter
Re: [v12, 7/8] base: soc: introduce soc_device_match() interface
On 2016-09-21 09:56, Alexander Shiyan wrote: >> Среда, 21 сентября 2016, 9:57 +03:00 от Yangbo Lu : >> >> From: Arnd Bergmann < a...@arndb.de > >> >> We keep running into cases where device drivers want to know the exact >> version of the a SoC they are currently running on. In the past, this has >> usually been done through a vendor specific API that can be called by a >> driver, or by directly accessing some kind of version register that is >> not part of the device itself but that belongs to a global register area >> of the chip. > ... >> +const struct soc_device_attribute *soc_device_match( >> +const struct soc_device_attribute *matches) >> +{ >> +int ret = 0; >> + >> +if (!matches) >> +return NULL; >> + >> +while (!ret) { >> +if (!(matches->machine || matches->family || >> + matches->revision || matches->soc_id)) >> +break; >> +ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches, >> + soc_device_match_one); >> +if (!ret) >> +matches++; > > So, what happen if next "matches" (after increment) will be NULL? A crash? > I think you should use while(matches) at the start of this procedure. *arrgh* *If* matches wrap, you indeed have *big* problems. *Elsewhere* Hint: Please read the review comments on the previous version of this series [1] before commenting further. Cheers, Peter [1] https://www.mail-archive.com/netdev@vger.kernel.org/msg126617.html
Re: [PATCH v2 0/4] gpio: fix an incorrect lockdep warning
On 2016-09-20 17:33, Thomas Gleixner wrote: > On Tue, 20 Sep 2016, Peter Rosin wrote: >> On 2016-09-19 11:03, Peter Zijlstra wrote: >>> >>> Use the -RT kernel and all locks will end up as rt_mutex. Avoiding >>> inversion on one specific lock, while there are then a gazillion other >>> than can equally create inversion doesn't make sense to me. > > That's true, but the locking of the i2c stuff is pretty much self contained > and the results of using an rtmutex speak for themself. > > One of the issues is that i2c needs to use threaded interrupt handlers and > blocking out the handler thread with a preempted user space task is hurting > performance badly. > > I don't think that using a rtmutex there is wrong. It cures at least a very > clear priority inversion issue versus the threaded interrupt handler. > > Forcing all i2c users off to RT is not really an option. RT has other > drawbacks vs. throughput which you don't want to impose on everything which > happens to use i2c. Oh, we're not talking about forcing *all* i2c users off to RT, only those that suffer from the priority inversion. The original report leading to the bus_lock changing to a rt_mutex seemed like if someone had suggested an -RT kernel instead of the patch being accepted, it would have been the better option. If -RT was a viable option back then? But ok, that was a long time ago and by now there's no way to be sure what troubles a change back to an ordinary mutex is going cause. The problem is of course that there is no way of knowing what, if anything, will suffer from inversion with ordinary mutexes instead of rt_mutexes. And this is also true about changing mux_lock to an ordinary mutex. There is simply no way of knowing if someone depends on avoiding inversion in a muxing scenario, that dependency may have developed at any point in time and is not related to the relatively recent addition of the mux_lock. So, there is a greater risk for regressions with turning mux_lock into a mutex than I originally thought. >> 2a will cause a lockdep splat if i2c0:mux_lock is in the same >> lockdep class & subclass as i2c1:mux_lock. So, lockdep needs >> separate lockdep classes depending on the i2c root adapter >> (subclasses are needed to handle deeper trees, so they are off >> limits). Great fun. How do I go about creating a new lockdep >> class for every i2c root adapter instance? Bzzzt. It is not enough to have one class per root adapter, just move everything down one mux level: .---. .. | | ||-- i2c3 | | .-|mux1| .. | l | .. / ||-- i2c4 --|gpio| | i | ||-- i2c1 -' '' '' | n |-- i2c0 --|mux0|.--' | u | ||-- i2c2 -. .. .. | x | '' \ ||-- i2c5 --|dev0| | | '-|mux2| '' | | ||-- i2c6 '---' '' access dev0 on i2c5 1. lock i2c2:mux_lock 2. switch mux2 to i2c5 using gpio on i2c4 a lock i2c1:mux_lock b switch mux1 to i2c4 using whatever c access gpio on i2c1->i2c4 ilock i2c0:mux_lock ii switch mux0 to i2c1 using whatever iiiaccess gpio on i2c0->i2c1->i2c4 iv unlock i2c0:mux_lock d unlock i2c1:mux_lock 3. access dev0 on i2c2->i2c5 a lock i2c0:mux_lock b switch mux0 to i2c2 using whatever c access dev0 on i2c0->i2c2->i2c5 d unlock i2c0:mux_lock 4. unlock i2c2:mux_lock 2a is the problematic step here too. i2c1:mux_lock and i2c2:mux_lock are on the same depth, so needs fully separate lockdep classes. Which means that using the adapter depth to set the lockdep subclass is pointless. And since they are branches on the same root adapter, using one lockdep class per root adapter also falls apart. > lockdep_set_class() . Right, thanks. But given the above, the only way I can think of to reduce the number of lockdep classes is to defer creating a lockdep class for an adapter until a mux is attached as a child adapter. But having extra code to reduce lockdep classes for mux_lock is pointless, since first of all given the above risk for regression, I'm no longer all that happy about the rt_mutex -> mutex conversion even for mux_lock. Then the only reason to consider lockdep classes is if someone adds support for lockdep to the rt_mutex, which is on the todo anyway. By then I bet the lockdep class problem will also present itself for the bus_lock in some manner with some form of interdependent devices requiring one lockdep class
Re: [PATCH 1/3] iio: potentiometer: mcp4531: Add support for MCP454x, MCP456x, MCP464x and MCP466x
On 2016-06-21 08:55, Florian Vaussard wrote: > This patch adds support for MCP454x, MCP456x, MCP464x and MCP466x parts. > The main difference with currently supported parts (MCP453x and alike) is > the addition of a non-volatile memory in order to recall the wiper setting > at power-on. This feature is currently not supported and only the > volatile memory is used to set the wiper. > > Signed-off-by: Florian Vaussard Acked-by: Peter Rosin Cheers, Peter
Re: [PATCH 3/3] iio: potentiometer: mcp4531: Add device tree binding
On 2016-06-21 08:55, Florian Vaussard wrote: > This patch adds the necessary device tree binding to allow DT probing of > currently supported parts. > > Signed-off-by: Florian Vaussard > --- > drivers/iio/potentiometer/mcp4531.c | 83 > - > 1 file changed, 82 insertions(+), 1 deletion(-) > > diff --git a/drivers/iio/potentiometer/mcp4531.c > b/drivers/iio/potentiometer/mcp4531.c > index 2251173..41a1e46 100644 > --- a/drivers/iio/potentiometer/mcp4531.c > +++ b/drivers/iio/potentiometer/mcp4531.c > @@ -31,6 +31,8 @@ > #include > #include > #include > +#include > +#include > > #include > > @@ -188,12 +190,84 @@ static const struct iio_info mcp4531_info = { > .driver_module = THIS_MODULE, > }; > > +#ifdef CONFIG_OF > +static const struct of_device_id mcp45xx_of_match[] = { Should be named mcp4531_of_match, also the casting to void and then back to an integer type is ugly. Would it work to store a pointer directly into the mcp4531_cfg array instead? I.e. { .compatible = "microchip,mcp4531-502", .data = &mcp4531_cfg[MCP453x_502] }, etc and then adjust accordingly in mcp4531_probe()? That is, if you need this patch at all, see my reply to 2/3... Cheers, Peter > + { .compatible = "microchip,mcp4531-502", .data = (void *)MCP453x_502 }, > + { .compatible = "microchip,mcp4531-103", .data = (void *)MCP453x_103 }, > + { .compatible = "microchip,mcp4531-503", .data = (void *)MCP453x_503 }, > + { .compatible = "microchip,mcp4531-104", .data = (void *)MCP453x_104 }, > + { .compatible = "microchip,mcp4532-502", .data = (void *)MCP453x_502 }, > + { .compatible = "microchip,mcp4532-103", .data = (void *)MCP453x_103 }, > + { .compatible = "microchip,mcp4532-503", .data = (void *)MCP453x_503 }, > + { .compatible = "microchip,mcp4532-104", .data = (void *)MCP453x_104 }, > + { .compatible = "microchip,mcp4541-502", .data = (void *)MCP454x_502 }, > + { .compatible = "microchip,mcp4541-103", .data = (void *)MCP454x_103 }, > + { .compatible = "microchip,mcp4541-503", .data = (void *)MCP454x_503 }, > + { .compatible = "microchip,mcp4541-104", .data = (void *)MCP454x_104 }, > + { .compatible = "microchip,mcp4542-502", .data = (void *)MCP454x_502 }, > + { .compatible = "microchip,mcp4542-103", .data = (void *)MCP454x_103 }, > + { .compatible = "microchip,mcp4542-503", .data = (void *)MCP454x_503 }, > + { .compatible = "microchip,mcp4542-104", .data = (void *)MCP454x_104 }, > + { .compatible = "microchip,mcp4551-502", .data = (void *)MCP455x_502 }, > + { .compatible = "microchip,mcp4551-103", .data = (void *)MCP455x_103 }, > + { .compatible = "microchip,mcp4551-503", .data = (void *)MCP455x_503 }, > + { .compatible = "microchip,mcp4551-104", .data = (void *)MCP455x_104 }, > + { .compatible = "microchip,mcp4552-502", .data = (void *)MCP455x_502 }, > + { .compatible = "microchip,mcp4552-103", .data = (void *)MCP455x_103 }, > + { .compatible = "microchip,mcp4552-503", .data = (void *)MCP455x_503 }, > + { .compatible = "microchip,mcp4552-104", .data = (void *)MCP455x_104 }, > + { .compatible = "microchip,mcp4561-502", .data = (void *)MCP456x_502 }, > + { .compatible = "microchip,mcp4561-103", .data = (void *)MCP456x_103 }, > + { .compatible = "microchip,mcp4561-503", .data = (void *)MCP456x_503 }, > + { .compatible = "microchip,mcp4561-104", .data = (void *)MCP456x_104 }, > + { .compatible = "microchip,mcp4562-502", .data = (void *)MCP456x_502 }, > + { .compatible = "microchip,mcp4562-103", .data = (void *)MCP456x_103 }, > + { .compatible = "microchip,mcp4562-503", .data = (void *)MCP456x_503 }, > + { .compatible = "microchip,mcp4562-104", .data = (void *)MCP456x_104 }, > + { .compatible = "microchip,mcp4631-502", .data = (void *)MCP463x_502 }, > + { .compatible = "microchip,mcp4631-103", .data = (void *)MCP463x_103 }, > + { .compatible = "microchip,mcp4631-503", .data = (void *)MCP463x_503 }, > + { .compatible = "microchip,mcp4631-104", .data = (void *)MCP463x_104 }, > + { .compatible = "microchip,mcp4632-502", .data = (void *)MCP463x_502 }, > + { .compatible = "microchip,mcp4632-103", .data = (void *)MCP463x_103 }, > + { .compatible = "microchip,mcp4632-503", .data = (void *)MCP463x_503 }, > + { .compatible = "microchip,mcp4632-104", .data = (void *)MCP463x_104 }, > + { .compatible = "microchip,mcp4641-502", .data = (void *)MCP464x_502 }, > + { .compatible = "microchip,mcp4641-103", .data = (void *)MCP464x_103 }, > + { .compatible = "microchip,mcp4641-503", .data = (void *)MCP464x_503 }, > + { .compatible = "microchip,mcp4641-104", .data = (void *)MCP464x_104 }, > + { .compatible = "microchip,mcp4642-502", .data = (void *)MCP464x_502 }, > + { .compatible = "microchip,mcp4642-103", .data = (void *)MCP464x_103 }, > + { .compatible = "microchip,mcp4642-503", .data = (void *)M
Re: [PATCH 2/3] iio: potentiometer: mcp4531: Add device tree binding documentation
On 2016-06-21 08:55, Florian Vaussard wrote: > Add the device tree documentation for all the supported parts. Apart the > compatible string and standard I2C binding, no other binding is currently > needed. > > Signed-off-by: Florian Vaussard > --- > .../bindings/iio/potentiometer/mcp4531.txt | 84 > ++ > 1 file changed, 84 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/iio/potentiometer/mcp4531.txt > > diff --git a/Documentation/devicetree/bindings/iio/potentiometer/mcp4531.txt > b/Documentation/devicetree/bindings/iio/potentiometer/mcp4531.txt > new file mode 100644 > index 000..b052299 > --- /dev/null > +++ b/Documentation/devicetree/bindings/iio/potentiometer/mcp4531.txt > @@ -0,0 +1,84 @@ > +* Microchip MCP453X/454X/455X/456X/463X/464X/465X/466X Digital Potentiometer > + driver > + > +The node for this driver must be a child node of a I2C controller, hence > +all mandatory properties for your controller must be specified. See > directory: > + > +Documentation/devicetree/bindings/i2c > + > +for more details. > + > +Required properties: > + - compatible: Must be one of the following, depending on the > + model: > + "microchip,mcp4531-502" > + "microchip,mcp4531-103" > + "microchip,mcp4531-503" *snip* I'm not directly opposed, but I have used the following and DT booting works like a charm here. mcp4651-104@28 { compatible = "mcp4651-104"; reg = <0x28>; }; But, I suppose some DT documentation is not bad, and my understanding of the device instantiation process and the i2c/dt interactions are not complete, so my DT snippet might be an abomination? I'll leave the decision if this is needed to someone with more experience on how other drivers handle this. Cheers, Peter
Re: [patch v5] i2c: mux: mellanox: add driver
On 2016-09-13 22:37, vad...@mellanox.com wrote: > From: Vadim Pasternak > > This driver allows I2C routing controlled through CPLD select registers on > a wide range of Mellanox systems (CPLD Lattice device). > MUX selection is provided by digital and analog HW. Analog part is not > under SW control. > Digital part is under CPLD control (channel selection/de-selection). > > Connectivity schema. > i2c-mlxcpld Digital Analog > driver > ** * -> mux1 (virt bus2) -> mux ->| > | I2CLPC | i2c physical* -> mux2 (virt bus3) -> mux ->| > | bridge | bus 1 *-* | > | logic |-> * mux reg * | > | in CPLD| *-* | > ** i2c-mux-mlxpcld ^* -> muxn (virt busn) -> mux ->| > |driver | | > |*---*| Devices > |* CPLD (i2c bus)* select | > |* registers for ** > |* mux selection * deselect > |*---* > | | > <> <---> > i2c cntrl Board cntrl reg > reg space space (mux select, >IO, LED, WD, info) Hmm, I'm wondering about the above schematics, which seems a bit overly complex. I mean, it's not relevant to this driver how the I2CLPC bridge logic in the CPLD is controlled. Particularly so since it does not need to be a this particular i2c adapter that is muxed. But what I'm really wondering is if this mux can mux same other bus than is used to control the mux. I.e. is it possible to do something like this: .---. .-. | | | |-- i2c2 -- | l |-- i2c0 --| mlxcpld mux | | i | | |-- i2c3 -- | n | '-' | u | | | x |-- i2c1 -' | | '---' Or is it always as below, with the mux being controlled from the same i2c bus it muxes? .---. .-. | l | | |-- i2c1 -- | i |-- i2c0 --+--| mlxcpld mux | | n | | | |-- i2c2 -- | u | | '-' | x | | | '---' '-' Cheers, Peter
Re: [PATCH v2] drm/panel: simple: add support for Sharp LQ150X1LG11 panels
On 2016-09-23 19:39, Rob Herring wrote: > On Sat, Sep 17, 2016 at 11:34:22AM +0200, Peter Rosin wrote: >> From: Gustaf Lindström >> >> The Sharp 15" LQ150X1LG11 panel is an XGA TFT LCD panel. >> >> Signed-off-by: Gustaf Lindström >> Signed-off-by: Peter Rosin >> --- >> .../bindings/display/panel/sharp,lq150x1lg11.txt | 7 ++ >> drivers/gpu/drm/panel/panel-simple.c | 27 >> ++ >> 2 files changed, 34 insertions(+) >> create mode 100644 >> Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt >> >> v1->v2: correct author >> >> diff --git >> a/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt >> b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt >> new file mode 100644 >> index ..014428c984c8 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt >> @@ -0,0 +1,7 @@ >> +Sharp 15" LQ150X1LG11 XGA TFT LCD panel >> + >> +Required properties: >> +- compatible: should be "sharp,lq150x1lg11" > > Looking at the spec, what about 12V VDD, 3.3V VCC, XSTABY (backlight > ctrl), VBR (PWM), RL/UD, SELLVDS signals? I guess you're saying that simple-panel isn't the best match? Is it ok to make the DT bindings more complete but still leave it to the simple-panel driver to support part of it? Or should we just give up for the time being, and carry a local patch pending a custom driver? Cheers, Peter
[PATCH v3 2/2] drm/panel: simple: add support for Sharp LQ150X1LG11 panels
From: Gustaf Lindström The Sharp 15" LQ150X1LG11 panel is an XGA TFT LCD panel. The simple-panel driver is used to get support for essential functionality of the panel. Signed-off-by: Gustaf Lindström Signed-off-by: Peter Rosin --- drivers/gpu/drm/panel/panel-simple.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 85143d1b9b31..58cfe0a7a9d6 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1386,6 +1386,30 @@ static const struct panel_desc sharp_lq123p1jx31 = { }, }; +static const struct drm_display_mode sharp_lq150x1lg11_mode = { + .clock = 71100, + .hdisplay = 1024, + .hsync_start = 1024 + 168, + .hsync_end = 1024 + 168 + 64, + .htotal = 1024 + 168 + 64 + 88, + .vdisplay = 768, + .vsync_start = 768 + 37, + .vsync_end = 768 + 37 + 2, + .vtotal = 768 + 37 + 2 + 8, + .vrefresh = 60, +}; + +static const struct panel_desc sharp_lq150x1lg11 = { + .modes = &sharp_lq150x1lg11_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 304, + .height = 228, + }, + .bus_format = MEDIA_BUS_FMT_RGB565_1X16, +}; + static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = { .clock = 33300, .hdisplay = 800, @@ -1641,6 +1665,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "sharp,lq123p1jx31", .data = &sharp_lq123p1jx31, }, { + .compatible = "sharp,lq150x1lg11", + .data = &sharp_lq150x1lg11, + }, { .compatible = "shelly,sca07010-bfn-lnn", .data = &shelly_sca07010_bfn_lnn, }, { -- 2.1.4
[PATCH v3 0/2] drm/panel: simple: add support for Sharp LQ150X1LG11 panels
Hi! I'm back with a new attempt at getting this panel upstream. This time with the bindings in a separate commit, as I hear that is preferred. I think I covered all the pins on the panel... Cheers, Peter Gustaf Lindström (1): drm/panel: simple: add support for Sharp LQ150X1LG11 panels Peter Rosin (1): dt-bindings: display: Add Sharp LQ150X1LG11 panel binding .../bindings/display/panel/sharp,lq150x1lg11.txt | 36 ++ drivers/gpu/drm/panel/panel-simple.c | 27 2 files changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt -- 2.1.4
[PATCH v3 1/2] dt-bindings: display: Add Sharp LQ150X1LG11 panel binding
The Sharp 15" LQ150X1LG11 panel is an XGA TFT LCD panel. Signed-off-by: Peter Rosin --- .../bindings/display/panel/sharp,lq150x1lg11.txt | 36 ++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt diff --git a/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt new file mode 100644 index ..715ff7e332f2 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt @@ -0,0 +1,36 @@ +Sharp 15" LQ150X1LG11 XGA TFT LCD panel + +Required properties: +- compatible: should be "sharp,lq150x1lg11" +- power-supply: regulator to provide the VCC supply voltage (3.3 volts) + +Optional properties: +- backlight: phandle of the backlight device +- rlud-gpios: a single GPIO for the RL/UD (rotate 180 degrees) pin. +- lvds-gpios: a single GPIO for the SELLVDS pin. + +If lrud-gpios and/or ldvs-gpios are not specified, the RL/UD and/or SELLVDS +pins are assumed to be handled appropriately by the hardware. + +Example: + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 10>; /* VBR */ + + brightness-levels = <0 20 40 60 80 100>; + default-brightness-level = <2>; + + power-supply = <&vdd_12v_reg>; /* VDD */ + enable-gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; /* XSTABY */ + }; + + panel { + compatible = "sharp,lq150x1lg11"; + + power-supply = <&vcc_3v3_reg>; /* VCC */ + + backlight = <&backlight>; + rlud-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;/* RL/UD */ + lvds-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;/* SELLVDS */ + }; -- 2.1.4
Re: [RFC PATCH 1/1] i2c: i2c-mux-pca954x: Add interrupt controller support.
On 2016-07-28 04:44, Phil Reid wrote: > G'day Peter, > > Thanks for the feedback. > +linux-kernel@vger.kernel.org > > On 27/07/2016 13:32, Peter Rosin wrote: >> On 2016-07-27 05:05, Phil Reid wrote: >>> +static void pca954x_irq_mask(struct irq_data *idata) >>> +{ >>> + struct i2c_mux_core *muxc = irq_data_get_irq_chip_data(idata); >>> + struct pca954x *data = i2c_mux_priv(muxc); >>> + unsigned int pos = idata->hwirq; >>> + >>> + data->irq_mask &= ~BIT(pos); >>> + if ((data->irq_mask & 0x3) != 0) >> >> The 0x3 mask should probably also go into struct chip_desc, then a non- >> empty value in this field could be used as trigger for initing the irq >> stuff. Ok, this comment just shows that I was not getting it. Please ignore it. Some other (new) thing in chip_desc is needed to trigger irq init for the chips that have irq support. >>> + disable_irq(data->client->irq); >>> +} >>> + >>> +static void pca954x_irq_unmask(struct irq_data *idata) >>> +{ >>> + struct i2c_mux_core *muxc = irq_data_get_irq_chip_data(idata); >>> + struct pca954x *data = i2c_mux_priv(muxc); >>> + unsigned int pos = idata->hwirq; >>> + >>> + data->irq_mask |= ~BIT(pos); >>> + if ((data->irq_mask & 0x3) == 0x3) >> >> This is what you mentioned in the commit message, but I don't get it. >> Please explain further, and also think about how the same problem >> could be handled should there be 4 incoming irq lines as in pca9544 >> and pca9545. > > Yes this is the tricky point. > > Consider this: > > Host - pca954x + Dev1 > \ Dev2 > > In my case devs are ltc1760 that generate SMBALERT's (active low irq) which > are not maskable in the device. There is nothing that can be configured in the > device to prevent them assert an irq. > > If just considering them as shared interrupts, ie pca954x is not an irq ctlr, > just a wired and. > On boot Dev1 is registered and enable shared irq. If Dev2 is asserting > SMBALERT > this results in irq being continuously triggered, trigger Dev1 irq handler > which > can't clear the irq because it's being asserted by Dev2. > > My system eventually boots but spends alot of time looping in the irq for dev1 > until dev2 gets registered. > > > > The same problem occurs with the pca954x driver present, unless I disable the > irq > until both slaves have unmasked the irq. This is not a good generic solution > as the > system may be used with only one irq active. > > It's really a deficiency in the hardware design but I'm not sure I'll get > that fixed. > Or I may be missing something obvious to deal with this situation Ok, I think I get the problem, but I too am at a loss and see no elegant solution. One sad thing about your workaround is that it is not working at all unless there is an irq user on all mux child segments that unmasks the corresponding irq. Right? I think the default should be that the driver assumes sane HW, i.e. the irq inputs are not asserted unless some driver is able to clear them. You can then add an option to keep irqs disabled when the mask "is wrong". As a bonus, I think this "is wrong" test should be configurable so that you specify a bitmask of irqs that all has to be unmasked for the irq to be enabled (and use that instead of the 0x3 in the pca954x_irq_mask/pca954x_irq_unmask functions). That makes the workaround more flexible. Cheers, Peter
[PATCH 2/2] i2c: move locking operations to their own struct
This makes it trivial to constify them, so do that. Signed-off-by: Peter Rosin --- drivers/i2c/i2c-core.c | 13 - drivers/i2c/i2c-mux.c | 25 - include/linux/i2c.h| 25 ++--- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2c9135ffdf10..ce252ba13247 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1511,6 +1511,12 @@ static int __process_new_adapter(struct device_driver *d, void *data) return i2c_do_add_adapter(to_i2c_driver(d), data); } +static const struct i2c_lock_operations i2c_adapter_lock_ops = { + .lock_bus =i2c_adapter_lock_bus, + .trylock_bus = i2c_adapter_trylock_bus, + .unlock_bus = i2c_adapter_unlock_bus, +}; + static int i2c_register_adapter(struct i2c_adapter *adap) { int res = 0; @@ -1533,11 +1539,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) return -EINVAL; } - if (!adap->lock_bus) { - adap->lock_bus = i2c_adapter_lock_bus; - adap->trylock_bus = i2c_adapter_trylock_bus; - adap->unlock_bus = i2c_adapter_unlock_bus; - } + if (!adap->lock_ops) + adap->lock_ops = &i2c_adapter_lock_ops; rt_mutex_init(&adap->bus_lock); rt_mutex_init(&adap->mux_lock); diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 764f195795e4..14741ff31041 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -263,6 +263,18 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, } EXPORT_SYMBOL_GPL(i2c_mux_alloc); +static const struct i2c_lock_operations i2c_mux_lock_ops = { + .lock_bus =i2c_mux_lock_bus, + .trylock_bus = i2c_mux_trylock_bus, + .unlock_bus = i2c_mux_unlock_bus, +}; + +static const struct i2c_lock_operations i2c_parent_lock_ops = { + .lock_bus =i2c_parent_lock_bus, + .trylock_bus = i2c_parent_trylock_bus, + .unlock_bus = i2c_parent_unlock_bus, +}; + int i2c_mux_add_adapter(struct i2c_mux_core *muxc, u32 force_nr, u32 chan_id, unsigned int class) @@ -312,15 +324,10 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, priv->adap.retries = parent->retries; priv->adap.timeout = parent->timeout; priv->adap.quirks = parent->quirks; - if (muxc->mux_locked) { - priv->adap.lock_bus = i2c_mux_lock_bus; - priv->adap.trylock_bus = i2c_mux_trylock_bus; - priv->adap.unlock_bus = i2c_mux_unlock_bus; - } else { - priv->adap.lock_bus = i2c_parent_lock_bus; - priv->adap.trylock_bus = i2c_parent_trylock_bus; - priv->adap.unlock_bus = i2c_parent_unlock_bus; - } + if (muxc->mux_locked) + priv->adap.lock_ops = &i2c_mux_lock_ops; + else + priv->adap.lock_ops = &i2c_parent_lock_ops; /* Sanity check on class */ if (i2c_mux_parent_classes(parent) & class) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index e1a8d72ebccb..765bea57eeb3 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -414,6 +414,20 @@ struct i2c_algorithm { }; /** + * struct i2c_lock_operations - represent I2C locking operations + * @lock_bus: Get exclusive access to an I2C bus segment + * @trylock_bus: Try to get exclusive access to an I2C bus segment + * @unlock_bus: Release exclusive access to an I2C bus segment + * + * The main operations are wrapped by i2c_lock_bus and i2c_unlock_bus. + */ +struct i2c_lock_operations { + void (*lock_bus)(struct i2c_adapter *, unsigned int flags); + int (*trylock_bus)(struct i2c_adapter *, unsigned int flags); + void (*unlock_bus)(struct i2c_adapter *, unsigned int flags); +}; + +/** * struct i2c_timings - I2C timing information * @bus_freq_hz: the bus frequency in Hz * @scl_rise_ns: time SCL signal takes to rise in ns; t(r) in the I2C specification @@ -523,6 +537,7 @@ struct i2c_adapter { void *algo_data; /* data fields that are valid for all devices */ + const struct i2c_lock_operations *lock_ops; struct rt_mutex bus_lock; struct rt_mutex mux_lock; @@ -539,10 +554,6 @@ struct i2c_adapter { struct i2c_bus_recovery_info *bus_recovery_info; const struct i2c_adapter_quirks *quirks; - - void (*lock_bus)(struct i2c_adapter *, unsigned int flags); - int (*trylock_bus)(struct i2c_adapter *, unsigned int flags); - void (*unlock_bus)(struct i2c_adapter *, unsigned int flags); }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) @@ -584,7 +595,7 @@ int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)); static inline void i2c_lock_
[PATCH 1/2] i2c: add i2c_trylock_bus wrapper, use it
This unifies usage with i2c_lock_bus and i2c_unlock_bus, and paves the way for the next patch which looks a bit saner with this preparatory work taken care of beforehand. Signed-off-by: Peter Rosin --- drivers/i2c/i2c-core.c | 2 +- drivers/i2c/i2c-mux.c | 4 ++-- include/linux/i2c.h| 14 ++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index af11b658984d..2c9135ffdf10 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -2311,7 +2311,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) #endif if (in_atomic() || irqs_disabled()) { - ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT); + ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT); if (!ret) /* I2C activity is ongoing. */ return -EAGAIN; diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 8eee98634cda..764f195795e4 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -159,7 +159,7 @@ static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags) return 0; /* mux_lock not locked, failure */ if (!(flags & I2C_LOCK_ROOT_ADAPTER)) return 1; /* we only want mux_lock, success */ - if (parent->trylock_bus(parent, flags)) + if (i2c_trylock_bus(parent, flags)) return 1; /* parent locked too, success */ rt_mutex_unlock(&parent->mux_lock); return 0; /* parent not locked, failure */ @@ -193,7 +193,7 @@ static int i2c_parent_trylock_bus(struct i2c_adapter *adapter, if (!rt_mutex_trylock(&parent->mux_lock)) return 0; /* mux_lock not locked, failure */ - if (parent->trylock_bus(parent, flags)) + if (i2c_trylock_bus(parent, flags)) return 1; /* parent locked too, success */ rt_mutex_unlock(&parent->mux_lock); return 0; /* parent not locked, failure */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 96a25ae14494..e1a8d72ebccb 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -588,6 +588,20 @@ i2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags) } /** + * i2c_trylock_bus - Try to get exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + * @flags: I2C_LOCK_ROOT_ADAPTER tries to locks the root i2c adapter, + * I2C_LOCK_SEGMENT tries to lock only this branch in the adapter tree + * + * Return: true if the I2C bus segment is locked, false otherwise + */ +static inline int +i2c_trylock_bus(struct i2c_adapter *adapter, unsigned int flags) +{ + return adapter->trylock_bus(adapter, flags); +} + +/** * i2c_unlock_bus - Release exclusive access to an I2C bus segment * @adapter: Target I2C bus segment * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT -- 2.1.4
[PATCH 0/2] i2c: move adapter locking ops to struct, constify
This allows the locking ops to be moved to .rodata, which is generally desireable. It also feels good to change all ops with one assignment. Cheers, Peter Peter Rosin (2): i2c: add i2c_trylock_bus wrapper, use it i2c: move locking operations to their own struct drivers/i2c/i2c-core.c | 15 +-- drivers/i2c/i2c-mux.c | 29 ++--- include/linux/i2c.h| 37 +++-- 3 files changed, 58 insertions(+), 23 deletions(-) -- 2.1.4
Re: [PATCH 3/7] dt-bindings: i2c: add support for 'i2c-gate' subnode
On 2016-07-29 23:25, Rob Herring wrote: > On Wed, Jul 27, 2016 at 10:43:26AM +0200, Peter Rosin wrote: >> Handle i2c gates similarly to how i2c arbitrators are handled. >> This gets rid of a pointless 'reg' property for i2c gates. >> >> I.e. this new and more compact style >> >> some-gate { >> i2c-gate { >> #address-cells = <1>; >> #size-cells = <0>; >> >> some-i2c-device@50 { >> reg = <0x50>; >> }; >> }; >> }; >> >> instead of the old >> >> some-gate { >> #address-cells = <1>; >> #size-cells = <0>; >> >> i2c@0 { >> reg = <0>; >> >> #address-cells = <1>; >> #size-cells = <0>; >> >> some-i2c-device@50 { >> reg = <0x50>; >> }; >> }; >> }; >> >> Signed-off-by: Peter Rosin >> --- >> Documentation/devicetree/bindings/i2c/i2c-gate.txt | 35 >> ++ >> MAINTAINERS| 1 + >> 2 files changed, 36 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/i2c/i2c-gate.txt >> >> diff --git a/Documentation/devicetree/bindings/i2c/i2c-gate.txt >> b/Documentation/devicetree/bindings/i2c/i2c-gate.txt >> new file mode 100644 >> index ..78f17892dfc6 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/i2c/i2c-gate.txt >> @@ -0,0 +1,35 @@ >> +Common i2c gate properties. > > Perhaps define what a gate is. How about the following paragraph at the very top of the file? An i2c gate is useful to e.g. reduce the digital noise for RF tuners connected to the i2c bus. Gates are similar to arbitrators in that you need to perform some kind of operation to access the i2c bus past the arbitrator/gate, but there are no competing masters to consider for gates and therefore there is no arbitration happening for gates. >> + >> +- i2c-gate child node >> + >> +Required properties for the i2c-gate child node: >> +- #address-cells = <1>; >> +- #size-cells = <0>; >> + >> +Optional properties for i2c-gate child node: >> +- Child nodes conforming to i2c bus binding >> + >> + >> +Example : >> + >> +/* >> + An Invensense mpu9150 at address 0x68 featuring an on-chip Asahi >> + Kasei ak8975 compass behind a gate. >> + */ >> + >> +mpu9150@68 { >> +compatible = "invensense,mpu9150"; >> +reg = <0x68>; >> +interrupt-parent = <&gpio1>; >> +interrupts = <18 1>; >> + >> +i2c-gate { >> +#address-cells = <1>; >> +#size-cells = <0>; >> + >> +ax8975@0c { >> +compatible = "ak,ak8975"; >> +reg = <0x0c>; >> +}; >> +}; >> +}; >> diff --git a/MAINTAINERS b/MAINTAINERS >> index 543052305a09..0e6cc071c480 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -5525,6 +5525,7 @@ F: Documentation/i2c/i2c-topology >> F: Documentation/i2c/muxes/ >> F: Documentation/devicetree/bindings/i2c/i2c-mux* >> F: Documentation/devicetree/bindings/i2c/i2c-arb* >> +F: Documentation/devicetree/bindings/i2c/i2c-gate* >> F: drivers/i2c/i2c-mux.c >> F: drivers/i2c/muxes/ >> F: include/linux/i2c-mux.h >> -- >> 2.1.4 >>
Re: [RFC PATCH 1/1] i2c: i2c-mux-pca954x: Add interrupt controller support.
On 2016-08-01 08:25, Phil Reid wrote: > On 29/07/2016 13:48, Peter Rosin wrote: >> Ok, I think I get the problem, but I too am at a loss and see no elegant >> solution. >> One sad thing about your workaround is that it is not working at all unless >> there >> is an irq user on all mux child segments that unmasks the corresponding irq. >> Right? >> >> I think the default should be that the driver assumes sane HW, i.e. the irq >> inputs >> are not asserted unless some driver is able to clear them. You can then add >> an >> option to keep irqs disabled when the mask "is wrong". As a bonus, I think >> this >> "is wrong" test should be configurable so that you specify a bitmask of irqs >> that >> all has to be unmasked for the irq to be enabled (and use that instead of >> the 0x3 >> in the pca954x_irq_mask/pca954x_irq_unmask functions). That makes the >> workaround >> more flexible. > > Correct, It works for my use case at the moment. There would need to be a way > to define a mask. > Via device tree for example. Yes, some optional property in DT was my vision also. > I think sane devices that have irq masking don't really need the pca954x to > be a irq source. > They could be configured with a shared IRQ as the pCA954x just ANDs then > incoming lines together. Right. And I suppose we don't know if this is already happening... AFAIU, that approach would still work even if pca954x is made an interrupt source. Or? I mean, as you say, the pca954x functions as an electrical AND, and if interrupt clients register with whatever the parent interrupt controller is, they would be not be affected if there is also an interrupt controller for pca954x? Yes, such imaginary uses could have just wired all the irq lines together, but we don't know if they actually did that or if they possibly went via the irq routing in the pca954x for whatever reason... > So does my use case and workaround justify the complexity added to the driver? > > Thou there is possibly a performance benefit from reading the pca954x to > dispatch the appropriate > irq, which would save alot of i2c transactions to probe each possible irq > source device and assocaited > i2c mux switching. > > WDYR? It was the last bit that I also realized, and it would be nice to not have to dig through all irq devices on the child side of the mux (and other clients sharing the irq line with the pca954x for that matter). In theory there could be quite a few... So, yes, I think it might be worthwhile to make it an interrupt controller. And then the tweak with your mask is no longer the big part of it... BTW, you also need to change bindings docs in Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt I also noticed that you are using irq_domain_add_legacy which is marked as, *tada* legacy, and that most drivers should use a linear domain. Sounds like a linear domain fits the use case here, no? And another note, the workaround for your limited hw is rather non-generic. I mean, if the irq line from the pca954x to the parent interrupt controller is shared with something else, then there would still be a flood even with the workaround. Or am I misunderstanding that? Cheers, Peter
Re: [patch v4] i2c: mux: mellanox: add driver
It's shaping up, a few last nitpicks... On 2016-09-13 16:38, vad...@mellanox.com wrote: > From: Vadim Pasternak > > This driver allows I2C routing controlled through CPLD select registers on > wide range of Mellanox systems (CPLD Lattice device). s/wide/a wide/ But is it really still "a wide range" now that i2c-mux-reg handles most CPLD mux types? > MUX selection is provided by digital and analog HW. Analog part is not > under SW control. > Digital part is under CPLD control (channel selection/de-selection). > > Connectivity schema. > i2c-mlxcpld Digital Analog > driver > ** * -> mux1 (virt bus2) -> mux ->| > | I2CLPC | i2c physical* -> mux2 (virt bus3) -> mux ->| > | bridge | bus 1 *-* | > | logic |-> * mux reg * | > | in CPLD| *-* | > ** i2c-mux-mlxpcld ^* -> muxn (virt busn) -> mux ->| > |driver | | > |*---*| Devices > |* CPLD (i2c bus)* select | > |* registers for ** > |* mux selection * deselect > |*---* > | | > <> <---> > i2c cntrl Board cntrl reg > reg space space (mux select, >IO, LED, WD, info) > > i2c-mux-mlxpcld does not necessarily require i2c-mlxcpld. It can be use s/use/used/ > along with another bus driver, and still control i2c routing through CPLD > mux selection, in case the system is equipped with CPLD capable of mux > selection control. > > The Kconfig currently controlling compilation of this code is: > drivers/i2c/muxes/Kconfig:config I2C_MUX_MLXCPLD > > Signed-off-by: Michael Shych > Signed-off-by: Vadim Pasternak > Reviewed-by: Jiri Pirko > --- > v3->v4 > Fixes issues pointed out by Peter: > - Remove mlxcpld_mux_type; > - Remove member type from mux control structure; > - Remove variable muxes; > - mlxcpld_mux_reg_write - set address from client; > - mlxcpld_mux_reg_write - try smbus_xfer > - mlxcpld_mux_select_chan - remove compare with for mux type; > - mlxcpld_mux_probe - use I2C_FUNC_SMBUS_WRITE_BYTE_DATA instead of > I2C_FUNC_SMBUS_BYTE > - mlxcpld_mux_probe - remove switch statement > - mlxcpld_mux_probe - update comment; > - mlxcpld_mux_probe -change logic in testing num_adaps; > - remove members first_channel and addr from mlxcpld_mux_plat_data > structure; > v2->v3 > Fixes issues pointed out by Peter: > - Fix several comments; > - In MAINTAINERS file use linux-i2c instead of linux-kernel; > - Place include files in alphabetic order; > - When channel select fail, set last_chan to zero for cleaning last value; > - Return with error from probe if there is no platform data; > - Use i2c_mux_reg driver for the lpc_access cases: > it fit well for Mellanox system with LPC access - has been tested and it > works good. > - Limit this driver to i2c_access only one device (mlxcpld_mux_module). > v1->v2 > Fixes issues pointed out by Peter: > - changes in commit cover massage; > - change leg to channel in comments; > - missed return err; > - use platform data mux array rather the offset from 1st channel in probe > routine; > - remove owner field from driver structure; > - use module_i2c_driver macros, instead if __init and __exit; > - remove deselect on exit flag; > - add record to MAINTAINER file; > --- > MAINTAINERS | 8 ++ > drivers/i2c/muxes/Kconfig | 11 ++ > drivers/i2c/muxes/Makefile | 1 + > drivers/i2c/muxes/i2c-mux-mlxcpld.c | 224 > > include/linux/i2c/mlxcpld.h | 52 + > 5 files changed, 296 insertions(+) > create mode 100644 drivers/i2c/muxes/i2c-mux-mlxcpld.c > create mode 100644 include/linux/i2c/mlxcpld.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index 0bbe4b1..be83d69 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -7655,6 +7655,14 @@ W: http://www.mellanox.com > Q: http://patchwork.ozlabs.org/project/netdev/list/ > F: drivers/net/ethernet/mellanox/mlxsw/ > > +MELLANOX MLXCPLD I2C MUX DRIVER > +M: Vadim Pasternak > +M: Michael Shych > +L: linux-...@vger.kernel.org > +S: Supported > +W: http://www.mellanox.com > +F: drivers/i2c/muxes/i2c-mux-mlxcpld.c > + > SOFT-ROCE DRIVER (rxe) > M: Moni Shoua > L: linux-r...@vger.kernel.org > diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig > index e280c8e..b7ab144 100644 > --- a/drivers/i2c/muxes/Kconfig > +++ b/drivers/i2c/muxes/Kconfig > @@ -81,4 +81,15 @@ config I2C_DEMUX_PINCTRL > demultiplexer that uses the pinctrl subsystem. This
Re: [patch v5] i2c: mux: mellanox: add driver
On 2016-09-13 22:37, vad...@mellanox.com wrote: > From: Vadim Pasternak > > This driver allows I2C routing controlled through CPLD select registers on > a wide range of Mellanox systems (CPLD Lattice device). > MUX selection is provided by digital and analog HW. Analog part is not > under SW control. > Digital part is under CPLD control (channel selection/de-selection). *snip* > +/* Platform data for the CPLD I2C multiplexers */ > + > +/* mlxcpld_mux_plat_data - per mux data, used with i2c_register_board_info > + * @adap_ids - adapter array > + * @num_adaps - number of adapters > + * @sel_reg_addr - mux select register offset in CPLD space > + */ > +struct mlxcpld_mux_plat_data { > + int *adap_ids; > + int num_adaps; > + int sel_reg_addr; > +}; > + > +#endif /* _LINUX_I2C_MLXCPLD_H */ > Hmm, you never confirmed that you need to support different register values in the CPLD with sel_reg_addr. I can see that there is a possibility that you actually really need it, but I'd like to remove that variable if at all possible. If you can confirm that you need that, this is Acked-by: Peter Rosin Otherwise, please just hard code the register address. Cheers, Peter
Re: [patch v5] i2c: mux: mellanox: add driver
Wolfram, please pick up v5 for i2c-next whenever timing is right so that it gets more testing etc. I didn't do any recent compile-testing myself, but if you think that is required on the final version I can of course spend some time on it. (But isn't that what all the infrastructure is there to help with?) Thanks! On 2016-09-14 10:10, Vadim Pasternak wrote: > Peter Rosin wrote: >> On 2016-09-13 22:37, vad...@mellanox.com wrote: >>> From: Vadim Pasternak >>> >>> This driver allows I2C routing controlled through CPLD select >>> registers on a wide range of Mellanox systems (CPLD Lattice device). >>> MUX selection is provided by digital and analog HW. Analog part is not >>> under SW control. >>> Digital part is under CPLD control (channel selection/de-selection). >> >> *snip* >> >>> +/* Platform data for the CPLD I2C multiplexers */ >>> + >>> +/* mlxcpld_mux_plat_data - per mux data, used with >>> +i2c_register_board_info >>> + * @adap_ids - adapter array >>> + * @num_adaps - number of adapters >>> + * @sel_reg_addr - mux select register offset in CPLD space */ >>> +struct mlxcpld_mux_plat_data { >>> + int *adap_ids; >>> + int num_adaps; >>> + int sel_reg_addr; >>> +}; >>> + >>> +#endif /* _LINUX_I2C_MLXCPLD_H */ >>> >> >> Hmm, you never confirmed that you need to support different register values >> in >> the CPLD with sel_reg_addr. I can see that there is a possibility that you >> actually >> really need it, but I'd like to remove that variable if at all possible. > > Yes, it could be different register values. > Actually CPLD can also be programmed in different way. > So, I really need it. Oh well :-) Cheers, Peter >> >> If you can confirm that you need that, this is >> >> Acked-by: Peter Rosin
Re: [PATCH v1 0/2] i2c: Stop i2c modules being unloaded while in use.
Hi Jim! On 2016-09-13 18:55, Baxter, Jim wrote: > Hi Peter, > >> nitpick: Patch subjects for the second patch is wrong. >> >> "reparented" is a bit dual when dealing with i2c adapter trees. >> i2c_mux_add_owned_adapter is perhaps clearer? > > Agreed, I will update that. > >> >> >> Aside from that, I'm not using modules much and need some enlightenment >> as to why the i2c_del_mux_adapter() call in i2c_mux_gpio_remove() is not >> sufficient and what exactly the problem is? Why would someone/something >> unload the i2c-mux module prematurely? > > It is not a normal operation to remove the i2c gpio mux, however systemd > could unload modules out of order if users are restarting services > incorrectly and cause unintended side-effects. This change would stop an > i2c-mux that maybe controlling a voltage regulator from being unloaded > and disabling power to parts of the system unexpectedly. I don't see how that can happen. The voltage regulator that sits behind the mux should be a user of one of the child adapters on the mux, so that child adapter can't be removed as long as the voltage regulator is there. And the i2c-mux can't be unloaded as long as the child adapter is there, since it is the owner. So what's going on? Simply changing the owner of the child adapter will break this chain leaving the i2c-mux as owner of nothing, thus *making* it a target for premature unloading. I must be fundamentally misunderstanding something. BTW, was this solving a real issue, or is it all theory? Cheers, Peter >> Would it be an alternative to make i2c-mux a proper kernel object of >> some kind? I mean, why do not all other mux users also need to modify >> the owner? Why is i2c-mux-gpio special? >> > > i2c-mux-gpio is not special, the code inserted by > [PATCH v1 1/2] i2c-mux: add i2c_mux_add_reparented_adapter api could be > used by other muxes if required.
[PATCH] i2c: i2c-mux-pca954x: retry updating the mux selection on failure
The cached value of the last selected channel prevents retries on the next call, even on failure to update the selected channel. Fix that. Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca954x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 528e755c468f..3278ebf1cc5c 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -164,7 +164,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) /* Only select the channel if its different from the last channel */ if (data->last_chan != regval) { ret = pca954x_reg_write(muxc->parent, client, regval); - data->last_chan = regval; + data->last_chan = ret ? 0 : regval; } return ret; -- 2.1.4
[PATCH] iio: imu: inv_mpu6050: inform the i2c mux core about how it is used
The i2c mux core can then take appropriate action depending on if it is used for an actual i2c mux, or for an arbitrator or gate. In this case it is used as a gate. This will make devicetree bindings simpler when they are eventually added. Signed-off-by: Peter Rosin --- drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) So, this depends on the i2c-mux-dt-3 branch [1] that Jonathan pulled to support the new mpu-3050 gyroscope driver. I had planned to submit this post 4.9-rc1, but since the iio tree got the prerequisite already, I'm sending it right away. Cheers, Peter [1] https://github.com/peda-r/i2c-mux.git i2c-mux-dt-3 diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 19580d1db597..2c3f8964a3ea 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -126,7 +126,7 @@ static int inv_mpu_probe(struct i2c_client *client, st = iio_priv(dev_get_drvdata(&client->dev)); st->muxc = i2c_mux_alloc(client->adapter, &client->dev, -1, 0, I2C_MUX_LOCKED, +1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE, inv_mpu6050_select_bypass, inv_mpu6050_deselect_bypass); if (!st->muxc) { -- 2.1.4
Re: [patch 2/2] i2c: mux: mellanox: add driver
On 2016-08-29 19:36, vad...@mellanox.com wrote: > From: Vadim Pasternak > > This driver allows I2C routing controlled through CPLD select registers on > wide range of Mellanox systems (CPLD Lattice device). > MUX selection is provided by digital and analog HW. Analog part is not > under SW control. > Digital part is under CPLD control (channel selection/de-selection). > > Connectivity schema. > i2c-mlxcpld Digital Analog > driver > ** * -> mux1 (virt bus2) -> mux ->| > | I2CLPC | i2c physical* -> mux2 (virt bus3) -> mux ->| > | bridge | bus 1 *-* | > | logic |-> * mux reg * | > | in CPLD| *-* | > ** i2c-mux-mlxpcld ^* -> muxn (virt busn) -> mux ->| > |driver | | > |*---*| Devices > |* CPLD (LPC bus)* select | > |* registers for ** > |* mux selection * deselect > |*---* > | | > <> <---> > i2c cntrl Board cntrl reg > reg space space (mux select, > | IO, LED, WD, info) > | | *-* *-* > *- LPC bus --| PCH |---| CPU | > *-* *-* > > i2c-mux-mlxpcld does not necessary required i2c-mlxcpld. It can be use s/necessary required/necessarily require a/ > along with another bus driver, and still control i2c routing through CPLD > mux selection, in case the system is equipped with CPLD capable of mux > selection control. > > The Kconfig currently controlling compilation of this code is: > drivers/i2c/muxes/Kconfig:config I2C_MUX_MLXCPLD > > Signed-off-by: Michael Shych > Signed-off-by: Vadim Pasternak > Reviewed-by: Jiri Pirko > --- > MAINTAINERS | 8 + > drivers/i2c/muxes/Kconfig | 11 ++ > drivers/i2c/muxes/Makefile | 1 + > drivers/i2c/muxes/i2c-mux-mlxcpld.c | 326 > > include/linux/i2c/mlxcpld.h | 57 +++ > 5 files changed, 403 insertions(+) > create mode 100644 drivers/i2c/muxes/i2c-mux-mlxcpld.c > create mode 100644 include/linux/i2c/mlxcpld.h It is customary to mark updated patches with v2, v3 etc in the subject and to include a short changelog right here in this space (or perhaps in a cover letter if it is a patch series). Please do so going forward. > > diff --git a/MAINTAINERS b/MAINTAINERS > index 8b3f8d7..a994455 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -7664,6 +7664,14 @@ W: http://www.mellanox.com > F: drivers/i2c/busses/i2c-mlxcpld.c > F: Documentation/i2c/busses/i2c-mlxcpld > > +MELLANOX MLXCPLD I2C MUX DRIVER > +M: Vadim Pasternak > +M: Michael Shych > +L: linux-kernel@vger.kernel.org Isn't the linux-i2c list a narrower and therefore better fit? > +S: Supported > +W: http://www.mellanox.com > +F: drivers/i2c/muxes/i2c-mux-mlxcpld.c > + > SOFT-ROCE DRIVER (rxe) > M: Moni Shoua > L: linux-r...@vger.kernel.org > diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig > index e280c8e..b7ab144 100644 > --- a/drivers/i2c/muxes/Kconfig > +++ b/drivers/i2c/muxes/Kconfig > @@ -81,4 +81,15 @@ config I2C_DEMUX_PINCTRL > demultiplexer that uses the pinctrl subsystem. This is useful if you > want to change the I2C master at run-time depending on features. > > +config I2C_MUX_MLXCPLD > +tristate "Mellanox CPLD based I2C multiplexer" > +help > + If you say yes to this option, support will be included for a > + CPLD based I2C multiplexer. This driver provides access to > + I2C busses connected through a MUX, which is controlled > + by a CPLD registers. > + > + This driver can also be built as a module. If so, the module > + will be called i2c-mux-mlxcpld. > + > endmenu > diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile > index 7c267c2..e5c990e 100644 > --- a/drivers/i2c/muxes/Makefile > +++ b/drivers/i2c/muxes/Makefile > @@ -10,5 +10,6 @@ obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o > obj-$(CONFIG_I2C_MUX_PCA954x)+= i2c-mux-pca954x.o > obj-$(CONFIG_I2C_MUX_PINCTRL)+= i2c-mux-pinctrl.o > obj-$(CONFIG_I2C_MUX_REG)+= i2c-mux-reg.o > +obj-$(CONFIG_I2C_MUX_MLXCPLD)+= i2c-mux-mlxcpld.o > > ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG > diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c > b/drivers/i2c/muxes/i2c-mux-mlxcpld.c > new file mode 100644 > index 000..9624613 > --- /dev/null > +++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c > @@ -0,0 +1,32
Re: [PATCH 2/2] i2c: move locking operations to their own struct
On 2016-08-23 23:16, Wolfram Sang wrote: > On Fri, Jul 29, 2016 at 10:17:57AM +0200, Peter Rosin wrote: >> This makes it trivial to constify them, so do that. >> >> Signed-off-by: Peter Rosin > > Looks good. Could you rebase to i2c/for-next? Right, no problem! Cheers, Peter The following changes since commit 00f0ea70d2b82b7d7afeb1bdedc9169eb8ea6675: eeprom: at24: check if the chip is functional in probe() (2016-08-22 08:19:58 +0200) are available in the git repository at: https://github.com/peda-r/i2c-mux.git i2c-lock-op for you to fetch changes up to 4b42b8c2e3233671e49deee71458edb6737a38bf: i2c: move locking operations to their own struct (2016-08-24 06:38:58 +0200) -------- Peter Rosin (2): i2c: add i2c_trylock_bus wrapper, use it i2c: move locking operations to their own struct drivers/i2c/i2c-core.c | 15 +-- drivers/i2c/i2c-mux.c | 29 ++--- include/linux/i2c.h| 37 +++-- 3 files changed, 58 insertions(+), 23 deletions(-)
Re: [patch 2/2] i2c: mux: mellanox: add driver
On 2016-08-24 15:56, Vadim Pasternak wrote: > From: Vadim Pasternak > > This driver allows I2C routing controlled through CPLD select registers on > wide > range of Mellanox systems (CPLD Lattice device). > MUX selection is provided by digital and analog HW. Analog part is not under > SW > control. Digital part is under CPLD control (channel selection/de-selection). > > MUX logic description. > Mux selector can control 256 mux (channels), if utilized one CPLD register > (8 bits) as select register - register value specifies mux id. > Mux selector can control n*256 mux, if utilized n CPLD registers as select > registers. > The number of registers within the same CPLD can be combined to support mux > hierarchy. > This logic can be applied for LPC attached CPLD and fro I2C attached CPLD. > Driver can support different mux control logic, according to CPLD > implementation. This paragraph is strangely wrapped. And please limit to 75 chars per line as per checkpatch. Also, I have a hard time getting the grips on the actual number of mux channels that can be controlled. You talk about n * 256 channels if you have n registers. But the code below appears to only deal with one register. So why complicate things in the comments and the commit message? It is also not entirely clear to me if you support 8 channels or if you really support 256 channels. That would be huge number of pins. Because from the text above, I would have guessed 256, but below... > Connectivity schema. > i2c-mlxcpld Digital Analog > driver > ** * -> mux1 (virt bus2) -> mux -> | > | I2CLPC | i2c physical* -> mux2 (virt bus3) -> mux -> | > | bridge | bus 1 *-* | > | logic |-> * mux reg * | > | in CPLD| *-* | > ** i2c-mux-mlxpcld ^* -> muxn (virt busn) -> mux -> | > |driver || > |*---*| Devices > |* CPLD (LPC bus)* select | > |* registers for ** > |* mux selection * deselect > |*---* > | | > <> <---> > i2c cntrl Board cntrl reg > reg space space (mux select, > | IO, LED, WD, info) > | | *-* *-* > *- LPC bus --| PCH |---| CPU | > *-* *-* > > i2c-mux-mlxpcld does not necessary required i2c-mlxcpld. It can be use along > with another bus driver, and still control i2c routing through CPLD mux > selection, in case the system is equipped with CPLD capable of mux selection > control. > > The Kconfig currently controlling compilation of this code is: > drivers/i2c/muxes/Kconfig:config I2C_MUX_MLXCPLD > > Signed-off-by: Michael Shych > Signed-off-by: Vadim Pasternak > Reviewed-by: Jiri Pirko > --- > drivers/i2c/muxes/Kconfig | 11 ++ > drivers/i2c/muxes/Makefile | 1 + > drivers/i2c/muxes/i2c-mux-mlxcpld.c | 352 > > include/linux/i2c/mlxcpld.h | 67 +++ > 4 files changed, 431 insertions(+) > create mode 100644 drivers/i2c/muxes/i2c-mux-mlxcpld.c > create mode 100644 include/linux/i2c/mlxcpld.h > > diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig > index e280c8e..b7ab144 100644 > --- a/drivers/i2c/muxes/Kconfig > +++ b/drivers/i2c/muxes/Kconfig > @@ -81,4 +81,15 @@ config I2C_DEMUX_PINCTRL > demultiplexer that uses the pinctrl subsystem. This is useful if you > want to change the I2C master at run-time depending on features. > > +config I2C_MUX_MLXCPLD > +tristate "Mellanox CPLD based I2C multiplexer" > +help > + If you say yes to this option, support will be included for a > + CPLD based I2C multiplexer. This driver provides access to > + I2C busses connected through a MUX, which is controlled > + by a CPLD registers. > + > + This driver can also be built as a module. If so, the module > + will be called i2c-mux-mlxcpld. > + > endmenu > diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile > index 7c267c2..e5c990e 100644 > --- a/drivers/i2c/muxes/Makefile > +++ b/drivers/i2c/muxes/Makefile > @@ -10,5 +10,6 @@ obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o > obj-$(CONFIG_I2C_MUX_PCA954x)+= i2c-mux-pca954x.o > obj-$(CONFIG_I2C_MUX_PINCTRL)+= i2c-mux-pinctrl.o > obj-$(CONFIG_I2C_MUX_REG)+= i2c-mux-reg.o > +obj-$(CONFIG_I2C_MUX_MLXCPLD)+= i2c-mux-mlxcpld.o > > ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG > diff --git a/drivers/i2c/muxes/i2c-mu
Re: [patch 2/2] i2c: mux: mellanox: add driver
On 2016-08-24 18:20, Vadim Pasternak wrote: > Hi Peter, > > Thank you very much for your review. > >> -Original Message----- >> From: Peter Rosin [mailto:p...@axentia.se] >> Sent: Wednesday, August 24, 2016 4:55 PM >> To: Vadim Pasternak ; w...@the-dreams.de >> Cc: linux-...@vger.kernel.org; linux-kernel@vger.kernel.org; >> j...@resnulli.us; >> Michael Shych >> Subject: Re: [patch 2/2] i2c: mux: mellanox: add driver >> >> On 2016-08-24 15:56, Vadim Pasternak wrote: >>> From: Vadim Pasternak >>> >>> This driver allows I2C routing controlled through CPLD select >>> registers on wide range of Mellanox systems (CPLD Lattice device). >>> MUX selection is provided by digital and analog HW. Analog part is not >>> under SW control. Digital part is under CPLD control (channel selection/de- >> selection). >>> >>> MUX logic description. >>> Mux selector can control 256 mux (channels), if utilized one CPLD >>> register >>> (8 bits) as select register - register value specifies mux id. >>> Mux selector can control n*256 mux, if utilized n CPLD registers as >>> select registers. >>> The number of registers within the same CPLD can be combined to >>> support mux hierarchy. >>> This logic can be applied for LPC attached CPLD and fro I2C attached CPLD. >>> Driver can support different mux control logic, according to CPLD >>> implementation. >> >> This paragraph is strangely wrapped. And please limit to 75 chars per line >> as per >> checkpatch. >> >> Also, I have a hard time getting the grips on the actual number of mux >> channels >> that can be controlled. You talk about n * 256 channels if you have n >> registers. >> But the code below appears to only deal with one register. So why complicate >> things in the comments and the commit message? It is also not entirely clear >> to >> me if you support 8 channels or if you really support 256 channels. That >> would >> be huge number of pins. > > In CPLD we have three channel selection registers, which one can support up > to 256 channels. > CPLD could be programmed with the bigger number of selection registers. > I tried to explain it in description. > Since it's misleading, I'll remove it. I'm a curious bastard though, and now I want to know how it works :-) So, the CPLD supports up to 768 channels, using three registers, but there is no HW that makes use of all of the options of this building block? At least there's no such "big" system yet? But then I wonder if that wouldn't be three parallel muxes, i.e. one mux for each register? Otherwise you would only need two more bits to get three times the number of channels... >> >> Because from the text above, I would have guessed 256, but below... >> >>> Connectivity schema. >>> i2c-mlxcpld Digital Analog >>> driver >>> ** * -> mux1 (virt bus2) -> mux -> | >>> | I2CLPC | i2c physical* -> mux2 (virt bus3) -> mux -> | >>> | bridge | bus 1 *-* | >>> | logic |-> * mux reg * | >>> | in CPLD| *-* | >>> ** i2c-mux-mlxpcld ^* -> muxn (virt busn) -> mux -> | >>> |driver || >>> |*---*| Devices >>> |* CPLD (LPC bus)* select | >>> |* registers for ** >>> |* mux selection * deselect >>> |*---* >>> | | >>> <> <---> >>> i2c cntrl Board cntrl reg >>> reg space space (mux select, >>> | IO, LED, WD, info) >>> | | *-* *-* >>> *- LPC bus --| PCH |---| CPU | >>> *-* *-* >>> >>> i2c-mux-mlxpcld does not necessary required i2c-mlxcpld. It can be use >>> along with another bus driver, and still control i2c routing through >>> CPLD mux selection, in case the system is equipped with CPLD capable >>> of mux selection control. >>> >>> The Kconfig currently controlling com
Re: [PATCH v2 6/8] i2c: mux: inform the i2c mux core about how it is used
On 2016-08-25 18:24, Wolfram Sang wrote: > On Thu, Aug 25, 2016 at 06:22:37PM +0200, Peter Rosin wrote: >> On 2016-08-25 18:19, Wolfram Sang wrote: >>> >>>> diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c >>>> b/drivers/i2c/muxes/i2c-mux-pca9541.c >>>> index 3cb8af635db5..f052c3067791 100644 >>>> --- a/drivers/i2c/muxes/i2c-mux-pca9541.c >>>> +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c >>>> @@ -349,7 +349,8 @@ static int pca9541_probe(struct i2c_client *client, >>>>force = 0; >>>>if (pdata) >>>>force = pdata->modes[0].adap_id; >>>> - muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0, >>>> + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), >>>> + I2C_MUX_ARBITRATOR, >>> >>> Does it make sense to rename the file to i2c-arb-* somewhen then? Just >>> asking, I'll apply the patch anyhow. >> >> There should be a clean branch with /only/ this series that both i2c and >> iio can share, to prevent merge problems. I said I'd make such a branch >> in the i2c-mux repo, but you are of course also welcome to provide that >> branch if you prefer... > > No, this is fine. Send me a pull request and I'll merge. Right, I was waiting for some confirmation if v4.8-rc3 was a good base, but I'm running out of patience... Anyway, I'll send the pull request no later that tomorrow morning (CEST). I assume I can add your ack? Cheers, Peter
[PATCH v2] i2c: move locking operations to their own struct
This makes it trivial to constify them, so do that. Signed-off-by: Peter Rosin --- drivers/gpu/drm/drm_dp_helper.c | 10 +++--- drivers/i2c/i2c-core.c | 13 - drivers/i2c/i2c-mux.c | 25 - include/linux/i2c.h | 25 ++--- 4 files changed, 49 insertions(+), 24 deletions(-) Changes since v1: - Also fix the user in drivers/gpu (only compile-tested, but it's simple enough...) This takes care of the 0-day splat reported in: http://marc.info/?l=linux-i2c&m=147215193023544&w=2 Cheers, Peter diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index eae5ef963cb7..2bd064493ae7 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -790,6 +790,12 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags) mutex_unlock(&i2c_to_aux(i2c)->hw_mutex); } +static const struct i2c_lock_operations drm_dp_i2c_lock_ops = { + .lock_bus = lock_bus, + .trylock_bus = trylock_bus, + .unlock_bus = unlock_bus, +}; + /** * drm_dp_aux_init() - minimally initialise an aux channel * @aux: DisplayPort AUX channel @@ -807,9 +813,7 @@ void drm_dp_aux_init(struct drm_dp_aux *aux) aux->ddc.algo_data = aux; aux->ddc.retries = 3; - aux->ddc.lock_bus = lock_bus; - aux->ddc.trylock_bus = trylock_bus; - aux->ddc.unlock_bus = unlock_bus; + aux->ddc.lock_ops = &drm_dp_i2c_lock_ops; } EXPORT_SYMBOL(drm_dp_aux_init); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 56e50ca905ba..0bdda24a10b2 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1691,6 +1691,12 @@ static int __process_new_adapter(struct device_driver *d, void *data) return i2c_do_add_adapter(to_i2c_driver(d), data); } +static const struct i2c_lock_operations i2c_adapter_lock_ops = { + .lock_bus =i2c_adapter_lock_bus, + .trylock_bus = i2c_adapter_trylock_bus, + .unlock_bus = i2c_adapter_unlock_bus, +}; + static int i2c_register_adapter(struct i2c_adapter *adap) { int res = -EINVAL; @@ -1710,11 +1716,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) goto out_list; } - if (!adap->lock_bus) { - adap->lock_bus = i2c_adapter_lock_bus; - adap->trylock_bus = i2c_adapter_trylock_bus; - adap->unlock_bus = i2c_adapter_unlock_bus; - } + if (!adap->lock_ops) + adap->lock_ops = &i2c_adapter_lock_ops; rt_mutex_init(&adap->bus_lock); rt_mutex_init(&adap->mux_lock); diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 764f195795e4..14741ff31041 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -263,6 +263,18 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, } EXPORT_SYMBOL_GPL(i2c_mux_alloc); +static const struct i2c_lock_operations i2c_mux_lock_ops = { + .lock_bus =i2c_mux_lock_bus, + .trylock_bus = i2c_mux_trylock_bus, + .unlock_bus = i2c_mux_unlock_bus, +}; + +static const struct i2c_lock_operations i2c_parent_lock_ops = { + .lock_bus =i2c_parent_lock_bus, + .trylock_bus = i2c_parent_trylock_bus, + .unlock_bus = i2c_parent_unlock_bus, +}; + int i2c_mux_add_adapter(struct i2c_mux_core *muxc, u32 force_nr, u32 chan_id, unsigned int class) @@ -312,15 +324,10 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, priv->adap.retries = parent->retries; priv->adap.timeout = parent->timeout; priv->adap.quirks = parent->quirks; - if (muxc->mux_locked) { - priv->adap.lock_bus = i2c_mux_lock_bus; - priv->adap.trylock_bus = i2c_mux_trylock_bus; - priv->adap.unlock_bus = i2c_mux_unlock_bus; - } else { - priv->adap.lock_bus = i2c_parent_lock_bus; - priv->adap.trylock_bus = i2c_parent_trylock_bus; - priv->adap.unlock_bus = i2c_parent_unlock_bus; - } + if (muxc->mux_locked) + priv->adap.lock_ops = &i2c_mux_lock_ops; + else + priv->adap.lock_ops = &i2c_parent_lock_ops; /* Sanity check on class */ if (i2c_mux_parent_classes(parent) & class) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index c1f60a345db7..616f67635734 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -427,6 +427,20 @@ struct i2c_algorithm { }; /** + * struct i2c_lock_operations - represent I2C locking operations + * @lock_bus: Get exclusive access to an I2C bus segment + * @trylock_bus: Try to get exclusive access to an I2C bus segment + * @unlock_bus: Release exclusive access to an I2C bus segment + * + * The main
Re: [PATCH v2 6/8] i2c: mux: inform the i2c mux core about how it is used
On 2016-08-25 18:19, Wolfram Sang wrote: > >> diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c >> b/drivers/i2c/muxes/i2c-mux-pca9541.c >> index 3cb8af635db5..f052c3067791 100644 >> --- a/drivers/i2c/muxes/i2c-mux-pca9541.c >> +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c >> @@ -349,7 +349,8 @@ static int pca9541_probe(struct i2c_client *client, >> force = 0; >> if (pdata) >> force = pdata->modes[0].adap_id; >> -muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0, >> +muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), >> + I2C_MUX_ARBITRATOR, > > Does it make sense to rename the file to i2c-arb-* somewhen then? Just > asking, I'll apply the patch anyhow. There should be a clean branch with /only/ this series that both i2c and iio can share, to prevent merge problems. I said I'd make such a branch in the i2c-mux repo, but you are of course also welcome to provide that branch if you prefer... Cheers, Peter
Re: [PATCH v3 0/5] iio: srf08: add support for similar devices and triggered buffers
On 2017-08-16 21:32, Andreas Klinger wrote: > This patch series adds support for: > - triggered buffer > - ultrasonic devices srf02 and srf10 > > Thanks for the review of Peter and Wolfram. > > @Wolfram: please let me know, if you want a separate patch for [PATCH 1/5] I think what you should do is rebase to something fresher, such as the togreg branch in the iio repo. As you have discovered, master branch is lagging behind in that repo. And I think Jonathan would like that as well, but perhaps it doesn't make a difference for him? Cheers, peda
Re: [RFC PATCH v2 1/3] drm: atmel-hlcdc: add support for 8-bit color lookup table mode
On 2017-06-20 11:40, Daniel Vetter wrote: > On Sat, Jun 17, 2017 at 07:48:02PM +0200, Peter Rosin wrote: >> All layers of all supported chips support this, the only variable is the >> base address of the lookup table in the register map. >> >> Signed-off-by: Peter Rosin > > As Boris said, pls use the new color manager stuff for atomic drivers, and > then use the helper to implement the legacy kms LUT support on top of it, > it's drm_atomic_helper_legacy_gamma_set(). > -Daniel Hmm, I don't see how this comment applies to this patch? Isn't this patch good as is, because I thought I already did wire this up with the drm_atomic_helper_legacy_gamma_set helper as requested? (sure, v3 has a register offset tweak, but that's just a detail) I totally agree that 2/3 and 3/3 are ugly and I am working on that, but if 1/3 is also not in the right direction I'd like to know ASAP. Thanks! Cheers, peda > >> --- >> drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 5 + >> drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 13 +++ >> drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h| 16 ++ >> drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 >> + >> 4 files changed, 63 insertions(+) >> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c >> b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c >> index 5348985..694adcc 100644 >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c >> @@ -429,6 +429,8 @@ static const struct drm_crtc_funcs >> atmel_hlcdc_crtc_funcs = { >> .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, >> .enable_vblank = atmel_hlcdc_crtc_enable_vblank, >> .disable_vblank = atmel_hlcdc_crtc_disable_vblank, >> +.set_property = drm_atomic_helper_crtc_set_property, >> +.gamma_set = drm_atomic_helper_legacy_gamma_set, >> }; >> >> int atmel_hlcdc_crtc_create(struct drm_device *dev) >> @@ -484,6 +486,9 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) >> drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); >> drm_crtc_vblank_reset(&crtc->base); >> >> +drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); >> +drm_crtc_enable_color_mgmt(&crtc->base, 0, false, >> ATMEL_HLCDC_CLUT_SIZE); >> + >> dc->crtc = &crtc->base; >> >> return 0; >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c >> b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c >> index 30dbffd..4f6ef07 100644 >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c >> @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc >> atmel_hlcdc_at91sam9n12_layers[] = { >> .default_color = 3, >> .general_config = 4, >> }, >> +.clut_offset = 0x400, >> }, >> }; >> >> @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc >> atmel_hlcdc_at91sam9x5_layers[] = { >> .disc_pos = 5, >> .disc_size = 6, >> }, >> +.clut_offset = 0x400, >> }, >> { >> .name = "overlay1", >> @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc >> atmel_hlcdc_at91sam9x5_layers[] = { >> .chroma_key_mask = 8, >> .general_config = 9, >> }, >> +.clut_offset = 0x800, >> }, >> { >> .name = "high-end-overlay", >> @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc >> atmel_hlcdc_at91sam9x5_layers[] = { >> .scaler_config = 13, >> .csc = 14, >> }, >> +.clut_offset = 0x1000, >> }, >> { >> .name = "cursor", >> @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc >> atmel_hlcdc_at91sam9x5_layers[] = { >> .chroma_key_mask = 8, >> .general_config = 9, >> }, >> +.clut_offset = 0x1400, >> }, >> }; >> >> @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc >> atmel_hlcdc_sama5d3_layers[] = { >> .disc_pos = 5, >> .disc_size = 6, >> }, >> +.clut_
[PATCH v4 2/2] drm: atmel-hlcdc: add support for 8-bit color lookup table mode
All layers of all supported chips support this, the only variable is the base address of the lookup table in the register map. Signed-off-by: Peter Rosin --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 4 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 13 +++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h| 16 ++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 + 4 files changed, 62 insertions(+) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index cc00ce3..694adcc 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -430,6 +430,7 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { .enable_vblank = atmel_hlcdc_crtc_enable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank, .set_property = drm_atomic_helper_crtc_set_property, + .gamma_set = drm_atomic_helper_legacy_gamma_set, }; int atmel_hlcdc_crtc_create(struct drm_device *dev) @@ -485,6 +486,9 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); drm_crtc_vblank_reset(&crtc->base); + drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); + drm_crtc_enable_color_mgmt(&crtc->base, 0, false, ATMEL_HLCDC_CLUT_SIZE); + dc->crtc = &crtc->base; return 0; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 30dbffd..4f6ef07 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = { .default_color = 3, .general_config = 4, }, + .clut_offset = 0x400, }, }; @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x400, }, { .name = "overlay1", @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x800, }, { .name = "high-end-overlay", @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .scaler_config = 13, .csc = 14, }, + .clut_offset = 0x1000, }, { .name = "cursor", @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x1400, }, }; @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, { .name = "overlay1", @@ -180,6 +186,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xa00, }, { .name = "overlay2", @@ -198,6 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xe00, }, { .name = "high-end-overlay", @@ -223,6 +231,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { }, .csc = 14, }, + .clut_offset = 0x1200, }, { .name = "cursor", @@ -244,6 +253,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .general_config = 9, .scaler_config = 13, }, + .clut_offset = 0x1600, }, }; @@ -275,6 +285,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, {
[PATCH v4 0/2] drm: atmel-hlcdc: clut support
Hi! This series adds support for an 8-bit clut mode in the atmel-hlcdc driver. This is the same code as in patch 1/3 of v3. I will redo 2/3 and 3/3 of that series some other way and it feels orthogonal to this driver, and that might take some time to get right, so I'm going to handle that on its own. Changes since v3: - Dropped ugly code (patches 2/3 and 3/3) for legacy fbdev interaction. - Slit out the .set_property change to a patch of its own. Changes since v2: - Fix mapping to the clut registers. Changes since v1: - Move the clut update from atmel_hlcdc_crtc_mode_valid to atmel_hlcdc_plane_atomic_update. - Add default .gamma_set helper (drm_atomic_helper_legacy_gamma_set). - Don't keep a spare copy of the clut, reuse gamma_store instead. - Don't try to synchronize the legacy fb clut with the drm clut. As I said in v2, I have not added any .clut_offset to the overlay2 layer of sama5d4, since the chip does not appear to have that layer. I didn't do that to make it easier to work with the patch previously sent to remove that layer, but I suspect bad things may happen to sama5d4 users if they do not have that layer removed. Cheers, peda Peter Rosin (2): drm: atmel-hlcdc: add missing .set_property helper to the crtc drm: atmel-hlcdc: add support for 8-bit color lookup table mode drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 5 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 13 +++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h| 16 ++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 + 4 files changed, 63 insertions(+) -- 2.1.4
[PATCH v4 1/2] drm: atmel-hlcdc: add missing .set_property helper to the crtc
The default implementation should be used. Signed-off-by: Peter Rosin --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 5348985..cc00ce3 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -429,6 +429,7 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, .enable_vblank = atmel_hlcdc_crtc_enable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank, + .set_property = drm_atomic_helper_crtc_set_property, }; int atmel_hlcdc_crtc_create(struct drm_device *dev) -- 2.1.4
[PATCH 00/11] improve the fb_setcmap helper
Hi! While trying to get CLUT support for the atmel_hlcdc driver, and specifically for the emulated fbdev interface, I received some push-back that my feeble in-driver attempts should be solved by the core. This is my attempt to do it right. Boris and Daniel, was this approximately what you had in mind? I have obviously not tested all of this with more than a compile, but the first patch is enough to make the atmel-hlcdc driver do what I need. The rest is just lots of removals and cleanup made possible by the improved core. Please test, I would not be surprised if I have fouled up some bit-manipulation somewhere in this mostly mechanical change... Cheers, peda Peter Rosin (11): drm/fb-helper: do a generic fb_setcmap helper in terms of crtc .gamma_set drm: amd: remove dead code and pointless local lut storage drm: ast: remove dead code and pointless local lut storage drm: cirrus: remove dead code and pointless local lut storage dmr: gma500: remove dead code and pointless local lut storage drm: i915: remove dead code and pointless local lut storage drm: mgag200: remove dead code and pointless local lut storage drm: nouveau: remove dead code and pointless local lut storage drm: radeon: remove dead code and pointless local lut storage drm: stm: remove dead code and pointless local lut storage drm: remove unused and redundant callbacks drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 24 - drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h| 1 - drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 27 ++ drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 27 ++ drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 27 ++ drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 27 ++ drivers/gpu/drm/amd/amdgpu/dce_virtual.c| 23 - drivers/gpu/drm/ast/ast_drv.h | 1 - drivers/gpu/drm/ast/ast_fb.c| 20 - drivers/gpu/drm/ast/ast_mode.c | 26 ++ drivers/gpu/drm/cirrus/cirrus_drv.h | 8 -- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 2 - drivers/gpu/drm/cirrus/cirrus_mode.c| 71 --- drivers/gpu/drm/drm_fb_helper.c | 131 +--- drivers/gpu/drm/gma500/framebuffer.c| 22 - drivers/gpu/drm/gma500/gma_display.c| 32 +++ drivers/gpu/drm/gma500/psb_intel_display.c | 7 +- drivers/gpu/drm/gma500/psb_intel_drv.h | 1 - drivers/gpu/drm/i915/intel_drv.h| 1 - drivers/gpu/drm/i915/intel_fbdev.c | 31 --- drivers/gpu/drm/mgag200/mgag200_drv.h | 5 -- drivers/gpu/drm/mgag200/mgag200_fb.c| 2 - drivers/gpu/drm/mgag200/mgag200_mode.c | 62 - drivers/gpu/drm/nouveau/dispnv04/crtc.c | 26 ++ drivers/gpu/drm/nouveau/nouveau_crtc.h | 3 - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 22 - drivers/gpu/drm/nouveau/nv50_display.c | 39 +++-- drivers/gpu/drm/radeon/atombios_crtc.c | 1 - drivers/gpu/drm/radeon/radeon_connectors.c | 7 +- drivers/gpu/drm/radeon/radeon_display.c | 71 ++- drivers/gpu/drm/radeon/radeon_fb.c | 2 - drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 1 - drivers/gpu/drm/stm/ltdc.c | 12 --- drivers/gpu/drm/stm/ltdc.h | 1 - include/drm/drm_fb_helper.h | 32 --- include/drm/drm_modeset_helper_vtables.h| 16 36 files changed, 171 insertions(+), 640 deletions(-) -- 2.1.4
[PATCH 05/11] dmr: gma500: remove dead code and pointless local lut storage
The redundant fb helpers .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. It is a bit strange that the fb helper .load_lut was not hooked up, so this change may well make the driver work for the C8 mode from the fbdev interface. But that is untested. Signed-off-by: Peter Rosin --- drivers/gpu/drm/gma500/framebuffer.c | 22 drivers/gpu/drm/gma500/gma_display.c | 32 ++ drivers/gpu/drm/gma500/psb_intel_display.c | 7 +-- drivers/gpu/drm/gma500/psb_intel_drv.h | 1 - 4 files changed, 12 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 7da70b6..2570c7f 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -479,26 +479,6 @@ static struct drm_framebuffer *psb_user_framebuffer_create return psb_framebuffer_create(dev, cmd, r); } -static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct gma_crtc *gma_crtc = to_gma_crtc(crtc); - - gma_crtc->lut_r[regno] = red >> 8; - gma_crtc->lut_g[regno] = green >> 8; - gma_crtc->lut_b[regno] = blue >> 8; -} - -static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, - u16 *green, u16 *blue, int regno) -{ - struct gma_crtc *gma_crtc = to_gma_crtc(crtc); - - *red = gma_crtc->lut_r[regno] << 8; - *green = gma_crtc->lut_g[regno] << 8; - *blue = gma_crtc->lut_b[regno] << 8; -} - static int psbfb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { @@ -525,8 +505,6 @@ static int psbfb_probe(struct drm_fb_helper *helper, } static const struct drm_fb_helper_funcs psb_fb_helper_funcs = { - .gamma_set = psbfb_gamma_set, - .gamma_get = psbfb_gamma_get, .fb_probe = psbfb_probe, }; diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index e7fd356..f3c48a2 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -144,33 +144,32 @@ void gma_crtc_load_lut(struct drm_crtc *crtc) struct gma_crtc *gma_crtc = to_gma_crtc(crtc); const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe]; int palreg = map->palette; + u16 *r, *g, *b; int i; /* The clocks have to be on to load the palette. */ if (!crtc->enabled) return; + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + if (gma_power_begin(dev, false)) { for (i = 0; i < 256; i++) { REG_WRITE(palreg + 4 * i, - ((gma_crtc->lut_r[i] + - gma_crtc->lut_adj[i]) << 16) | - ((gma_crtc->lut_g[i] + - gma_crtc->lut_adj[i]) << 8) | - (gma_crtc->lut_b[i] + - gma_crtc->lut_adj[i])); + (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) | + (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) | + ((*b++ >> 8) + gma_crtc->lut_adj[i])); } gma_power_end(dev); } else { for (i = 0; i < 256; i++) { /* FIXME: Why pipe[0] and not pipe[..._crtc->pipe]? */ dev_priv->regs.pipe[0].palette[i] = - ((gma_crtc->lut_r[i] + - gma_crtc->lut_adj[i]) << 16) | - ((gma_crtc->lut_g[i] + - gma_crtc->lut_adj[i]) << 8) | - (gma_crtc->lut_b[i] + - gma_crtc->lut_adj[i]); + (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) | + (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) | + ((*b++ >> 8) + gma_crtc->lut_adj[i]); } } @@ -180,15 +179,6 @@ int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, u32 size, struct drm_modeset_acquire_ctx *ctx) { - struct gma_crtc *gma_crtc = to_gma_crtc(crtc); - int i; - - for (i = 0; i < size; i++) { - gma_c
[PATCH 03/11] drm: ast: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/ast/ast_drv.h | 1 - drivers/gpu/drm/ast/ast_fb.c | 20 drivers/gpu/drm/ast/ast_mode.c | 26 ++ 3 files changed, 6 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 8880f0b..569a148 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -245,7 +245,6 @@ struct ast_connector { struct ast_crtc { struct drm_crtc base; - u8 lut_r[256], lut_g[256], lut_b[256]; struct drm_gem_object *cursor_bo; uint64_t cursor_addr; int cursor_width, cursor_height; diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 4ad4acd..dbabcac 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -255,27 +255,7 @@ static int astfb_create(struct drm_fb_helper *helper, return ret; } -static void ast_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - ast_crtc->lut_r[regno] = red >> 8; - ast_crtc->lut_g[regno] = green >> 8; - ast_crtc->lut_b[regno] = blue >> 8; -} - -static void ast_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - *red = ast_crtc->lut_r[regno] << 8; - *green = ast_crtc->lut_g[regno] << 8; - *blue = ast_crtc->lut_b[regno] << 8; -} - static const struct drm_fb_helper_funcs ast_fb_helper_funcs = { - .gamma_set = ast_fb_gamma_set, - .gamma_get = ast_fb_gamma_get, .fb_probe = astfb_create, }; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index aaef0a6..724c16b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -63,15 +63,18 @@ static inline void ast_load_palette_index(struct ast_private *ast, static void ast_crtc_load_lut(struct drm_crtc *crtc) { struct ast_private *ast = crtc->dev->dev_private; - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); + u16 *r, *g, *b; int i; if (!crtc->enabled) return; + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + for (i = 0; i < 256; i++) - ast_load_palette_index(ast, i, ast_crtc->lut_r[i], - ast_crtc->lut_g[i], ast_crtc->lut_b[i]); + ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8); } static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, @@ -633,7 +636,6 @@ static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .mode_set = ast_crtc_mode_set, .mode_set_base = ast_crtc_mode_set_base, .disable = ast_crtc_disable, - .load_lut = ast_crtc_load_lut, .prepare = ast_crtc_prepare, .commit = ast_crtc_commit, @@ -648,15 +650,6 @@ static int ast_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - int i; - - /* userspace palettes are always correct as is */ - for (i = 0; i < size; i++) { - ast_crtc->lut_r[i] = red[i] >> 8; - ast_crtc->lut_g[i] = green[i] >> 8; - ast_crtc->lut_b[i] = blue[i] >> 8; - } ast_crtc_load_lut(crtc); return 0; @@ -681,7 +674,6 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_crtc *crtc; - int i; crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); if (!crtc) @@ -690,12 +682,6 @@ static int ast_crtc_init(struct drm_device *dev) drm_crtc_init(dev, &crtc->base, &ast_crtc_funcs); drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs); - - for (i = 0; i < 256; i++) { - crtc->lut_r[i] = i; - crtc->lut_g[i] = i; - crtc->lut_b[i] = i; - } return 0; } -- 2.1.4
[PATCH 06/11] drm: i915: remove dead code and pointless local lut storage
The driver stores lut values from the fbdev interface, and is able to give them back, but does not appear to do anything with these lut values. The generic fb helpers have replaced this function, and may even have made the driver work for the C8 mode from the fbdev interface. But that is untested. Since the fb helper .gamma_set and .gamma_get are no longer used, just kill the mysterious dead code. Signed-off-by: Peter Rosin --- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_fbdev.c | 31 --- 2 files changed, 32 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 83dd409..503edf3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -785,7 +785,6 @@ struct intel_crtc { struct drm_crtc base; enum pipe pipe; enum plane plane; - u8 lut_r[256], lut_g[256], lut_b[256]; /* * Whether the crtc and the connected output pipeline is active. Implies * that crtc->enabled is set, i.e. the current mode configuration has diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 03347c6..5bac953 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -281,27 +281,6 @@ static int intelfb_create(struct drm_fb_helper *helper, return ret; } -/** Sets the color ramps on behalf of RandR */ -static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - intel_crtc->lut_r[regno] = red >> 8; - intel_crtc->lut_g[regno] = green >> 8; - intel_crtc->lut_b[regno] = blue >> 8; -} - -static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - *red = intel_crtc->lut_r[regno] << 8; - *green = intel_crtc->lut_g[regno] << 8; - *blue = intel_crtc->lut_b[regno] << 8; -} - static struct drm_fb_helper_crtc * intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) { @@ -370,7 +349,6 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, struct drm_connector *connector; struct drm_encoder *encoder; struct drm_fb_helper_crtc *new_crtc; - struct intel_crtc *intel_crtc; fb_conn = fb_helper->connector_info[i]; connector = fb_conn->connector; @@ -412,13 +390,6 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, num_connectors_enabled++; - intel_crtc = to_intel_crtc(connector->state->crtc); - for (j = 0; j < 256; j++) { - intel_crtc->lut_r[j] = j; - intel_crtc->lut_g[j] = j; - intel_crtc->lut_b[j] = j; - } - new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc); @@ -519,8 +490,6 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { .initial_config = intel_fb_initial_config, - .gamma_set = intel_crtc_fb_gamma_set, - .gamma_get = intel_crtc_fb_gamma_get, .fb_probe = intelfb_create, }; -- 2.1.4
[PATCH 08/11] drm: nouveau: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 26 -- drivers/gpu/drm/nouveau/nouveau_crtc.h | 3 --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 22 --- drivers/gpu/drm/nouveau/nv50_display.c | 39 ++--- 4 files changed, 21 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 4b4b0b4..8f689f1 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -764,13 +764,18 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = nv_crtc->base.dev; struct rgb { uint8_t r, g, b; } __attribute__((packed)) *rgbs; + u16 *r, *g, *b; int i; rgbs = (struct rgb *)nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index].DAC; + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + for (i = 0; i < 256; i++) { - rgbs[i].r = nv_crtc->lut.r[i] >> 8; - rgbs[i].g = nv_crtc->lut.g[i] >> 8; - rgbs[i].b = nv_crtc->lut.b[i] >> 8; + rgbs[i].r = *r++ >> 8; + rgbs[i].g = *g++ >> 8; + rgbs[i].b = *b++ >> 8; } nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg); @@ -792,13 +797,6 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, struct drm_modeset_acquire_ctx *ctx) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - int i; - - for (i = 0; i < size; i++) { - nv_crtc->lut.r[i] = r[i]; - nv_crtc->lut.g[i] = g[i]; - nv_crtc->lut.b[i] = b[i]; - } /* We need to know the depth before we upload, but it's possible to * get called before a framebuffer is bound. If this is the case, @@ -1095,7 +1093,6 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { .mode_set = nv_crtc_mode_set, .mode_set_base = nv04_crtc_mode_set_base, .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, - .load_lut = nv_crtc_gamma_load, .disable = nv_crtc_disable, }; @@ -1103,17 +1100,12 @@ int nv04_crtc_create(struct drm_device *dev, int crtc_num) { struct nouveau_crtc *nv_crtc; - int ret, i; + int ret; nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); if (!nv_crtc) return -ENOMEM; - for (i = 0; i < 256; i++) { - nv_crtc->lut.r[i] = i << 8; - nv_crtc->lut.g[i] = i << 8; - nv_crtc->lut.b[i] = i << 8; - } nv_crtc->lut.depth = 0; nv_crtc->index = crtc_num; diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h index 050fcf3..b7a18fb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -61,9 +61,6 @@ struct nouveau_crtc { struct { struct nouveau_bo *nvbo; - uint16_t r[256]; - uint16_t g[256]; - uint16_t b[256]; int depth; } lut; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 2665a07..f770784 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -278,26 +278,6 @@ nouveau_fbcon_accel_init(struct drm_device *dev) info->fbops = &nouveau_fbcon_ops; } -static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - nv_crtc->lut.r[regno] = red; - nv_crtc->lut.g[regno] = green; - nv_crtc->lut.b[regno] = blue; -} - -static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - *red = nv_crtc->lut.r[regno]; - *green = nv_crtc->lut.g[regno]; - *blue = nv_crtc->lut.b[regno]; -} - static void nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon) { @@ -467,8 +447,6 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info) } static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { - .gamma_set = nouveau_fbcon_gamma_set, - .gamma_get = nouveau_fbcon_gamm
[PATCH 11/11] drm: remove unused and redundant callbacks
Drivers no longer have any need for these callbacks, and there are no users. Zap. Zap-zap-zzzap-p-pp-p. Signed-off-by: Peter Rosin --- include/drm/drm_fb_helper.h | 32 include/drm/drm_modeset_helper_vtables.h | 16 2 files changed, 48 deletions(-) diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 119e5e4..80d9853 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -85,38 +85,6 @@ struct drm_fb_helper_surface_size { */ struct drm_fb_helper_funcs { /** -* @gamma_set: -* -* Set the given gamma LUT register on the given CRTC. -* -* This callback is optional. -* -* FIXME: -* -* This callback is functionally redundant with the core gamma table -* support and simply exists because the fbdev hasn't yet been -* refactored to use the core gamma table interfaces. -*/ - void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno); - /** -* @gamma_get: -* -* Read the given gamma LUT register on the given CRTC, used to save the -* current LUT when force-restoring the fbdev for e.g. kdbg. -* -* This callback is optional. -* -* FIXME: -* -* This callback is functionally redundant with the core gamma table -* support and simply exists because the fbdev hasn't yet been -* refactored to use the core gamma table interfaces. -*/ - void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno); - - /** * @fb_probe: * * Driver callback to allocate and initialize the fbdev info structure. diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 85984b2..0773db9 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -267,22 +267,6 @@ struct drm_crtc_helper_funcs { enum mode_set_atomic); /** -* @load_lut: -* -* Load a LUT prepared with the &drm_fb_helper_funcs.gamma_set vfunc. -* -* This callback is optional and is only used by the fbdev emulation -* helpers. -* -* FIXME: -* -* This callback is functionally redundant with the core gamma table -* support and simply exists because the fbdev hasn't yet been -* refactored to use the core gamma table interfaces. -*/ - void (*load_lut)(struct drm_crtc *crtc); - - /** * @disable: * * This callback should be used to disable the CRTC. With the atomic -- 2.1.4
[PATCH 10/11] drm: stm: remove dead code and pointless local lut storage
The redundant fb helper .load_lut is no longer used, and can not work right without also providing the fb helpers .gamma_set and .gamma_get thus rendering the code in this driver suspect. Just remove the dead code. Signed-off-by: Peter Rosin --- drivers/gpu/drm/stm/ltdc.c | 12 drivers/gpu/drm/stm/ltdc.h | 1 - 2 files changed, 13 deletions(-) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 1b9483d..87829b9 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -375,17 +375,6 @@ static irqreturn_t ltdc_irq(int irq, void *arg) * DRM_CRTC */ -static void ltdc_crtc_load_lut(struct drm_crtc *crtc) -{ - struct ltdc_device *ldev = crtc_to_ltdc(crtc); - unsigned int i, lay; - - for (lay = 0; lay < ldev->caps.nb_layers; lay++) - for (i = 0; i < 256; i++) - reg_write(ldev->regs, LTDC_L1CLUTWR + lay * LAY_OFS, - ldev->clut[i]); -} - static void ltdc_crtc_enable(struct drm_crtc *crtc) { struct ltdc_device *ldev = crtc_to_ltdc(crtc); @@ -523,7 +512,6 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, } static struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = { - .load_lut = ltdc_crtc_load_lut, .enable = ltdc_crtc_enable, .disable = ltdc_crtc_disable, .mode_set_nofb = ltdc_crtc_mode_set_nofb, diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h index d7a9c73..620ca55 100644 --- a/drivers/gpu/drm/stm/ltdc.h +++ b/drivers/gpu/drm/stm/ltdc.h @@ -27,7 +27,6 @@ struct ltdc_device { struct drm_panel *panel; struct mutex err_lock; /* protecting error_status */ struct ltdc_caps caps; - u32 clut[256]; /* color look up table */ u32 error_status; u32 irq_status; }; -- 2.1.4
[PATCH 09/11] drm: radeon: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/radeon/atombios_crtc.c | 1 - drivers/gpu/drm/radeon/radeon_connectors.c | 7 ++- drivers/gpu/drm/radeon/radeon_display.c | 71 - drivers/gpu/drm/radeon/radeon_fb.c | 2 - drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 1 - 5 files changed, 33 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 3c492a0..02baaaf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -2217,7 +2217,6 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = { .mode_set_base_atomic = atombios_crtc_set_base_atomic, .prepare = atombios_crtc_prepare, .commit = atombios_crtc_commit, - .load_lut = radeon_crtc_load_lut, .disable = atombios_crtc_disable, }; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 27affbd..2f642cb 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -773,12 +773,15 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct if (connector->encoder->crtc) { struct drm_crtc *crtc = connector->encoder->crtc; - const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); radeon_crtc->output_csc = radeon_encoder->output_csc; - (*crtc_funcs->load_lut)(crtc); + /* +* Our .gamma_set assumes the .gamma_store has been +* prefilled and don't care about its arguments. +*/ + crtc->funcs->gamma_set(crtc, NULL, NULL, NULL, 0, NULL); } } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 17d3daf..8b7d7a0 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -42,6 +42,7 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + u16 *r, *g, *b; int i; DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); @@ -60,11 +61,14 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) WREG32(AVIVO_DC_LUT_WRITE_EN_MASK, 0x003f); WREG8(AVIVO_DC_LUT_RW_INDEX, 0); + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; for (i = 0; i < 256; i++) { WREG32(AVIVO_DC_LUT_30_COLOR, -(radeon_crtc->lut_r[i] << 20) | -(radeon_crtc->lut_g[i] << 10) | -(radeon_crtc->lut_b[i] << 0)); + ((*r++ & 0xffc0) << 14) | + ((*g++ & 0xffc0) << 4) | + (*b++ >> 6)); } /* Only change bit 0 of LUT_SEL, other bits are set elsewhere */ @@ -76,6 +80,7 @@ static void dce4_crtc_load_lut(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + u16 *r, *g, *b; int i; DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); @@ -93,11 +98,14 @@ static void dce4_crtc_load_lut(struct drm_crtc *crtc) WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x0007); WREG32(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, 0); + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; for (i = 0; i < 256; i++) { WREG32(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset, - (radeon_crtc->lut_r[i] << 20) | - (radeon_crtc->lut_g[i] << 10) | - (radeon_crtc->lut_b[i] << 0)); + ((*r++ & 0xffc0) << 14) | + ((*g++ & 0xffc0) << 4) | + (*b++ >> 6)); } } @@ -106,6 +114,7 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev =
[PATCH 07/11] drm: mgag200: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/mgag200/mgag200_drv.h | 5 --- drivers/gpu/drm/mgag200/mgag200_fb.c | 2 -- drivers/gpu/drm/mgag200/mgag200_mode.c | 62 -- 3 files changed, 15 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index c88b6ec..04f1dfb 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -237,11 +237,6 @@ mgag200_bo(struct ttm_buffer_object *bo) { return container_of(bo, struct mgag200_bo, bo); } - /* mgag200_crtc.c */ -void mga_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, -u16 blue, int regno); -void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, -u16 *blue, int regno); /* mgag200_mode.c */ int mgag200_modeset_init(struct mga_device *mdev); diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 5d3b1fa..5cf980a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -258,8 +258,6 @@ static int mga_fbdev_destroy(struct drm_device *dev, } static const struct drm_fb_helper_funcs mga_fb_helper_funcs = { - .gamma_set = mga_crtc_fb_gamma_set, - .gamma_get = mga_crtc_fb_gamma_get, .fb_probe = mgag200fb_create, }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index adb411a..117bec3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -27,15 +27,19 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) { - struct mga_crtc *mga_crtc = to_mga_crtc(crtc); struct drm_device *dev = crtc->dev; struct mga_device *mdev = dev->dev_private; struct drm_framebuffer *fb = crtc->primary->fb; + u16 *r_ptr, *g_ptr, *b_ptr; int i; if (!crtc->enabled) return; + r_ptr = crtc->gamma_store; + g_ptr = r_ptr + crtc->gamma_size; + b_ptr = g_ptr + crtc->gamma_size; + WREG8(DAC_INDEX + MGA1064_INDEX, 0); if (fb && fb->format->cpp[0] * 8 == 16) { @@ -46,25 +50,27 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) if (i > (MGAG200_LUT_SIZE >> 1)) { r = b = 0; } else { - r = mga_crtc->lut_r[i << 1]; - b = mga_crtc->lut_b[i << 1]; + r = *r_ptr++ >> 8; + b = *b_ptr++ >> 8; + r_ptr++; + b_ptr++; } } else { - r = mga_crtc->lut_r[i]; - b = mga_crtc->lut_b[i]; + r = *r_ptr++ >> 8; + b = *b_ptr++ >> 8; } /* VGA registers */ WREG8(DAC_INDEX + MGA1064_COL_PAL, r); - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *g_ptr++ >> 8); WREG8(DAC_INDEX + MGA1064_COL_PAL, b); } return; } for (i = 0; i < MGAG200_LUT_SIZE; i++) { /* VGA registers */ - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_r[i]); - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]); - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_b[i]); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *r_ptr++ >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *g_ptr++ >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *b_ptr++ >> 8); } } @@ -1396,14 +1402,6 @@ static int mga_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct mga_crtc *mga_crtc = to_mga_crtc(crtc); - int i; - - for (i = 0; i < size; i++) { - mga_crtc->lut_r[i] = red[i] >> 8; - mga_crtc->lut_g[i] = green[i] >> 8; - mga_crtc->lut_b[i] = blue[i] >> 8; - } mga_crtc_load_lu
[PATCH 02/11] drm: amd: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 24 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 - drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 27 +++ drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 27 +++ drivers/gpu/drm/amd/amdgpu/dce_v6_0.c| 27 +++ drivers/gpu/drm/amd/amdgpu/dce_v8_0.c| 27 +++ drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 23 --- 7 files changed, 28 insertions(+), 128 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index c0d8c6f..7dc3780 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -312,31 +312,7 @@ static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfb return 0; } -/** Sets the color ramps on behalf of fbcon */ -static void amdgpu_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - amdgpu_crtc->lut_r[regno] = red >> 6; - amdgpu_crtc->lut_g[regno] = green >> 6; - amdgpu_crtc->lut_b[regno] = blue >> 6; -} - -/** Gets the color ramps on behalf of fbcon */ -static void amdgpu_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - *red = amdgpu_crtc->lut_r[regno] << 6; - *green = amdgpu_crtc->lut_g[regno] << 6; - *blue = amdgpu_crtc->lut_b[regno] << 6; -} - static const struct drm_fb_helper_funcs amdgpu_fb_helper_funcs = { - .gamma_set = amdgpu_crtc_fb_gamma_set, - .gamma_get = amdgpu_crtc_fb_gamma_get, .fb_probe = amdgpufb_create, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 43a9d3a..39f7eda 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -369,7 +369,6 @@ struct amdgpu_atom_ss { struct amdgpu_crtc { struct drm_crtc base; int crtc_id; - u16 lut_r[256], lut_g[256], lut_b[256]; bool enabled; bool can_tile; uint32_t crtc_offset; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 3c62c45..8e8c028 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2264,6 +2264,7 @@ static void dce_v10_0_crtc_load_lut(struct drm_crtc *crtc) struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; + u16 *r, *g, *b; int i; u32 tmp; @@ -2301,11 +2302,14 @@ static void dce_v10_0_crtc_load_lut(struct drm_crtc *crtc) WREG32(mmDC_LUT_WRITE_EN_MASK + amdgpu_crtc->crtc_offset, 0x0007); WREG32(mmDC_LUT_RW_INDEX + amdgpu_crtc->crtc_offset, 0); + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; for (i = 0; i < 256; i++) { WREG32(mmDC_LUT_30_COLOR + amdgpu_crtc->crtc_offset, - (amdgpu_crtc->lut_r[i] << 20) | - (amdgpu_crtc->lut_g[i] << 10) | - (amdgpu_crtc->lut_b[i] << 0)); + ((*r++ & 0xffc0) << 14) | + ((*g++ & 0xffc0) << 4) | + (*b++ >> 6)); } tmp = RREG32(mmDEGAMMA_CONTROL + amdgpu_crtc->crtc_offset); @@ -2621,15 +2625,6 @@ static int dce_v10_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - int i; - - /* userspace palettes are always correct as is */ - for (i = 0; i < size; i++) { - amdgpu_crtc->lut_r[i] = red[i] >> 6; - amdgpu_crtc->lut_g[i] = green[i] >> 6; - amdgpu_crtc->lut_b[i] = blue[i] >> 6; - } dce_v10_0_crtc_load_lut(crtc); return 0; @@ -2841,14 +2836,12 @@ static const struct drm_crtc_helper_funcs dce_v10_0_crtc_helper_funcs = { .mode_set_base_atomic = dce_v10_0_crtc_set_base_atomic, .prepare = dce_v10_0_crtc_prepare, .commit = dce_v10_0_crt
[PATCH 01/11] drm/fb-helper: do a generic fb_setcmap helper in terms of crtc .gamma_set
This makes the redundant fb helpers .load_lut, .gamma_set and .gamma_get totally obsolete. I think the gamma_store can end up invalid on error. But the way I read it, that can happen in drm_mode_gamma_set_ioctl as well, so why should this pesky legacy fbdev stuff be any better? drm_fb_helper_save_lut_atomic justs saves the gamma lut for later. However, it saves it to the gamma_store which should already be up to date with what .gamma_get would return and is thus a nop. So, zap it. Signed-off-by: Peter Rosin --- drivers/gpu/drm/drm_fb_helper.c | 131 1 file changed, 40 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 574af01..cc2d55d 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -229,22 +229,6 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); -static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) -{ - uint16_t *r_base, *g_base, *b_base; - int i; - - if (helper->funcs->gamma_get == NULL) - return; - - r_base = crtc->gamma_store; - g_base = r_base + crtc->gamma_size; - b_base = g_base + crtc->gamma_size; - - for (i = 0; i < crtc->gamma_size; i++) - helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i); -} - static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) { uint16_t *r_base, *g_base, *b_base; @@ -285,7 +269,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info) if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev)) continue; - drm_fb_helper_save_lut_atomic(mode_set->crtc, helper); funcs->mode_set_base_atomic(mode_set->crtc, mode_set->fb, mode_set->x, @@ -1167,50 +1150,6 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked); -static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, -u16 blue, u16 regno, struct fb_info *info) -{ - struct drm_fb_helper *fb_helper = info->par; - struct drm_framebuffer *fb = fb_helper->fb; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 *palette; - u32 value; - /* place color in psuedopalette */ - if (regno > 16) - return -EINVAL; - palette = (u32 *)info->pseudo_palette; - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - if (info->var.transp.length > 0) { - u32 mask = (1 << info->var.transp.length) - 1; - - mask <<= info->var.transp.offset; - value |= mask; - } - palette[regno] = value; - return 0; - } - - /* -* The driver really shouldn't advertise pseudo/directcolor -* visuals if it can't deal with the palette. -*/ - if (WARN_ON(!fb_helper->funcs->gamma_set || - !fb_helper->funcs->gamma_get)) - return -EINVAL; - - WARN_ON(fb->format->cpp[0] != 1); - - fb_helper->funcs->gamma_set(crtc, red, green, blue, regno); - - return 0; -} - /** * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap * @cmap: cmap to set @@ -1220,51 +1159,61 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; - const struct drm_crtc_helper_funcs *crtc_funcs; - u16 *red, *green, *blue, *transp; + struct drm_modeset_acquire_ctx ctx; struct drm_crtc *crtc; - int i, j, rc = 0; - int start; + u16 *r, *g, *b; + int i, ret; if (oops_in_progress) return -EBUSY; - drm_modeset_lock_all(dev); + if (cmap->start + cmap->len < cmap->start) + return -EINVAL; + + drm_modeset_acquire_init(&ctx, 0); +retry: + ret = drm_modeset_lock_all_ctx(dev, &ctx); + if (ret) + goto out; if (!drm_fb_helper_is_bound(fb_helper)) { -
[PATCH 04/11] drm: cirrus: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/cirrus/cirrus_drv.h | 8 drivers/gpu/drm/cirrus/cirrus_fbdev.c | 2 - drivers/gpu/drm/cirrus/cirrus_mode.c | 71 --- 3 files changed, 16 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index 8690352..be2d7e48 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -96,7 +96,6 @@ struct cirrus_crtc { struct drm_crtc base; - u8 lut_r[256], lut_g[256], lut_b[256]; int last_dpms; boolenabled; }; @@ -180,13 +179,6 @@ cirrus_bo(struct ttm_buffer_object *bo) #define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base) #define DRM_FILE_PAGE_OFFSET (0x1ULL >> PAGE_SHIFT) - /* cirrus_mode.c */ -void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, -u16 blue, int regno); -void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, -u16 *blue, int regno); - - /* cirrus_main.c */ int cirrus_device_init(struct cirrus_device *cdev, struct drm_device *ddev, diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 7fa58ee..1fedab0 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -265,8 +265,6 @@ static int cirrus_fbdev_destroy(struct drm_device *dev, } static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = { - .gamma_set = cirrus_crtc_fb_gamma_set, - .gamma_get = cirrus_crtc_fb_gamma_get, .fb_probe = cirrusfb_create, }; diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 53f6f0f..a4c4a46 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -31,25 +31,6 @@ * This file contains setup code for the CRTC. */ -static void cirrus_crtc_load_lut(struct drm_crtc *crtc) -{ - struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct cirrus_device *cdev = dev->dev_private; - int i; - - if (!crtc->enabled) - return; - - for (i = 0; i < CIRRUS_LUT_SIZE; i++) { - /* VGA registers */ - WREG8(PALETTE_INDEX, i); - WREG8(PALETTE_DATA, cirrus_crtc->lut_r[i]); - WREG8(PALETTE_DATA, cirrus_crtc->lut_g[i]); - WREG8(PALETTE_DATA, cirrus_crtc->lut_b[i]); - } -} - /* * The DRM core requires DPMS functions, but they make little sense in our * case and so are just stubs @@ -330,15 +311,25 @@ static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct cirrus_device *cdev = dev->dev_private; + u16 *r, *g, *b; int i; - for (i = 0; i < size; i++) { - cirrus_crtc->lut_r[i] = red[i]; - cirrus_crtc->lut_g[i] = green[i]; - cirrus_crtc->lut_b[i] = blue[i]; + if (!crtc->enabled) + return 0; + + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + + for (i = 0; i < CIRRUS_LUT_SIZE; i++) { + /* VGA registers */ + WREG8(PALETTE_INDEX, i); + WREG8(PALETTE_DATA, *r++ >> 8); + WREG8(PALETTE_DATA, *g++ >> 8); + WREG8(PALETTE_DATA, *b++ >> 8); } - cirrus_crtc_load_lut(crtc); return 0; } @@ -365,7 +356,6 @@ static const struct drm_crtc_helper_funcs cirrus_helper_funcs = { .mode_set_base = cirrus_crtc_mode_set_base, .prepare = cirrus_crtc_prepare, .commit = cirrus_crtc_commit, - .load_lut = cirrus_crtc_load_lut, }; /* CRTC setup */ @@ -373,7 +363,6 @@ static void cirrus_crtc_init(struct drm_device *dev) { struct cirrus_device *cdev = dev->dev_private; struct cirrus_crtc *cirrus_crtc; - int i; cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) + (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)), @@ -387,37 +376,9 @@ static void cirrus_crtc_init(struct drm_devi
Re: [PATCH 01/11] drm/fb-helper: do a generic fb_setcmap helper in terms of crtc .gamma_set
On 2017-06-21 09:38, Daniel Vetter wrote: > On Tue, Jun 20, 2017 at 09:25:25PM +0200, Peter Rosin wrote: >> This makes the redundant fb helpers .load_lut, .gamma_set and .gamma_get >> totally obsolete. >> >> I think the gamma_store can end up invalid on error. But the way I read >> it, that can happen in drm_mode_gamma_set_ioctl as well, so why should >> this pesky legacy fbdev stuff be any better? >> >> drm_fb_helper_save_lut_atomic justs saves the gamma lut for later. However, >> it saves it to the gamma_store which should already be up to date with what >> .gamma_get would return and is thus a nop. So, zap it. > > Removing drm_fb_helper_save_lut_atomic should be a separate patch I > think. Then 3 patches would be needed, first some hybrid thing that does it the old way, but also stores the lut in .gamma_store, then the split-out that removes drm_fb_helper_save_lut_atomic, then whatever is needed to get to the desired code. I can certainly do that, but do you want me to? I.e., the statement that drm_fb_helper_save_lut_atomic is a nop is only true when (part of) the other patch is also considered. >> Signed-off-by: Peter Rosin > >> --- >> drivers/gpu/drm/drm_fb_helper.c | 131 >> >> 1 file changed, 40 insertions(+), 91 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_fb_helper.c >> b/drivers/gpu/drm/drm_fb_helper.c >> index 574af01..cc2d55d 100644 >> --- a/drivers/gpu/drm/drm_fb_helper.c >> +++ b/drivers/gpu/drm/drm_fb_helper.c >> @@ -229,22 +229,6 @@ int drm_fb_helper_remove_one_connector(struct >> drm_fb_helper *fb_helper, >> } >> EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); >> >> -static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct >> drm_fb_helper *helper) >> -{ >> -uint16_t *r_base, *g_base, *b_base; >> -int i; >> - >> -if (helper->funcs->gamma_get == NULL) >> -return; >> - >> -r_base = crtc->gamma_store; >> -g_base = r_base + crtc->gamma_size; >> -b_base = g_base + crtc->gamma_size; >> - >> -for (i = 0; i < crtc->gamma_size; i++) >> -helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], >> &b_base[i], i); >> -} >> - >> static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) >> { >> uint16_t *r_base, *g_base, *b_base; >> @@ -285,7 +269,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info) >> if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev)) >> continue; >> >> -drm_fb_helper_save_lut_atomic(mode_set->crtc, helper); >> funcs->mode_set_base_atomic(mode_set->crtc, >> mode_set->fb, >> mode_set->x, >> @@ -1167,50 +1150,6 @@ void drm_fb_helper_set_suspend_unlocked(struct >> drm_fb_helper *fb_helper, >> } >> EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked); >> >> -static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, >> - u16 blue, u16 regno, struct fb_info *info) >> -{ >> -struct drm_fb_helper *fb_helper = info->par; >> -struct drm_framebuffer *fb = fb_helper->fb; >> - >> -if (info->fix.visual == FB_VISUAL_TRUECOLOR) { > > This case here seems gone, and it was also the pièce de résistance when I > tried tackling fbdev lut support. As far as I understand this stuff we do > not support FB_VISUAL_TRUECOLOR palette, and all that bitshifting here is > pointless. But I'm honestly not really clear. Oops, sorry, I simply missed that, I'll have a closer look... > I think removing this case should also be a separate patch, and I'd very > much prefer that someone with some fbdev-clue would ack it. > >> -u32 *palette; >> -u32 value; >> -/* place color in psuedopalette */ >> -if (regno > 16) >> -return -EINVAL; >> -palette = (u32 *)info->pseudo_palette; >> -red >>= (16 - info->var.red.length); >> -green >>= (16 - info->var.green.length); >> -blue >>= (16 - info->var.blue.length); >> -value = (red << info->var.red.offset) | >> -(green << info->var.green.offset) | >> -(blue << info->var.blue.offset); >> -
Re: [PATCH 08/11] drm: nouveau: remove dead code and pointless local lut storage
On 2017-06-20 21:25, Peter Rosin wrote: > The redundant fb helpers .load_lut, .gamma_set and .gamma_get are > no longer used. Remove the dead code and hook up the crtc .gamma_set > to use the crtc gamma_store directly instead of duplicating that > info locally. [...] > - for (i = 0; i < 256; i++) { > - u16 r = nv_crtc->lut.r[i] >> 2; > - u16 g = nv_crtc->lut.g[i] >> 2; > - u16 b = nv_crtc->lut.b[i] >> 2; > + r = crtc->gamma_store; > + g = r + crtc->gamma_size; > + b = g + crtc->gamma_size; > > + for (i = 0; i < 256; i++) { > if (disp->disp->oclass < GF110_DISP) { > - writew(r + 0x, lut + (i * 0x08) + 0); > - writew(g + 0x, lut + (i * 0x08) + 2); > - writew(b + 0x, lut + (i * 0x08) + 4); > + writew((*r++ >> 2) + 0x, lut + (i * 0x08) + 0); > + writew((*g++ >> 2) + 0x, lut + (i * 0x08) + 2); > + writew((*b++ >> 2) + 0x, lut + (i * 0x08) + 4); > } else { > - writew(r + 0x6000, lut + (i * 0x20) + 0); > - writew(g + 0x6000, lut + (i * 0x20) + 2); > - writew(b + 0x6000, lut + (i * 0x20) + 4); > + writew((*r++ >> 2) + 0x6000, lut + (i * 0x20) + 0); > + writew((*g++ >> 2) + 0x6000, lut + (i * 0x20) + 2); > + writew((*b++ >> 2) + 0x6000, lut + (i * 0x20) + 4); > } > } > } I forgot to mention this, but the above is very strange for disp->disp->oclass >= GF110_DISP because 0x6000 interferes with the 14 bits that appear to be the lut depth in the registers. I suspect some other bit-shift should be used for that case? Someone should probably consult a datasheet... Cheers, peda
Re: [PATCH] drm: atmel-hlcdc: sama5d4 does not have overlay2
On 2017-06-21 17:14, Nicolas Ferre wrote: > On 16/06/2017 at 00:40, Peter Rosin wrote: >> On 2017-06-15 11:37, Boris Brezillon wrote: >>> On Thu, 15 Jun 2017 11:24:13 +0200 >>> Peter Rosin wrote: >>> >>>> From: Peter Rosin >>>> >>>> Remove the layer. >>> >>> Duh. It was present in the datasheet I had. Just downloaded last >>> version of the datasheet and it's no longer there. >> >> Heh. >> >>> Nicolas, there's still a reference to OVR2 in the block diagram >>> (Section "31.3 Block Diagram"), can ask fix that (or ask someone who >>> can). >> >> Also, on page 2 (the Features chapter under peripherals) there's: >> >>"LCD TFT Controller with 4 overlays..." >> >> I think it should be three? > > Hi Peter and Boris, > > After checking with the designers here, it seems that it's an issue with > the latest datasheet. This is why Boris implemented it some time ago. > > So, the conclusion is: the OVR2 was removed from latest sama5d4 > documentation by mistake. It will be corrected in next datasheet release. > The OVR2 exists and works correctly on sama5d4. > > So, please don't remove this layer ;-) Right :-) I assume the CLUT offset for overlay 2 is at 0xe00, just as it is for sama5d3? When I know for sure, I can send a v5 of the other patch. > Peter, thanks a lot for your work with supporting the CLUT feature! I needed to get rid of some memory load... Cheers, peda
[PATCH v5 0/2] drm: atmel-hlcdc: clut support
Hi! This series adds support for an 8-bit clut mode in the atmel-hlcdc driver. Changes since v4: - Added .clut_offset for overlay2 at 0xe00 for sama5d4 (unconfirmed if 0xe00 is the correct offset, but I'll eat my hat if it's not there). The sama5d4 overlay2 is indeed there, it is just AWOL in the current datasheet. - Added Acked-by from Daniel on patch 2/2. Changes since v3: - Dropped ugly code (patches 2/3 and 3/3) for legacy fbdev interaction. - Slit out the .set_property change to a patch of its own. Changes since v2: - Fix mapping to the clut registers. Changes since v1: - Move the clut update from atmel_hlcdc_crtc_mode_valid to atmel_hlcdc_plane_atomic_update. - Add default .gamma_set helper (drm_atomic_helper_legacy_gamma_set). - Don't keep a spare copy of the clut, reuse gamma_store instead. - Don't try to synchronize the legacy fb clut with the drm clut. Cheers, peda Peter Rosin (2): drm: atmel-hlcdc: add missing .set_property helper to the crtc drm: atmel-hlcdc: add support for 8-bit color lookup table mode drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 5 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 14 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h| 16 ++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 + 4 files changed, 64 insertions(+) -- 2.1.4
[PATCH v5 2/2] drm: atmel-hlcdc: add support for 8-bit color lookup table mode
All layers of all supported chips support this, the only variable is the base address of the lookup table in the register map. Acked-by: Daniel Vetter Signed-off-by: Peter Rosin --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 4 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 14 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h| 16 ++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 + 4 files changed, 63 insertions(+) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index cc00ce3..694adcc 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -430,6 +430,7 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { .enable_vblank = atmel_hlcdc_crtc_enable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank, .set_property = drm_atomic_helper_crtc_set_property, + .gamma_set = drm_atomic_helper_legacy_gamma_set, }; int atmel_hlcdc_crtc_create(struct drm_device *dev) @@ -485,6 +486,9 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); drm_crtc_vblank_reset(&crtc->base); + drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); + drm_crtc_enable_color_mgmt(&crtc->base, 0, false, ATMEL_HLCDC_CLUT_SIZE); + dc->crtc = &crtc->base; return 0; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 30dbffd..6ff771c 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = { .default_color = 3, .general_config = 4, }, + .clut_offset = 0x400, }, }; @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x400, }, { .name = "overlay1", @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x800, }, { .name = "high-end-overlay", @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .scaler_config = 13, .csc = 14, }, + .clut_offset = 0x1000, }, { .name = "cursor", @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x1400, }, }; @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, { .name = "overlay1", @@ -180,6 +186,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xa00, }, { .name = "overlay2", @@ -198,6 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xe00, }, { .name = "high-end-overlay", @@ -223,6 +231,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { }, .csc = 14, }, + .clut_offset = 0x1200, }, { .name = "cursor", @@ -244,6 +253,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .general_config = 9, .scaler_config = 13, }, + .clut_offset = 0x1600, }, }; @@ -275,6 +285,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, {
[PATCH v5 1/2] drm: atmel-hlcdc: add missing .set_property helper to the crtc
The default implementation should be used. Signed-off-by: Peter Rosin --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 5348985..cc00ce3 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -429,6 +429,7 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, .enable_vblank = atmel_hlcdc_crtc_enable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank, + .set_property = drm_atomic_helper_crtc_set_property, }; int atmel_hlcdc_crtc_create(struct drm_device *dev) -- 2.1.4
[PATCH v2 03/14] drm/fb-helper: do a generic fb_setcmap helper in terms of crtc .gamma_set
This makes the redundant fb helpers .load_lut, .gamma_set and .gamma_get totally obsolete. Signed-off-by: Peter Rosin --- drivers/gpu/drm/drm_fb_helper.c | 154 1 file changed, 63 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 7ade384..58eb045 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1150,50 +1150,6 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked); -static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, -u16 blue, u16 regno, struct fb_info *info) -{ - struct drm_fb_helper *fb_helper = info->par; - struct drm_framebuffer *fb = fb_helper->fb; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 *palette; - u32 value; - /* place color in psuedopalette */ - if (regno > 16) - return -EINVAL; - palette = (u32 *)info->pseudo_palette; - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - if (info->var.transp.length > 0) { - u32 mask = (1 << info->var.transp.length) - 1; - - mask <<= info->var.transp.offset; - value |= mask; - } - palette[regno] = value; - return 0; - } - - /* -* The driver really shouldn't advertise pseudo/directcolor -* visuals if it can't deal with the palette. -*/ - if (WARN_ON(!fb_helper->funcs->gamma_set || - !fb_helper->funcs->gamma_get)) - return -EINVAL; - - WARN_ON(fb->format->cpp[0] != 1); - - fb_helper->funcs->gamma_set(crtc, red, green, blue, regno); - - return 0; -} - /** * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap * @cmap: cmap to set @@ -1203,12 +1159,10 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; - const struct drm_crtc_helper_funcs *crtc_funcs; - u16 *red, *green, *blue, *transp; + struct drm_modeset_acquire_ctx ctx; struct drm_crtc *crtc; u16 *r, *g, *b; - int i, j, rc = 0; - int start; + int i, ret; if (oops_in_progress) return -EBUSY; @@ -1216,65 +1170,83 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) if (cmap->start + cmap->len < cmap->start) return -EINVAL; - drm_modeset_lock_all(dev); + drm_modeset_acquire_init(&ctx, 0); +retry: + ret = drm_modeset_lock_all_ctx(dev, &ctx); + if (ret) + goto out; if (!drm_fb_helper_is_bound(fb_helper)) { - drm_modeset_unlock_all(dev); - return -EBUSY; + ret = -EBUSY; + goto out; } for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; - crtc_funcs = crtc->helper_private; - - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - start = cmap->start; + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *palette; + int j; - if (info->fix.visual != FB_VISUAL_TRUECOLOR) { - if (!crtc->gamma_size) { - rc = -EINVAL; + if (cmap->start + cmap->len > 16) { + ret = -EINVAL; goto out; } - if (cmap->start + cmap->len > crtc->gamma_size) { - rc = -EINVAL; - goto out; + palette = (u32 *)info->pseudo_palette; + for (j = 0; j < cmap->len; ++j) { + u16 red = cmap->red[j]; + u16 green = cmap->green[j]; + u16 blue = cmap->blue[j]; + u32 value; + + red >>
[PATCH v2 07/14] drm: cirrus: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/cirrus/cirrus_drv.h | 8 drivers/gpu/drm/cirrus/cirrus_fbdev.c | 2 - drivers/gpu/drm/cirrus/cirrus_mode.c | 71 --- 3 files changed, 16 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index 8690352..be2d7e48 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -96,7 +96,6 @@ struct cirrus_crtc { struct drm_crtc base; - u8 lut_r[256], lut_g[256], lut_b[256]; int last_dpms; boolenabled; }; @@ -180,13 +179,6 @@ cirrus_bo(struct ttm_buffer_object *bo) #define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base) #define DRM_FILE_PAGE_OFFSET (0x1ULL >> PAGE_SHIFT) - /* cirrus_mode.c */ -void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, -u16 blue, int regno); -void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, -u16 *blue, int regno); - - /* cirrus_main.c */ int cirrus_device_init(struct cirrus_device *cdev, struct drm_device *ddev, diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 7fa58ee..1fedab0 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -265,8 +265,6 @@ static int cirrus_fbdev_destroy(struct drm_device *dev, } static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = { - .gamma_set = cirrus_crtc_fb_gamma_set, - .gamma_get = cirrus_crtc_fb_gamma_get, .fb_probe = cirrusfb_create, }; diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 53f6f0f..a4c4a46 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -31,25 +31,6 @@ * This file contains setup code for the CRTC. */ -static void cirrus_crtc_load_lut(struct drm_crtc *crtc) -{ - struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct cirrus_device *cdev = dev->dev_private; - int i; - - if (!crtc->enabled) - return; - - for (i = 0; i < CIRRUS_LUT_SIZE; i++) { - /* VGA registers */ - WREG8(PALETTE_INDEX, i); - WREG8(PALETTE_DATA, cirrus_crtc->lut_r[i]); - WREG8(PALETTE_DATA, cirrus_crtc->lut_g[i]); - WREG8(PALETTE_DATA, cirrus_crtc->lut_b[i]); - } -} - /* * The DRM core requires DPMS functions, but they make little sense in our * case and so are just stubs @@ -330,15 +311,25 @@ static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct cirrus_device *cdev = dev->dev_private; + u16 *r, *g, *b; int i; - for (i = 0; i < size; i++) { - cirrus_crtc->lut_r[i] = red[i]; - cirrus_crtc->lut_g[i] = green[i]; - cirrus_crtc->lut_b[i] = blue[i]; + if (!crtc->enabled) + return 0; + + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + + for (i = 0; i < CIRRUS_LUT_SIZE; i++) { + /* VGA registers */ + WREG8(PALETTE_INDEX, i); + WREG8(PALETTE_DATA, *r++ >> 8); + WREG8(PALETTE_DATA, *g++ >> 8); + WREG8(PALETTE_DATA, *b++ >> 8); } - cirrus_crtc_load_lut(crtc); return 0; } @@ -365,7 +356,6 @@ static const struct drm_crtc_helper_funcs cirrus_helper_funcs = { .mode_set_base = cirrus_crtc_mode_set_base, .prepare = cirrus_crtc_prepare, .commit = cirrus_crtc_commit, - .load_lut = cirrus_crtc_load_lut, }; /* CRTC setup */ @@ -373,7 +363,6 @@ static void cirrus_crtc_init(struct drm_device *dev) { struct cirrus_device *cdev = dev->dev_private; struct cirrus_crtc *cirrus_crtc; - int i; cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) + (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)), @@ -387,37 +376,9 @@ static void cirrus_crtc_init(struct drm_devi
[PATCH v2 01/14] drm/fb-helper: keep the .gamma_store updated in drm_fb_helper_setcmap
I think the gamma_store can end up invalid on error. But the way I read it, that can happen in drm_mode_gamma_set_ioctl as well, so why should this pesky legacy fbdev stuff be any better? Signed-off-by: Peter Rosin --- drivers/gpu/drm/drm_fb_helper.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 574af01..25315fb 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1223,12 +1223,16 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) const struct drm_crtc_helper_funcs *crtc_funcs; u16 *red, *green, *blue, *transp; struct drm_crtc *crtc; + u16 *r, *g, *b; int i, j, rc = 0; int start; if (oops_in_progress) return -EBUSY; + if (cmap->start + cmap->len < cmap->start) + return -EINVAL; + drm_modeset_lock_all(dev); if (!drm_fb_helper_is_bound(fb_helper)) { drm_modeset_unlock_all(dev); @@ -1245,6 +1249,29 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) transp = cmap->transp; start = cmap->start; + if (info->fix.visual != FB_VISUAL_TRUECOLOR) { + if (!crtc->gamma_size) { + rc = -EINVAL; + goto out; + } + + if (cmap->start + cmap->len > crtc->gamma_size) { + rc = -EINVAL; + goto out; + } + + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + + memcpy(r + cmap->start, cmap->red, + cmap->len * sizeof(u16)); + memcpy(g + cmap->start, cmap->green, + cmap->len * sizeof(u16)); + memcpy(b + cmap->start, cmap->blue, + cmap->len * sizeof(u16)); + } + for (j = 0; j < cmap->len; j++) { u16 hred, hgreen, hblue, htransp = 0x; -- 2.1.4
[PATCH v2 10/14] drm: mgag200: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/mgag200/mgag200_drv.h | 5 --- drivers/gpu/drm/mgag200/mgag200_fb.c | 2 -- drivers/gpu/drm/mgag200/mgag200_mode.c | 62 -- 3 files changed, 15 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index c88b6ec..04f1dfb 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -237,11 +237,6 @@ mgag200_bo(struct ttm_buffer_object *bo) { return container_of(bo, struct mgag200_bo, bo); } - /* mgag200_crtc.c */ -void mga_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, -u16 blue, int regno); -void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, -u16 *blue, int regno); /* mgag200_mode.c */ int mgag200_modeset_init(struct mga_device *mdev); diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 5d3b1fa..5cf980a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -258,8 +258,6 @@ static int mga_fbdev_destroy(struct drm_device *dev, } static const struct drm_fb_helper_funcs mga_fb_helper_funcs = { - .gamma_set = mga_crtc_fb_gamma_set, - .gamma_get = mga_crtc_fb_gamma_get, .fb_probe = mgag200fb_create, }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index f4b5358..5e9cd4c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -27,15 +27,19 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) { - struct mga_crtc *mga_crtc = to_mga_crtc(crtc); struct drm_device *dev = crtc->dev; struct mga_device *mdev = dev->dev_private; struct drm_framebuffer *fb = crtc->primary->fb; + u16 *r_ptr, *g_ptr, *b_ptr; int i; if (!crtc->enabled) return; + r_ptr = crtc->gamma_store; + g_ptr = r_ptr + crtc->gamma_size; + b_ptr = g_ptr + crtc->gamma_size; + WREG8(DAC_INDEX + MGA1064_INDEX, 0); if (fb && fb->format->cpp[0] * 8 == 16) { @@ -46,25 +50,27 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) if (i > (MGAG200_LUT_SIZE >> 1)) { r = b = 0; } else { - r = mga_crtc->lut_r[i << 1]; - b = mga_crtc->lut_b[i << 1]; + r = *r_ptr++ >> 8; + b = *b_ptr++ >> 8; + r_ptr++; + b_ptr++; } } else { - r = mga_crtc->lut_r[i]; - b = mga_crtc->lut_b[i]; + r = *r_ptr++ >> 8; + b = *b_ptr++ >> 8; } /* VGA registers */ WREG8(DAC_INDEX + MGA1064_COL_PAL, r); - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *g_ptr++ >> 8); WREG8(DAC_INDEX + MGA1064_COL_PAL, b); } return; } for (i = 0; i < MGAG200_LUT_SIZE; i++) { /* VGA registers */ - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_r[i]); - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]); - WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_b[i]); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *r_ptr++ >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *g_ptr++ >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, *b_ptr++ >> 8); } } @@ -1399,14 +1405,6 @@ static int mga_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct mga_crtc *mga_crtc = to_mga_crtc(crtc); - int i; - - for (i = 0; i < size; i++) { - mga_crtc->lut_r[i] = red[i] >> 8; - mga_crtc->lut_g[i] = green[i] >> 8; - mga_crtc->lut_b[i] = blue[i] >> 8; - } mga_crtc_load_lu
[PATCH v2 12/14] drm: radeon: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/radeon/atombios_crtc.c | 1 - drivers/gpu/drm/radeon/radeon_connectors.c | 7 ++- drivers/gpu/drm/radeon/radeon_display.c | 71 - drivers/gpu/drm/radeon/radeon_fb.c | 2 - drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 1 - drivers/gpu/drm/radeon/radeon_mode.h| 4 -- 6 files changed, 33 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 3c492a0..02baaaf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -2217,7 +2217,6 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = { .mode_set_base_atomic = atombios_crtc_set_base_atomic, .prepare = atombios_crtc_prepare, .commit = atombios_crtc_commit, - .load_lut = radeon_crtc_load_lut, .disable = atombios_crtc_disable, }; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 27affbd..2f642cb 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -773,12 +773,15 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct if (connector->encoder->crtc) { struct drm_crtc *crtc = connector->encoder->crtc; - const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); radeon_crtc->output_csc = radeon_encoder->output_csc; - (*crtc_funcs->load_lut)(crtc); + /* +* Our .gamma_set assumes the .gamma_store has been +* prefilled and don't care about its arguments. +*/ + crtc->funcs->gamma_set(crtc, NULL, NULL, NULL, 0, NULL); } } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 17d3daf..8b7d7a0 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -42,6 +42,7 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + u16 *r, *g, *b; int i; DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); @@ -60,11 +61,14 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) WREG32(AVIVO_DC_LUT_WRITE_EN_MASK, 0x003f); WREG8(AVIVO_DC_LUT_RW_INDEX, 0); + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; for (i = 0; i < 256; i++) { WREG32(AVIVO_DC_LUT_30_COLOR, -(radeon_crtc->lut_r[i] << 20) | -(radeon_crtc->lut_g[i] << 10) | -(radeon_crtc->lut_b[i] << 0)); + ((*r++ & 0xffc0) << 14) | + ((*g++ & 0xffc0) << 4) | + (*b++ >> 6)); } /* Only change bit 0 of LUT_SEL, other bits are set elsewhere */ @@ -76,6 +80,7 @@ static void dce4_crtc_load_lut(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + u16 *r, *g, *b; int i; DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); @@ -93,11 +98,14 @@ static void dce4_crtc_load_lut(struct drm_crtc *crtc) WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x0007); WREG32(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, 0); + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; for (i = 0; i < 256; i++) { WREG32(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset, - (radeon_crtc->lut_r[i] << 20) | - (radeon_crtc->lut_g[i] << 10) | - (radeon_crtc->lut_b[i] << 0)); + ((*r++ & 0xffc0) << 14) | + ((*g++ & 0xffc0) << 4) | + (*b++ >> 6)); } } @@ -106,6 +114,7 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc =
[PATCH v2 11/14] drm: nouveau: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 26 - drivers/gpu/drm/nouveau/nouveau_crtc.h | 3 --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 22 -- drivers/gpu/drm/nouveau/nv50_display.c | 40 +++-- 4 files changed, 22 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 4b4b0b4..8f689f1 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -764,13 +764,18 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = nv_crtc->base.dev; struct rgb { uint8_t r, g, b; } __attribute__((packed)) *rgbs; + u16 *r, *g, *b; int i; rgbs = (struct rgb *)nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index].DAC; + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + for (i = 0; i < 256; i++) { - rgbs[i].r = nv_crtc->lut.r[i] >> 8; - rgbs[i].g = nv_crtc->lut.g[i] >> 8; - rgbs[i].b = nv_crtc->lut.b[i] >> 8; + rgbs[i].r = *r++ >> 8; + rgbs[i].g = *g++ >> 8; + rgbs[i].b = *b++ >> 8; } nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg); @@ -792,13 +797,6 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, struct drm_modeset_acquire_ctx *ctx) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - int i; - - for (i = 0; i < size; i++) { - nv_crtc->lut.r[i] = r[i]; - nv_crtc->lut.g[i] = g[i]; - nv_crtc->lut.b[i] = b[i]; - } /* We need to know the depth before we upload, but it's possible to * get called before a framebuffer is bound. If this is the case, @@ -1095,7 +1093,6 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { .mode_set = nv_crtc_mode_set, .mode_set_base = nv04_crtc_mode_set_base, .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, - .load_lut = nv_crtc_gamma_load, .disable = nv_crtc_disable, }; @@ -1103,17 +1100,12 @@ int nv04_crtc_create(struct drm_device *dev, int crtc_num) { struct nouveau_crtc *nv_crtc; - int ret, i; + int ret; nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); if (!nv_crtc) return -ENOMEM; - for (i = 0; i < 256; i++) { - nv_crtc->lut.r[i] = i << 8; - nv_crtc->lut.g[i] = i << 8; - nv_crtc->lut.b[i] = i << 8; - } nv_crtc->lut.depth = 0; nv_crtc->index = crtc_num; diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h index 050fcf3..b7a18fb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -61,9 +61,6 @@ struct nouveau_crtc { struct { struct nouveau_bo *nvbo; - uint16_t r[256]; - uint16_t g[256]; - uint16_t b[256]; int depth; } lut; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 2665a07..f770784 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -278,26 +278,6 @@ nouveau_fbcon_accel_init(struct drm_device *dev) info->fbops = &nouveau_fbcon_ops; } -static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - nv_crtc->lut.r[regno] = red; - nv_crtc->lut.g[regno] = green; - nv_crtc->lut.b[regno] = blue; -} - -static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - *red = nv_crtc->lut.r[regno]; - *green = nv_crtc->lut.g[regno]; - *blue = nv_crtc->lut.b[regno]; -} - static void nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon) { @@ -467,8 +447,6 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info) } static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { - .gamma_set = nouveau_fbcon_gamma_set, - .gamma_get = nouveau_fbcon_gamm
[PATCH v2 09/14] drm: i915: remove dead code and pointless local lut storage
The driver stores lut values from the fbdev interface, and is able to give them back, but does not appear to do anything with these lut values. The generic fb helpers have replaced this function, and may even have made the driver work for the C8 mode from the fbdev interface. But that is untested. Since the fb helpers .gamma_set and .gamma_get are obsolete, remove the dead code. Signed-off-by: Peter Rosin --- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_fbdev.c | 31 --- 2 files changed, 32 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d93efb4..bc7bfa0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -786,7 +786,6 @@ struct intel_crtc { struct drm_crtc base; enum pipe pipe; enum plane plane; - u8 lut_r[256], lut_g[256], lut_b[256]; /* * Whether the crtc and the connected output pipeline is active. Implies * that crtc->enabled is set, i.e. the current mode configuration has diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 03347c6..5bac953 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -281,27 +281,6 @@ static int intelfb_create(struct drm_fb_helper *helper, return ret; } -/** Sets the color ramps on behalf of RandR */ -static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - intel_crtc->lut_r[regno] = red >> 8; - intel_crtc->lut_g[regno] = green >> 8; - intel_crtc->lut_b[regno] = blue >> 8; -} - -static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - *red = intel_crtc->lut_r[regno] << 8; - *green = intel_crtc->lut_g[regno] << 8; - *blue = intel_crtc->lut_b[regno] << 8; -} - static struct drm_fb_helper_crtc * intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) { @@ -370,7 +349,6 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, struct drm_connector *connector; struct drm_encoder *encoder; struct drm_fb_helper_crtc *new_crtc; - struct intel_crtc *intel_crtc; fb_conn = fb_helper->connector_info[i]; connector = fb_conn->connector; @@ -412,13 +390,6 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, num_connectors_enabled++; - intel_crtc = to_intel_crtc(connector->state->crtc); - for (j = 0; j < 256; j++) { - intel_crtc->lut_r[j] = j; - intel_crtc->lut_g[j] = j; - intel_crtc->lut_b[j] = j; - } - new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc); @@ -519,8 +490,6 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { .initial_config = intel_fb_initial_config, - .gamma_set = intel_crtc_fb_gamma_set, - .gamma_get = intel_crtc_fb_gamma_get, .fb_probe = intelfb_create, }; -- 2.1.4
[PATCH v2 13/14] drm: stm: remove dead code and pointless local lut storage
The redundant fb helper .load_lut is no longer used, and can not work right without also providing the fb helpers .gamma_set and .gamma_get thus rendering the code in this driver suspect. Just remove the dead code. Signed-off-by: Peter Rosin --- drivers/gpu/drm/stm/ltdc.c | 12 drivers/gpu/drm/stm/ltdc.h | 1 - 2 files changed, 13 deletions(-) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 1b9483d..87829b9 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -375,17 +375,6 @@ static irqreturn_t ltdc_irq(int irq, void *arg) * DRM_CRTC */ -static void ltdc_crtc_load_lut(struct drm_crtc *crtc) -{ - struct ltdc_device *ldev = crtc_to_ltdc(crtc); - unsigned int i, lay; - - for (lay = 0; lay < ldev->caps.nb_layers; lay++) - for (i = 0; i < 256; i++) - reg_write(ldev->regs, LTDC_L1CLUTWR + lay * LAY_OFS, - ldev->clut[i]); -} - static void ltdc_crtc_enable(struct drm_crtc *crtc) { struct ltdc_device *ldev = crtc_to_ltdc(crtc); @@ -523,7 +512,6 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, } static struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = { - .load_lut = ltdc_crtc_load_lut, .enable = ltdc_crtc_enable, .disable = ltdc_crtc_disable, .mode_set_nofb = ltdc_crtc_mode_set_nofb, diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h index d7a9c73..620ca55 100644 --- a/drivers/gpu/drm/stm/ltdc.h +++ b/drivers/gpu/drm/stm/ltdc.h @@ -27,7 +27,6 @@ struct ltdc_device { struct drm_panel *panel; struct mutex err_lock; /* protecting error_status */ struct ltdc_caps caps; - u32 clut[256]; /* color look up table */ u32 error_status; u32 irq_status; }; -- 2.1.4
[PATCH v2 14/14] drm: remove unused and redundant callbacks
Drivers no longer have any need for these callbacks, and there are no users. Zap. Zap-zap-zzzap-p-pp-p. Signed-off-by: Peter Rosin --- include/drm/drm_fb_helper.h | 32 include/drm/drm_modeset_helper_vtables.h | 16 2 files changed, 48 deletions(-) diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 119e5e4..80d9853 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -85,38 +85,6 @@ struct drm_fb_helper_surface_size { */ struct drm_fb_helper_funcs { /** -* @gamma_set: -* -* Set the given gamma LUT register on the given CRTC. -* -* This callback is optional. -* -* FIXME: -* -* This callback is functionally redundant with the core gamma table -* support and simply exists because the fbdev hasn't yet been -* refactored to use the core gamma table interfaces. -*/ - void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno); - /** -* @gamma_get: -* -* Read the given gamma LUT register on the given CRTC, used to save the -* current LUT when force-restoring the fbdev for e.g. kdbg. -* -* This callback is optional. -* -* FIXME: -* -* This callback is functionally redundant with the core gamma table -* support and simply exists because the fbdev hasn't yet been -* refactored to use the core gamma table interfaces. -*/ - void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno); - - /** * @fb_probe: * * Driver callback to allocate and initialize the fbdev info structure. diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 85984b2..0773db9 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -267,22 +267,6 @@ struct drm_crtc_helper_funcs { enum mode_set_atomic); /** -* @load_lut: -* -* Load a LUT prepared with the &drm_fb_helper_funcs.gamma_set vfunc. -* -* This callback is optional and is only used by the fbdev emulation -* helpers. -* -* FIXME: -* -* This callback is functionally redundant with the core gamma table -* support and simply exists because the fbdev hasn't yet been -* refactored to use the core gamma table interfaces. -*/ - void (*load_lut)(struct drm_crtc *crtc); - - /** * @disable: * * This callback should be used to disable the CRTC. With the atomic -- 2.1.4
[PATCH v2 02/14] drm/fb-helper: remove drm_fb_helper_save_lut_atomic
drm_fb_helper_save_lut_atomic is redundant since the .gamma_store is now always kept up to date by drm_fb_helper_setcmap. Signed-off-by: Peter Rosin --- drivers/gpu/drm/drm_fb_helper.c | 17 - 1 file changed, 17 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 25315fb..7ade384 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -229,22 +229,6 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); -static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) -{ - uint16_t *r_base, *g_base, *b_base; - int i; - - if (helper->funcs->gamma_get == NULL) - return; - - r_base = crtc->gamma_store; - g_base = r_base + crtc->gamma_size; - b_base = g_base + crtc->gamma_size; - - for (i = 0; i < crtc->gamma_size; i++) - helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i); -} - static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) { uint16_t *r_base, *g_base, *b_base; @@ -285,7 +269,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info) if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev)) continue; - drm_fb_helper_save_lut_atomic(mode_set->crtc, helper); funcs->mode_set_base_atomic(mode_set->crtc, mode_set->fb, mode_set->x, -- 2.1.4
[PATCH v2 08/14] drm: gma500: remove dead code and pointless local lut storage
The redundant fb helpers .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/gma500/framebuffer.c | 22 drivers/gpu/drm/gma500/gma_display.c | 32 ++ drivers/gpu/drm/gma500/psb_intel_display.c | 7 +-- drivers/gpu/drm/gma500/psb_intel_drv.h | 1 - 4 files changed, 12 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 7da70b6..2570c7f 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -479,26 +479,6 @@ static struct drm_framebuffer *psb_user_framebuffer_create return psb_framebuffer_create(dev, cmd, r); } -static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct gma_crtc *gma_crtc = to_gma_crtc(crtc); - - gma_crtc->lut_r[regno] = red >> 8; - gma_crtc->lut_g[regno] = green >> 8; - gma_crtc->lut_b[regno] = blue >> 8; -} - -static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, - u16 *green, u16 *blue, int regno) -{ - struct gma_crtc *gma_crtc = to_gma_crtc(crtc); - - *red = gma_crtc->lut_r[regno] << 8; - *green = gma_crtc->lut_g[regno] << 8; - *blue = gma_crtc->lut_b[regno] << 8; -} - static int psbfb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { @@ -525,8 +505,6 @@ static int psbfb_probe(struct drm_fb_helper *helper, } static const struct drm_fb_helper_funcs psb_fb_helper_funcs = { - .gamma_set = psbfb_gamma_set, - .gamma_get = psbfb_gamma_get, .fb_probe = psbfb_probe, }; diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index e7fd356..f3c48a2 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -144,33 +144,32 @@ void gma_crtc_load_lut(struct drm_crtc *crtc) struct gma_crtc *gma_crtc = to_gma_crtc(crtc); const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe]; int palreg = map->palette; + u16 *r, *g, *b; int i; /* The clocks have to be on to load the palette. */ if (!crtc->enabled) return; + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + if (gma_power_begin(dev, false)) { for (i = 0; i < 256; i++) { REG_WRITE(palreg + 4 * i, - ((gma_crtc->lut_r[i] + - gma_crtc->lut_adj[i]) << 16) | - ((gma_crtc->lut_g[i] + - gma_crtc->lut_adj[i]) << 8) | - (gma_crtc->lut_b[i] + - gma_crtc->lut_adj[i])); + (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) | + (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) | + ((*b++ >> 8) + gma_crtc->lut_adj[i])); } gma_power_end(dev); } else { for (i = 0; i < 256; i++) { /* FIXME: Why pipe[0] and not pipe[..._crtc->pipe]? */ dev_priv->regs.pipe[0].palette[i] = - ((gma_crtc->lut_r[i] + - gma_crtc->lut_adj[i]) << 16) | - ((gma_crtc->lut_g[i] + - gma_crtc->lut_adj[i]) << 8) | - (gma_crtc->lut_b[i] + - gma_crtc->lut_adj[i]); + (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) | + (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) | + ((*b++ >> 8) + gma_crtc->lut_adj[i]); } } @@ -180,15 +179,6 @@ int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, u32 size, struct drm_modeset_acquire_ctx *ctx) { - struct gma_crtc *gma_crtc = to_gma_crtc(crtc); - int i; - - for (i = 0; i < size; i++) { - gma_crtc->lut_r[i] = red[i] >> 8; - gma_crtc->lut_g[i] = green[i] >> 8; - gma_crtc->lut_b[i] = blue[i] >> 8; - } -
[PATCH v2 06/14] drm: ast: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/ast/ast_drv.h | 1 - drivers/gpu/drm/ast/ast_fb.c | 20 drivers/gpu/drm/ast/ast_mode.c | 26 ++ 3 files changed, 6 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 8880f0b..569a148 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -245,7 +245,6 @@ struct ast_connector { struct ast_crtc { struct drm_crtc base; - u8 lut_r[256], lut_g[256], lut_b[256]; struct drm_gem_object *cursor_bo; uint64_t cursor_addr; int cursor_width, cursor_height; diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 4ad4acd..dbabcac 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -255,27 +255,7 @@ static int astfb_create(struct drm_fb_helper *helper, return ret; } -static void ast_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - ast_crtc->lut_r[regno] = red >> 8; - ast_crtc->lut_g[regno] = green >> 8; - ast_crtc->lut_b[regno] = blue >> 8; -} - -static void ast_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - *red = ast_crtc->lut_r[regno] << 8; - *green = ast_crtc->lut_g[regno] << 8; - *blue = ast_crtc->lut_b[regno] << 8; -} - static const struct drm_fb_helper_funcs ast_fb_helper_funcs = { - .gamma_set = ast_fb_gamma_set, - .gamma_get = ast_fb_gamma_get, .fb_probe = astfb_create, }; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index aaef0a6..724c16b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -63,15 +63,18 @@ static inline void ast_load_palette_index(struct ast_private *ast, static void ast_crtc_load_lut(struct drm_crtc *crtc) { struct ast_private *ast = crtc->dev->dev_private; - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); + u16 *r, *g, *b; int i; if (!crtc->enabled) return; + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + for (i = 0; i < 256; i++) - ast_load_palette_index(ast, i, ast_crtc->lut_r[i], - ast_crtc->lut_g[i], ast_crtc->lut_b[i]); + ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8); } static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, @@ -633,7 +636,6 @@ static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .mode_set = ast_crtc_mode_set, .mode_set_base = ast_crtc_mode_set_base, .disable = ast_crtc_disable, - .load_lut = ast_crtc_load_lut, .prepare = ast_crtc_prepare, .commit = ast_crtc_commit, @@ -648,15 +650,6 @@ static int ast_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - int i; - - /* userspace palettes are always correct as is */ - for (i = 0; i < size; i++) { - ast_crtc->lut_r[i] = red[i] >> 8; - ast_crtc->lut_g[i] = green[i] >> 8; - ast_crtc->lut_b[i] = blue[i] >> 8; - } ast_crtc_load_lut(crtc); return 0; @@ -681,7 +674,6 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_crtc *crtc; - int i; crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); if (!crtc) @@ -690,12 +682,6 @@ static int ast_crtc_init(struct drm_device *dev) drm_crtc_init(dev, &crtc->base, &ast_crtc_funcs); drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs); - - for (i = 0; i < 256; i++) { - crtc->lut_r[i] = i; - crtc->lut_g[i] = i; - crtc->lut_b[i] = i; - } return 0; } -- 2.1.4
[PATCH v2 05/14] drm: armada: remove dead empty functions
The redundant fb helpers .gamma_set and .gamma_get are no longer used. Remove the dead code. Signed-off-by: Peter Rosin --- drivers/gpu/drm/armada/armada_crtc.c | 10 -- drivers/gpu/drm/armada/armada_crtc.h | 2 -- drivers/gpu/drm/armada/armada_fbdev.c | 2 -- 3 files changed, 14 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 4fe19fd..96bccf8 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -334,16 +334,6 @@ static void armada_drm_vblank_off(struct armada_crtc *dcrtc) armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary); } -void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b, - int idx) -{ -} - -void armada_drm_crtc_gamma_get(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, - int idx) -{ -} - /* The mode_config.mutex will be held for this call */ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms) { diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 7e8906d..bab11f4 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -102,8 +102,6 @@ struct armada_crtc { }; #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) -void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); -void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc, diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 602dfea..5fa076d 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -118,8 +118,6 @@ static int armada_fb_probe(struct drm_fb_helper *fbh, } static const struct drm_fb_helper_funcs armada_fb_helper_funcs = { - .gamma_set = armada_drm_crtc_gamma_set, - .gamma_get = armada_drm_crtc_gamma_get, .fb_probe = armada_fb_probe, }; -- 2.1.4
[PATCH v2 04/14] drm: amd: remove dead code and pointless local lut storage
The redundant fb helpers .load_lut, .gamma_set and .gamma_get are no longer used. Remove the dead code and hook up the crtc .gamma_set to use the crtc gamma_store directly instead of duplicating that info locally. Signed-off-by: Peter Rosin --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 24 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 - drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 27 +++ drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 27 +++ drivers/gpu/drm/amd/amdgpu/dce_v6_0.c| 27 +++ drivers/gpu/drm/amd/amdgpu/dce_v8_0.c| 27 +++ drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 23 --- 7 files changed, 28 insertions(+), 128 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index c0d8c6f..7dc3780 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -312,31 +312,7 @@ static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfb return 0; } -/** Sets the color ramps on behalf of fbcon */ -static void amdgpu_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - amdgpu_crtc->lut_r[regno] = red >> 6; - amdgpu_crtc->lut_g[regno] = green >> 6; - amdgpu_crtc->lut_b[regno] = blue >> 6; -} - -/** Gets the color ramps on behalf of fbcon */ -static void amdgpu_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - *red = amdgpu_crtc->lut_r[regno] << 6; - *green = amdgpu_crtc->lut_g[regno] << 6; - *blue = amdgpu_crtc->lut_b[regno] << 6; -} - static const struct drm_fb_helper_funcs amdgpu_fb_helper_funcs = { - .gamma_set = amdgpu_crtc_fb_gamma_set, - .gamma_get = amdgpu_crtc_fb_gamma_get, .fb_probe = amdgpufb_create, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 43a9d3a..39f7eda 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -369,7 +369,6 @@ struct amdgpu_atom_ss { struct amdgpu_crtc { struct drm_crtc base; int crtc_id; - u16 lut_r[256], lut_g[256], lut_b[256]; bool enabled; bool can_tile; uint32_t crtc_offset; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 9f78c03..c958023 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2267,6 +2267,7 @@ static void dce_v10_0_crtc_load_lut(struct drm_crtc *crtc) struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; + u16 *r, *g, *b; int i; u32 tmp; @@ -2304,11 +2305,14 @@ static void dce_v10_0_crtc_load_lut(struct drm_crtc *crtc) WREG32(mmDC_LUT_WRITE_EN_MASK + amdgpu_crtc->crtc_offset, 0x0007); WREG32(mmDC_LUT_RW_INDEX + amdgpu_crtc->crtc_offset, 0); + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; for (i = 0; i < 256; i++) { WREG32(mmDC_LUT_30_COLOR + amdgpu_crtc->crtc_offset, - (amdgpu_crtc->lut_r[i] << 20) | - (amdgpu_crtc->lut_g[i] << 10) | - (amdgpu_crtc->lut_b[i] << 0)); + ((*r++ & 0xffc0) << 14) | + ((*g++ & 0xffc0) << 4) | + (*b++ >> 6)); } tmp = RREG32(mmDEGAMMA_CONTROL + amdgpu_crtc->crtc_offset); @@ -2624,15 +2628,6 @@ static int dce_v10_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - int i; - - /* userspace palettes are always correct as is */ - for (i = 0; i < size; i++) { - amdgpu_crtc->lut_r[i] = red[i] >> 6; - amdgpu_crtc->lut_g[i] = green[i] >> 6; - amdgpu_crtc->lut_b[i] = blue[i] >> 6; - } dce_v10_0_crtc_load_lut(crtc); return 0; @@ -2844,14 +2839,12 @@ static const struct drm_crtc_helper_funcs dce_v10_0_crtc_helper_funcs = { .mode_set_base_atomic = dce_v10_0_crtc_set_base_atomic, .prepare = dce_v10_0_crtc_prepare, .commit = dce_v10_0_crt
[PATCH v2 00/14] improve the fb_setcmap helper
Hi! While trying to get CLUT support for the atmel_hlcdc driver, and specifically for the emulated fbdev interface, I received some push-back that my feeble in-driver attempts should be solved by the core. This is my attempt to do it right. I have obviously not tested all of this with more than a compile, but patches 1 and 3 are enough to make the atmel-hlcdc driver do what I need (when patched to support CLUT modes). The rest is just lots of removals and cleanup made possible by the improved core. Please test, I would not be surprised if I have fouled up some bit-manipulation somewhere in this mostly mechanical change... Changes since v1: - Rebased to next-20170621 - Split 1/11 into a preparatory patch, a cleanup patch and then the meat in 3/14. - Handle pseudo-palette for FB_VISUAL_TRUECOLOR. - Removed the empty .gamma_get/.gamma_set fb helpers from the armada driver that I had somehow managed to ignore but which 0day found real quick. - Be less judgemental on drivers only providing .gamma_get and .gamma_set, but no .load_lut. That's actually a valid thing to do if you only need pseudo-palette for FB_VISUAL_TRUECOLOR. - Add a comment about colliding bitfields in the nouveau driver. - Remove gamma_set/gamma_get declarations from the radeon driver (the definitions were removed in v1). Cheers, peda Peter Rosin (14): drm/fb-helper: keep the .gamma_store updated in drm_fb_helper_setcmap drm/fb-helper: remove drm_fb_helper_save_lut_atomic drm/fb-helper: do a generic fb_setcmap helper in terms of crtc .gamma_set drm: amd: remove dead code and pointless local lut storage drm: armada: remove dead empty functions drm: ast: remove dead code and pointless local lut storage drm: cirrus: remove dead code and pointless local lut storage drm: gma500: remove dead code and pointless local lut storage drm: i915: remove dead code and pointless local lut storage drm: mgag200: remove dead code and pointless local lut storage drm: nouveau: remove dead code and pointless local lut storage drm: radeon: remove dead code and pointless local lut storage drm: stm: remove dead code and pointless local lut storage drm: remove unused and redundant callbacks drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 24 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h| 1 - drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 27 ++--- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 27 ++--- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 27 ++--- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 27 ++--- drivers/gpu/drm/amd/amdgpu/dce_virtual.c| 23 drivers/gpu/drm/armada/armada_crtc.c| 10 -- drivers/gpu/drm/armada/armada_crtc.h| 2 - drivers/gpu/drm/armada/armada_fbdev.c | 2 - drivers/gpu/drm/ast/ast_drv.h | 1 - drivers/gpu/drm/ast/ast_fb.c| 20 drivers/gpu/drm/ast/ast_mode.c | 26 + drivers/gpu/drm/cirrus/cirrus_drv.h | 8 -- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 2 - drivers/gpu/drm/cirrus/cirrus_mode.c| 71 +++- drivers/gpu/drm/drm_fb_helper.c | 164 +--- drivers/gpu/drm/gma500/framebuffer.c| 22 drivers/gpu/drm/gma500/gma_display.c| 32 ++ drivers/gpu/drm/gma500/psb_intel_display.c | 7 +- drivers/gpu/drm/gma500/psb_intel_drv.h | 1 - drivers/gpu/drm/i915/intel_drv.h| 1 - drivers/gpu/drm/i915/intel_fbdev.c | 31 -- drivers/gpu/drm/mgag200/mgag200_drv.h | 5 - drivers/gpu/drm/mgag200/mgag200_fb.c| 2 - drivers/gpu/drm/mgag200/mgag200_mode.c | 62 +++ drivers/gpu/drm/nouveau/dispnv04/crtc.c | 26 ++--- drivers/gpu/drm/nouveau/nouveau_crtc.h | 3 - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 22 drivers/gpu/drm/nouveau/nv50_display.c | 40 +++ drivers/gpu/drm/radeon/atombios_crtc.c | 1 - drivers/gpu/drm/radeon/radeon_connectors.c | 7 +- drivers/gpu/drm/radeon/radeon_display.c | 71 +--- drivers/gpu/drm/radeon/radeon_fb.c | 2 - drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 1 - drivers/gpu/drm/radeon/radeon_mode.h| 4 - drivers/gpu/drm/stm/ltdc.c | 12 -- drivers/gpu/drm/stm/ltdc.h | 1 - include/drm/drm_fb_helper.h | 32 -- include/drm/drm_modeset_helper_vtables.h| 16 --- 40 files changed, 205 insertions(+), 658 deletions(-) -- 2.1.4
Re: [PATCH 01/11] drm/fb-helper: do a generic fb_setcmap helper in terms of crtc .gamma_set
On 2017-06-22 08:36, Daniel Vetter wrote: > On Wed, Jun 21, 2017 at 11:40:52AM +0200, Peter Rosin wrote: >> On 2017-06-21 09:38, Daniel Vetter wrote: >>> On Tue, Jun 20, 2017 at 09:25:25PM +0200, Peter Rosin wrote: >>>> This makes the redundant fb helpers .load_lut, .gamma_set and .gamma_get >>>> totally obsolete. >>>> >>>> I think the gamma_store can end up invalid on error. But the way I read >>>> it, that can happen in drm_mode_gamma_set_ioctl as well, so why should >>>> this pesky legacy fbdev stuff be any better? >>>> >>>> drm_fb_helper_save_lut_atomic justs saves the gamma lut for later. However, >>>> it saves it to the gamma_store which should already be up to date with what >>>> .gamma_get would return and is thus a nop. So, zap it. >>> >>> Removing drm_fb_helper_save_lut_atomic should be a separate patch I >>> think. >> >> Then 3 patches would be needed, first some hybrid thing that does it the >> old way, but also stores the lut in .gamma_store, then the split-out that >> removes drm_fb_helper_save_lut_atomic, then whatever is needed to get >> to the desired code. I can certainly do that, but do you want me to? > > Explain that in the commit message and it's fine. I did the split in v2, I assume that's ok too. Better in case anyone ever needs to run a bisect on this... >>> It's a pre-existing bug, but should we also try to restore the fbdev lut >>> in drm_fb_helper_restore_fbdev_mode_unlocked()? Would be yet another bug, >>> but might be relevant for your use-case. Just try to run both an fbdev >>> application and some kms-native thing, and then SIGKILL the native kms >>> app. >>> >>> But since pre-existing not really required, and probably too much effort. >> >> Good thing too, because I don't really know my way around this code... > > Btw I cc'ed you on one of my patches in the fbdev locking series, we might > need to do the same legacy vs. atomic split for the new lut code as I did > for dpms. The rule with atomic is that you can't do multiple commits under > drm_modeset_lock_all, you either have to do one overall atomic commit > (preferred) or drop&reacquire locks again. This matters for LUT since > you're updating the LUT on all CRTCs, which when using the gamma_set > atomic helper would be multiple commits :-/ Ahh, ok, I see the problem. > Using the dpms patch as template it shouldn't be too hard to address that > for your patch here too. Hmm, in that patch you handle the legacy case in a separate function, and doing that for the lut case looks difficult when the atomic commit happens inside the helper (typically drm_atomic_helper_legacy_gamma_set which could perhaps be handled, but a real drag to handle for drivers that have a custom crtc .gamma_set). So, I'm aiming for the drop&reacquire approach... However, I don't have all of that series, and I suspect that is why I do not have any fb_helper->lock. I'll send my best guess as a follow-up to patch 3/14 in v2. Cheers, peda
[PATCH v2 01/14] drm/fb-helper: keep the .gamma_store updated in drm_fb_helper_setcmap
I think the gamma_store can end up invalid on error. But the way I read it, that can happen in drm_mode_gamma_set_ioctl as well, so why should this pesky legacy fbdev stuff be any better? Signed-off-by: Peter Rosin --- drivers/gpu/drm/drm_fb_helper.c | 27 +++ 1 file changed, 27 insertions(+) This is an alternative version rebased on top of Daniels "fbdev helper locking rework and deferred setup" series. Cheers, peda diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index a4cfef9..c7122c9 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1330,12 +1330,16 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) const struct drm_crtc_helper_funcs *crtc_funcs; u16 *red, *green, *blue, *transp; struct drm_crtc *crtc; + u16 *r, *g, *b; int i, j, rc = 0; int start; if (oops_in_progress) return -EBUSY; + if (cmap->start + cmap->len < cmap->start) + return -EINVAL; + mutex_lock(&fb_helper->lock); if (!drm_fb_helper_is_bound(fb_helper)) { mutex_unlock(&fb_helper->lock); @@ -1353,6 +1357,29 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) transp = cmap->transp; start = cmap->start; + if (info->fix.visual != FB_VISUAL_TRUECOLOR) { + if (!crtc->gamma_size) { + rc = -EINVAL; + goto out; + } + + if (cmap->start + cmap->len > crtc->gamma_size) { + rc = -EINVAL; + goto out; + } + + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + + memcpy(r + cmap->start, cmap->red, + cmap->len * sizeof(u16)); + memcpy(g + cmap->start, cmap->green, + cmap->len * sizeof(u16)); + memcpy(b + cmap->start, cmap->blue, + cmap->len * sizeof(u16)); + } + for (j = 0; j < cmap->len; j++) { u16 hred, hgreen, hblue, htransp = 0x; -- 2.1.4
[PATCH v2 03/14] drm/fb-helper: do a generic fb_setcmap helper in terms of crtc .gamma_set
This makes the redundant fb helpers .load_lut, .gamma_set and .gamma_get totally obsolete. Signed-off-by: Peter Rosin --- drivers/gpu/drm/drm_fb_helper.c | 151 +--- 1 file changed, 63 insertions(+), 88 deletions(-) This is an alternative version rebased on top of Daniel's "fbdev helper locking rework and deferred setup" series. And as noted by Daniel, .gamma_set does an atomic commit. Thus, the locks needs to be dropped and reacquired for each crtc. So, that is fixed here too. Doing it like this with a couple of individual alternative patches instead of sending a whole new series since the dependency on Daniel's series makes life somewhat difficult... Cheers, peda diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 4aceb59..aa025f1 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1257,50 +1257,6 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked); -static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, -u16 blue, u16 regno, struct fb_info *info) -{ - struct drm_fb_helper *fb_helper = info->par; - struct drm_framebuffer *fb = fb_helper->fb; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 *palette; - u32 value; - /* place color in psuedopalette */ - if (regno > 16) - return -EINVAL; - palette = (u32 *)info->pseudo_palette; - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - if (info->var.transp.length > 0) { - u32 mask = (1 << info->var.transp.length) - 1; - - mask <<= info->var.transp.offset; - value |= mask; - } - palette[regno] = value; - return 0; - } - - /* -* The driver really shouldn't advertise pseudo/directcolor -* visuals if it can't deal with the palette. -*/ - if (WARN_ON(!fb_helper->funcs->gamma_set || - !fb_helper->funcs->gamma_get)) - return -EINVAL; - - WARN_ON(fb->format->cpp[0] != 1); - - fb_helper->funcs->gamma_set(crtc, red, green, blue, regno); - - return 0; -} - /** * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap * @cmap: cmap to set @@ -1310,12 +1266,10 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; - const struct drm_crtc_helper_funcs *crtc_funcs; - u16 *red, *green, *blue, *transp; + struct drm_modeset_acquire_ctx ctx; struct drm_crtc *crtc; u16 *r, *g, *b; - int i, j, rc = 0; - int start; + int i, ret = 0; if (oops_in_progress) return -EBUSY; @@ -1329,61 +1283,82 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) return -EBUSY; } - drm_modeset_lock_all(dev); - for (i = 0; i < fb_helper->crtc_count; i++) { - crtc = fb_helper->crtc_info[i].mode_set.crtc; - crtc_funcs = crtc->helper_private; + drm_modeset_acquire_init(&ctx, 0); - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - start = cmap->start; + for (i = 0; i < fb_helper->crtc_count; i++) { + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *palette; + int j; - if (info->fix.visual != FB_VISUAL_TRUECOLOR) { - if (!crtc->gamma_size) { - rc = -EINVAL; - goto out; + if (cmap->start + cmap->len > 16) { + ret = -EINVAL; + break; } - if (cmap->start + cmap->len > crtc->gamma_size) { - rc = -EINVAL; - goto out; + palette = (u32 *)info->pseudo_palette; + for (j = 0; j < cmap->len; ++j) { + u16 red = cmap->
Re: [PATCH v1 1/1] mux: mux-intel-usb: Add Intel USB Multiplexer driver
On 2017-05-30 02:47, sathyanarayanan.kuppusw...@linux.intel.com wrote: > From: Kuppuswamy Sathyanarayanan > > In some Intel SOCs, a single USB port is shared between USB device and > host controller and an internal mux is used to control the selection of > port by host/device controllers. This driver adds support for the USB > internal mux, and all consumers of this mux can use interfaces provided > by mux subsytem to control the state of the internal mux. > > Signed-off-by: Kuppuswamy Sathyanarayanan > Hi! A few things make me curious... 1. How are platform devices w/o any match table probed? Do you have to manually load them, or what? 2. What are these "all the consumers of this mux" that you mention, and how do they find the correct mux control to interact with? > --- > drivers/mux/Kconfig | 13 > drivers/mux/Makefile | 1 + > drivers/mux/mux-intel-usb.c | 132 > ++ > include/linux/mux/mux-intel-usb.h | 22 +++ > 4 files changed, 168 insertions(+) > create mode 100644 drivers/mux/mux-intel-usb.c > create mode 100644 include/linux/mux/mux-intel-usb.h > > diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig > index e8f1df7..0e3af09 100644 > --- a/drivers/mux/Kconfig > +++ b/drivers/mux/Kconfig > @@ -56,4 +56,17 @@ config MUX_MMIO > To compile the driver as a module, choose M here: the module will > be called mux-mmio. > > +config MUX_INTEL_USB > + tristate "Intel USB Mux" > + depends on USB Why depend on USB? > + help > + In some Intel SOCs, a single USB port is shared between USB > + device and host controller and an internal mux is used to > + control the selection of port by host/device controllers. This > + driver adds support for the USB internal mux, and all consumers > + of this mux can use interfaces provided by mux subsytem to control > + the state of the internal mux. > + > + To compile the driver as a module, choose M here. > + > endif > diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile > index 6bac5b0..9154616 100644 > --- a/drivers/mux/Makefile > +++ b/drivers/mux/Makefile > @@ -6,3 +6,4 @@ obj-$(CONFIG_MULTIPLEXER) += mux-core.o > obj-$(CONFIG_MUX_ADG792A)+= mux-adg792a.o > obj-$(CONFIG_MUX_GPIO) += mux-gpio.o > obj-$(CONFIG_MUX_MMIO) += mux-mmio.o > +obj-$(CONFIG_MUX_INTEL_USB) += mux-intel-usb.o Alphabetical order, please. > diff --git a/drivers/mux/mux-intel-usb.c b/drivers/mux/mux-intel-usb.c > new file mode 100644 > index 000..587e9bb > --- /dev/null > +++ b/drivers/mux/mux-intel-usb.c > @@ -0,0 +1,132 @@ > +/* > + * Intel USB Multiplexer Driver > + * > + * Copyright (C) 2017 Intel Corporation > + * > + * Author: Kuppuswamy Sathyanarayanan > + * > + * This driver is written based on extcon-intel-usb driver submitted by > + * Heikki Krogerus > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include Alphabetical order, please. > + > +#define INTEL_MUX_CFG0 0x00 > +#define INTEL_MUX_CFG1 0x04 > + > +#define CFG0_SW_DRD_MODE_MASK0x3 > +#define CFG0_SW_DRD_DYN 0 > +#define CFG0_SW_DRD_STATIC_HOST 1 > +#define CFG0_SW_DRD_STATIC_DEV 2 > +#define CFG0_SW_SYNC_SS_AND_HS BIT(2) > +#define CFG0_SW_SWITCH_ENBIT(16) > +#define CFG0_SW_IDPINBIT(20) > +#define CFG0_SW_IDPIN_EN BIT(21) > +#define CFG0_SW_VBUS_VALID BIT(24) > + > +#define CFG1_MODEBIT(29) > + > +struct mux_intel_usb { > + struct device *dev; > + void __iomem *regs; > +}; > + > +static int mux_intel_usb_set(struct mux_control *mux_ctrl, int state) > +{ > + struct mux_intel_usb *mux = mux_chip_priv(mux_ctrl->chip); > + u32 val; > + > + dev_info(mux->dev, "Intel USB mux set called"); Isn't this very spammy? Cheers, peda > + > + switch (state) { > + case INTEL_USB_MUX_STATE_HOST: > + val = CFG0_SW_IDPIN_EN | CFG0_SW_DRD_STATIC_HOST; > + break; > + case INTEL_USB_MUX_STATE_DEVICE: > + val = CFG0_SW_IDPIN_EN | CFG0_SW_IDPIN | CFG0_SW_VBUS_VALID | > + CFG0_SW_DRD_STATIC_DEV; > + break; > + default: > + return 0; > + }; > + > + writel(val, mux->regs); > + > + return 0; > +} > + > +static const struct mux_control_ops mux_intel_usb_ops = { > + .set = mux_intel_usb_set, > +}; > + > +static int mux_intel_usb_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct mux_chip *mux_chip; > + struct mux_intel_usb *mux; > + struct resource *res; > + int ret; > + > +
Re: Sluggish AT91 I2C driver causes SMBus timeouts
Hi Ludovic, On 2017-10-17 09:58, Ludovic Desroches wrote: > Hi Peter, > > On Fri, Oct 13, 2017 at 05:01:04PM +0200, Peter Rosin wrote: >> On 2017-10-13 15:29, Alan Cox wrote: >>> On Thu, 12 Oct 2017 13:35:17 +0200 >>> Peter Rosin wrote: >>> >>>> Hi! >>>> >>>> I have encountered an "interesting" bug. It silently corrupts data >>>> and is generally nasty... >>>> >>>> On an I2C bus, driven by the at91 driver and DMA (an Atmel >>>> sama5d31 chip), I have an 256 byte eeprom (NXP SE97BTP). I'm using >>>> Linux v4.13. >>> >>> If your force the transfer to PIO does it behave ? Does the controller in >>> fact need to siwtch to PIO for SMBUS ? >> >> Like, what if I disable DMA? >> >> I saw no way to do that, short of short-cutting a few things in the >> driver code. So, did that and I cannot tickle the bug. But I don't >> know if that makes me safe? >> >> Ludovic, any reason to believe disabling DMA will prevent these >> stalls, or will they just appear under different circumstances? > > Sorry I am currently on vacation. I outlined this discussion. And I got buried in other stuff so I managed to ignore and then forget this for a couple of days. Sorry for the delay... > As you noticed, there are some hardware constraints when using DMA. > Switching from DMA to PIO to handle the end of the transfer is probably the > root cause of the delay you get. > > I read you added traces, did you manage to get some information about > timings? Do we waste time waiting for the dma callback? for the RXRDY > interrupt? I *think* the stalls I'm seeing are from the dma callback. > If we spend time waiting for the dma callback for sure, disabling DMA > should prevent these stalls. If the stall is inbetween the two last > RXRDY interrupts, it seems it can appear under different circumstances. Exactly my point. It is hard to tell for sure. If we don't do dma, there is simply no guarantee that the problem goes away. I fear that disabling dma will only make the problem less likely, and that it therefore is not a real fix. I can test this any number of times, and Murphy will make sure that it doesn't trigger. Until it's in the hands of the customer... The smbus timeout is quite hard to handle when there is no way to guarantee that deadlines are met. The way I see it, the only safe option is to disable the smbus timeout. I prefer that over killing dma completely. See my patches that take that approach (sorry for not having you on the cc list) https://lkml.org/lkml/2017/10/13/184 >> >> I used this dirty "patch" to i2c-at91.c:at91_twi_configure_dma() for >> testing: >> >> -dev->use_dma = true; >> +//dev->use_dma = true; >> > > You can simply remove dma bindings from the i2c node to force the i2c > controller to use the PIO mode. Ok, that's less intrusive... Cheers, Peter
Re: [PATCH 1/2] hwmon: (jc42) optionally try to disable the SMBUS timeout
On 2017-10-18 04:38, Guenter Roeck wrote: > On 10/17/2017 03:16 PM, Rob Herring wrote: >> On Fri, Oct 13, 2017 at 01:35:27PM -0700, Guenter Roeck wrote: >>> On Fri, Oct 13, 2017 at 04:26:57PM +0200, Peter Rosin wrote: >>>> On 2017-10-13 15:50, Guenter Roeck wrote: >>>>> On 10/13/2017 02:27 AM, Peter Rosin wrote: >>>>>> With a nxp,se97 chip on an atmel sama5d31 board, the I2C adapter driver >>>>>> is not always capable of avoiding the 25-35 ms timeout as specified by >>>>>> the SMBUS protocol. This may cause silent corruption of the last bit of >>>>>> any transfer, e.g. a one is read instead of a zero if the sensor chip >>>>>> times out. This also affects the eeprom half of the nxp-se97 chip, where >>>>>> this silent corruption was originally noticed. Other I2C adapters >>>>>> probably >>>>>> suffer similar issues, e.g. bit-banging comes to mind as risky... >>>>>> >>>>>> The SMBUS register in the nxp chip is not a standard Jedec register, but >>>>>> it is not special to the nxp chips either, at least the atmel chips >>>>>> have the same mechanism. Therefore, do not special case this on the >>>>>> manufacturer, it is opt-in via the device property anyway. >>>>>> >>>>>> Signed-off-by: Peter Rosin >>>>>> --- >>>>>>Documentation/devicetree/bindings/hwmon/jc42.txt | 4 >>>>>>drivers/hwmon/jc42.c | 20 >>>>>> >>>>>>2 files changed, 24 insertions(+) >>>>>> >>>>>> diff --git a/Documentation/devicetree/bindings/hwmon/jc42.txt >>>>>> b/Documentation/devicetree/bindings/hwmon/jc42.txt >>>>>> index 07a250498fbb..f569db58f64a 100644 >>>>>> --- a/Documentation/devicetree/bindings/hwmon/jc42.txt >>>>>> +++ b/Documentation/devicetree/bindings/hwmon/jc42.txt >>>>>> @@ -34,6 +34,10 @@ Required properties: >>>>>> >>>>>>- reg: I2C address >>>>>> >>>>>> +Optional properties: >>>>>> +- smbus-timeout-disable: When set, the smbus timeout function will be >>>>>> disabled. >>>>>> + This is not supported on all chips. >> >> Is this only for jc24 devices or could be any smbus device? >> > > SMBus timeout is a standard SMBus functionality, so I would say any. It is by > default enabled on an SMBus device (actually it is not just enabled, it is > mandatory). The ability to disable it comes handy if a SMBus chip is connected > to an I2C controller which does not (or not necessarily) follow SMBus rules. > > I had seen that problem myself with MAX6697, and STTS751 (and its driver) also > supports it. So, is the approach with an optional smbus-timeout-disable property documented in .../bindings/hwmon/jc42.txt good-to-go or should it be documented in some common SMBus client-device file? I don't fine any such beast, so I'm unsure how to proceed in that case. Cheers, Peter
Re: [PATCH] drm/stm: ltdc: add clut mode support
On 2017-11-10 17:12, Philippe CORNU wrote: > Hi Peter, > > On 11/07/2017 05:34 PM, Peter Rosin wrote: >> On 2017-11-07 16:53, Philippe CORNU wrote: >>> + Peter >>> >>> Hi Peter, >>> >>> CLUT support on STM32 has been removed thanks to your clean up patch >> >> Support is a bit strong for what I thought was a dead function, or >> are you saying that it used to work before my series? Really sorry >> if that is the case! > > As I wrote in the previous related thread > (https://lists.freedesktop.org/archives/dri-devel/2017-June/145070.html), > STM32 chipsets supports 8-bit CLUT mode but this driver version does not > support it "yet"... > > So, no worry regarding your clean up, I gave you an "acked-by" for that : ) Ok, good. Thanks for clearing that up! >> >> Anyway, the function I removed seemed to indicate that the hardware >> could handle a separate clut for each layer, but your new version >> does not. Why is that? > > Yes I confirm the clut support is available for each layer... but I > thought the gamma_lut was only at the crtc level, not at layer level... > Maybe I am wrong. > Moreover, small test applications I used play only with clut at crtc > level... > > Anyway, could you please help me to "find" a per-layer clut > implementation because when I read "crtc->state->gamma_lut->data" it > looks like gamma_lut is per crtc, not per plane...? or maybe I have to > add extra properties for that... I wasn't clear enough. Yes, there is to my knowledge only one clut, not one per plane. What I noticed was that the function I removed seemed to touch clut registers for multiple layers, but your new function appears to only touch registers for one layer. So, I wondered if the "one and only" clut needed to be copied to the registers for the other layers, or if the old dead code was simply confused. Clearer? Cheers. Peter
Re: [PULL REQUEST] i2c-mux for 4.15-rc1
On 2017-10-27 21:27, Wolfram Sang wrote: > Hi Peda, > >> This cycle has been real quiet for me. There's only the one trivial patch >> that somewhat simplifies DT parsing in the i2c-mux-reg driver. > > Did this maybe slip through the cracks? > > http://patchwork.ozlabs.org/patch/816846/ > > ("[trivial] dt-bindings: i2c: i2c-mux: Spelling s/required is/required > if/") Right. Blush. I blame the immense flow of patches. I just can't seem to keep up... :-) Anyway, thanks for catching this and sorry for making you do that. Some words for the merge commit: This trivial patch managed to fall through the cracks and was forgotten in the first pull request, as noticed by Wolfram. Thanks. Please pull. Cheers, Peter The following changes since commit 3997fb74846f35d0364c5e88e54bc9b166d5a1bc: i2c: mux: reg: use of_property_read_bool() (2017-10-20 16:33:07 +0200) are available in the git repository at: https://github.com/peda-r/i2c-mux.git tags/i2c-mux/for-4.15-2 for you to fetch changes up to fcc046801b934ad27ba80e20e3e0f4c97957af58: dt-bindings: i2c: i2c-mux: spelling s/required is/required if/ (2017-10-27 22:45:28 +0200) Geert Uytterhoeven (1): dt-bindings: i2c: i2c-mux: spelling s/required is/required if/ Documentation/devicetree/bindings/i2c/i2c-mux.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Re: [PULL REQUEST] i2c-mux for 4.15-rc1
On 2017-10-28 14:25, Wolfram Sang wrote: > >> Right. Blush. I blame the immense flow of patches. I just can't seem to >> keep up... :-) Anyway, thanks for catching this and sorry for making you >> do that. > > No worries. Patchwork makes it easy for me to track patches. Speaking > of, if you register at patchwork.ozlabs.org, then I could assign you the > patches for the mux subsystem. Then you'd have the patches listed. Just > saying... Sounds like a splendid idea. I signed up as 'peda'. Do you need anything else? Cheers, Peter
Re: Regression: at24 eeprom writing
On 2015-10-05 17:00, Ludovic Desroches wrote: > Hi Peter > > On Mon, Oct 05, 2015 at 10:45:29AM +0200, Peter Rosin wrote: >> On 2015-10-03 01:05, Peter Rosin wrote: > > [...] > >> Ok, I found the culprit, and I double and triple checked it this time... >> >> If I move to the very latest on the linux-3.18-at91 branch, the bug is >> there too. Which made it vastly more palatable to bisect the bug. >> >> The offender (in the 4.2 kernel) is 93563a6a71bb69dd324fc7354c60fb05f84aae6b >> "i2c: at91: fix a race condition when using the DMA controller" >> which is far more understandable. Ao, adding Cyrille Pitchen to the Cc list. >> > > Thanks for the bisecting effort. I am currently at ELCE where I have > met someone with the same kind of issue. Is it easily reproducible? It > doesn't seem to be the case for him. Yes, easy as pie, happens on every eeprom write of 256 bytes so far... > I'll have a look once back. Ok good, to further help understanding, I'm seeing this on the i2c bus (I hope you understand the notation, or just ask): Working (4.2 + the revert from my previous message) === S W50 0x00 "product = 1-776-" P S W50 NACK P S W50 NACK P delay 15.2 ms S W50 0x10 "3.0\n" P delay 19.5 ms S W50 0x10 "3.0\n" P S W50 NACK P S W50 NACK P S W50 NACK P delay 19.0 ms S W50 0x14 "serial = 380" P delay 18.8 ms S W50 0x14 "serial = 380" P S W50 NACK P S W50 NACK P delay 18.4 ms S W50 0x20 "02\n" P delay 19.2 ms S W50 0x20 "02\n" P delay 10.8 ms S W50 0x27 " " P S W50 NACK P (repeated 5 times) delay 16.7 ms S W50 0x30 "" P delay 18.4 ms S W50 0x30 "" P S W50 NACK P (repeated 3 times) delay 17.9 ms S W50 0x40 "" P etc I.e. every write (but the first) seems to fail the first time and is then retried, even if the i2c bus shows no failure indication (at least that I can find). Not working (vanilla 4.2) = S W50 0x00 "product = 1-776-" P S W50 NACK P S W50 NACK P delay 17.3 ms S W50 0x10 ACK... delay 19.8 with both SDA and SCL low ...ACK 0x10 "3.0\n" P S W50 NACK P S W50 NACK P delay 19.3 ms S W50 0x14 "serial = 380" P S W50 NACK P S W50 NACK P delay 18.5 ms S W50 0x20 ACK... delay 19.9 with both SDA and SCL low ...ACK 0x20 "02\n" P S W50 NACK P S W50 NACK P delay 18.9 ms S W50 0x27 " " P S W50 NACK P S W50 NACK P delay 19.2 ms S W50 0x30 "" P S W50 NACK P S W50 NACK P delay 17.6 ms S W50 0x40 "" P S W50 NACK P S W50 NACK P etc I.e. when there is a disturbance (the long ACks) the recovery mechanism appears to attempt to heal it by resending only the failing byte, but the eeprom appears to not see the failure and takes both bytes instead of just the resend. It seems dangerous to attempt to fix apparent trouble with an i2c command by anything less than a full retry, like the working version appears to do. No? But what trouble does the i2c bus driver see? Admittedly I only have a simple logic level bus viewer, and not a full-blown oscilloscope, so there might be something analogue going on? I don't think so though, those signals looked fine last time we looked (but we obviously didn't have these issues then, and didn't really look that closely). I'll see if I can recheck with a real scope too. Cheers, Peter -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Regression: at24 eeprom writing
On 2015-10-05 17:28, Cyrille Pitchen wrote: > Le 05/10/2015 10:45, Peter Rosin a écrit : >> On 2015-10-03 01:05, Peter Rosin wrote: >>> Hi! >>> >>> I recently upgraded from the atmel linux-3.18-at91 kernel to vanilla 4.2 >>> and everything seemed fine. Until I tried to write to the little eeprom >>> chip. I then tried the linux-4.1-at91 kernel and that suffers too. >>> >>> The symptoms are that it seems like writes get interrupted, and restarted >>> again without properly initializing everything again. Inspecting the i2c >>> bus during these fails gets me something like this (int hex) when I >>> >>> echo abcdefghijklmnopqr > /sys/bus/i2c/devices/0-0050/eeprom >>> >>> S a0 00 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 P >>> S a0 10 (clk and data low for a "long" time) 10 71 72 0a P >>> >>> Notice how the address byte in the second chunk (10) is repeated after >>> the strange event on the i2c bus. >>> >>> I looked around and found that if I revert >>> a839ce663b3183209fdf7b1fc4796bfe2a4679c3 >>> "eeprom: at24: extend driver to allow writing via i2c_smbus_write_byte_data" >>> eeprom writing starts working again. >>> >>> AFAICT, the i2c-at91 bus driver makes the eeprom driver use the >>> i2c_transfer code path both with that patch and with it reverted, >>> so I sadly don't see why the patch makes a difference. >>> >>> I'm on a board that is based on the sama5d31 evaluation kit, with a >>> NXP SE97BTP,547 chip and this in the devicetree: >>> >>> i2c0: i2c@f0014000 { >>> status = "okay"; >>> >>> jc42@18 { >>> compatible = "jc42"; >>> reg = <0x18>; >>> }; >>> >>> eeprom@50 { >>> compatible = "24c02"; >>> reg = <0x50>; >>> pagesize = <16>; >>> }; >>> }; >> >> Ok, I found the culprit, and I double and triple checked it this time... >> >> If I move to the very latest on the linux-3.18-at91 branch, the bug is >> there too. Which made it vastly more palatable to bisect the bug. >> >> The offender (in the 4.2 kernel) is 93563a6a71bb69dd324fc7354c60fb05f84aae6b >> "i2c: at91: fix a race condition when using the DMA controller" >> which is far more understandable. Ao, adding Cyrille Pitchen to the Cc list. >> >> If I add that patch on top of my previously working tree, it behaves just >> as newer kernels, i.e. equally bad. The patch doesn't revert cleanly, but >> reverting the patch and quick-n-dirty-fixing the conflict on vanilla 4.2 >> makes the problem go away. >> >> I have attached what I actually reverted. >> >> Cheers, >> Peter >> > > Hi Peter, > > Can you tell me whether your device tree sets the I2C controller i2c0 to use > dma channels, especially the "tx" one. I guess so but it is just to confirm > hence we look in the right direction. I think yes, I'm including sama5d3.dtsi and am not overriding anything interesting in that area. > Then I think we should look at this part of the original patch: > > } else { > if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) { > + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK); > at91_twi_write_data_dma(dev); > - at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); > } else { > at91_twi_write_next_byte(dev); > at91_twi_write(dev, AT91_TWI_IER, > > Here, for DMA TX transfers, we enable the NACK interrupt instead of the TXCOMP > one. This is the actual fix of the DMA race. Indeed there were two issues when > using TXCOMP to detect NACK conditions. > > As written in the datasheet and confirmed by the IP designer, the TXCOMP bit > is > set in the Status Register when both the Transmit Holding Register (THR) and > its internal shifter are empty and the STOP condition has been sent. > So when a first transfer successfully completes, the TXCOMP bit is set. Then > this bit remains set until the next write into THR. > > T
Re: Regression: at24 eeprom writing
On 2015-10-05 08:16, Christian Gmeiner wrote: > Hi Peter. > > Sorry for the late answer - I am currently on my way to Dublin. Maybe > it helps if you enable > I2C_DEBUG_CORE and I2C_DEBUG_BUS. In theory you should see a little > bit better what > happens on the bus. Good suggestion. I did a new run (vanilla 4.2), and this is what I saw on the bus this time: [0.0] S W50 0x00 "product = 1-776-" P [0.00184] S W50 NACK P [0.00195] S W50 NACK P [0.02027] S W50 0x10 ACK... [0.04035] ...ACK 0x10 "3.0\n" P [0.04100] S W50 NACK P [0.04111] S W50 NACK P [0.06032] S W50 "serial = 380" P [0.06174] S W50 NACK P [0.06185] S W50 NACK P [0.08032] S W50 0x20 ACK... [0.10034] ...ACK 0x20 "02\n" P [0.10127] S W50 NACK P [0.10138] S W50 NACK P [0.12039] S W50 0x27 " " P [0.12155] S W50 NACK P [0.12166] S W50 NACK P [0.14040] S W50 0x30 "" P [0.14219] S W50 NACK P [0.14230] S W50 NACK P [0.16042] S W50 0x40 "" P ... And this is the corresponding part of the log from the same run (offset ~197.79 s): [ 197.79] i2c i2c-0: master_xfer[0] W, addr=0x50, len=17 [ 197.79] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.79] at91_i2c f0014000.i2c: transfer: write 17 bytes. [ 197.80] at91_i2c f0014000.i2c: transfer complete [ 197.80] i2c i2c-0: master_xfer[0] W, addr=0x50, len=5 [ 197.80] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.80] at91_i2c f0014000.i2c: transfer: write 5 bytes. [ 197.80] at91_i2c f0014000.i2c: wrote 0x10, to go 4 [ 197.80] at91_i2c f0014000.i2c: wrote 0x33, to go 3 [ 197.80] at91_i2c f0014000.i2c: received nack [ 197.82] i2c i2c-0: master_xfer[0] W, addr=0x50, len=5 [ 197.82] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.82] at91_i2c f0014000.i2c: transfer: write 5 bytes. [ 197.82] at91_i2c f0014000.i2c: wrote 0x10, to go 4 [ 197.82] at91_i2c f0014000.i2c: received nack [ 197.84] i2c i2c-0: master_xfer[0] W, addr=0x50, len=5 [ 197.84] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.84] at91_i2c f0014000.i2c: transfer: write 5 bytes. [ 197.84] at91_i2c f0014000.i2c: wrote 0x10, to go 4 [ 197.84] at91_i2c f0014000.i2c: wrote 0x33, to go 3 [ 197.84] at91_i2c f0014000.i2c: wrote 0x2e, to go 2 [ 197.84] at91_i2c f0014000.i2c: wrote 0x30, to go 1 [ 197.84] at91_i2c f0014000.i2c: wrote 0xa, to go 0 [ 197.84] at91_i2c f0014000.i2c: transfer complete [ 197.84] i2c i2c-0: master_xfer[0] W, addr=0x50, len=13 [ 197.84] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.84] at91_i2c f0014000.i2c: transfer: write 13 bytes. [ 197.84] at91_i2c f0014000.i2c: received nack [ 197.86] i2c i2c-0: master_xfer[0] W, addr=0x50, len=13 [ 197.86] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.86] at91_i2c f0014000.i2c: transfer: write 13 bytes. [ 197.86] at91_i2c f0014000.i2c: transfer complete [ 197.86] i2c i2c-0: master_xfer[0] W, addr=0x50, len=8 [ 197.86] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.86] at91_i2c f0014000.i2c: transfer: write 8 bytes. [ 197.86] at91_i2c f0014000.i2c: wrote 0x20, to go 7 [ 197.86] at91_i2c f0014000.i2c: wrote 0x30, to go 6 [ 197.86] at91_i2c f0014000.i2c: received nack [ 197.88] i2c i2c-0: master_xfer[0] W, addr=0x50, len=8 [ 197.88] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.88] at91_i2c f0014000.i2c: transfer: write 8 bytes. [ 197.88] at91_i2c f0014000.i2c: wrote 0x20, to go 7 [ 197.88] at91_i2c f0014000.i2c: received nack [ 197.90] i2c i2c-0: master_xfer[0] W, addr=0x50, len=8 [ 197.90] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.90] at91_i2c f0014000.i2c: transfer: write 8 bytes. [ 197.90] at91_i2c f0014000.i2c: wrote 0x20, to go 7 [ 197.90] at91_i2c f0014000.i2c: wrote 0x30, to go 6 [ 197.90] at91_i2c f0014000.i2c: wrote 0x30, to go 5 [ 197.90] at91_i2c f0014000.i2c: wrote 0x30, to go 4 [ 197.90] at91_i2c f0014000.i2c: wrote 0x30, to go 3 [ 197.90] at91_i2c f0014000.i2c: wrote 0x30, to go 2 [ 197.90] at91_i2c f0014000.i2c: wrote 0x32, to go 1 [ 197.90] at91_i2c f0014000.i2c: wrote 0xa, to go 0 [ 197.90] at91_i2c f0014000.i2c: transfer complete [ 197.90] i2c i2c-0: master_xfer[0] W, addr=0x50, len=10 [ 197.90] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.90] at91_i2c f0014000.i2c: transfer: write 10 bytes. [ 197.90] at91_i2c f0014000.i2c: received nack [ 197.92] i2c i2c-0: master_xfer[0] W, addr=0x50, len=10 [ 197.92] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.92] at91_i2c f0014000.i2c: transfer: write 10 bytes. [ 197.92] at91_i2c f0014000.i2c: transfer complete [ 197.92] i2c i2c-0: master_xfer[0] W, addr=0x50, len=17 [ 197.92] i2c i2c-0: at91_xfer: processing 1 messages: [ 197.92] at91_i2c f0014000.i2c: transfer: write 17 bytes. [ 197.92] at91_i2c f0014000.i2c: rec
Re: Regression: at24 eeprom writing
On 2015-10-05 17:09, Peter Rosin wrote: > But what trouble does the i2c bus driver see? Admittedly I only > have a simple logic level bus viewer, and not a full-blown > oscilloscope, so there might be something analogue going on? > I don't think so though, those signals looked fine last time we > looked (but we obviously didn't have these issues then, and > didn't really look that closely). I'll see if I can recheck > with a real scope too. We redid the tests with a real scope, and the signal looks nice and square, so it is not that. Speculating further on the cause of the long ACKs, I think that the i2c driver gets confused by an interrupt that marks the transfer complete, and thinks it's a NACK interrupt instead. Is that plausible? If the peripheral unit is such that it generates a stop automatically on NACKs, then this makes perfect sense. I.e. the TWI sees that the transfer is complete, generates an interrupt, and waits for further data or a stop command. Meanwhile the driver thinks it's a NACK and that a stop condition has already been sent to the bus, and just notifies the i2c consumer (the eeprom driver in this case) of the failure and frees up the bus for any future user. This also matches what I see when I turn on some more traffic on the bus, that is interleaved with the eeprom traffic. AFAICT, it can be any command that gets chewed up by the eeprom if it is sent to the i2c driver during the long ACK. Are you Atmel people making any progress on this data corrupting regression? Is there anything else I can do to help? Cheers, Peter -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Regression: at24 eeprom writing
On 2015-10-12 18:13, Cyrille Pitchen wrote: > Le 12/10/2015 17:13, Peter Rosin a écrit : >> On 2015-10-05 17:09, Peter Rosin wrote: >>> But what trouble does the i2c bus driver see? Admittedly I only >>> have a simple logic level bus viewer, and not a full-blown >>> oscilloscope, so there might be something analogue going on? >>> I don't think so though, those signals looked fine last time we >>> looked (but we obviously didn't have these issues then, and >>> didn't really look that closely). I'll see if I can recheck >>> with a real scope too. >> >> We redid the tests with a real scope, and the signal looks nice >> and square, so it is not that. >> >> Speculating further on the cause of the long ACKs, I think that >> the i2c driver gets confused by an interrupt that marks the >> transfer complete, and thinks it's a NACK interrupt instead. Is that >> plausible? >> >> If the peripheral unit is such that it generates a stop automatically >> on NACKs, then this makes perfect sense. I.e. the TWI sees that the >> transfer is complete, generates an interrupt, and waits for further >> data or a stop command. Meanwhile the driver thinks it's a NACK and >> that a stop condition has already been sent to the bus, and just >> notifies the i2c consumer (the eeprom driver in this case) of the >> failure and frees up the bus for any future user. >> >> This also matches what I see when I turn on some more traffic on the >> bus, that is interleaved with the eeprom traffic. AFAICT, it can be >> any command that gets chewed up by the eeprom if it is sent to the >> i2c driver during the long ACK. >> >> Are you Atmel people making any progress on this data corrupting >> regression? Is there anything else I can do to help? >> >> Cheers, >> Peter >> > > Hi Peter, > > I have sent a patch to Ludovic for a first internal review before publishing > to > mainline. The patch should fix your issue since it fixes it on my sama5d36ek > board with an at24 eeprom. > > More details on the reason of this bug would be provided in both the commit > message and comments in the code provided by the reviewed patch but I you want > an early fix just read the Status Register (AT91_TWI_SR) at the beginning of > at91_do_twi_transfer(). This read clears the NACK bit in the Status Register. > Then the following source code can safely enable the NACK interrupt, otherwise > in some cases a pending NACK interrupt would rise immediately after the line: > at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK); > hence breaking the sequence of operations to be done because the interrupt > handler would call complete() too early so wait_for_completion_timeout() > also exits too early. > > So reading the Status Register at the beginning of at91_do_twi_transfer() > should be enough to fix the issue. Yes, I see no more long ACKs after that reading the Status Register there. Great! > Another mistake is in the interrupt handler itself, ie atmel_twi_interrupt(): > we should check the TWI_TXRDY status bit before calling > at91_twi_write_next_byte() only if both the TWI_TXCOMP and TWI_NACK status > bits > are clear. Otherwise, writing a new byte into the THR tells the I2C controller > to start a new transfer. Then the I2C slave, the at24 eeprom, is likely to > also reply by a second NACK. Hence the NACK bit is already set into the Status > Register on the next call of at91_do_twi_transfer(). > This is what I saw on my scope for PIO transfers. I interpret this as a proposed solution for the strange double NACKs? Anyway, I find it unnecessarily hard to grasp exactly what you mean (wasteful policy you are apparently suffering from where it is OK to publish a patch written in English, but apparently a big no-no to send a diff until it passes some internal review???). I interpreted your "patch" in English as: at91_twi_read_next_byte(dev); - else if (irqstatus & AT_TWI_TXRDY) + else if ((irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_TXRDY | AT91_TWI_NACK)) == AT91_TWI_TXRDY) at91_twi_write_next_byte(dev); But still see some double NACKs. Not always though, and it doesn't wreak any havoc. But it still looks strange and I can't explain them when looking at what the eeprom driver requests. Does this mean that there are more races present? Or, did I just parse your English "patch" badly? > By the way, in my case, the first NACK occurs because the at24 driver tries to > perform a second write transfer too quickly and the eeprom is not ready yet, > then replies with a NACK. Yes, I believe this is by design. Noone wants to encod
Re: Regression: at24 eeprom writing
On 2015-10-13 14:57, Nicolas Ferre wrote: > Le 13/10/2015 12:38, Peter Rosin a écrit : >> On 2015-10-12 18:13, Cyrille Pitchen wrote: >>> Le 12/10/2015 17:13, Peter Rosin a écrit : >>>> On 2015-10-05 17:09, Peter Rosin wrote: >>>>> But what trouble does the i2c bus driver see? Admittedly I only >>>>> have a simple logic level bus viewer, and not a full-blown >>>>> oscilloscope, so there might be something analogue going on? >>>>> I don't think so though, those signals looked fine last time we >>>>> looked (but we obviously didn't have these issues then, and >>>>> didn't really look that closely). I'll see if I can recheck >>>>> with a real scope too. >>>> >>>> We redid the tests with a real scope, and the signal looks nice >>>> and square, so it is not that. >>>> >>>> Speculating further on the cause of the long ACKs, I think that >>>> the i2c driver gets confused by an interrupt that marks the >>>> transfer complete, and thinks it's a NACK interrupt instead. Is that >>>> plausible? >>>> >>>> If the peripheral unit is such that it generates a stop automatically >>>> on NACKs, then this makes perfect sense. I.e. the TWI sees that the >>>> transfer is complete, generates an interrupt, and waits for further >>>> data or a stop command. Meanwhile the driver thinks it's a NACK and >>>> that a stop condition has already been sent to the bus, and just >>>> notifies the i2c consumer (the eeprom driver in this case) of the >>>> failure and frees up the bus for any future user. >>>> >>>> This also matches what I see when I turn on some more traffic on the >>>> bus, that is interleaved with the eeprom traffic. AFAICT, it can be >>>> any command that gets chewed up by the eeprom if it is sent to the >>>> i2c driver during the long ACK. >>>> >>>> Are you Atmel people making any progress on this data corrupting >>>> regression? Is there anything else I can do to help? >>>> >>>> Cheers, >>>> Peter >>>> >>> >>> Hi Peter, >>> >>> I have sent a patch to Ludovic for a first internal review before >>> publishing to >>> mainline. The patch should fix your issue since it fixes it on my sama5d36ek >>> board with an at24 eeprom. >>> >>> More details on the reason of this bug would be provided in both the commit >>> message and comments in the code provided by the reviewed patch but I you >>> want >>> an early fix just read the Status Register (AT91_TWI_SR) at the beginning of >>> at91_do_twi_transfer(). This read clears the NACK bit in the Status >>> Register. >>> Then the following source code can safely enable the NACK interrupt, >>> otherwise >>> in some cases a pending NACK interrupt would rise immediately after the >>> line: >>> at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK); >>> hence breaking the sequence of operations to be done because the interrupt >>> handler would call complete() too early so wait_for_completion_timeout() >>> also exits too early. >>> >>> So reading the Status Register at the beginning of at91_do_twi_transfer() >>> should be enough to fix the issue. >> >> Yes, I see no more long ACKs after that reading the Status Register there. >> Great! >> >>> Another mistake is in the interrupt handler itself, ie >>> atmel_twi_interrupt(): >>> we should check the TWI_TXRDY status bit before calling >>> at91_twi_write_next_byte() only if both the TWI_TXCOMP and TWI_NACK status >>> bits >>> are clear. Otherwise, writing a new byte into the THR tells the I2C >>> controller >>> to start a new transfer. Then the I2C slave, the at24 eeprom, is likely to >>> also reply by a second NACK. Hence the NACK bit is already set into the >>> Status >>> Register on the next call of at91_do_twi_transfer(). >>> This is what I saw on my scope for PIO transfers. >> >> I interpret this as a proposed solution for the strange double NACKs? >> >> Anyway, I find it unnecessarily hard to grasp exactly what you mean >> (wasteful policy you are apparently suffering from where it is OK to >> publish a patch written in English, but apparently a big no-no to >> send a diff until it passes some internal review???). I interpreted > > I find y
Re: [PATCH] i2c: at91: fix write transfers by clearing pending interrupt first
On 2015-10-13 16:21, Ludovic Desroches wrote: > From: Cyrille Pitchen > > In some cases a NACK interrupt may be pending in the Status Register (SR) > as a result of a previous transfer. However at91_do_twi_transfer() did not > read the SR to clear pending interruptions before starting a new transfer. > Hence a NACK interrupt rose as soon as it was enabled again at the I2C > controller level, resulting in a wrong sequence of operations and strange > patterns of behaviour on the I2C bus, such as a clock stretch followed by > a restart of the transfer. > > This first issue occurred with both DMA and PIO write transfers. > > Also when a NACK error was detected during a PIO write transfer, the > interrupt handler used to wrongly start a new transfer by writing into the > Transmit Holding Register (THR). Then the I2C slave was likely to reply > with a second NACK. > > This second issue is fixed in atmel_twi_interrupt() by handling the TXRDY > status bit only if both the TXCOMP and NACK status bits are cleared. > > Tested with a at24 eeprom on sama5d36ek board running a linux-4.1-at91 > kernel image. Adapted to linux-next. > > Signed-off-by: Cyrille Pitchen > Fixes: 93563a6a71bb ("i2c: at91: fix a race condition when using the DMA > controller") > Reported-by: Peter Rosin > Signed-off-by: Ludovic Desroches > Cc: sta...@vger.kernel.org #4.1 The regression is gone with this patch (vanilla 4.2), thank you! However, looking at the bus, there are two NACKs after each successful chunk of memory written by the eeprom driver. Looking at the eeprom driver, I expect this on the bus: S 0x50 0x00 "hello there guys" P S 0x50 NACK P delay for at least 1 ms (since the eeprom driver has a msleep(1) call). S 0x50 NACK P delay for at least 1 ms ... ... S 0x50 NACK P delay for at least 1 ms S 0x50 0x10 "and girls\n" P This is not what I observe on the bus, most of the time there is a second NACK immediately following the first. I suspect that it is the i2c bus driver that somehow confuses itself and reissues the command for some reason? But this behavior has been there since the beginning, so it's probably orthogonal, and killing the data corrupting regression is much more important to me than fussing over a surplus failed transfer. Hence Tested-by: Peter Rosin Cheers, Peter -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] i2c: at91: fix write transfers by clearing pending interrupt first
On 2015-10-13 18:47, Cyrille Pitchen wrote: > Le 13/10/2015 17:19, Peter Rosin a écrit : >> On 2015-10-13 16:21, Ludovic Desroches wrote: >>> From: Cyrille Pitchen >>> >>> In some cases a NACK interrupt may be pending in the Status Register (SR) >>> as a result of a previous transfer. However at91_do_twi_transfer() did not >>> read the SR to clear pending interruptions before starting a new transfer. >>> Hence a NACK interrupt rose as soon as it was enabled again at the I2C >>> controller level, resulting in a wrong sequence of operations and strange >>> patterns of behaviour on the I2C bus, such as a clock stretch followed by >>> a restart of the transfer. >>> >>> This first issue occurred with both DMA and PIO write transfers. >>> >>> Also when a NACK error was detected during a PIO write transfer, the >>> interrupt handler used to wrongly start a new transfer by writing into the >>> Transmit Holding Register (THR). Then the I2C slave was likely to reply >>> with a second NACK. >>> >>> This second issue is fixed in atmel_twi_interrupt() by handling the TXRDY >>> status bit only if both the TXCOMP and NACK status bits are cleared. >>> >>> Tested with a at24 eeprom on sama5d36ek board running a linux-4.1-at91 >>> kernel image. Adapted to linux-next. >>> >>> Signed-off-by: Cyrille Pitchen >>> Fixes: 93563a6a71bb ("i2c: at91: fix a race condition when using the DMA >>> controller") >>> Reported-by: Peter Rosin >>> Signed-off-by: Ludovic Desroches >>> Cc: sta...@vger.kernel.org #4.1 >> >> The regression is gone with this patch (vanilla 4.2), thank you! >> >> However, looking at the bus, there are two NACKs after each >> successful chunk of memory written by the eeprom driver. >> >> Looking at the eeprom driver, I expect this on the bus: >> >> S 0x50 0x00 "hello there guys" P >> S 0x50 NACK P >> delay for at least 1 ms (since the eeprom driver has a msleep(1) call). >> S 0x50 NACK P >> delay for at least 1 ms >> ... >> ... >> S 0x50 NACK P >> delay for at least 1 ms >> S 0x50 0x10 "and girls\n" P >> >> This is not what I observe on the bus, most of the time there is a >> second NACK immediately following the first. I suspect that it is >> the i2c bus driver that somehow confuses itself and reissues the >> command for some reason? >> >> But this behavior has been there since the beginning, so it's probably >> orthogonal, and killing the data corrupting regression is much more >> important to me than fussing over a surplus failed transfer. Hence >> >> Tested-by: Peter Rosin >> >> Cheers, >> Peter >> > > Hi Peter, > > sama5d3x and sama5d4x don't support the so called "Alternative Command mode" > whereas sama5d2x do. The Alternative Command mode comes with a new hardware > mechanism inside the I2C controller which locks the transmission of data on > the I2C bus when a NACK is detected. It means that even if a data is written > into the THR, the I2C controller doesn't push this data on the I2C bus but > retains the data in the THR (and its associated FIFO for sama5d2x and future > SoCs) until the driver unlocks the transmitter by writing the LOCKCLR (Lock > Clear) bit in the Control Register. Then and only then, the transmitter > outputs > pending data again. > This new mechanism was introduced to cope with an unwanted DMA write into the > THR after a NACK. Indeed, as I've tried to explain in my patch, when a first > NACK is detected, the I2C controller sets the TXCOMP, NACK and TXRDY bits > alltogether in the Status Register. However setting the TXRDY bit also > triggers > the DMA controller to write the next data into the THR. Pitifully, WITHOUT the > new lock mechanism, writing into the THR starts a new I2C frame. Since the > eeprom is likely not to be ready yet, it replies by a second NACK. So you > see on the scope two consecutive NACKs. > > On sama5d3x and sama5d4x, which do not support this lock mechanism, you are > likely to see a successful write transfer followed by two NACKs then a delay > and finally a new successful write transfer. This is the case 2b: > > 1 - A successfull write transfer is completed. > 2 - The at24 driver immediately tries to perform the next write transfer... > 3 - ... but the eeprom is not ready yet and replies with a first NACK. > 4 - The I2C controller detects this NACK and sets the NACK, TXCOMP and TXRDY > bits in its Status Register (and interrup
Re: [PATCH] i2c: at91: fix write transfers by clearing pending interrupt first
On 2015-10-14 07:43, Ludovic Desroches wrote: > On Tue, Oct 13, 2015 at 08:01:34PM +0200, Peter Rosin wrote: >> On 2015-10-13 18:47, Cyrille Pitchen wrote: >>> Le 13/10/2015 17:19, Peter Rosin a écrit : >>>> On 2015-10-13 16:21, Ludovic Desroches wrote: >>>>> From: Cyrille Pitchen >>>>> >>>>> In some cases a NACK interrupt may be pending in the Status Register (SR) >>>>> as a result of a previous transfer. However at91_do_twi_transfer() did not >>>>> read the SR to clear pending interruptions before starting a new transfer. >>>>> Hence a NACK interrupt rose as soon as it was enabled again at the I2C >>>>> controller level, resulting in a wrong sequence of operations and strange >>>>> patterns of behaviour on the I2C bus, such as a clock stretch followed by >>>>> a restart of the transfer. >>>>> >>>>> This first issue occurred with both DMA and PIO write transfers. >>>>> >>>>> Also when a NACK error was detected during a PIO write transfer, the >>>>> interrupt handler used to wrongly start a new transfer by writing into the >>>>> Transmit Holding Register (THR). Then the I2C slave was likely to reply >>>>> with a second NACK. >>>>> >>>>> This second issue is fixed in atmel_twi_interrupt() by handling the TXRDY >>>>> status bit only if both the TXCOMP and NACK status bits are cleared. >>>>> >>>>> Tested with a at24 eeprom on sama5d36ek board running a linux-4.1-at91 >>>>> kernel image. Adapted to linux-next. >>>>> >>>>> Signed-off-by: Cyrille Pitchen >>>>> Fixes: 93563a6a71bb ("i2c: at91: fix a race condition when using the DMA >>>>> controller") >>>>> Reported-by: Peter Rosin >>>>> Signed-off-by: Ludovic Desroches >>>>> Cc: sta...@vger.kernel.org #4.1 >>>> >>>> The regression is gone with this patch (vanilla 4.2), thank you! >>>> >>>> However, looking at the bus, there are two NACKs after each >>>> successful chunk of memory written by the eeprom driver. >>>> >>>> Looking at the eeprom driver, I expect this on the bus: >>>> >>>> S 0x50 0x00 "hello there guys" P >>>> S 0x50 NACK P >>>> delay for at least 1 ms (since the eeprom driver has a msleep(1) call). >>>> S 0x50 NACK P >>>> delay for at least 1 ms >>>> ... >>>> ... >>>> S 0x50 NACK P >>>> delay for at least 1 ms >>>> S 0x50 0x10 "and girls\n" P >>>> >>>> This is not what I observe on the bus, most of the time there is a >>>> second NACK immediately following the first. I suspect that it is >>>> the i2c bus driver that somehow confuses itself and reissues the >>>> command for some reason? >>>> >>>> But this behavior has been there since the beginning, so it's probably >>>> orthogonal, and killing the data corrupting regression is much more >>>> important to me than fussing over a surplus failed transfer. Hence >>>> >>>> Tested-by: Peter Rosin >>>> >>>> Cheers, >>>> Peter >>>> >>> >>> Hi Peter, >>> >>> sama5d3x and sama5d4x don't support the so called "Alternative Command mode" >>> whereas sama5d2x do. The Alternative Command mode comes with a new hardware >>> mechanism inside the I2C controller which locks the transmission of data on >>> the I2C bus when a NACK is detected. It means that even if a data is written >>> into the THR, the I2C controller doesn't push this data on the I2C bus but >>> retains the data in the THR (and its associated FIFO for sama5d2x and future >>> SoCs) until the driver unlocks the transmitter by writing the LOCKCLR (Lock >>> Clear) bit in the Control Register. Then and only then, the transmitter >>> outputs >>> pending data again. >>> This new mechanism was introduced to cope with an unwanted DMA write into >>> the >>> THR after a NACK. Indeed, as I've tried to explain in my patch, when a first >>> NACK is detected, the I2C controller sets the TXCOMP, NACK and TXRDY bits >>> alltogether in the Status Register. However setting the TXRDY bit also >>> triggers >>> the DMA controller to write the next data into the THR. Pitifully, WI
Re: [PATCH] i2c: at91: fix write transfers by clearing pending interrupt first
On 2015-10-16 01:47, Peter Rosin wrote: > On 2015-10-14 07:43, Ludovic Desroches wrote: >> On Tue, Oct 13, 2015 at 08:01:34PM +0200, Peter Rosin wrote: >>> On 2015-10-13 18:47, Cyrille Pitchen wrote: >>>> Le 13/10/2015 17:19, Peter Rosin a écrit : >>>>> On 2015-10-13 16:21, Ludovic Desroches wrote: >>>>>> From: Cyrille Pitchen >>>>>> >>>>>> In some cases a NACK interrupt may be pending in the Status Register (SR) >>>>>> as a result of a previous transfer. However at91_do_twi_transfer() did >>>>>> not >>>>>> read the SR to clear pending interruptions before starting a new >>>>>> transfer. >>>>>> Hence a NACK interrupt rose as soon as it was enabled again at the I2C >>>>>> controller level, resulting in a wrong sequence of operations and strange >>>>>> patterns of behaviour on the I2C bus, such as a clock stretch followed by >>>>>> a restart of the transfer. >>>>>> >>>>>> This first issue occurred with both DMA and PIO write transfers. >>>>>> >>>>>> Also when a NACK error was detected during a PIO write transfer, the >>>>>> interrupt handler used to wrongly start a new transfer by writing into >>>>>> the >>>>>> Transmit Holding Register (THR). Then the I2C slave was likely to reply >>>>>> with a second NACK. >>>>>> >>>>>> This second issue is fixed in atmel_twi_interrupt() by handling the TXRDY >>>>>> status bit only if both the TXCOMP and NACK status bits are cleared. >>>>>> >>>>>> Tested with a at24 eeprom on sama5d36ek board running a linux-4.1-at91 >>>>>> kernel image. Adapted to linux-next. >>>>>> >>>>>> Signed-off-by: Cyrille Pitchen >>>>>> Fixes: 93563a6a71bb ("i2c: at91: fix a race condition when using the DMA >>>>>> controller") >>>>>> Reported-by: Peter Rosin >>>>>> Signed-off-by: Ludovic Desroches >>>>>> Cc: sta...@vger.kernel.org #4.1 >>>>> >>>>> The regression is gone with this patch (vanilla 4.2), thank you! >>>>> >>>>> However, looking at the bus, there are two NACKs after each >>>>> successful chunk of memory written by the eeprom driver. >>>>> >>>>> Looking at the eeprom driver, I expect this on the bus: >>>>> >>>>> S 0x50 0x00 "hello there guys" P >>>>> S 0x50 NACK P >>>>> delay for at least 1 ms (since the eeprom driver has a msleep(1) call). >>>>> S 0x50 NACK P >>>>> delay for at least 1 ms >>>>> ... >>>>> ... >>>>> S 0x50 NACK P >>>>> delay for at least 1 ms >>>>> S 0x50 0x10 "and girls\n" P >>>>> >>>>> This is not what I observe on the bus, most of the time there is a >>>>> second NACK immediately following the first. I suspect that it is >>>>> the i2c bus driver that somehow confuses itself and reissues the >>>>> command for some reason? >>>>> >>>>> But this behavior has been there since the beginning, so it's probably >>>>> orthogonal, and killing the data corrupting regression is much more >>>>> important to me than fussing over a surplus failed transfer. Hence >>>>> >>>>> Tested-by: Peter Rosin >>>>> >>>>> Cheers, >>>>> Peter >>>>> >>>> >>>> Hi Peter, >>>> >>>> sama5d3x and sama5d4x don't support the so called "Alternative Command >>>> mode" >>>> whereas sama5d2x do. The Alternative Command mode comes with a new hardware >>>> mechanism inside the I2C controller which locks the transmission of data on >>>> the I2C bus when a NACK is detected. It means that even if a data is >>>> written >>>> into the THR, the I2C controller doesn't push this data on the I2C bus but >>>> retains the data in the THR (and its associated FIFO for sama5d2x and >>>> future >>>> SoCs) until the driver unlocks the transmitter by writing the LOCKCLR (Lock >>>> Clear) bit in the Control Register. Then and only then, the transmitter >>>> outputs >>>> pending da
Re: [PATCH] i2c: at91: fix write transfers by clearing pending interrupt first
On 2015-10-20 15:27, Ludovic Desroches wrote: > On Mon, Oct 19, 2015 at 12:49:03PM +0200, Peter Rosin wrote: >> On 2015-10-19 10:51, Ludovic Desroches wrote: >>> Hi Peter, >>> >>> On Fri, Oct 16, 2015 at 11:08:42AM +0200, Peter Rosin wrote: >>>> On 2015-10-16 01:47, Peter Rosin wrote: >>>>> On 2015-10-14 07:43, Ludovic Desroches wrote: >>>>>> On Tue, Oct 13, 2015 at 08:01:34PM +0200, Peter Rosin wrote: >>>>>>> On 2015-10-13 18:47, Cyrille Pitchen wrote: >>>>>>>> Le 13/10/2015 17:19, Peter Rosin a écrit : >>>>>>>>> On 2015-10-13 16:21, Ludovic Desroches wrote: >>> >>> [...] >>> >>>>> I have started to get this when I run with this patch: >>>>> >>>>> [ 73.31] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 198.20] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 509.88] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 615.75] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 617.75] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 1766.64] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 2035.38] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 2227.19] at91_i2c f0014000.i2c: RXRDY still set! >>>>> [ 2313.10] at91_i2c f0014000.i2c: RXRDY still set! >>>>> >>>>> My USB serial dongle was hung which was why I didn't notice until just >>>>> now. >>>>> >>>>> This is probably not when communication with the eeprom though, and >>>>> certainly not >>>>> writing to it, but perhpaps when polling the temperature (using the jc42 >>>>> driver). >>>>> I'll investigate further in the morning to see if I can pinpoint it. >>>> >>>> Yep, it's the jc42 accesses that triggers this (to the same chip as the >>>> eeprom, but a different block of transistors I suppose). >>>> >>>> Looking at the i2c bus, the accesses normally go like this: >>>> >>>> [0.00] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >>>> [0.000521] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >>>> [0.001024] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >>>> [0.001524] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >>>> [0.196991] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >>>> [0.197514] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >>>> [0.198019] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >>>> [0.198520] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >>>> >>>> I.e. chunks of four transfers every ~200 ms (I removed the 1Hz rate >>>> limiter in the jc42 driver to get more frequent incidents). >>>> >>>> But when the diagnostic (RXRDY still set!) is output it continues >>>> with this: >>>> >>>> [0.399755] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >>>> [0.404998] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >>>> [0.405508] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >>>> [0.406008] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >>>> >>>> Notice the ~5 ms delay (about the time it should take to output >>>> the diagnostic at 115200 baud) after the access to register 0x05 >>>> at 0.399755. >>>> >>>> This is the only thing that I can observe on the bus, so it appears >>>> to be harmless. >>>> >>>> It appears that the i2c access at 0.399755 finds the TWI >>>> registers in an odd state, but nothing from the access at >>>> 0.198520 appears to have gone wrong. Is this a race? Anyway, >>>> the diagnostic is pretty frequent and annoying. printk_once? >>> >>> I'll try to reproduce it on my side. The only issue you have is having >>> the message about RXRDY? I mean no issue with i2c transfers? >> >> Exactly, the only issue is the message, the bus looks good and transfers >> work as they should AFAICT. >>> It is not the possible bug we had in mind, this bug will prevent the >>> master device to release the i2c bus. It will stop the transfer but >>> without sending a stop on the bus. >> >> Agreed, this is not about the extra frame caused by the spurious write >> to the THR register. This is something else. >> >> One suspicion is that the driver gets an unexpected irq from its own >> NACK (the one that it puts out to end the read) and races with the >>
Re: [PATCH] i2c: at91: fix write transfers by clearing pending interrupt first
On 2015-10-21 09:21, Peter Rosin wrote: > On 2015-10-20 15:27, Ludovic Desroches wrote: >> On Mon, Oct 19, 2015 at 12:49:03PM +0200, Peter Rosin wrote: >>> On 2015-10-19 10:51, Ludovic Desroches wrote: >>>> Hi Peter, >>>> >>>> On Fri, Oct 16, 2015 at 11:08:42AM +0200, Peter Rosin wrote: >>>>> On 2015-10-16 01:47, Peter Rosin wrote: >>>>>> On 2015-10-14 07:43, Ludovic Desroches wrote: >>>>>>> On Tue, Oct 13, 2015 at 08:01:34PM +0200, Peter Rosin wrote: >>>>>>>> On 2015-10-13 18:47, Cyrille Pitchen wrote: >>>>>>>>> Le 13/10/2015 17:19, Peter Rosin a écrit : >>>>>>>>>> On 2015-10-13 16:21, Ludovic Desroches wrote: >>>> >>>> [...] >>>> >>>>>> I have started to get this when I run with this patch: >>>>>> >>>>>> [ 73.31] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 198.20] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 509.88] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 615.75] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 617.75] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 1766.64] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 2035.38] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 2227.19] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> [ 2313.10] at91_i2c f0014000.i2c: RXRDY still set! >>>>>> >>>>>> My USB serial dongle was hung which was why I didn't notice until just >>>>>> now. >>>>>> >>>>>> This is probably not when communication with the eeprom though, and >>>>>> certainly not >>>>>> writing to it, but perhpaps when polling the temperature (using the jc42 >>>>>> driver). >>>>>> I'll investigate further in the morning to see if I can pinpoint it. >>>>> >>>>> Yep, it's the jc42 accesses that triggers this (to the same chip as the >>>>> eeprom, but a different block of transistors I suppose). >>>>> >>>>> Looking at the i2c bus, the accesses normally go like this: >>>>> >>>>> [0.00] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >>>>> [0.000521] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >>>>> [0.001024] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >>>>> [0.001524] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >>>>> [0.196991] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >>>>> [0.197514] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >>>>> [0.198019] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >>>>> [0.198520] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >>>>> >>>>> I.e. chunks of four transfers every ~200 ms (I removed the 1Hz rate >>>>> limiter in the jc42 driver to get more frequent incidents). >>>>> >>>>> But when the diagnostic (RXRDY still set!) is output it continues >>>>> with this: >>>>> >>>>> [0.399755] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >>>>> [0.404998] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >>>>> [0.405508] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >>>>> [0.406008] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >>>>> >>>>> Notice the ~5 ms delay (about the time it should take to output >>>>> the diagnostic at 115200 baud) after the access to register 0x05 >>>>> at 0.399755. >>>>> >>>>> This is the only thing that I can observe on the bus, so it appears >>>>> to be harmless. >>>>> >>>>> It appears that the i2c access at 0.399755 finds the TWI >>>>> registers in an odd state, but nothing from the access at >>>>> 0.198520 appears to have gone wrong. Is this a race? Anyway, >>>>> the diagnostic is pretty frequent and annoying. printk_once? >>>> >>>> I'll try to reproduce it on my side. The only issue you have is having >>>> the message about RXRDY? I mean no issue with i2c transfers? >>> >>> Exactly, the only issue is the message, the bus looks good and transfers >>> work as they should AFAICT. >>>> It is not the possible bug we had in mind, this bug will prevent the >>>> master device to release the i2c bus. It will stop the transfer but >&
Re: [PATCH] i2c: at91: fix write transfers by clearing pending interrupt first
On 2015-10-19 10:51, Ludovic Desroches wrote: > Hi Peter, > > On Fri, Oct 16, 2015 at 11:08:42AM +0200, Peter Rosin wrote: >> On 2015-10-16 01:47, Peter Rosin wrote: >>> On 2015-10-14 07:43, Ludovic Desroches wrote: >>>> On Tue, Oct 13, 2015 at 08:01:34PM +0200, Peter Rosin wrote: >>>>> On 2015-10-13 18:47, Cyrille Pitchen wrote: >>>>>> Le 13/10/2015 17:19, Peter Rosin a écrit : >>>>>>> On 2015-10-13 16:21, Ludovic Desroches wrote: > > [...] > >>> I have started to get this when I run with this patch: >>> >>> [ 73.31] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 198.20] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 509.88] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 615.75] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 617.75] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 1766.64] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 2035.38] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 2227.19] at91_i2c f0014000.i2c: RXRDY still set! >>> [ 2313.10] at91_i2c f0014000.i2c: RXRDY still set! >>> >>> My USB serial dongle was hung which was why I didn't notice until just now. >>> >>> This is probably not when communication with the eeprom though, and >>> certainly not >>> writing to it, but perhpaps when polling the temperature (using the jc42 >>> driver). >>> I'll investigate further in the morning to see if I can pinpoint it. >> >> Yep, it's the jc42 accesses that triggers this (to the same chip as the >> eeprom, but a different block of transistors I suppose). >> >> Looking at the i2c bus, the accesses normally go like this: >> >> [0.00] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >> [0.000521] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >> [0.001024] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >> [0.001524] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >> [0.196991] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >> [0.197514] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >> [0.198019] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >> [0.198520] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >> >> I.e. chunks of four transfers every ~200 ms (I removed the 1Hz rate >> limiter in the jc42 driver to get more frequent incidents). >> >> But when the diagnostic (RXRDY still set!) is output it continues >> with this: >> >> [0.399755] S 0x18 W 0x05 S 0x18 R 0xc1 0xbe NACK P >> [0.404998] S 0x18 W 0x04 S 0x18 R 0x00 0x00 NACK P >> [0.405508] S 0x18 W 0x03 S 0x18 R 0x00 0x00 NACK P >> [0.406008] S 0x18 W 0x02 S 0x18 R 0x00 0x00 NACK P >> >> Notice the ~5 ms delay (about the time it should take to output >> the diagnostic at 115200 baud) after the access to register 0x05 >> at 0.399755. >> >> This is the only thing that I can observe on the bus, so it appears >> to be harmless. >> >> It appears that the i2c access at 0.399755 finds the TWI >> registers in an odd state, but nothing from the access at >> 0.198520 appears to have gone wrong. Is this a race? Anyway, >> the diagnostic is pretty frequent and annoying. printk_once? > > I'll try to reproduce it on my side. The only issue you have is having > the message about RXRDY? I mean no issue with i2c transfers? Exactly, the only issue is the message, the bus looks good and transfers work as they should AFAICT. > It is not the possible bug we had in mind, this bug will prevent the > master device to release the i2c bus. It will stop the transfer but > without sending a stop on the bus. Agreed, this is not about the extra frame caused by the spurious write to the THR register. This is something else. One suspicion is that the driver gets an unexpected irq from its own NACK (the one that it puts out to end the read) and races with the expected interrupt at TXCOMP? Cheers, Peter -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Regression: at24 eeprom writing
Hi! I recently upgraded from the atmel linux-3.18-at91 kernel to vanilla 4.2 and everything seemed fine. Until I tried to write to the little eeprom chip. I then tried the linux-4.1-at91 kernel and that suffers too. The symptoms are that it seems like writes get interrupted, and restarted again without properly initializing everything again. Inspecting the i2c bus during these fails gets me something like this (int hex) when I echo abcdefghijklmnopqr > /sys/bus/i2c/devices/0-0050/eeprom S a0 00 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 P S a0 10 (clk and data low for a "long" time) 10 71 72 0a P Notice how the address byte in the second chunk (10) is repeated after the strange event on the i2c bus. I looked around and found that if I revert a839ce663b3183209fdf7b1fc4796bfe2a4679c3 "eeprom: at24: extend driver to allow writing via i2c_smbus_write_byte_data" eeprom writing starts working again. AFAICT, the i2c-at91 bus driver makes the eeprom driver use the i2c_transfer code path both with that patch and with it reverted, so I sadly don't see why the patch makes a difference. I'm on a board that is based on the sama5d31 evaluation kit, with a NXP SE97BTP,547 chip and this in the devicetree: i2c0: i2c@f0014000 { status = "okay"; jc42@18 { compatible = "jc42"; reg = <0x18>; }; eeprom@50 { compatible = "24c02"; reg = <0x50>; pagesize = <16>; }; }; Any ideas? Cheers, Peter -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Regression: at24 eeprom writing
On 2015-10-03 01:05, Peter Rosin wrote: > I looked around and found that if I revert > a839ce663b3183209fdf7b1fc4796bfe2a4679c3 > "eeprom: at24: extend driver to allow writing via i2c_smbus_write_byte_data" > eeprom writing starts working again. > > AFAICT, the i2c-at91 bus driver makes the eeprom driver use the > i2c_transfer code path both with that patch and with it reverted, > so I sadly don't see why the patch makes a difference. And now when I retry the same thing, that patch is no longer affecting things. I must have confused myself over what kernel was actually running. Christian, please accept my deepest apologies for implicating you in this regression. But the regression is still there. In short, linux-3.18-at91 from the linux4sam tree works, linux-4.1-at91 from the same tree does not, and vanilla 4.2 also doesn't work. I have a hard time bisecting this thing though, since the last known good version has a long list of atmel patches that I refuse to even try to rebase... Ideas still welcome of course. Cheers, Peter -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Regression: at24 eeprom writing
On 2015-10-03 01:05, Peter Rosin wrote: > Hi! > > I recently upgraded from the atmel linux-3.18-at91 kernel to vanilla 4.2 > and everything seemed fine. Until I tried to write to the little eeprom > chip. I then tried the linux-4.1-at91 kernel and that suffers too. > > The symptoms are that it seems like writes get interrupted, and restarted > again without properly initializing everything again. Inspecting the i2c > bus during these fails gets me something like this (int hex) when I > > echo abcdefghijklmnopqr > /sys/bus/i2c/devices/0-0050/eeprom > > S a0 00 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 P > S a0 10 (clk and data low for a "long" time) 10 71 72 0a P > > Notice how the address byte in the second chunk (10) is repeated after > the strange event on the i2c bus. > > I looked around and found that if I revert > a839ce663b3183209fdf7b1fc4796bfe2a4679c3 > "eeprom: at24: extend driver to allow writing via i2c_smbus_write_byte_data" > eeprom writing starts working again. > > AFAICT, the i2c-at91 bus driver makes the eeprom driver use the > i2c_transfer code path both with that patch and with it reverted, > so I sadly don't see why the patch makes a difference. > > I'm on a board that is based on the sama5d31 evaluation kit, with a > NXP SE97BTP,547 chip and this in the devicetree: > > i2c0: i2c@f0014000 { > status = "okay"; > > jc42@18 { > compatible = "jc42"; > reg = <0x18>; > }; > > eeprom@50 { > compatible = "24c02"; > reg = <0x50>; > pagesize = <16>; > }; > }; Ok, I found the culprit, and I double and triple checked it this time... If I move to the very latest on the linux-3.18-at91 branch, the bug is there too. Which made it vastly more palatable to bisect the bug. The offender (in the 4.2 kernel) is 93563a6a71bb69dd324fc7354c60fb05f84aae6b "i2c: at91: fix a race condition when using the DMA controller" which is far more understandable. Ao, adding Cyrille Pitchen to the Cc list. If I add that patch on top of my previously working tree, it behaves just as newer kernels, i.e. equally bad. The patch doesn't revert cleanly, but reverting the patch and quick-n-dirty-fixing the conflict on vanilla 4.2 makes the problem go away. I have attached what I actually reverted. Cheers, Peter >From d178e0636358e61503ac55d39c8612ef93c1d893 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Mon, 5 Oct 2015 10:16:18 +0200 Subject: [PATCH] Revert "i2c: at91: fix a race condition when using the DMA controller" This reverts commit 93563a6a71bb69dd324fc7354c60fb05f84aae6b. Conflicts: drivers/i2c/busses/i2c-at91.c --- drivers/i2c/busses/i2c-at91.c | 97 + 1 file changed, 21 insertions(+), 76 deletions(-) diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 1c758cd1e1ba..b5a5ef26b142 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -74,9 +74,6 @@ #define AT91_TWI_NACK BIT(8) /* Not Acknowledged */ #define AT91_TWI_LOCK BIT(23) /* TWI Lock due to Frame Errors */ -#define AT91_TWI_INT_MASK \ - (AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY | AT91_TWI_NACK) - #define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */ #define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */ #define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */ @@ -155,12 +152,13 @@ static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val) static void at91_disable_twi_interrupts(struct at91_twi_dev *dev) { - at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_INT_MASK); + at91_twi_write(dev, AT91_TWI_IDR, + AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); } static void at91_twi_irq_save(struct at91_twi_dev *dev) { - dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & AT91_TWI_INT_MASK; + dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7; at91_disable_twi_interrupts(dev); } @@ -255,16 +253,7 @@ static void at91_twi_write_data_dma_callback(void *data) dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg[0]), dev->buf_len, DMA_TO_DEVICE); - /* - * When this callback is called, THR/TX FIFO is likely not to be empty - * yet. So we have to wait for TXCOMP or NACK bits to be set into the - * Status Register to be sure that the STOP bit has been sent and the - * transfer is completed. The NACK interrupt has alread
Re: [PATCH] drivers/i2c: Include SPDX-license-identifier
On 2018-06-21 11:40, Mawanda Henry wrote: > including the SPDX license identifier header makes it easy for > developers and machines to know the lecense that is governing the file If you do changes like this, you should also remove the actual license text (it follows later in the comment in this case). And more importantly, you should make *sure* that you use the correct SPDX tag, which you don't in this case. So, you need to fix those issues. Cheers, Peter > Signed-off-by: Mawanda Henry > --- > drivers/i2c/i2c-core-slave.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c > index 4a78c65..883ca836 100644 > --- a/drivers/i2c/i2c-core-slave.c > +++ b/drivers/i2c/i2c-core-slave.c > @@ -1,3 +1,4 @@ > +// SPDX-License-Identifier: GPL-2.0 > /* > * Linux I2C core slave support code > * >
Re: [PATCH] drivers/i2c: include SPDX-license header
On 2018-06-21 12:02, Mawanda Henry wrote: > SPDX license headers makes it easy for developers and machines to know > the license that is governing that file This patch appears to be on top of the previously rejected patch. Please remove that broken patch first so that this patch applies to a clean tree. > Signed-off-by: Mawanda Henry > --- > drivers/i2c/i2c-core-slave.c | 6 +- > 1 file changed, 1 insertion(+), 5 deletions(-) > > diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c > index 883ca836..fd6a405 100644 > --- a/drivers/i2c/i2c-core-slave.c > +++ b/drivers/i2c/i2c-core-slave.c > @@ -1,13 +1,9 @@ > -// SPDX-License-Identifier: GPL-2.0 > +// SPDX-License-Identifier: GPL-2.0+ > /* > * Linux I2C core slave support code > * > * Copyright (C) 2014 by Wolfram Sang > * Also, the above empty "*" line should also be removed. Cheers, Peter > - * 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 >
Re: [PATCH] drivers/i2c: SPDX-License-header information
On 2018-06-21 14:36, Mawanda Henry wrote: > SPDX License header included to easy developers and machine to know the > license governing a particular file > > Signed-off-by: Mawanda Henry > --- > drivers/i2c/i2c-core-slave.c | 7 +-- > 1 file changed, 1 insertion(+), 6 deletions(-) > It is customary to make note of the patch revision in the subject. In your case that would be [PATCH v3] for this patch and [PATCH v4] for the next iteration. Speaking of the subject, a better subject for this message would have been Subject: [PATCH v3] i2c: slave: use SPDX license information Also, when doing multiple revisions of a patch it is valuable to record the history of changes, so that reviewers get a reminder of what has happened. For a single patch, this space here, just before the first "diff" line is a good spot for that patch history. For a trivial patch like this, this is not super-important, but still best practice. > diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c > index 4a78c65..d2cc8fc 100644 > --- a/drivers/i2c/i2c-core-slave.c > +++ b/drivers/i2c/i2c-core-slave.c > @@ -1,12 +1,7 @@ > +// SPDX-License-Identifier: GPL-2.0+ Apparently, GPL-2.0+ is a thing of the past. Should be GPL-2.0-or-later according to https://spdx.org/licenses/ > /* > * Linux I2C core slave support code > - * I said "line", not "lines". The above line should be left as-is. Cheers, Peter > * Copyright (C) 2014 by Wolfram Sang > - * > - * 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 >
Re: [PATCH v4] i2c: slave: Apply SPDX Lincense-Information
On 2018-06-21 18:05, Mawanda Henry wrote: > SPDX license header eases work for developers and machines to know the > license that is governing a particular file > > Signed-off-by: Mawanda Henry > --- > drivers/i2c/i2c-core-slave.c | 6 +- > 1 file changed, 1 insertion(+), 5 deletions(-) > > diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c > index 4a78c65..6f56e65 100644 > --- a/drivers/i2c/i2c-core-slave.c > +++ b/drivers/i2c/i2c-core-slave.c > @@ -1,12 +1,8 @@ > +// SPDX-License-Identifier: GPL-2.0+ Why did you not change this to "GPL-2.0-or-later"? Also, you now have a spelling error in the subject. Why did you not use the subject exactly as I suggested? I will not respond if there are further issues with this patch, this is getting ridiculous... Cheers, Peter > /* > * Linux I2C core slave support code > * > * Copyright (C) 2014 by Wolfram Sang > - * > - * 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 >
[PATCH 4/5] ARM: dts: at91: nattis: move pinctrls for the lvds chip to the lvds node
The atmel hlcdc controller has nothing to do with these pins, so move them to where they belong. Signed-off-by: Peter Rosin --- arch/arm/boot/dts/at91-nattis-2-natte-2.dts | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/at91-nattis-2-natte-2.dts b/arch/arm/boot/dts/at91-nattis-2-natte-2.dts index fbc796125c56..2eb0f947ab86 100644 --- a/arch/arm/boot/dts/at91-nattis-2-natte-2.dts +++ b/arch/arm/boot/dts/at91-nattis-2-natte-2.dts @@ -34,7 +34,7 @@ AT91_PINCTRL_PULL_UP_DEGLITCH>; }; - pinctrl_lcd_prlud0: lcd_prlud0 { + pinctrl_lvds_prlud0: lvds_prlud0 { atmel,pins = ; }; - pinctrl_lcd_hipow0: lcd_hipow0 { + pinctrl_lvds_hipow0: lvds_hipow0 { atmel,pins = ; + ports { #address-cells = <1>; #size-cells = <0>; @@ -197,10 +200,7 @@ hlcdc-display-controller { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_lcd_base -&pinctrl_lcd_rgb565 -&pinctrl_lcd_prlud0 -&pinctrl_lcd_hipow0>; + pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb565>; port@0 { hlcdc_output: endpoint { -- 2.11.0