[radeon-alex:amd-staging-drm-next 1019/1033] drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:237:5: warning: no previous prototype for 'rn_vbios_smu_is_periodic_retrainin

2020-07-14 Thread kernel test robot
tree:   git://people.freedesktop.org/~agd5f/linux.git amd-staging-drm-next
head:   2c6fefb23a0e94add694b04a82bf020aed1898a0
commit: 8e37efbf94c9516cbec8ac650ecae7c8647d4d7f [1019/1033] drm/amd/display: 
reduce sr_xxx_time by 3 us when ppt disable
config: i386-allyesconfig (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
reproduce (this is a W=1 build):
git checkout 8e37efbf94c9516cbec8ac650ecae7c8647d4d7f
# save the attached .config to linux build tree
make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All warnings (new ones prefixed by >>):

   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:89:5:
 warning: no previous prototype for 'rn_vbios_smu_send_msg_with_param' 
[-Wmissing-prototypes]
  89 | int rn_vbios_smu_send_msg_with_param(struct clk_mgr_internal 
*clk_mgr, unsigned int msg_id, unsigned int param)
 | ^~~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:110:5:
 warning: no previous prototype for 'rn_vbios_smu_get_smu_version' 
[-Wmissing-prototypes]
 110 | int rn_vbios_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
 | ^~~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:119:5:
 warning: no previous prototype for 'rn_vbios_smu_set_dispclk' 
[-Wmissing-prototypes]
 119 | int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int 
requested_dispclk_khz)
 | ^~~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:142:5:
 warning: no previous prototype for 'rn_vbios_smu_set_dprefclk' 
[-Wmissing-prototypes]
 142 | int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
 | ^
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:156:5:
 warning: no previous prototype for 'rn_vbios_smu_set_hard_min_dcfclk' 
[-Wmissing-prototypes]
 156 | int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal 
*clk_mgr, int requested_dcfclk_khz)
 | ^~~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:171:5:
 warning: no previous prototype for 'rn_vbios_smu_set_min_deep_sleep_dcfclk' 
[-Wmissing-prototypes]
 171 | int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal 
*clk_mgr, int requested_min_ds_dcfclk_khz)
 | ^~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:186:6:
 warning: no previous prototype for 'rn_vbios_smu_set_phyclk' 
[-Wmissing-prototypes]
 186 | void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int 
requested_phyclk_khz)
 |  ^~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:194:5:
 warning: no previous prototype for 'rn_vbios_smu_set_dppclk' 
[-Wmissing-prototypes]
 194 | int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int 
requested_dpp_khz)
 | ^~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:206:6:
 warning: no previous prototype for 'rn_vbios_smu_set_dcn_low_power_state' 
[-Wmissing-prototypes]
 206 | void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal 
*clk_mgr, enum dcn_pwr_state state)
 |  ^~~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:221:6:
 warning: no previous prototype for 
'rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn' [-Wmissing-prototypes]
 221 | void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct 
clk_mgr_internal *clk_mgr, bool enable)
 |  ^~~~
   
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:229:6:
 warning: no previous prototype for 'rn_vbios_smu_enable_pme_wa' 
[-Wmissing-prototypes]
 229 | void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
 |  ^~
>> drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:237:5:
>>  warning: no previous prototype for 
>> 'rn_vbios_smu_is_periodic_retraining_disabled' [-Wmissing-prototypes]
 237 | int rn_vbios_smu_is_periodic_retraining_disabled(struct 
clk_mgr_internal *clk_mgr)
 | ^~~~
   In file included from 
drivers/gpu/drm/amd/amdgpu/../display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c:31:
   drivers/gpu/drm/amd/amdgpu/../include/renoir_ip_offset.h:226:29: warning: 
'UVD0_BASE' defined but not used [-Wunused-const-variable=]
 226 | static const struct IP_BASE UVD0_BASE ={ { { { 0x7800, 
0x7E00, 0x02403000, 0, 0 } },
 |  

Re: [PATCH] drm/vmwgfx: Fix two list_for_each loop exit tests

2020-07-14 Thread Roland Scheidegger
Am 14.07.20 um 10:25 schrieb Dan Carpenter:
> On Tue, Jul 14, 2020 at 03:39:13AM +0200, Roland Scheidegger wrote:
>> Am 26.06.20 um 12:39 schrieb Dan Carpenter:
>>> These if statements are supposed to be true if we ended the
>>> list_for_each_entry() loops without hitting a break statement but they
>>> don't work.
>>>
>>> In the first loop, we increment "i" after the "if (i == unit)" condition
>>> so we don't necessarily know that "i" is not equal to unit at the end of
>>> the loop.
>> So, if I understand this right, this would only really be a problem if
>> there's no list entries at all, right? That is i == unit == 0.
>> Not sure if that can actually happen, but in any case the fix looks correct.
> 
> An empty list and there is another potential issue where unit is exactly
> off by one.
> 
>   list_for_each_entry(con, &dev_priv->dev->mode_config.connector_list,
>   head) {
>   if (i == unit)
>   break;
>   ++i;  <-- this is the last iteration and it's off by one
> so now i == unit but we didn't exit via the
> break statement.
>   }
> 
>   if (i != unit) {
> ^
> Since we didn't exit by the break statement we want this to be true but
> it's false instead.
> 
>   DRM_ERROR("Could not find initial display unit.\n");
> 
> I don't know how *likely* this is, but static checkers complain.
> Technically correct is the best kind of correct!  ;)
Ahh indeed seems obvious now. But kinda difficult to spot :-).

Thanks again,

Roland


> 
> regards,
> dan carpenter
> 

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 207383] [Regression] 5.7 amdgpu/polaris11 gpf: amdgpu_atomic_commit_tail

2020-07-14 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=207383

Duncan (1i5t5.dun...@cox.net) changed:

   What|Removed |Added

 Kernel Version|5.7-rc1 - 5.7 - 5.8-rc4+|5.7-rc1 - 5.7 - 5.8-rc5+

--- Comment #62 from Duncan (1i5t5.dun...@cox.net) ---
(In reply to Duncan from comment #48)
> (In reply to Duncan from comment #47)
> > So I tried [patch-reverting] with the 11 above commits against
> > 5.8.0-rc4-00025-gbfe91da29, which previously tested as triggering the
> freeze
> > for me.  Of the 11, nine clean-reversed and I simply noted and skipped the
> > other two (3202fa62f and 630f289b7) for the moment.  The patched kernel
> > successfully built and I'm booted to it now.
> 
> Bah, humbug!  Got a freeze and the infamous logged trace on that too

After taking a few days discouragement-break I'm back at trying to pin it down.
 The quoted above left two candidate commits, 3202fa62f and 630f289b7, neither
of which would clean-revert as commits since were preventing that.

630f289b7 is a few lines changed in many files so I'm focusing on the simpler
3202fa62f first.  Turns out the reason 320... wasn't reverting was two
additional fixes to it that landed before v5.7.  Since they had Fixes: 320...
labels they were easy enough to find and patch-revert, after which
patch-reverting 320... itself worked against a current v5.8-rc5-8-g0dc589da8. 
I first tested it without the reverts to be sure it's still triggering this bug
for me, and just confirmed it was, freeze with the telltale log dump.

So for me at least, v5.8-rc5 is bad (just updated the version field to reflect
that).

Meanwhile I've applied the three 320-and-followups revert-patches to
v5.8-rc5-8-g0dc589da8 and just did the rebuild with them applied.  Now to
reboot to it and see if it still has our bug.  If no, great, pinned down.  If
yes, there's still that 630... commit to try to test.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [Freedreno] [PATCH 0/9] drm/msm: Avoid possible infinite probe deferral and speed booting

2020-07-14 Thread Rob Herring
On Tue, Jul 14, 2020 at 10:33 AM Jeffrey Hugo  wrote:
>
> On Mon, Jul 13, 2020 at 5:50 PM Doug Anderson  wrote:
> >
> > Hi,
> >
> > On Mon, Jul 13, 2020 at 1:25 PM Rob Herring  wrote:
> > >
> > > On Mon, Jul 13, 2020 at 9:08 AM Doug Anderson  
> > > wrote:
> > > >
> > > > Hi,
> > > >
> > > > On Mon, Jul 13, 2020 at 7:11 AM Rob Herring  wrote:
> > > > >
> > > > > On Fri, Jul 10, 2020 at 5:02 PM Douglas Anderson 
> > > > >  wrote:
> > > > > >
> > > > > > I found that if I ever had a little mistake in my kernel config,
> > > > > > or device tree, or graphics driver that my system would sit in a 
> > > > > > loop
> > > > > > at bootup trying again and again and again.  An example log was:
> > > > >
> > > > > Why do we care about optimizing the error case?
> > > >
> > > > It actually results in a _fully_ infinite loop.  That is: if anything
> > > > small causes a component of DRM to fail to probe then the whole system
> > > > doesn't boot because it just loops trying to probe over and over
> > > > again.  The messages I put in the commit message are printed over and
> > > > over and over again.
> > >
> > > Sounds like a bug as that's not what should happen.
> > >
> > > If you defer during boot (initcalls), then you'll be on the deferred
> > > list until late_initcall and everything is retried. After
> > > late_initcall, only devices getting added should trigger probing. But
> > > maybe the adding and then removing a device is causing a re-trigger.
> >
> > Right, I'm nearly certain that the adding and then removing is causing
> > a re-trigger.  I believe the loop would happen for any case where we
> > have a probe function that:
> >
> > 1. Adds devices.
> > 2. After adding devices it decides that it needs to defer.
> > 3. Removes the devices it added.
> > 4. Return -EPROBE_DEFER from its probe function.
> >
> > Specifically from what I know about how -EPROBE_DEFER works I'm not
> > sure how it wouldn't cause an infinite loop in that case.
> >
> > Perhaps the missing part of my explanation, though, is why it never
> > gets out of this infinite loop.  In my case I purposely made the
> > bridge chip "ti-sn65dsi86.c" return an error (-EINVAL) in its probe
> > every time.  Obviously I wasn't going to get a display up like this,
> > but I just wanted to not loop forever at bootup.  I tracked down
> > exactly why we get an - EPROBE_DEFER over and over in this case.
> >
> > You can see it in msm_dsi_host_register().  If some components haven't
> > shown up when that function runs it will _always_ return
> > -EPROBE_DEFER.
> >
> > In my case, since I caused the bridge to fail to probe, those
> > components will _never_ show up.  That means that
> > msm_dsi_host_register() will _always_ return -EPROBE_DEFER.
> >
> > I haven't dug through all the DRM code enough, but it doesn't
> > necessarily seem like the wrong behavior.  If the bridge driver or a
> > panel was a module then (presumably) they could show up later and so
> > it should be OK for it to defer, right?
> >
> > So with all that, it doesn't really feel like this is a bug so much as
> > it's an unsupported use case.  The current deferral logic simply can't
> > handle the case we're throwing at it.  You cannot return -EPROBE_DEFER
> > if your probe function adds devices each time through the probe
> > function.
> >
> > Assuming all the above makes sense, that means we're stuck with:
> >
> > a) This patch series, which makes us not add devices.
> >
> > b) Some other patch series which rearchitects the MSM graphics stack
> > to not return -EPROBE_DEFER in this case.
>
> This isn't a MSM specific issue.  This is an issue with how the DSI
> interface works, and how software is structured in Linux.  I would
> expect that pretty much any DSI host in the kernel would have some
> version of this issue.
>
> The problem is that DSI is not "hot pluggable", so to give the DRM
> stack the info it needs, we need both the DSI controller (aka the MSM
> graphics stack in your case), and the thing it connects to (in your
> case, the TI bridge, normally the actual panel) because the DRM stack
> expects that if init completes, it has certain information
> (resolution, etc), and some of that information is in the DSI
> controller, and some of it is on the DSI device.

Ah yes, DRM's lack of hot-plug and discrete component support... Is
that not improved with some of the bridge rework?

Anyways, given there is a child dependency on the parent, I don't
think we should work-around DRM deficiencies in DT.

BTW, There's also a deferred probe timeout you can use which stops
deferring probe some number of seconds after late_initcall.

Rob
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] ksz884x: switch from 'pci_' to 'dma_' API

2020-07-14 Thread David Miller
From: Christophe JAILLET 
Date: Tue, 14 Jul 2020 20:35:01 +0200

> The wrappers in include/linux/pci-dma-compat.h should go away.
> 
> The patch has been generated with the coccinelle script below and has been
> hand modified to replace GFP_ with a correct flag.
> It has been compile tested.
> 
> When memory is allocated in 'ksz_alloc_desc()', GFP_KERNEL can be used
> because a few lines below, GFP_KERNEL is also used in the
> 'ksz_alloc_soft_desc()' calls.
 ...
> Signed-off-by: Christophe JAILLET 

Applied, thank you.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 1/3] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Chris Wilson
From: Bas Nieuwenhuizen 

Calltree:
  timeline_fence_release
  drm_sched_entity_wakeup
  dma_fence_signal_locked
  sync_timeline_signal
  sw_sync_ioctl

Releasing the reference to the fence in the fence signal callback
seems reasonable to me, so this patch avoids the locking issue in
sw_sync.

d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
fixed the recursive locking issue but caused an use-after-free. Later
d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
fixed the use-after-free but reintroduced the recursive locking issue.

In this attempt we avoid the use-after-free still because the release
function still always locks, and outside of the locking region in the
signal function we have properly refcounted references.

We furthermore also avoid the recurive lock by making sure that either:

1) We have a properly refcounted reference, preventing the signal from
   triggering the release function inside the locked region.
2) The refcount was already zero, and hence nobody will be able to trigger
   the release function from the signal function.

v2: Move dma_fence_signal() into second loop in preparation to moving
the callback out of the timeline obj->lock.

Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
Cc: Sumit Semwal 
Cc: Chris Wilson 
Cc: Gustavo Padovan 
Cc: Christian König 
Cc: 
Signed-off-by: Bas Nieuwenhuizen 
Signed-off-by: Chris Wilson 
---
 drivers/dma-buf/sw_sync.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 348b3a9170fa..807c82148062 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -192,6 +192,7 @@ static const struct dma_fence_ops timeline_fence_ops = {
 static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
 {
struct sync_pt *pt, *next;
+   LIST_HEAD(signal);
 
trace_sync_timeline(obj);
 
@@ -203,21 +204,32 @@ static void sync_timeline_signal(struct sync_timeline 
*obj, unsigned int inc)
if (!timeline_fence_signaled(&pt->base))
break;
 
-   list_del_init(&pt->link);
-   rb_erase(&pt->node, &obj->pt_tree);
-
/*
-* A signal callback may release the last reference to this
-* fence, causing it to be freed. That operation has to be
-* last to avoid a use after free inside this loop, and must
-* be after we remove the fence from the timeline in order to
-* prevent deadlocking on timeline->lock inside
-* timeline_fence_release().
+* We need to take a reference to avoid a release during
+* signalling (which can cause a recursive lock of obj->lock).
+* If refcount was already zero, another thread is already
+* taking care of destroying the fence.
 */
-   dma_fence_signal_locked(&pt->base);
+   if (!dma_fence_get_rcu(&pt->base))
+   continue;
+
+   list_move_tail(&pt->link, &signal);
+   rb_erase(&pt->node, &obj->pt_tree);
}
 
spin_unlock_irq(&obj->lock);
+
+   list_for_each_entry_safe(pt, next, &signal, link) {
+   /*
+* This needs to be cleared before release, otherwise the
+* timeline_fence_release function gets confused about also
+* removing the fence from the pt_tree.
+*/
+   list_del_init(&pt->link);
+
+   dma_fence_signal(&pt->base);
+   dma_fence_put(&pt->base);
+   }
 }
 
 /**
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 2/3] dma-buf/sw_sync: Separate signal/timeline locks

2020-07-14 Thread Chris Wilson
Since we decouple the sync_pt from the timeline tree upon release, in
order to allow releasing the sync_pt from a signal callback we need to
separate the sync_pt signaling lock from the timeline tree lock.

v2: Mark up the unlocked read of the current timeline value.
v3: Store a timeline pointer in the sync_pt as we cannot use the common
fence->lock trick to find our parent anymore.

Suggested-by: Bas Nieuwenhuizen 
Signed-off-by: Chris Wilson 
Cc: Bas Nieuwenhuizen 
---
 drivers/dma-buf/sw_sync.c| 40 +---
 drivers/dma-buf/sync_debug.c |  2 +-
 drivers/dma-buf/sync_debug.h | 13 +++-
 3 files changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 807c82148062..17a5c1a3b7ce 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -123,33 +123,39 @@ static const char *timeline_fence_get_driver_name(struct 
dma_fence *fence)
 
 static const char *timeline_fence_get_timeline_name(struct dma_fence *fence)
 {
-   struct sync_timeline *parent = dma_fence_parent(fence);
-
-   return parent->name;
+   return sync_timeline(fence)->name;
 }
 
 static void timeline_fence_release(struct dma_fence *fence)
 {
struct sync_pt *pt = dma_fence_to_sync_pt(fence);
-   struct sync_timeline *parent = dma_fence_parent(fence);
-   unsigned long flags;
+   struct sync_timeline *parent = pt->timeline;
 
-   spin_lock_irqsave(fence->lock, flags);
if (!list_empty(&pt->link)) {
-   list_del(&pt->link);
-   rb_erase(&pt->node, &parent->pt_tree);
+   unsigned long flags;
+
+   spin_lock_irqsave(&parent->lock, flags);
+   if (!list_empty(&pt->link)) {
+   list_del(&pt->link);
+   rb_erase(&pt->node, &parent->pt_tree);
+   }
+   spin_unlock_irqrestore(&parent->lock, flags);
}
-   spin_unlock_irqrestore(fence->lock, flags);
 
sync_timeline_put(parent);
dma_fence_free(fence);
 }
 
-static bool timeline_fence_signaled(struct dma_fence *fence)
+static int timeline_value(struct dma_fence *fence)
 {
-   struct sync_timeline *parent = dma_fence_parent(fence);
+   return READ_ONCE(sync_timeline(fence)->value);
+}
 
-   return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops);
+static bool timeline_fence_signaled(struct dma_fence *fence)
+{
+   return !__dma_fence_is_later(fence->seqno,
+timeline_value(fence),
+fence->ops);
 }
 
 static bool timeline_fence_enable_signaling(struct dma_fence *fence)
@@ -166,9 +172,7 @@ static void timeline_fence_value_str(struct dma_fence 
*fence,
 static void timeline_fence_timeline_value_str(struct dma_fence *fence,
 char *str, int size)
 {
-   struct sync_timeline *parent = dma_fence_parent(fence);
-
-   snprintf(str, size, "%d", parent->value);
+   snprintf(str, size, "%d", timeline_value(fence));
 }
 
 static const struct dma_fence_ops timeline_fence_ops = {
@@ -252,12 +256,14 @@ static struct sync_pt *sync_pt_create(struct 
sync_timeline *obj,
return NULL;
 
sync_timeline_get(obj);
-   dma_fence_init(&pt->base, &timeline_fence_ops, &obj->lock,
+   spin_lock_init(&pt->lock);
+   dma_fence_init(&pt->base, &timeline_fence_ops, &pt->lock,
   obj->context, value);
INIT_LIST_HEAD(&pt->link);
+   pt->timeline = obj;
 
spin_lock_irq(&obj->lock);
-   if (!dma_fence_is_signaled_locked(&pt->base)) {
+   if (!dma_fence_is_signaled(&pt->base)) {
struct rb_node **p = &obj->pt_tree.rb_node;
struct rb_node *parent = NULL;
 
diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c
index 101394f16930..2188ee17e889 100644
--- a/drivers/dma-buf/sync_debug.c
+++ b/drivers/dma-buf/sync_debug.c
@@ -65,7 +65,7 @@ static const char *sync_status_str(int status)
 static void sync_print_fence(struct seq_file *s,
 struct dma_fence *fence, bool show)
 {
-   struct sync_timeline *parent = dma_fence_parent(fence);
+   struct sync_timeline *parent = sync_timeline(fence);
int status;
 
status = dma_fence_get_status_locked(fence);
diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h
index 6176e52ba2d7..56589dae2159 100644
--- a/drivers/dma-buf/sync_debug.h
+++ b/drivers/dma-buf/sync_debug.h
@@ -45,23 +45,26 @@ struct sync_timeline {
struct list_headsync_timeline_list;
 };
 
-static inline struct sync_timeline *dma_fence_parent(struct dma_fence *fence)
-{
-   return container_of(fence->lock, struct sync_timeline, lock);
-}
-
 /**
  * struct sync_pt - sync_pt object
  * @base: base fence object
  * @link: link on the sync timeline's list
  * @node: node in the s

[PATCH v2 3/3] dma-buf/selftests: Add locking selftests for sw_sync

2020-07-14 Thread Chris Wilson
While sw_sync is purely a debug facility for userspace to create fences
and timelines it can control, nevertheless it has some tricky locking
semantics of its own. In particular, Bas Nieuwenhuizen reported that we
had reintroduced a deadlock if a signal callback attempted to destroy
the fence. So let's add a few trivial selftests to make sure that once
fixed again, it stays fixed.

Signed-off-by: Chris Wilson 
Cc: Bas Nieuwenhuizen 
Reviewed-by: Bas Nieuwenhuizen 
---
 drivers/dma-buf/Makefile |   3 +-
 drivers/dma-buf/selftests.h  |   1 +
 drivers/dma-buf/st-sw_sync.c | 279 +++
 drivers/dma-buf/sw_sync.c|  39 +
 drivers/dma-buf/sync_debug.h |   8 +
 5 files changed, 329 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma-buf/st-sw_sync.c

diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 995e05f609ff..9be4d4611609 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_UDMABUF) += udmabuf.o
 dmabuf_selftests-y := \
selftest.o \
st-dma-fence.o \
-   st-dma-fence-chain.o
+   st-dma-fence-chain.o \
+   st-sw_sync.o
 
 obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
index bc8cea67bf1e..232499a24872 100644
--- a/drivers/dma-buf/selftests.h
+++ b/drivers/dma-buf/selftests.h
@@ -12,3 +12,4 @@
 selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
 selftest(dma_fence, dma_fence)
 selftest(dma_fence_chain, dma_fence_chain)
+selftest(sw_sync, sw_sync)
diff --git a/drivers/dma-buf/st-sw_sync.c b/drivers/dma-buf/st-sw_sync.c
new file mode 100644
index ..145fd330f1c6
--- /dev/null
+++ b/drivers/dma-buf/st-sw_sync.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "sync_debug.h"
+#include "selftest.h"
+
+static int sanitycheck(void *arg)
+{
+   struct sync_timeline *tl;
+   struct dma_fence *f;
+   int err = -ENOMEM;
+
+   /* Quick check we can create the timeline and syncpt */
+
+   tl = st_sync_timeline_create("mock");
+   if (!tl)
+   return -ENOMEM;
+
+   f = st_sync_pt_create(tl, 1);
+   if (!f)
+   goto out;
+
+   dma_fence_signal(f);
+   dma_fence_put(f);
+
+   err = 0;
+out:
+   st_sync_timeline_put(tl);
+   return err;
+}
+
+static int signal(void *arg)
+{
+   struct sync_timeline *tl;
+   struct dma_fence *f;
+   int err = -EINVAL;
+
+   /* Check that the syncpt fence is signaled when the timeline advances */
+
+   tl = st_sync_timeline_create("mock");
+   if (!tl)
+   return -ENOMEM;
+
+   f = st_sync_pt_create(tl, 1);
+   if (!f) {
+   err = -ENOMEM;
+   goto out;
+   }
+
+   if (dma_fence_is_signaled(f)) {
+   pr_err("syncpt:%lld signaled too early\n", f->seqno);
+   goto out_fence;
+   }
+
+   st_sync_timeline_signal(tl, 1);
+
+   if (!dma_fence_is_signaled(f)) {
+   pr_err("syncpt:%lld not signaled after increment\n", f->seqno);
+   goto out_fence;
+   }
+
+   err = 0;
+out_fence:
+   dma_fence_signal(f);
+   dma_fence_put(f);
+out:
+   st_sync_timeline_put(tl);
+   return err;
+}
+
+struct cb_destroy {
+   struct dma_fence_cb cb;
+   struct dma_fence *f;
+};
+
+static void cb_destroy(struct dma_fence *fence, struct dma_fence_cb *_cb)
+{
+   struct cb_destroy *cb = container_of(_cb, typeof(*cb), cb);
+
+   pr_info("syncpt:%llx destroying syncpt:%llx\n",
+   fence->seqno, cb->f->seqno);
+   dma_fence_put(cb->f);
+   cb->f = NULL;
+}
+
+static int cb_autodestroy(void *arg)
+{
+   struct sync_timeline *tl;
+   struct cb_destroy cb;
+   int err = -EINVAL;
+
+   /* Check that we can drop the final syncpt reference from a callback */
+
+   tl = st_sync_timeline_create("mock");
+   if (!tl)
+   return -ENOMEM;
+
+   cb.f = st_sync_pt_create(tl, 1);
+   if (!cb.f) {
+   err = -ENOMEM;
+   goto out;
+   }
+
+   if (dma_fence_add_callback(cb.f, &cb.cb, cb_destroy)) {
+   pr_err("syncpt:%lld signaled before increment\n", cb.f->seqno);
+   goto out;
+   }
+
+   st_sync_timeline_signal(tl, 1);
+   if (cb.f) {
+   pr_err("syncpt:%lld callback not run\n", cb.f->seqno);
+   dma_fence_put(cb.f);
+   goto out;
+   }
+
+   err = 0;
+out:
+   st_sync_timeline_put(tl);
+   return err;
+}
+
+static int cb_destroy_12(void *arg)
+{
+   struct sync_timeline *tl;
+   struct cb_destroy cb;
+   struct dma_fence *f;
+   int err = -EINVAL;
+
+   /* Check that we can drop some other syncpt refe

sw_sync callback deadlock

2020-07-14 Thread Chris Wilson
Take 2. dma_fence_parent() relied on fence->lock pointing into the
sync_timeline which is no more, so we need a sync_pt->timeline
backpointer instead.
-Chris


___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 25/59] drm/kmb: Display clock enable/disable

2020-07-14 Thread Anitha Chrisanthus
Get clock info from DT and enable it during initialization.
Also changed name of the driver to "kmb,display" to match other
entries in the DT.

v2: fixed error in clk_disable

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 41 +++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 5a2ff9d..71fdb94 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -32,6 +32,25 @@
 /*IRQ handler*/
 static irqreturn_t kmb_isr(int irq, void *arg);
 
+static struct clk *clk_lcd;
+static struct clk *clk_mipi;
+
+static int kmb_display_clk_enable(void)
+{
+   clk_prepare_enable(clk_lcd);
+   clk_prepare_enable(clk_mipi);
+   return 0;
+}
+
+static int kmb_display_clk_disable(void)
+{
+   if (clk_lcd)
+   clk_disable_unprepare(clk_lcd);
+   if (clk_mipi)
+   clk_disable_unprepare(clk_mipi);
+   return 0;
+}
+
 static int kmb_load(struct drm_device *drm, unsigned long flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
@@ -153,6 +172,19 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}
 
+   /* enable display clocks*/
+   clk_lcd = clk_get(&pdev->dev, "clk_lcd");
+   if (!clk_lcd) {
+   DRM_ERROR("clk_get() failed clk_lcd\n");
+   goto setup_fail;
+   }
+   clk_mipi = clk_get(&pdev->dev, "clk_mipi");
+   if (!clk_mipi) {
+   DRM_ERROR("clk_get() failed clk_mipi\n");
+   goto setup_fail;
+   }
+   kmb_display_clk_enable();
+
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n");
@@ -382,6 +414,11 @@ static void kmb_drm_unbind(struct device *dev)
of_reserved_mem_device_release(drm->dev);
drm_mode_config_cleanup(drm);
 
+   /*release clks */
+   kmb_display_clk_disable();
+   clk_put(clk_lcd);
+   clk_put(clk_mipi);
+
drm_dev_put(drm);
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
@@ -420,8 +457,8 @@ static int kmb_remove(struct platform_device *pdev)
return 0;
 }
 
-static const struct of_device_id kmb_of_match[] = {
-   {.compatible = "lcd"},
+static const struct of_device_id  kmb_of_match[] = {
+   {.compatible = "kmb,display"},
{},
 };
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 43/59] drm/kmb: Changed name of driver to kmb-drm

2020-07-14 Thread Anitha Chrisanthus
name change

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/Makefile  | 4 ++--
 drivers/gpu/drm/kmb/kmb_drv.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/kmb/Makefile b/drivers/gpu/drm/kmb/Makefile
index 8102bc9..527d737 100644
--- a/drivers/gpu/drm/kmb/Makefile
+++ b/drivers/gpu/drm/kmb/Makefile
@@ -1,2 +1,2 @@
-kmb-display-y := kmb_crtc.o kmb_drv.o kmb_plane.o kmb_dsi.o
-obj-$(CONFIG_DRM_KMB_DISPLAY)  += kmb-display.o
+kmb-drm-y := kmb_crtc.o kmb_drv.o kmb_plane.o kmb_dsi.o
+obj-$(CONFIG_DRM_KMB_DISPLAY)  += kmb-drm.o
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 039dd21..bbf3e649 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -447,7 +447,7 @@ static struct drm_driver kmb_driver = {
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
.gem_prime_mmap = drm_gem_cma_prime_mmap,
.fops = &fops,
-   .name = "kmb_display",
+   .name = "kmb-drm",
.desc = "KEEMBAY DISPLAY DRIVER ",
.date = "20190122",
.major = 1,
@@ -630,7 +630,7 @@ static struct platform_driver kmb_platform_driver = {
.probe  = kmb_probe,
.remove = kmb_remove,
.driver = {
-   .name = "kmb_display",
+   .name = "kmb-drm",
.pm = &kmb_pm_ops,
.of_match_table = kmb_of_match,
},
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 55/59] drm/kmb: Added useful messages in LCD ISR

2020-07-14 Thread Anitha Chrisanthus
Print messages for LCD DMA FIFO errors.

v2: corrected spelling

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c   | 68 +++--
 drivers/gpu/drm/kmb/kmb_plane.h |  2 ++
 2 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 55574c1..7fcab4b 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -361,15 +361,15 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
 * disabled but actually disable the plane when EOF irq is
 * being handled.
 */
-   for (plane_id = LAYER_0; plane_id < KMB_MAX_PLANES;
-   plane_id++) {
+   for (plane_id = LAYER_0; plane_id < KMB_MAX_PLANES; plane_id++) 
{
if (plane_status[plane_id].disable) {
kmb_clr_bitmask_lcd(dev_p,
-   LCD_LAYERn_DMA_CFG(plane_id),
-   LCD_DMA_LAYER_ENABLE);
+   LCD_LAYERn_DMA_CFG
+   (plane_id),
+   LCD_DMA_LAYER_ENABLE);
 
kmb_clr_bitmask_lcd(dev_p, LCD_CONTROL,
-   plane_status[plane_id].ctrl);
+   plane_status[plane_id].ctrl);
 
plane_status[plane_id].disable = false;
}
@@ -381,11 +381,6 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_LINE_CMP);
}
 
-   if (status & LCD_INT_LAYER) {
-   /* Clear layer interrupts */
-   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_LAYER);
-   }
-
if (status & LCD_INT_VERT_COMP) {
/* Read VSTATUS */
val = kmb_read_lcd(dev_p, LCD_VSTATUS);
@@ -403,6 +398,59 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
}
}
 
+   if (status & LCD_INT_DMA_ERR) {
+   val = (status & LCD_INT_DMA_ERR);
+   /* LAYER0 - VL0 */
+   if (val & LAYER0_DMA_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER0:VL0 DMA UNDERFLOW val = 0x%lx", val);
+   if (val & LAYER0_DMA_FIFO_OVERFLOW)
+   DRM_INFO("LAYER0:VL0 DMA OVERFLOW val = 0x%lx", val);
+   if (val & LAYER0_DMA_CB_FIFO_OVERFLOW)
+   DRM_INFO("LAYER0:VL0 DMA CB OVERFLOW val = 0x%lx", val);
+   if (val & LAYER0_DMA_CB_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER0:VL0 DMA CB UNDERFLOW val = 0x%lx",
+val);
+   if (val & LAYER0_DMA_CR_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER0:VL0 DMA CR UNDERFLOW val = 0x%lx",
+val);
+   if (val & LAYER0_DMA_CR_FIFO_OVERFLOW)
+   DRM_INFO("LAYER0:VL0 DMA CR OVERFLOW val = 0x%lx", val);
+
+   /* LAYER1 - VL1 */
+   if (val & LAYER1_DMA_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER1:VL1 DMA UNDERFLOW val = 0x%lx", val);
+   if (val & LAYER1_DMA_FIFO_OVERFLOW)
+   DRM_INFO("LAYER1:VL1 DMA OVERFLOW val = 0x%lx", val);
+   if (val & LAYER1_DMA_CB_FIFO_OVERFLOW)
+   DRM_INFO("LAYER1:VL1 DMA CB OVERFLOW val = 0x%lx", val);
+   if (val & LAYER1_DMA_CB_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER1:VL1 DMA CB UNDERFLOW val = 0x%lx",
+val);
+   if (val & LAYER1_DMA_CR_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER1:VL1 DMA CR UNDERFLOW val = 0x%lx",
+val);
+   if (val & LAYER1_DMA_CR_FIFO_OVERFLOW)
+   DRM_INFO("LAYER1:VL1 DMA CR OVERFLOW val = 0x%lx", val);
+
+   /* LAYER2 - GL0 */
+   if (val & LAYER2_DMA_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER2:GL0 DMA UNDERFLOW val = 0x%lx", val);
+   if (val & LAYER2_DMA_FIFO_OVERFLOW)
+   DRM_INFO("LAYER2:GL0 DMA OVERFLOW val = 0x%lx", val);
+
+   /* LAYER3 - GL1 */
+   if (val & LAYER3_DMA_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER3:GL1 DMA UNDERFLOW val = 0x%lx", val);
+   if (val & LAYER3_DMA_FIFO_UNDERFLOW)
+   DRM_INFO("LAYER3:GL1 DMA OVERFLOW val = 0x%lx", val);
+
+   }
+
+   if (status & LCD_INT_LAYER) {
+   /* Clear layer interrupts */
+   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_LAYER);
+   }
+
/* Clear all interrupts */
kmb_set_bitmask_lcd(dev_p, LCD_INT_CLEAR, 1);
re

[PATCH v2 30/59] drm/kmb: call bridge init in the very beginning

2020-07-14 Thread Anitha Chrisanthus
of probe and return probe_defer early on, so that all the other
initializations can be done after adv driver is loaded successfully.

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c |  74 +-
 drivers/gpu/drm/kmb/kmb_dsi.c | 144 ++
 drivers/gpu/drm/kmb/kmb_dsi.h |   6 +-
 3 files changed, 138 insertions(+), 86 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 36edfbf..76f3c43 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -37,11 +37,24 @@ static struct clk *clk_lcd;
 static struct clk *clk_mipi;
 
 static int probe_deferred;
+struct drm_bridge *adv_bridge;
 
 static int kmb_display_clk_enable(void)
 {
-   clk_prepare_enable(clk_lcd);
-   clk_prepare_enable(clk_mipi);
+   int ret;
+
+   ret = clk_prepare_enable(clk_lcd);
+   if (ret) {
+   DRM_ERROR("Failed to enable LCD clock: %d\n", ret);
+   return ret;
+   }
+
+   ret = clk_prepare_enable(clk_mipi);
+   if (ret) {
+   DRM_ERROR("Failed to enable MIPI clock: %d\n", ret);
+   return ret;
+   }
+   DRM_INFO("SUCCESS : enabled LCD MIPI clocks\n");
return 0;
 }
 
@@ -86,8 +99,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 *}
 */
/* LCD mmio */
-   if (!probe_deferred) {
-   probe_deferred = 1;
+   probe_deferred = 1;
 
if (!request_mem_region(LCD_BASE_ADDR, LCD_MMIO_SIZE, "kmb-lcd")) {
DRM_ERROR("failed to reserve LCD registers\n");
@@ -120,9 +132,10 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 * lists LCD at 79 and 82 for MIPI under MSS CPU -
 * firmware has to redirect it to A53
 */
-/*TBD read and check for correct product version here */
 
-   /* Get the optional framebuffer memory resource */
+   /*TBD read and check for correct product version here */
+
+   /* Get the optional framebuffer memory resource */
ret = of_reserved_mem_device_init(drm->dev);
if (ret && ret != -ENODEV)
return ret;
@@ -134,8 +147,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}
 
-/* ret = kmb_dsi_init(drm, bridge);*/
-   ret = kmb_dsi_init(drm);
+   ret = kmb_dsi_init(drm, adv_bridge);
if (ret == -EPROBE_DEFER) {
DRM_INFO("%s: wait for external bridge driver DT", __func__);
return -EPROBE_DEFER;
@@ -143,7 +155,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
DRM_ERROR("failed to initialize DSI\n");
goto setup_fail;
}
-}
/* enable display clocks*/
clk_lcd = clk_get(&pdev->dev, "clk_lcd");
if (!clk_lcd) {
@@ -157,10 +168,9 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}
DRM_INFO("%s : %d\n", __func__, __LINE__);
-   kmb_display_clk_enable();
-
-   DRM_INFO("%s : %d\n", __func__, __LINE__);
+   ret = kmb_display_clk_enable();
 
+   DRM_INFO("%s : %d clk enabling ret=%d\n", __func__, __LINE__, ret);
return 0;
 
drm_crtc_cleanup(&dev_p->crtc);
@@ -268,7 +278,7 @@ static struct drm_driver kmb_driver = {
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
.gem_prime_mmap = drm_gem_cma_prime_mmap,
.fops = &fops,
-   .name = "kmb",
+   .name = "kmb_display",
.desc = "KEEMBAY DISPLAY DRIVER ",
.date = "20190122",
.major = 1,
@@ -277,7 +287,7 @@ static struct drm_driver kmb_driver = {
 
 static int kmb_drm_bind(struct device *dev)
 {
-   struct drm_device *drm;
+   struct drm_device *drm = NULL;
struct kmb_drm_private *lcd;
int ret;
 
@@ -296,7 +306,9 @@ static int kmb_drm_bind(struct device *dev)
dev_set_drvdata(dev, drm);
 
kmb_setup_mode_config(drm);
-   DRM_DEBUG("kmb_bind : after kmb_setup_mode_config\n");
+   dev_set_drvdata(dev, drm);
+
+   /* load the driver */
ret = kmb_load(drm, 0);
DRM_INFO("%s : %d ret = %d\n", __func__, __LINE__, ret);
if (ret == -EPROBE_DEFER) {
@@ -337,7 +349,6 @@ static int kmb_drm_bind(struct device *dev)
drm_kms_helper_poll_fini(drm);
 err_vblank:
pm_runtime_disable(drm->dev);
-   component_unbind_all(dev, drm);
of_node_put(lcd->crtc.port);
lcd->crtc.port = NULL;
drm_irq_uninstall(drm);
@@ -355,9 +366,9 @@ static void kmb_drm_unbind(struct device *dev)
struct drm_device *drm = dev_get_drvdata(dev);
struct kmb_drm_private *dev_p = to_kmb(drm);
 
+   dump_stack();
drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm);
-   component_unbind_all(dev, drm);
of_node_put(dev_p->crtc.port);
 

[PATCH v2 07/59] drm/kmb: Set OUT_FORMAT_CFG register

2020-07-14 Thread Anitha Chrisanthus
v2: code review changes
Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 14 +-
 drivers/gpu/drm/kmb/kmb_regs.h  |  1 +
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 74a3573..cb05cb8 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -208,7 +208,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
unsigned int dma_len;
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
unsigned int dma_cfg;
-   unsigned int ctrl = 0, val = 0;
+   unsigned int ctrl = 0, val = 0, out_format = 0;
unsigned int src_w, src_h, crtc_x, crtc_y;
unsigned char plane_id = kmb_plane->id;
 
@@ -279,6 +279,18 @@ static void kmb_plane_atomic_update(struct drm_plane 
*plane,
/* enable DMA */
kmb_write(lcd, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
 
+   /* FIXME no doc on how to set output format - may need to change
+* this later
+*/
+   if (val & LCD_LAYER_BGR_ORDER)
+   out_format |= LCD_OUTF_BGR_ORDER;
+   else if (val & LCD_LAYER_CRCB_ORDER)
+   out_format |= LCD_OUTF_CRCB_ORDER;
+   /* do not interleave RGB channels for mipi Tx compatibility */
+   out_format |= LCD_OUTF_MIPI_RGB_MODE;
+   /* pixel format from LCD_LAYER_CFG */
+   out_format |= ((val >> 9) & 0x1F);
+   kmb_write(lcd, LCD_OUT_FORMAT_CFG, out_format);
 }
 
 static const struct drm_plane_helper_funcs kmb_plane_helper_funcs = {
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index 8346a04..8b67f2b 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -320,6 +320,7 @@
 #define LCD_OUTF_BGR_ORDER   (1 << 5)
 #define LCD_OUTF_Y_ORDER (1 << 6)
 #define LCD_OUTF_CRCB_ORDER  (1 << 7)
+#define LCD_OUTF_MIPI_RGB_MODE   (1 << 18)
 
 #define LCD_HSYNC_WIDTH(0x4 * 0x801)
 #define LCD_H_BACKPORCH(0x4 * 0x802)
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 12/59] drm/kmb: Part3 of Mipi Tx initialization

2020-07-14 Thread Anitha Chrisanthus
This initializes the multichannel fifo in the mipi transmitter and
sets the LCD to mipi interconnect which connects LCD to MIPI ctrl #6

v2: code review changes to make code simpler

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.h  | 25 +++---
 drivers/gpu/drm/kmb/kmb_dsi.c  | 58 ++
 drivers/gpu/drm/kmb/kmb_dsi.h  |  3 +++
 drivers/gpu/drm/kmb/kmb_regs.h | 30 +++---
 4 files changed, 99 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index d2a0f91..f1d5b3a 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -8,8 +8,8 @@
 
 #include "kmb_regs.h"
 
-#define KMB_MAX_WIDTH  16384 /*max width in pixels */
-#define KMB_MAX_HEIGHT 16384 /*max height in pixels */
+#define KMB_MAX_WIDTH  16384   /*max width in pixels */
+#define KMB_MAX_HEIGHT 16384   /*max height in pixels */
 
 struct kmb_drm_private {
struct drm_device drm;
@@ -64,6 +64,11 @@ static inline void kmb_write_bits(struct kmb_drm_private 
*lcd,
 }
 #endif
 
+static inline void kmb_write(void *reg, u32 value)
+{
+   writel(value, reg);
+}
+
 static inline void kmb_write_lcd(unsigned int reg, u32 value)
 {
writel(value, (LCD_BASE_ADDR + reg));
@@ -85,7 +90,7 @@ static inline u32 kmb_read_mipi(unsigned int reg)
 }
 
 static inline void kmb_write_bits_mipi(unsigned int reg, u32 offset,
-   u32 num_bits, u32 value)
+  u32 num_bits, u32 value)
 {
u32 reg_val = kmb_read_mipi(reg);
u32 mask = (1 << num_bits) - 1;
@@ -97,6 +102,20 @@ static inline void kmb_write_bits_mipi(unsigned int reg, 
u32 offset,
kmb_write_mipi(reg, reg_val);
 }
 
+static inline void kmb_set_bit_mipi(unsigned int reg, u32 offset)
+{
+   u32 reg_val = kmb_read_mipi(reg);
+
+   kmb_write_mipi(reg, reg_val | (1 << offset));
+}
+
+static inline void kmb_clr_bit_mipi(unsigned int reg, u32 offset)
+{
+   u32 reg_val = kmb_read_mipi(reg);
+
+   kmb_write_mipi(reg, reg_val & (~(1 << offset)));
+}
+
 int kmb_setup_crtc(struct drm_device *dev);
 void kmb_set_scanout(struct kmb_drm_private *lcd);
 #endif /* __KMB_DRV_H__ */
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 2326d3b..a5b9681 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -503,10 +503,41 @@ static void mipi_tx_fg_cfg(struct kmb_drm_private 
*dev_priv, u8 frame_gen,
mipi_tx_fg_cfg_regs(dev_priv, frame_gen, &fg_t_cfg);
 }
 
+static void mipi_tx_multichannel_fifo_cfg(u8 active_lanes, u8 vchannel_id)
+{
+   u32 fifo_size, fifo_rthreshold;
+   u32 ctrl_no = MIPI_CTRL6;
+
+   /*clear all mc fifo channel sizes and thresholds*/
+   kmb_write_mipi(MIPI_TX_HS_MC_FIFO_CTRL_EN, 0);
+   kmb_write_mipi(MIPI_TX_HS_MC_FIFO_CHAN_ALLOC0, 0);
+   kmb_write_mipi(MIPI_TX_HS_MC_FIFO_CHAN_ALLOC1, 0);
+   kmb_write_mipi(MIPI_TX_HS_MC_FIFO_RTHRESHOLD0, 0);
+   kmb_write_mipi(MIPI_TX_HS_MC_FIFO_RTHRESHOLD1, 0);
+
+   fifo_size = (active_lanes > MIPI_D_LANES_PER_DPHY) ?
+   MIPI_CTRL_4LANE_MAX_MC_FIFO_LOC :
+   MIPI_CTRL_2LANE_MAX_MC_FIFO_LOC;
+   /*MC fifo size for virtual channels 0-3 */
+   /*
+*REG_MC_FIFO_CHAN_ALLOC0: [8:0]-channel0, [24:16]-channel1
+*REG_MC_FIFO_CHAN_ALLOC1: [8:0]-2, [24:16]-channel3
+*/
+   SET_MC_FIFO_CHAN_ALLOC(ctrl_no, vchannel_id, fifo_size);
+
+   /*set threshold to half the fifo size, actual size=size*16*/
+   fifo_rthreshold = ((fifo_size + 1) * 8) & BIT_MASK_16;
+   SET_MC_FIFO_RTHRESHOLD(ctrl_no, vchannel_id, fifo_rthreshold);
+
+   /*enable the MC FIFO channel corresponding to the Virtual Channel */
+   kmb_set_bit_mipi(MIPI_TXm_HS_MC_FIFO_CTRL_EN(ctrl_no), vchannel_id);
+}
+
 static u32 mipi_tx_init_cntrl(struct kmb_drm_private *dev_priv,
- struct mipi_ctrl_cfg *ctrl_cfg)
+   struct mipi_ctrl_cfg *ctrl_cfg)
 {
u32 ret;
+   u8 active_vchannels = 0;
u8 frame_id, sect;
u32 bits_per_pclk = 0;
u32 word_count = 0;
@@ -544,18 +575,23 @@ static u32 mipi_tx_init_cntrl(struct kmb_drm_private 
*dev_priv,
 
/* set frame specific parameters */
mipi_tx_fg_cfg(dev_priv, frame_id, ctrl_cfg->active_lanes,
-  bits_per_pclk,
-  word_count,
-  ctrl_cfg->lane_rate_mbps,
-  ctrl_cfg->tx_ctrl_cfg.frames[frame_id]);
-   /*function for setting frame sepecific parameters will be
-* called here
-*/
-   /*bits_per_pclk and word_count will be passed in to this
-* function
-*/
+

[PATCH v2 58/59] drm/kmb: Get System Clock from SCMI

2020-07-14 Thread Anitha Chrisanthus
System clock is different for A0 and B0 silicons, so get it directly
from clk_PLL0 through SCMI calls.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 11 +++
 drivers/gpu/drm/kmb/kmb_drv.h |  1 +
 drivers/gpu/drm/kmb/kmb_dsi.c | 12 +---
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 559742b8..17d303f 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -39,6 +39,7 @@ static struct clk *clk_lcd;
 static struct clk *clk_mipi;
 static struct clk *clk_mipi_ecfg;
 static struct clk *clk_mipi_cfg;
+static struct clk *clk_pll0;
 
 struct drm_bridge *adv_bridge;
 
@@ -122,6 +123,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 #ifdef ICAM_LCD_QOS
int val = 0;
 #endif
+   struct device_node *vpu_dev;
 
/* Map MIPI MMIO registers */
dev_p->mipi_mmio = kmb_map_mmio(pdev, "mipi_regs");
@@ -188,6 +190,15 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
DRM_ERROR("clk_get() failed clk_mipi_cfg\n");
goto setup_fail;
}
+   vpu_dev = of_find_node_by_path("/soc/vpu-ipc");
+   DRM_INFO("vpu node = %pOF", vpu_dev);
+   clk_pll0 = of_clk_get_by_name(vpu_dev, "pll_0_out_0");
+   if (IS_ERR(clk_pll0)) {
+   DRM_ERROR("clk_get() failed clk_pll0 ");
+   goto setup_fail;
+   }
+   dev_p->sys_clk_mhz = clk_get_rate(clk_pll0)/100;
+   DRM_INFO("system clk = %d Mhz", dev_p->sys_clk_mhz);
 #ifdef LCD_TEST
/* Set LCD clock to 200 Mhz */
DRM_DEBUG("Get clk_lcd before set = %ld\n", clk_get_rate(clk_lcd));
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 939f8b4..72d0746 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -38,6 +38,7 @@ struct kmb_drm_private {
spinlock_t  irq_lock;
int irq_lcd;
int irq_mipi;
+   int sys_clk_mhz;
dma_addr_t  fb_addr;
 };
 
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 47798ed..8f8b50c 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -588,20 +588,10 @@ static void mipi_tx_fg_cfg_regs(struct kmb_drm_private 
*dev_p, u8 frame_gen,
u32 ppl_llp_ratio;
u32 ctrl_no = MIPI_CTRL6, reg_adr, val, offset;
 
-#ifdef GET_SYS_CLK
-   /* Get system clock for blanking period cnfigurations */
-   sc = get_clock_frequency(CPR_CLK_SYSTEM, &sysclk);
-   if (sc)
-   return sc;
-
-   /* Convert to MHZ */
-   sysclk /= 1000;
-#else
/* 500 Mhz system clock minus 50 to account for the difference in
 * MIPI clock speed in RTL tests
 */
-   sysclk = KMB_SYS_CLK_MHZ - 50;
-#endif
+   sysclk = dev_p->sys_clk_mhz - 50;
 
/* PPL-Pixel Packing Layer, LLP-Low Level Protocol
 * Frame genartor timing parameters are clocked on the system clock,
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 49/59] drm/kmb: Disable ping pong mode

2020-07-14 Thread Anitha Chrisanthus
Disable ping pong mode otherwise video corruption results,
use continuous mode and also fetch the dma
addresses before disabling dma. For now, only initialize the dma and
planes once and for next plane updates only update the addresses for
dma.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 301 
 drivers/gpu/drm/kmb/kmb_plane.h |   8 ++
 2 files changed, 159 insertions(+), 150 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 5fd1837..a1d616a 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -83,11 +83,12 @@ static const u32 kmb_formats_v[] = {
 #define LCD_INT_GL1 (LAYER3_DMA_DONE | LAYER3_DMA_IDLE | LCD_INT_GL1_ERR)
 
 const uint32_t layer_irqs[] = {
-   LCD_INT_VL0,
-   LCD_INT_VL1,
-   LCD_INT_GL0,
-   LCD_INT_GL1
- };
+   LCD_INT_VL0,
+   LCD_INT_VL1,
+   LCD_INT_GL0,
+   LCD_INT_GL1
+};
+
 /*Conversion (yuv->rgb) matrix from myriadx */
 static const u32 csc_coef_lcd[] = {
1024, 0, 1436,
@@ -96,7 +97,6 @@ static const u32 csc_coef_lcd[] = {
-179, 125, -226
 };
 
-
 static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
 {
int i;
@@ -114,7 +114,6 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
struct drm_framebuffer *fb;
int ret;
 
-
fb = state->fb;
 
if (!fb || !state->crtc)
@@ -130,7 +129,7 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
 }
 
 static void kmb_plane_atomic_disable(struct drm_plane *plane,
-   struct drm_plane_state *state)
+struct drm_plane_state *state)
 {
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
int ctrl = 0;
@@ -156,14 +155,13 @@ static void kmb_plane_atomic_disable(struct drm_plane 
*plane,
}
 
kmb_clr_bitmask_lcd(dev_p, LCD_LAYERn_DMA_CFG(plane_id),
-   LCD_DMA_LAYER_ENABLE);
+   LCD_DMA_LAYER_ENABLE);
kmb_clr_bitmask_lcd(dev_p, LCD_CONTROL, ctrl);
DRM_INFO("%s : %d lcd_ctrl = 0x%x lcd_int_enable=0x%x\n",
-   __func__, __LINE__, kmb_read_lcd(dev_p, LCD_CONTROL),
-   kmb_read_lcd(dev_p, LCD_INT_ENABLE));
+__func__, __LINE__, kmb_read_lcd(dev_p, LCD_CONTROL),
+kmb_read_lcd(dev_p, LCD_INT_ENABLE));
 }
 
-
 unsigned int set_pixel_format(u32 format)
 {
unsigned int val = 0;
@@ -198,8 +196,8 @@ unsigned int set_pixel_format(u32 format)
val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
| LCD_LAYER_CRCB_ORDER;
break;
-   /* packed formats */
-   /* looks hw requires B & G to be swapped when RGB */
+   /* packed formats */
+   /* looks hw requires B & G to be swapped when RGB */
case DRM_FORMAT_RGB332:
val = LCD_LAYER_FORMAT_RGB332 | LCD_LAYER_BGR_ORDER;
break;
@@ -263,7 +261,7 @@ unsigned int set_bits_per_pixel(const struct 
drm_format_info *format)
return val;
}
 
-   bpp += 8*format->cpp[0];
+   bpp += 8 * format->cpp[0];
 
switch (bpp) {
case 8:
@@ -310,7 +308,6 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
 #ifdef LCD_TEST
struct drm_framebuffer *fb;
struct kmb_drm_private *dev_p;
-   dma_addr_t addr;
unsigned int width;
unsigned int height;
unsigned int dma_len;
@@ -320,6 +317,9 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
unsigned int src_w, src_h, crtc_x, crtc_y;
unsigned char plane_id;
int num_planes;
+   /*plane initialization status */
+   static int plane_init_status[KMB_MAX_PLANES] = { 0, 0, 0, 0 };
+   static dma_addr_t addr[MAX_SUB_PLANES] = { 0, 0, 0 };
 
if (!plane || !plane->state || !state)
return;
@@ -339,146 +339,145 @@ static void kmb_plane_atomic_update(struct drm_plane 
*plane,
crtc_x = plane->state->crtc_x;
crtc_y = plane->state->crtc_y;
 
-   DRM_INFO("src_w=%d src_h=%d\n", src_w, src_h);
-   kmb_write_lcd(dev_p, LCD_LAYERn_WIDTH(plane_id), src_w-1);
-   kmb_write_lcd(dev_p, LCD_LAYERn_HEIGHT(plane_id), src_h-1);
-   kmb_write_lcd(dev_p, LCD_LAYERn_COL_START(plane_id), crtc_x);
-   kmb_write_lcd(dev_p, LCD_LAYERn_ROW_START(plane_id), crtc_y);
-
-   val = set_pixel_format(fb->format->format);
-   val |= set_bits_per_pixel(fb->format);
-   /*CHECKME Leon drvr sets it to 100 try this for now */
-   val |= LCD_LAYER_FIFO_100;
-   kmb_write_lcd(dev_p, LCD_LAYERn_CFG(plane_id), val);
-
-   /*re-initialize interrupts */
-  

[PATCH v2 16/59] drm/kmb: Part6 of Mipi Tx Initialization

2020-07-14 Thread Anitha Chrisanthus
This is part2 of DPHY initialization- sets up DPHY PLLs.

v2: simplified mipi_tx_get_vco_params() based on review
v3: added WARN_ON for invalid freq
v4: fixed bug in mipi_tx_get_vco_params

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_dsi.c  | 194 +++--
 drivers/gpu/drm/kmb/kmb_regs.h |   2 +
 2 files changed, 189 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index d15cf6f..02555c6 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -28,11 +28,33 @@
 #define MIPI_TX_CFG_CLK_KHZ 24000
 
 /*DPHY Tx test codes*/
-#define TEST_CODE_HS_FREQ_RANGE_CFG0x44
-#define TEST_CODE_PLL_ANALOG_PROG  0x1F
-#define TEST_CODE_SLEW_RATE_OVERRIDE_CTRL  0xA0
-#define TEST_CODE_SLEW_RATE_DDL_LOOP_CTRL  0xA3
-#define TEST_CODE_SLEW_RATE_DDL_CYCLES 0xA4
+#define TEST_CODE_PLL_PROPORTIONAL_CHARGE_PUMP_CTRL0x0E
+#define TEST_CODE_PLL_INTEGRAL_CHARGE_PUMP_CTRL0x0F
+#define TEST_CODE_PLL_VCO_CTRL 0x12
+#define TEST_CODE_PLL_GMP_CTRL 0x13
+#define TEST_CODE_PLL_PHASE_ERR_CTRL   0x14
+#define TEST_CODE_PLL_LOCK_FILTER  0x15
+#define TEST_CODE_PLL_UNLOCK_FILTER0x16
+#define TEST_CODE_PLL_INPUT_DIVIDER0x17
+#define TEST_CODE_PLL_FEEDBACK_DIVIDER 0x18
+#define   PLL_FEEDBACK_DIVIDER_HIGH(1 << 7)
+#define TEST_CODE_PLL_OUTPUT_CLK_SEL   0x19
+#define   PLL_N_OVR_EN (1 << 4)
+#define   PLL_M_OVR_EN (1 << 5)
+#define TEST_CODE_PLL_CHARGE_PUMP_BIAS 0x1C
+#define TEST_CODE_PLL_LOCK_DETECTOR0x1D
+#define TEST_CODE_HS_FREQ_RANGE_CFG0x44
+#define TEST_CODE_PLL_ANALOG_PROG  0x1F
+#define TEST_CODE_SLEW_RATE_OVERRIDE_CTRL  0xA0
+#define TEST_CODE_SLEW_RATE_DDL_LOOP_CTRL  0xA3
+#define TEST_CODE_SLEW_RATE_DDL_CYCLES 0xA4
+
+/* D-Phy params  */
+#define PLL_N_MIN  0
+#define PLL_N_MAX  15
+#define PLL_M_MIN  62
+#define PLL_M_MAX  623
+#define PLL_FVCO_MAX   1250
 
 /*
  * These are added here only temporarily for testing,
@@ -780,8 +802,158 @@ static inline void 
set_test_mode_src_osc_freq_target_hi_bits(u32 dphy_no,
test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_DDL_CYCLES, data);
 }
 
+struct vco_params {
+   u32 freq;
+   u32 range;
+   u32 divider;
+};
+
+static struct vco_params vco_table[] = {
+   {52, 0x3f, 8},
+   {80, 0x39, 8},
+   {105, 0x2f, 4},
+   {160, 0x29, 4},
+   {210, 0x1f, 2},
+   {320, 0x19, 2},
+   {420, 0x0f, 1},
+   {630, 0x09, 1},
+   {1100, 0x03, 1},
+   {0x, 0x01, 1},
+};
+
+static void mipi_tx_get_vco_params(struct vco_params *vco)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(vco_table); i++) {
+   if (vco->freq < vco_table[i].freq) {
+   *vco = vco_table[i];
+   return;
+   }
+   }
+   WARN_ONCE(1, "Invalid vco freq = %u for PLL setup\n", vco->freq);
+}
+
+static void mipi_tx_pll_setup(u32 dphy_no, u32 ref_clk_mhz, u32 
target_freq_mhz)
+{
+   /* pll_ref_clk: - valid range: 2~64 MHz; Typically 24 MHz
+* Fvco: - valid range: 320~1250 MHz (Gen3 D-PHY)
+* Fout: - valid range: 40~1250 MHz (Gen3 D-PHY)
+* n: - valid range [0 15]
+* N: - N = n + 1
+*  -valid range: [1 16]
+*  -conditions: - (pll_ref_clk / N) >= 2 MHz
+*  -(pll_ref_clk / N) <= 8 MHz
+* m: valid range [62 623]
+* M: - M = m + 2
+*  -valid range [64 625]
+*  -Fvco = (M/N) * pll_ref_clk
+*/
+   struct vco_params vco_p = {
+   .range = 0,
+   .divider = 1,
+   };
+   u32 best_n = 0, best_m = 0;
+   u32 n = 0, m = 0, div = 0, delta, freq = 0, t_freq;
+   u32 best_freq_delta = 3000;
+
+   vco_p.freq = target_freq_mhz;
+   mipi_tx_get_vco_params(&vco_p);
+   /*search pll n parameter */
+   for (n = PLL_N_MIN; n <= PLL_N_MAX; n++) {
+   /*calculate the pll input frequency division ratio
+* multiply by 1000 for precision -
+* no floating point, add n for rounding
+*/
+   div = ((ref_clk_mhz * 1000) + n)/(n+1);
+   /*found a valid n parameter */
+   if ((div < 2000 || div > 8000))
+   continue;
+   /*search pll m parameter */
+   for (m = PLL_M_MIN; m <= PLL_M_MAX; m++) {
+   /*calculate the Fvco(DPHY PLL output frequency)
+* using the current n,m params
+  

[PATCH v2 02/59] drm/kmb: Added id to kmb_plane

2020-07-14 Thread Anitha Chrisanthus
This is to keep track of the id of the plane as there are 4 planes in
Kmb and when update() is called, we need to know which plane need to be
updated so that the corresponding plane's registers can be programmed.

v2: moved extern to .h, upclassed dev_private,
minor changes from code review.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  | 13 ---
 drivers/gpu/drm/kmb/kmb_crtc.h  |  2 +-
 drivers/gpu/drm/kmb/kmb_drv.h   |  2 +-
 drivers/gpu/drm/kmb/kmb_plane.c | 80 +++--
 drivers/gpu/drm/kmb/kmb_plane.h | 28 +--
 5 files changed, 79 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index 1a00015..63821ed 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -105,9 +105,8 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_write(lcd, LCD_VSYNC_START_EVEN, vsync_start_offset);
kmb_write(lcd, LCD_VSYNC_END_EVEN, vsync_end_offset);
}
-   /* enable all 4 layers */
-   ctrl = LCD_CTRL_ENABLE | LCD_CTRL_VL1_ENABLE
-   | LCD_CTRL_VL2_ENABLE | LCD_CTRL_GL1_ENABLE | LCD_CTRL_GL2_ENABLE;
+   /* enable VL1 layer as default */
+   ctrl = LCD_CTRL_ENABLE | LCD_CTRL_VL1_ENABLE;
ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
| LCD_CTRL_OUTPUT_ENABLED;
kmb_write(lcd, LCD_CONTROL, ctrl);
@@ -175,17 +174,17 @@ static const struct drm_crtc_helper_funcs 
kmb_crtc_helper_funcs = {
 int kmb_setup_crtc(struct drm_device *drm)
 {
struct kmb_drm_private *lcd = to_kmb(drm);
-   struct drm_plane *primary;
+   struct kmb_plane *primary;
int ret;
 
primary = kmb_plane_init(drm);
if (IS_ERR(primary))
return PTR_ERR(primary);
 
-   ret = drm_crtc_init_with_planes(drm, &lcd->crtc, primary, NULL,
-   &kmb_crtc_funcs, NULL);
+   ret = drm_crtc_init_with_planes(drm, &lcd->crtc, &primary->base_plane,
+   NULL, &kmb_crtc_funcs, NULL);
if (ret) {
-   kmb_plane_destroy(primary);
+   kmb_plane_destroy(&primary->base_plane);
return ret;
}
 
diff --git a/drivers/gpu/drm/kmb/kmb_crtc.h b/drivers/gpu/drm/kmb/kmb_crtc.h
index d7cc441..6c3efdd 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.h
+++ b/drivers/gpu/drm/kmb/kmb_crtc.h
@@ -35,5 +35,5 @@ struct kmb_crtc_state {
 #define to_kmb_crtc_state(x) container_of(x, struct kmb_crtc_state, crtc_base)
 #define to_kmb_crtc(x) container_of(x, struct kmb_crtc, crtc_base)
 extern void kmb_plane_destroy(struct drm_plane *plane);
-extern struct drm_plane *kmb_plane_init(struct drm_device *drm);
+extern struct kmb_plane *kmb_plane_init(struct drm_device *drm);
 #endif /* __KMB_CRTC_H__ */
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 90e1c86..23299a5 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -16,7 +16,7 @@ struct kmb_drm_private {
struct clk *clk;
struct drm_fbdev_cma *fbdev;
struct drm_crtc crtc;
-   struct drm_plane *plane;
+   struct kmb_plane *plane;
struct drm_atomic_state *state;
 };
 
diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 9d4c8dc..7077a4c 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -41,46 +41,69 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
dma_addr_t addr;
unsigned int width;
unsigned int height;
-   unsigned int i;
unsigned int dma_len;
-   struct kmb_plane_state *kmb_state = to_kmb_plane_state(plane->state);
+   struct kmb_plane *kmb_plane = to_kmb_plane(plane);
unsigned int dma_cfg;
+   unsigned int ctrl = 0;
+   unsigned char plane_id = kmb_plane->id;
 
if (!fb)
return;
 
lcd = to_kmb(plane->dev);
 
+   switch (plane_id) {
+   case LAYER_0:
+   ctrl = LCD_CTRL_VL1_ENABLE;
+   break;
+   case LAYER_1:
+   ctrl = LCD_CTRL_VL2_ENABLE;
+   break;
+   case LAYER_2:
+   ctrl = LCD_CTRL_GL1_ENABLE;
+   break;
+   case LAYER_3:
+   ctrl = LCD_CTRL_GL2_ENABLE;
+   break;
+   }
+
+   ctrl |= LCD_CTRL_ENABLE;
+   ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
+   | LCD_CTRL_OUTPUT_ENABLED;
+   kmb_write(lcd, LCD_CONTROL, ctrl);
+
/* TBD */
/*set LCD_LAYERn_WIDTH, LCD_LAYERn_HEIGHT, LCD_LAYERn_COL_START,
 * LCD_LAYERn_ROW_START, LCD_LAYERn_CFG
 * CFG should set the pixel format, FIFO level and BPP
 */
 
+   /*TBD check visible? */
+
/* we may have to set LCD_DMA_VSTRIDE_ENABLE in the future */
dma_cfg = LCD_DMA_LAYE

[PATCH v2 26/59] drm/kmb: rebase to newer kernel version

2020-07-14 Thread Anitha Chrisanthus
cleanup code

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 5 +++--
 drivers/gpu/drm/kmb/kmb_drv.h | 1 -
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 71fdb94..78cb91b 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -282,8 +282,7 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver kmb_driver = {
.driver_features = DRIVER_GEM |
-   DRIVER_MODESET |
-   DRIVER_ATOMIC,
+   DRIVER_MODESET | DRIVER_ATOMIC,
.irq_handler = kmb_isr,
.irq_preinstall = kmb_irq_reset,
.irq_uninstall = kmb_irq_reset,
@@ -362,6 +361,8 @@ static int kmb_drm_bind(struct device *dev)
if (ret)
goto err_register;
 
+   drm_fbdev_generic_setup(drm, 32);
+
return 0;
 
 err_register:
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 586b53e..1150505 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -18,7 +18,6 @@ struct kmb_drm_private {
void __iomem*msscam_mmio;
unsigned char   n_layers;
struct clk  *clk;
-   struct drm_fbdev_cma*fbdev;
struct drm_crtc crtc;
struct kmb_plane*plane;
struct drm_atomic_state *state;
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 57/59] drm/kmb: workaround for dma undeflow issue

2020-07-14 Thread Anitha Chrisanthus
Initial issue was that display remains shifted after undeflow, this fix is
to recover the dma after underflow so display is clean. Major changes are
reduce LCD_CLK to 200Mhz and some changes in the lcd timing params
run recovery sequence at the EOF after underflow happens
do nothing in plan_update() during recovery
reenable dma at the vsync interrupt after recovery is done

v2: renamed global vars, upclassed dev_private.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  |  27 +++
 drivers/gpu/drm/kmb/kmb_drv.c   | 154 +++-
 drivers/gpu/drm/kmb/kmb_drv.h   |  33 +
 drivers/gpu/drm/kmb/kmb_plane.c |  12 +++-
 drivers/gpu/drm/kmb/kmb_plane.h |  29 
 drivers/gpu/drm/kmb/kmb_regs.h  |   5 ++
 6 files changed, 185 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index aceca94..8308a9e1 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -96,25 +96,25 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
vm.vfront_porch = 2;
 //  vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
vm.vback_porch = 2;
-//  vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
-   vm.vsync_len = 1;
+// vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
+   vm.vsync_len = 8;
//vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
vm.hfront_porch = 0;
vm.hback_porch = 0;
//vm.hback_porch = m->crtc_htotal - m->crtc_hsync_end;
-   vm.hsync_len = 7;
-//  vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
+   vm.hsync_len = 28;
+// vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
 
-   vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
-   vsync_end_offset = m->crtc_vsync_end - m->crtc_hsync_end;
+   vsync_start_offset =  m->crtc_vsync_start -  m->crtc_hsync_start;
+   vsync_end_offset =  m->crtc_vsync_end - m->crtc_hsync_end;
 
-   DRM_DEBUG
-   ("%s : %dactive height= %d vbp=%d vfp=%d vsync-w=%d h-active=%d 
h-bp=%d h-fp=%d hysnc-l=%d",
-__func__, __LINE__, m->crtc_vdisplay, vm.vback_porch,
-vm.vfront_porch, vm.vsync_len, m->crtc_hdisplay, vm.hback_porch,
-vm.hfront_porch, vm.hsync_len);
+   DRM_DEBUG("%s : %dactive height= %d vbp=%d vfp=%d vsync-w=%d 
h-active=%d h-bp=%d h-fp=%d hysnc-l=%d",
+   __func__, __LINE__,
+   m->crtc_vdisplay, vm.vback_porch, vm.vfront_porch,
+   vm.vsync_len, m->crtc_hdisplay, vm.hback_porch,
+   vm.hfront_porch, vm.hsync_len);
kmb_write_lcd(dev_p, LCD_V_ACTIVEHEIGHT,
- m->crtc_vdisplay - 1);
+   m->crtc_vdisplay - 1);
kmb_write_lcd(dev_p, LCD_V_BACKPORCH, vm.vback_porch);
kmb_write_lcd(dev_p, LCD_V_FRONTPORCH, vm.vfront_porch);
kmb_write_lcd(dev_p, LCD_VSYNC_WIDTH, vm.vsync_len - 1);
@@ -126,7 +126,8 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
/*this is hardcoded as 0 in the Myriadx code */
kmb_write_lcd(dev_p, LCD_VSYNC_START, 0);
kmb_write_lcd(dev_p, LCD_VSYNC_END, 0);
-
+   /* back ground color */
+   kmb_write_lcd(dev_p, LCD_BG_COLOUR_LS, 0x4);
if (m->flags == DRM_MODE_FLAG_INTERLACE) {
kmb_write_lcd(dev_p,
  LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index b844c77..559742b8 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -31,10 +31,10 @@
 #include "kmb_regs.h"
 
 //#define DEBUG
-
 /* IRQ handler */
 static irqreturn_t kmb_isr(int irq, void *arg);
 
+int kmb_under_flow = 0, kmb_flush_done = 0, layer_no = 0;
 static struct clk *clk_lcd;
 static struct clk *clk_mipi;
 static struct clk *clk_mipi_ecfg;
@@ -111,6 +111,7 @@ static void __iomem *kmb_map_mmio(struct platform_device 
*pdev, char *name)
return mem;
 }
 
+//#define ICAM_LCD_QOS
 static int kmb_load(struct drm_device *drm, unsigned long flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
@@ -118,6 +119,9 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
int irq_lcd;
int ret = 0;
unsigned long clk;
+#ifdef ICAM_LCD_QOS
+   int val = 0;
+#endif
 
/* Map MIPI MMIO registers */
dev_p->mipi_mmio = kmb_map_mmio(pdev, "mipi_regs");
@@ -151,6 +155,13 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
iounmap(dev_p->mipi_mmio);
return -ENOMEM;
}
+#ifdef ICAM_LCD_QOS
+   dev_p->icamlcd_mmio = ioremap_nocache(ICAM_MMIO, ICAM_MMIO_SIZE);
+   if (IS_ERR(dev_p->icamlcd_mmio)) {
+   DRM_ERROR("failed to map ICAM registers\n");
+   return -ENOMEM;
+  

[PATCH v2 21/59] drm/kmb: IRQ handlers for LCD and mipi dsi

2020-07-14 Thread Anitha Chrisanthus
Added handlers for lcd and mipi, it only finds and clears the interrupt
as of now, more functionality can be added as needed.

v2: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c  | 55 +++---
 drivers/gpu/drm/kmb/kmb_drv.h  |  2 ++
 drivers/gpu/drm/kmb/kmb_dsi.c  | 37 ++--
 drivers/gpu/drm/kmb/kmb_dsi.h  |  1 +
 drivers/gpu/drm/kmb/kmb_regs.h | 35 ---
 5 files changed, 110 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 594e64c..f4553c2 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -38,7 +38,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
struct platform_device *pdev = to_platform_device(drm->dev);
/*struct resource *res;*/
/*u32 version;*/
-   /*int irq_lcd, irq_mipi; */
+   int irq_lcd, irq_mipi;
int ret;
 
/* TBD - not sure if clock_get needs to be called here */
@@ -89,11 +89,29 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
dev_p->msscam_mmio = ioremap_cache(MSS_CAM_BASE_ADDR,
MSS_CAM_MMIO_SIZE);
 
-   /*TODO - register irqs here - section 17.3 in databook
-* lists LCD at 79 under MSS CPU - firmware has to redirect it to A53
-* May be 33 for LCD and 34 for MIPI? Will wait till firmware
-* finalizes the IRQ numbers for redirection
+   /* register irqs here - section 17.3 in databook
+* lists LCD at 79 and 82 for MIPI under MSS CPU -
+* firmware has to redirect it to A53
 */
+   irq_lcd = platform_get_irq_byname(pdev, "irq_lcd");
+   if (irq_lcd < 0) {
+   DRM_ERROR("irq_lcd not found");
+   return irq_lcd;
+   }
+   pr_info("irq_lcd platform_get_irq = %d\n", irq_lcd);
+   ret = request_irq(irq_lcd, kmb_isr, IRQF_SHARED, "irq_lcd", dev_p);
+   dev_p->irq_lcd = irq_lcd;
+
+   irq_mipi = platform_get_irq_byname(pdev, "irq_mipi");
+   if (irq_mipi < 0) {
+   DRM_ERROR("irq_mipi not found");
+   return irq_mipi;
+   }
+   pr_info("irq_mipi platform_get_irq = %d\n", irq_mipi);
+   ret = request_irq(irq_mipi, kmb_isr, IRQF_SHARED, "irq_mipi", dev_p);
+   dev_p->irq_mipi = irq_mipi;
+
+
 
 /*TBD read and check for correct product version here */
 
@@ -142,9 +160,9 @@ static void kmb_setup_mode_config(struct drm_device *drm)
drm->mode_config.funcs = &kmb_mode_config_funcs;
 }
 
-static irqreturn_t kmb_isr(int irq, void *arg)
+
+static irqreturn_t handle_lcd_irq(struct drm_device *dev)
 {
-   struct drm_device *dev = (struct drm_device *)arg;
unsigned long status, val;
struct kmb_drm_private *dev_p = to_kmb(dev);
 
@@ -174,14 +192,33 @@ static irqreturn_t kmb_isr(int irq, void *arg)
break;
}
}
+   return IRQ_HANDLED;
+}
 
+static irqreturn_t  handle_mipi_irq(struct drm_device *dev)
+{
+   mipi_tx_handle_irqs(to_kmb(dev));
return IRQ_HANDLED;
 }
 
+static irqreturn_t kmb_isr(int irq, void *arg)
+{
+   struct drm_device *dev = (struct drm_device *)arg;
+   struct kmb_drm_private *dev_p = to_kmb(dev);
+   irqreturn_t ret = IRQ_NONE;
+
+   if (irq == dev_p->irq_lcd)
+   ret = handle_lcd_irq(dev);
+   else if (irq == dev_p->irq_mipi)
+   ret = handle_mipi_irq(dev);
+
+   return ret;
+}
+
 static void kmb_irq_reset(struct drm_device *drm)
 {
-   kmb_write_lcd(drm->dev_private, LCD_INT_CLEAR, 0x);
-   kmb_write_lcd(drm->dev_private, LCD_INT_ENABLE, 0);
+   kmb_write_lcd(to_kmb(drm), LCD_INT_CLEAR, 0x);
+   kmb_write_lcd(to_kmb(drm), LCD_INT_ENABLE, 0);
 }
 
 DEFINE_DRM_GEM_CMA_FOPS(fops);
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index a56d548..1e81d44 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -23,6 +23,8 @@ struct kmb_drm_private {
struct kmb_plane*plane;
struct drm_atomic_state *state;
spinlock_t  irq_lock;
+   int irq_lcd;
+   int irq_mipi;
 };
 
 static inline struct kmb_drm_private *to_kmb(const struct drm_device *dev)
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 94c9adc..969890b 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -1214,7 +1214,7 @@ static void mipi_tx_init_irqs(struct kmb_drm_private 
*dev_p,
SET_MIPI_TX_HS_IRQ_CLEAR(dev_p, MIPI_CTRL6, MIPI_TX_HS_IRQ_ALL);
/*global interrupts */
SET_MIPI_CTRL_IRQ_CLEAR0(dev_p, MIPI_CTRL6, MIPI_HS_IRQ);
-   SET_MIPI_CTRL_IRQ_CLEAR0(dev_p, MIPI_CTRL6, MIPI_DHY_ERR_IRQ);
+   SET_MIPI_CT

[PATCH v2 37/59] drm/kmb: Set MSS_CAM_RSTN_CTRL along with enable

2020-07-14 Thread Anitha Chrisanthus
Also moved num_planes init before load, time out for dsi
fixed kmb regs read/write to only pass dev_p and few other minor
changes.

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c   | 32 ++--
 drivers/gpu/drm/kmb/kmb_drv.h   | 34 +-
 drivers/gpu/drm/kmb/kmb_dsi.c   | 37 -
 drivers/gpu/drm/kmb/kmb_plane.c | 27 +--
 drivers/gpu/drm/kmb/kmb_regs.h  |  1 +
 5 files changed, 77 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 861aa97..64db9a1 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -58,11 +58,12 @@ static int kmb_display_clk_enable(void)
return ret;
}
 
-   ret = clk_prepare_enable(clk_msscam);
+/* ret = clk_prepare_enable(clk_msscam);
if (ret) {
DRM_ERROR("Failed to enable MSSCAM clock: %d\n", ret);
return ret;
}
+   */
 
ret = clk_prepare_enable(clk_mipi_ecfg);
if (ret) {
@@ -116,6 +117,8 @@ static void __iomem *kmb_map_mmio(struct platform_device 
*pdev, char *name)
release_mem_region(res->start, size);
return ERR_PTR(-ENOMEM);
}
+   DRM_INFO("%s : %d mapped %s mmio size = %d\n", __func__, __LINE__,
+   name, size);
return mem;
 }
 
@@ -130,13 +133,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
int ret = 0;
unsigned long clk;
 
-   /* Map LCD MMIO registers */
-   dev_p->lcd_mmio = kmb_map_mmio(pdev, "lcd_regs");
-   if (IS_ERR(dev_p->lcd_mmio)) {
-   DRM_ERROR("failed to map LCD registers\n");
-   return -ENOMEM;
-   }
-
/* Map MIPI MMIO registers */
dev_p->mipi_mmio = kmb_map_mmio(pdev, "mipi_regs");
if (IS_ERR(dev_p->mipi_mmio)) {
@@ -145,6 +141,13 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
return -ENOMEM;
}
 
+   /* Map LCD MMIO registers */
+   dev_p->lcd_mmio = kmb_map_mmio(pdev, "lcd_regs");
+   if (IS_ERR(dev_p->lcd_mmio)) {
+   DRM_ERROR("failed to map LCD registers\n");
+   return -ENOMEM;
+   }
+
/* This is only for MIPI_TX_MSS_LCD_MIPI_CFG and MSS_CAM_CLK_CTRL
 * register
 */
@@ -169,12 +172,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}
 
-   clk_msscam = clk_get(&pdev->dev, "clk_msscam");
-   if (IS_ERR(clk_msscam)) {
-   DRM_ERROR("clk_get() failed clk_msscam\n");
-   goto setup_fail;
-   }
-
clk_mipi_ecfg = clk_get(&pdev->dev, "clk_mipi_ecfg");
if (IS_ERR(clk_mipi_ecfg)) {
DRM_ERROR("clk_get() failed clk_mipi_ecfg\n");
@@ -195,7 +192,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
if (clk_get_rate(clk_lcd) != KMB_LCD_DEFAULT_CLK) {
DRM_ERROR("failed to set to clk_lcd to %d\n",
KMB_LCD_DEFAULT_CLK);
-   goto setup_fail;
}
DRM_INFO("Setting LCD clock to %d Mhz ret = %d\n",
KMB_LCD_DEFAULT_CLK/100, ret);
@@ -245,8 +241,8 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
}
 
/* enable MSS_CAM_CLK_CTRL for MIPI TX and LCD */
-   kmb_set_bitmask_msscam(dev_p, MSS_CAM_CLK_CTRL, LCD | MIPI_COMMON |
-   MIPI_TX0);
+   kmb_set_bitmask_msscam(dev_p, MSS_CAM_CLK_CTRL, 0xfff);
+   kmb_set_bitmask_msscam(dev_p, MSS_CAM_RSTN_CTRL, 0xfff);
 #ifdef WIP
/* Register irqs here - section 17.3 in databook
 * lists LCD at 79 and 82 for MIPI under MSS CPU -
@@ -514,6 +510,7 @@ static int kmb_probe(struct platform_device *pdev)
dev_set_drvdata(dev, drm);
 
/* Load driver */
+   lcd->n_layers = KMB_MAX_PLANES;
ret = kmb_load(drm, 0);
if (ret == -EPROBE_DEFER) {
DRM_INFO("wait for external bridge driver DT\n");
@@ -536,7 +533,6 @@ static int kmb_probe(struct platform_device *pdev)
/* Register graphics device with the kernel */
ret = drm_dev_register(drm, 0);
 
-   lcd->n_layers = KMB_MAX_PLANES;
if (ret)
goto err_register;
 
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 71dc883..f3f2c34 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -8,9 +8,9 @@
 
 #include "kmb_regs.h"
 
-#define KMB_MAX_WIDTH  16384   /*max width in pixels */
-#define KMB_MAX_HEIGHT 16384   /*max height in pixels */
-#define KMB_LCD_DEFAULT_CLK2
+#define KMB_MAX_WIDTH  1920 /*max width in pixels */
+#define KMB_MAX_HEIGHT 108

[PATCH v2 38/59] drm/kmb: Mipi DPHY initialization changes

2020-07-14 Thread Anitha Chrisanthus
Fix test_mode_send and dphy_wait_fsm for 2-lane MIPI

- Fix test_mode_send when sending normal mode test codes
- Change dphy_wait_fsm to check for IDLE status rather than LOCK
  status for 2-lane MIPI

v2: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
Signed-off-by: Edmund Dea 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  |  23 +-
 drivers/gpu/drm/kmb/kmb_drv.c   |  90 ++--
 drivers/gpu/drm/kmb/kmb_drv.h   |  23 +-
 drivers/gpu/drm/kmb/kmb_dsi.c   | 904 +---
 drivers/gpu/drm/kmb/kmb_dsi.h   |   2 +-
 drivers/gpu/drm/kmb/kmb_plane.c |  57 ++-
 drivers/gpu/drm/kmb/kmb_regs.h  |  34 +-
 7 files changed, 838 insertions(+), 295 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index eca0f3a..21b2d7f 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -20,6 +20,7 @@
 #include "kmb_drv.h"
 #include "kmb_plane.h"
 #include "kmb_regs.h"
+#include "kmb_dsi.h"
 
 static void kmb_crtc_cleanup(struct drm_crtc *crtc)
 {
@@ -74,24 +75,34 @@ static const struct drm_crtc_funcs kmb_crtc_funcs = {
 
 static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
-   struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct drm_device *dev = crtc->dev;
+#ifdef LCD_TEST
+   struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct videomode vm;
int vsync_start_offset;
int vsync_end_offset;
unsigned int ctrl = 0;
struct kmb_drm_private *dev_p = to_kmb(dev);
-
+#endif
+   /* initialize mipi */
+   kmb_dsi_hw_init(dev);
+#ifdef LCD_TEST
vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
-   vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
+   //vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
+   vm.hfront_porch = 0;
vm.hback_porch = m->crtc_htotal - m->crtc_hsync_end;
vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
 
vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
vsync_end_offset = m->crtc_vsync_end - m->crtc_hsync_end;
 
+   DRM_INFO("%s : %dactive height= %d vbp=%d vfp=%d vsync-w=%d h-active=%d 
h-bp=%d h-fp=%d hysnc-l=%d\n",
+   __func__, __LINE__, m->crtc_vdisplay,
+   vm.vback_porch, vm.vfront_porch,
+   vm.vsync_len, m->crtc_hdisplay,
+   vm.hback_porch, vm.hfront_porch, vm.hsync_len);
kmb_write_lcd(dev_p, LCD_V_ACTIVEHEIGHT,
m->crtc_vdisplay - 1);
kmb_write_lcd(dev_p, LCD_V_BACKPORCH, vm.vback_porch - 1);
@@ -126,7 +137,7 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_write_lcd(dev_p, LCD_CONTROL, ctrl);
 
kmb_write_lcd(dev_p, LCD_TIMING_GEN_TRIG, ENABLE);
-
+#endif
/* TBD */
/* set clocks here */
 }
@@ -138,7 +149,7 @@ static void kmb_crtc_atomic_enable(struct drm_crtc *crtc,
 
clk_prepare_enable(lcd->clk);
kmb_crtc_mode_set_nofb(crtc);
-   drm_crtc_vblank_on(crtc);
+// drm_crtc_vblank_on(crtc);
 }
 
 static void kmb_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -149,7 +160,7 @@ static void kmb_crtc_atomic_disable(struct drm_crtc *crtc,
/* always disable planes on the CRTC that is being turned off */
drm_atomic_helper_disable_planes_on_crtc(old_state, false);
 
-   drm_crtc_vblank_off(crtc);
+// drm_crtc_vblank_off(crtc);
clk_disable_unprepare(lcd->clk);
 }
 
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 64db9a1..2a93b13 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -37,27 +38,27 @@ static irqreturn_t kmb_isr(int irq, void *arg);
 static struct clk *clk_lcd;
 static struct clk *clk_mipi;
 static struct clk *clk_msscam;
+static struct clk *clk_pll0out0;
 static struct clk *clk_mipi_ecfg;
 static struct clk *clk_mipi_cfg;
 
 struct drm_bridge *adv_bridge;
 
-static int kmb_display_clk_enable(void)
+int kmb_display_clk_enable(void)
 {
int ret = 0;
-
+#ifdef LCD_TEST
ret = clk_prepare_enable(clk_lcd);
if (ret) {
DRM_ERROR("Failed to enable LCD clock: %d\n", ret);
return ret;
}
-
+#endif
ret = clk_prepare_enable(clk_mipi);
if (ret) {
DRM_ERROR("Failed to enable MIPI clock: %d\n", ret);
return ret;
}
-
 /* ret = clk_prepare_enable(clk_msscam);
if (ret) {
DRM_ERROR("Failed to enable MSSCAM clock: %d\n", ret);
@@ -158,19 +159,47 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
iounmap(dev_p->mipi_mmio);
return -ENOMEM;
}
+/*test

[PATCH v2 24/59] drm/kmb: Add ADV7535 bridge

2020-07-14 Thread Anitha Chrisanthus
Find ADV 7535 from the device tree and get the bridge driver and attach
it to the DRM and the MIPI encoder.

v2: check for valid encoder node

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 27 ++-
 drivers/gpu/drm/kmb/kmb_dsi.c | 26 +-
 drivers/gpu/drm/kmb/kmb_dsi.h |  3 ++-
 3 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index f4553c2..5a2ff9d 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -36,10 +36,12 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
+   struct drm_bridge *bridge;
/*struct resource *res;*/
/*u32 version;*/
int irq_lcd, irq_mipi;
int ret;
+   struct device_node *encoder_node;
 
/* TBD - not sure if clock_get needs to be called here */
/*
@@ -127,7 +129,30 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}
 
-   kmb_dsi_init(drm);
+   /* find ADV7535 node and initialize it */
+   encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
+   if (!encoder_node) {
+   DRM_ERROR("failed to get bridge info from DT\n");
+   ret = -EPROBE_DEFER;
+   goto setup_fail;
+   }
+
+   /* Locate drm bridge from the hdmi encoder DT node */
+   bridge = of_drm_find_bridge(encoder_node);
+   if (!bridge) {
+   DRM_ERROR("failed to get bridge driver from DT\n");
+   ret = -EPROBE_DEFER;
+   goto setup_fail;
+   }
+
+   of_node_put(encoder_node);
+
+   ret = kmb_dsi_init(drm, bridge);
+   if (ret) {
+   DRM_ERROR("failed to initialize DSI\n");
+   goto setup_fail;
+   }
+
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n");
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 969890b..09d5805 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1240,7 +1241,6 @@ static void mipi_tx_init_irqs(struct kmb_drm_private 
*dev_p,
spin_unlock_irqrestore(&dev_p->irq_lock, irqflags);
 }
 
-
 void mipi_tx_handle_irqs(struct kmb_drm_private *dev_p)
 {
uint32_t irq_ctrl_stat_0, hs_stat, hs_enable;
@@ -1273,7 +1273,7 @@ void mipi_tx_handle_irqs(struct kmb_drm_private *dev_p)
 
 }
 
-void kmb_dsi_init(struct drm_device *dev)
+int kmb_dsi_init(struct drm_device *dev, struct drm_bridge *bridge)
 {
struct kmb_dsi *kmb_dsi;
struct drm_encoder *encoder;
@@ -1281,21 +1281,27 @@ void kmb_dsi_init(struct drm_device *dev)
struct drm_connector *connector;
struct kmb_dsi_host *host;
struct kmb_drm_private *dev_p = dev->dev_private;
+   int ret = 0;
 
kmb_dsi = kzalloc(sizeof(*kmb_dsi), GFP_KERNEL);
-   if (!kmb_dsi)
-   return;
+   if (!kmb_dsi) {
+   DRM_ERROR("failed to allocate kmb_dsi\n");
+   return -ENOMEM;
+   }
 
kmb_connector = kzalloc(sizeof(*kmb_connector), GFP_KERNEL);
if (!kmb_connector) {
kfree(kmb_dsi);
-   return;
+   DRM_ERROR("failed to allocate kmb_connector\n");
+   return -ENOMEM;
}
 
kmb_dsi->attached_connector = kmb_connector;
 
connector = &kmb_connector->base;
encoder = &kmb_dsi->base;
+   encoder->possible_crtcs = 1;
+   encoder->possible_clones = 0;
drm_encoder_init(dev, encoder, &kmb_dsi_funcs, DRM_MODE_ENCODER_DSI,
 "MIPI-DSI");
 
@@ -1313,6 +1319,14 @@ void kmb_dsi_init(struct drm_device *dev)
connector->encoder = encoder;
drm_connector_attach_encoder(connector, encoder);
 
+   /* Link drm_bridge to encoder */
+   ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+   if (ret) {
+   DRM_ERROR("failed to attach bridge to MIPI\n");
+   drm_encoder_cleanup(encoder);
+   return ret;
+   }
+
/* initialize mipi controller */
mipi_tx_init_cntrl(dev_p, &mipi_tx_init_cfg);
 
@@ -1321,4 +1335,6 @@ void kmb_dsi_init(struct drm_device *dev)
 
/* irq initialization */
mipi_tx_init_irqs(dev_p, &int_cfg, &mipi_tx_init_cfg.tx_ctrl_cfg);
+
+   return 0;
 }
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.h b/drivers/gpu/drm/kmb/kmb_dsi.h
index f7e2f9e..702ad58 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.h
+++ b/drivers/gpu/drm/kmb/kmb_dsi.h
@@ -18,6 +18,7 @@ struct kmb_dsi {
struct drm_encoder base;
   

[PATCH v2 45/59] drm/kmb: Enable LCD interrupts

2020-07-14 Thread Anitha Chrisanthus
Enabled vblank interrupts for LCD.

v2: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  | 36 +++-
 drivers/gpu/drm/kmb/kmb_drv.c   | 41 +
 drivers/gpu/drm/kmb/kmb_plane.c |  6 +++---
 drivers/gpu/drm/kmb/kmb_regs.h  |  2 +-
 4 files changed, 40 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index 1987185e..589a841 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -41,7 +41,8 @@ static int kmb_crtc_enable_vblank(struct drm_crtc *crtc)
kmb_write_lcd(dev_p, LCD_VSTATUS_COMPARE,
LCD_VSTATUS_COMPARE_VSYNC);
/* enable vertical interrupt */
-   kmb_write_lcd(dev_p, LCD_INT_ENABLE, LCD_INT_VERT_COMP);
+   kmb_set_bitmask_lcd(dev_p, LCD_INT_ENABLE,
+   LCD_INT_VERT_COMP);
return 0;
 }
 
@@ -53,13 +54,8 @@ static void kmb_crtc_disable_vblank(struct drm_crtc *crtc)
/*clear interrupt */
kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
/* disable vertical interrupt */
-   kmb_write_lcd(dev_p, LCD_INT_ENABLE, 0);
-
-/* TBD
- *  set the BIT2 (VERTICAL_COMPARE_INTERRUPT) of the LCD_INT_ENABLE register
- *  set the required bit LCD_VSTATUS_COMPARE register
- *  Not sure if anything needs to be done in the ICB
- */
+   kmb_clr_bitmask_lcd(dev_p, LCD_INT_ENABLE,
+   LCD_INT_VERT_COMP);
 }
 
 static const struct drm_crtc_funcs kmb_crtc_funcs = {
@@ -82,7 +78,7 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
int vsync_start_offset;
int vsync_end_offset;
struct kmb_drm_private *dev_p = to_kmb(dev);
-#endif
+
/* initialize mipi */
kmb_dsi_hw_init(dev, m);
DRM_INFO("vfp= %d vbp= %d vsyc_len=%d hfp=%d hbp=%d hsync_len=%d\n",
@@ -92,7 +88,6 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
m->crtc_hsync_start - m->crtc_hdisplay,
m->crtc_htotal - m->crtc_hsync_end,
m->crtc_hsync_end - m->crtc_hsync_start);
-#ifdef LCD_TEST
 // vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vfront_porch = 2;
 // vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -156,7 +151,7 @@ static void kmb_crtc_atomic_enable(struct drm_crtc *crtc,
 
clk_prepare_enable(lcd->clk);
kmb_crtc_mode_set_nofb(crtc);
-// drm_crtc_vblank_on(crtc);
+   drm_crtc_vblank_on(crtc);
 }
 
 static void kmb_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -167,33 +162,32 @@ static void kmb_crtc_atomic_disable(struct drm_crtc *crtc,
/* always disable planes on the CRTC that is being turned off */
drm_atomic_helper_disable_planes_on_crtc(old_state, false);
 
-// drm_crtc_vblank_off(crtc);
+   drm_crtc_vblank_off(crtc);
clk_disable_unprepare(lcd->clk);
 }
 
 static void kmb_crtc_atomic_begin(struct drm_crtc *crtc,
  struct drm_crtc_state *state)
 {
-   /* TBD */
-   /*disable  vblank interrupts here
-* clear BIT 2 (VERTICAL_COMPARE_INTERRUPT) LCD_INT_ENABLE
-*/
+   struct drm_device *dev = crtc->dev;
+
+   kmb_clr_bitmask_lcd(dev->dev_private, LCD_INT_ENABLE,
+   LCD_INT_VERT_COMP);
 }
 
 static void kmb_crtc_atomic_flush(struct drm_crtc *crtc,
  struct drm_crtc_state *state)
 {
-   /* TBD */
-   /*enable  vblank interrupts after
-* set BIT 2 (VERTICAL_COMPARE_INTERRUPT) LCD_INT_ENABLE
-*/
+   struct drm_device *dev = crtc->dev;
+
+   kmb_set_bitmask_lcd(dev->dev_private, LCD_INT_ENABLE,
+   LCD_INT_VERT_COMP);
 
spin_lock_irq(&crtc->dev->event_lock);
if (crtc->state->event)
drm_crtc_send_vblank_event(crtc, crtc->state->event);
crtc->state->event = NULL;
spin_unlock_irq(&crtc->dev->event_lock);
-
 }
 
 static const struct drm_crtc_helper_funcs kmb_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index bbf3e649..e6aa32c 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -127,10 +127,8 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
-#ifdef WIP
/*u32 version;*/
-   int irq_lcd, irq_mipi;
-#endif
+   int irq_lcd;// irq_mipi;
int ret = 0;
unsigned long clk;
 
@@ -266,10 +264,9 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
kmb_set_bitmask_msscam(dev_p, MSS_CAM_CLK_CTRL, 0x1fff);
kmb_set_bitmask_msscam(dev_p, MSS_CAM_RSTN_CTRL, 0x);
 #endif //KMB_CLOCKS
-#ifdef WIP
/* Register

[PATCH v2 27/59] drm/kmb: minor name change to match device tree

2020-07-14 Thread Anitha Chrisanthus
name change

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 78cb91b..4afdb9c 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -459,7 +459,7 @@ static int kmb_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id  kmb_of_match[] = {
-   {.compatible = "kmb,display"},
+   {.compatible = "intel,kmb_display"},
{},
 };
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 05/59] drm/kmb: Updated kmb_plane_atomic_check

2020-07-14 Thread Anitha Chrisanthus
Check if format is supported and size is within limits.

v2: simplified the code as per code review

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 111 +++-
 1 file changed, 65 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 877314a..74a3573 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -21,15 +21,66 @@
 #include "kmb_plane.h"
 #include "kmb_regs.h"
 
+/* graphics layer ( layers 2 & 3) formats, only packed formats  are supported*/
+static const u32 kmb_formats_g[] = {
+   DRM_FORMAT_RGB332,
+   DRM_FORMAT_XRGB, DRM_FORMAT_XBGR,
+   DRM_FORMAT_ARGB, DRM_FORMAT_ABGR,
+   DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
+   DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
+   DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
+   DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
+   DRM_FORMAT_XRGB, DRM_FORMAT_XBGR,
+   DRM_FORMAT_ARGB, DRM_FORMAT_ABGR,
+};
+
+#define MAX_FORMAT_G   (ARRAY_SIZE(kmb_formats_g))
+#define MAX_FORMAT_V   (ARRAY_SIZE(kmb_formats_v))
+
+/* video layer ( 0 & 1) formats, packed and planar formats are supported */
+static const u32 kmb_formats_v[] = {
+   /* packed formats */
+   DRM_FORMAT_RGB332,
+   DRM_FORMAT_XRGB, DRM_FORMAT_XBGR,
+   DRM_FORMAT_ARGB, DRM_FORMAT_ABGR,
+   DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
+   DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
+   DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
+   DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
+   DRM_FORMAT_XRGB, DRM_FORMAT_XBGR,
+   DRM_FORMAT_ARGB, DRM_FORMAT_ABGR,
+   /*planar formats */
+   DRM_FORMAT_YUV420, DRM_FORMAT_YVU420,
+   DRM_FORMAT_YUV422, DRM_FORMAT_YVU422,
+   DRM_FORMAT_YUV444, DRM_FORMAT_YVU444,
+   DRM_FORMAT_NV12, DRM_FORMAT_NV21,
+};
+
+static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
+{
+   int i;
+
+   for (i = 0; i < plane->format_count; i++) {
+   if (plane->format_types[i] == format)
+   return 0;
+   }
+   return -EINVAL;
+}
+
 static int kmb_plane_atomic_check(struct drm_plane *plane,
  struct drm_plane_state *state)
 {
-/* TBD below structure will be used for implementation later
- * struct drm_crtc_state *crtc_state;
- */
-   /* TBD */
-   /* Plane based checking */
+   struct drm_framebuffer *fb;
+   int ret;
+
+   fb = state->fb;
 
+   ret = check_pixel_format(plane, fb->format->format);
+   if (ret)
+   return ret;
+
+   if (state->crtc_w > KMB_MAX_WIDTH || state->crtc_h > KMB_MAX_HEIGHT)
+   return -EINVAL;
return 0;
 }
 
@@ -38,36 +89,36 @@ unsigned int set_pixel_format(u32 format)
unsigned int val = 0;
 
switch (format) {
-   /*planar formats */
+   /*planar formats */
case DRM_FORMAT_YUV444:
val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE;
break;
case DRM_FORMAT_YVU444:
val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE
-   | LCD_LAYER_CRCB_ORDER;
+   | LCD_LAYER_CRCB_ORDER;
break;
case DRM_FORMAT_YUV422:
val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE;
break;
case DRM_FORMAT_YVU422:
val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE
-  | LCD_LAYER_CRCB_ORDER;
+   | LCD_LAYER_CRCB_ORDER;
break;
case DRM_FORMAT_YUV420:
val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE;
break;
case DRM_FORMAT_YVU420:
val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE
-  | LCD_LAYER_CRCB_ORDER;
+   | LCD_LAYER_CRCB_ORDER;
break;
case DRM_FORMAT_NV12:
val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE;
break;
case DRM_FORMAT_NV21:
val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
-  | LCD_LAYER_CRCB_ORDER;
+   | LCD_LAYER_CRCB_ORDER;
break;
-   /* packed formats */
+   /* packed formats */
case DRM_FORMAT_RGB332:
val = LCD_LAYER_FORMAT_RGB332;
break;
@@ -127,7 +178,7 @@ unsigned int set_bits_per_pixel(const struct 
drm_format_info *format)
unsigned int val = 0;
 
for (i = 0; i < format->num_planes; i++)
-   bpp += 8*format->cpp[i];
+   bpp += 8 * format->cpp[i];
 
switch (bpp) {
case 8:
@@ -171,8 +222,8 @@ static void kmb_plane_atomic_update(struct 

[PATCH v2 17/59] drm/kmb: Part7 of Mipi Tx Initialization

2020-07-14 Thread Anitha Chrisanthus
This completes the DPHY initialization and Tx initialization.

v2: minor code review changes
Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_dsi.c  | 65 ++
 drivers/gpu/drm/kmb/kmb_dsi.h  | 18 
 drivers/gpu/drm/kmb/kmb_regs.h | 15 --
 3 files changed, 91 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 02555c6..f8ddb87 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -28,6 +28,7 @@
 #define MIPI_TX_CFG_CLK_KHZ 24000
 
 /*DPHY Tx test codes*/
+#define TEST_CODE_FSM_CONTROL  0x03
 #define TEST_CODE_PLL_PROPORTIONAL_CHARGE_PUMP_CTRL0x0E
 #define TEST_CODE_PLL_INTEGRAL_CHARGE_PUMP_CTRL0x0F
 #define TEST_CODE_PLL_VCO_CTRL 0x12
@@ -1061,10 +1062,10 @@ static void dphy_init_sequence(struct mipi_ctrl_cfg 
*cfg, u32 dphy_no,
cfg->lane_rate_mbps/2);
 
/*Set clksel */
-   kmb_write_bits_mipi(DPHY_INIT_CTRL1, 18, 2, 0x01);
+   kmb_write_bits_mipi(DPHY_INIT_CTRL1, PLL_CLKSEL_0, 2, 0x01);
 
/*Set pll_shadow_control */
-   kmb_write_bits_mipi(DPHY_INIT_CTRL1, 16, 1, 0x01);
+   kmb_set_bit_mipi(DPHY_INIT_CTRL1, PLL_SHADOW_CTRL);
}
 
/*Send NORMAL OPERATION test code */
@@ -1087,7 +1088,48 @@ static void dphy_init_sequence(struct mipi_ctrl_cfg 
*cfg, u32 dphy_no,
 
/* enable DATA LANES */
kmb_write_bits_mipi(DPHY_ENABLE, dphy_no * 2, 2,
-   ((1 << cfg->active_lanes) - 1));
+   ((1 << cfg->active_lanes) - 1));
+
+   /*Take D-PHY out of shutdown mode */
+   /* deassert SHUTDOWNZ signal*/
+   SET_DPHY_INIT_CTRL0(dphy_no, SHUTDOWNZ);
+   /*deassert RSTZ signal */
+   SET_DPHY_INIT_CTRL0(dphy_no, RESETZ);
+}
+
+static void dphy_wait_fsm(u32 dphy_no, enum dphy_tx_fsm fsm_state)
+{
+   enum dphy_tx_fsm val = DPHY_TX_POWERDWN;
+
+   do {
+   test_mode_send(dphy_no, TEST_CODE_FSM_CONTROL, 0x80);
+   /*TODO-need to add a time out and return failure */
+   val = GET_TEST_DOUT0_3(dphy_no);
+   } while (val != fsm_state);
+
+}
+
+static u32 wait_init_done(u32 dphy_no, u32 active_lanes)
+{
+   u32 stopstatedata = 0;
+   u32 data_lanes = (1 << active_lanes) - 1;
+
+   do {
+   stopstatedata = GET_STOPSTATE_DATA(dphy_no);
+   /*TODO-need to add a time out and return failure */
+   } while (stopstatedata != data_lanes);
+
+   return 0;
+}
+
+static u32 wait_pll_lock(u32 dphy_no)
+{
+   do {
+   ;
+   /*TODO-need to add a time out and return failure */
+   } while (!GET_PLL_LOCK(dphy_no));
+
+   return 0;
 }
 
 static u32 mipi_tx_init_dphy(struct mipi_ctrl_cfg *cfg)
@@ -1113,9 +1155,22 @@ static u32 mipi_tx_init_dphy(struct mipi_ctrl_cfg *cfg)
 */
/*PHY #N+1 ('slave') */
dphy_init_sequence(cfg, dphy_no + 1, MIPI_DPHY_SLAVE);
-   /*TODO PHY #N master */
+
+   dphy_wait_fsm(dphy_no + 1, DPHY_TX_LOCK);
+
+   /*PHY #N master*/
+   dphy_init_sequence(cfg, dphy_no, MIPI_DPHY_MASTER);
+   /* wait for DPHY init to complete */
+   wait_init_done(dphy_no, MIPI_DPHY_D_LANES);
+   wait_init_done(dphy_no + 1,
+   cfg->active_lanes - MIPI_DPHY_D_LANES);
+   wait_pll_lock(dphy_no);
+   wait_pll_lock(dphy_no + 1);
+   } else {/* Single DPHY */
+   dphy_init_sequence(cfg, dphy_no, MIPI_DPHY_MASTER);
+   wait_init_done(dphy_no, cfg->active_lanes);
+   wait_pll_lock(dphy_no);
}
-   /*TODO- Single DPHY */
return 0;
 }
 
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.h b/drivers/gpu/drm/kmb/kmb_dsi.h
index deaee3e..7db7f58 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.h
+++ b/drivers/gpu/drm/kmb/kmb_dsi.h
@@ -184,12 +184,30 @@ enum dphy_mode {
MIPI_DPHY_MASTER
 };
 
+enum dphy_tx_fsm {
+   DPHY_TX_POWERDWN = 0,
+   DPHY_TX_BGPON,
+   DPHY_TX_TERMCAL,
+   DPHY_TX_TERMCALUP,
+   DPHY_TX_OFFSETCAL,
+   DPHY_TX_LOCK,
+   DPHY_TX_SRCAL,
+   DPHY_TX_IDLE,
+   DPHY_TX_ULP,
+   DPHY_TX_LANESTART,
+   DPHY_TX_CLKALIGN,
+   DPHY_TX_DDLTUNNING,
+   DPHY_TX_ULP_FORCE_PLL,
+   DPHY_TX_LOCK_LOSS
+};
+
 struct mipi_data_type_params {
uint8_t size_constraint_pixels;
uint8_t size_constraint_bytes;
uint8_t pixels_per_pclk;
uint8_t bits_per_pclk;
 };
+
 struct mipi_tx_dsi_cfg {
uint8_t hfp_blank_en;   /*horizontal front porch blanking enable */
uint8_t eotp_en;/*End of transmission packet enable */
diff --git a/drivers/gpu/drm/k

[PATCH v2 23/59] drm/kmb: Additional register programming to update_plane

2020-07-14 Thread Anitha Chrisanthus
These changes are ported from Myriadx which has additional registers
updated for planes. This change does the following
reinitialize plane interrupts
program Cb/Cr for planar formats
set LCD_CTRL_VHSYNC_IDLE_LVL
set output format and configure csc

v2: code review changes
v3: corrected spelling

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.h   |  16 
 drivers/gpu/drm/kmb/kmb_plane.c | 183 
 drivers/gpu/drm/kmb/kmb_regs.h  |  72 ++--
 3 files changed, 210 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 1e81d44..586b53e 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -92,6 +92,22 @@ static inline u32 kmb_read_lcd(struct kmb_drm_private 
*dev_p, unsigned int reg)
return readl(dev_p->lcd_mmio + reg);
 }
 
+static inline void kmb_set_bitmask_lcd(struct kmb_drm_private *dev_p,
+   unsigned int reg, u32 mask)
+{
+   u32 reg_val = kmb_read_lcd(dev_p->lcd_mmio, reg);
+
+   kmb_write_lcd(dev_p->lcd_mmio, reg, (reg_val | mask));
+}
+
+static inline void kmb_clr_bitmask_lcd(struct kmb_drm_private *dev_p,
+   unsigned int reg, u32 mask)
+{
+   u32 reg_val = kmb_read_lcd(dev_p->lcd_mmio, reg);
+
+   kmb_write_lcd(dev_p->lcd_mmio, reg, (reg_val & (~mask)));
+}
+
 static inline u32 kmb_read_mipi(struct kmb_drm_private *dev_p, unsigned int 
reg)
 {
return readl(dev_p->mipi_mmio + reg);
diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 946349a..2980764 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -56,6 +56,46 @@ static const u32 kmb_formats_v[] = {
DRM_FORMAT_NV12, DRM_FORMAT_NV21,
 };
 
+#define LCD_INT_VL0_ERR (LAYER0_DMA_FIFO_UNDERFLOW | \
+   LAYER0_DMA_FIFO_OVERFLOW | \
+   LAYER0_DMA_CB_FIFO_OVERFLOW | \
+   LAYER0_DMA_CB_FIFO_UNDERFLOW | \
+   LAYER0_DMA_CR_FIFO_OVERFLOW | \
+   LAYER0_DMA_CR_FIFO_UNDERFLOW)
+
+#define LCD_INT_VL1_ERR (LAYER1_DMA_FIFO_UNDERFLOW | \
+   LAYER1_DMA_FIFO_OVERFLOW | \
+   LAYER1_DMA_CB_FIFO_OVERFLOW | \
+   LAYER1_DMA_CB_FIFO_UNDERFLOW | \
+   LAYER1_DMA_CR_FIFO_OVERFLOW | \
+   LAYER1_DMA_CR_FIFO_UNDERFLOW)
+
+#define LCD_INT_GL0_ERR (LAYER2_DMA_FIFO_OVERFLOW | LAYER2_DMA_FIFO_UNDERFLOW)
+
+#define LCD_INT_GL1_ERR (LAYER3_DMA_FIFO_OVERFLOW | LAYER3_DMA_FIFO_UNDERFLOW)
+
+#define LCD_INT_VL0 (LAYER0_DMA_DONE | LAYER0_DMA_IDLE | LCD_INT_VL0_ERR)
+
+#define LCD_INT_VL1 (LAYER1_DMA_DONE | LAYER1_DMA_IDLE | LCD_INT_VL1_ERR)
+
+#define LCD_INT_GL0 (LAYER2_DMA_DONE | LAYER2_DMA_IDLE | LCD_INT_GL0_ERR)
+
+#define LCD_INT_GL1 (LAYER3_DMA_DONE | LAYER3_DMA_IDLE | LCD_INT_GL1_ERR)
+
+const uint32_t layer_irqs[] = {
+   LCD_INT_VL0,
+   LCD_INT_VL1,
+   LCD_INT_GL0,
+   LCD_INT_GL1
+ };
+/*Conversion (yuv->rgb) matrix from myriadx */
+static const u32 csc_coef_lcd[] = {
+   1024, 0, 1436,
+   1024, -352, -731,
+   1024, 1814, 0,
+   -179, 125, -226
+};
+
 static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
 {
int i;
@@ -197,6 +237,24 @@ unsigned int set_bits_per_pixel(const struct 
drm_format_info *format)
return val;
 }
 
+static void config_csc(struct kmb_drm_private *dev_p, int plane_id)
+{
+   /*YUV to RGB conversion using the fixed matrix csc_coef_lcd */
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF11(plane_id), csc_coef_lcd[0]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF12(plane_id), csc_coef_lcd[1]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF13(plane_id), csc_coef_lcd[2]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF21(plane_id), csc_coef_lcd[3]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF22(plane_id), csc_coef_lcd[4]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF23(plane_id), csc_coef_lcd[5]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF31(plane_id), csc_coef_lcd[6]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF32(plane_id), csc_coef_lcd[7]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_COEFF33(plane_id), csc_coef_lcd[8]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_OFF1(plane_id), csc_coef_lcd[9]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_OFF2(plane_id), csc_coef_lcd[10]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]);
+   kmb_set_bitmask_lcd(dev_p, LCD_LAYERn_CFG(plane_id), LCD_LAYER_CSC_EN);
+}
+
 static void kmb_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *state)
 {
@@ -211,6 +269,7 @@ static void kmb_plane_atomic_upd

[PATCH v2 46/59] drm/kmb: Enable LCD interrupts during modeset

2020-07-14 Thread Anitha Chrisanthus
The issue was that spurious interrupts were happening before the LCD
controller was enabled and system hangs. Fix is to
clear LCD interrupts and disable them before modeset
and re enable them after enabling LCD controller.

v2: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c | 12 +---
 drivers/gpu/drm/kmb/kmb_drv.c  | 21 +++--
 2 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index 589a841..c390bbe 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -78,6 +78,7 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
int vsync_start_offset;
int vsync_end_offset;
struct kmb_drm_private *dev_p = to_kmb(dev);
+   unsigned int val = 0;
 
/* initialize mipi */
kmb_dsi_hw_init(dev, m);
@@ -88,6 +89,9 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
m->crtc_hsync_start - m->crtc_hdisplay,
m->crtc_htotal - m->crtc_hsync_end,
m->crtc_hsync_end - m->crtc_hsync_start);
+   val = kmb_read_lcd(dev_p, LCD_INT_ENABLE);
+   kmb_clr_bitmask_lcd(dev_p, LCD_INT_ENABLE, val);
+   kmb_set_bitmask_lcd(dev_p, LCD_INT_CLEAR, ~0x0);
 // vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vfront_porch = 2;
 // vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -136,9 +140,9 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_write_lcd(dev_p, LCD_VSYNC_START_EVEN, 10);
kmb_write_lcd(dev_p, LCD_VSYNC_END_EVEN, 10);
}
-   /* enable VL1 layer as default */
kmb_write_lcd(dev_p, LCD_TIMING_GEN_TRIG, ENABLE);
kmb_set_bitmask_lcd(dev_p, LCD_CONTROL, LCD_CTRL_ENABLE);
+   kmb_set_bitmask_lcd(dev_p, LCD_INT_ENABLE, val);
 #endif
/* TBD */
/* set clocks here */
@@ -170,8 +174,9 @@ static void kmb_crtc_atomic_begin(struct drm_crtc *crtc,
  struct drm_crtc_state *state)
 {
struct drm_device *dev = crtc->dev;
+   struct kmb_drm_private *dev_p = to_kmb(dev);
 
-   kmb_clr_bitmask_lcd(dev->dev_private, LCD_INT_ENABLE,
+   kmb_clr_bitmask_lcd(dev_p, LCD_INT_ENABLE,
LCD_INT_VERT_COMP);
 }
 
@@ -179,8 +184,9 @@ static void kmb_crtc_atomic_flush(struct drm_crtc *crtc,
  struct drm_crtc_state *state)
 {
struct drm_device *dev = crtc->dev;
+   struct kmb_drm_private *dev_p = to_kmb(dev);
 
-   kmb_set_bitmask_lcd(dev->dev_private, LCD_INT_ENABLE,
+   kmb_set_bitmask_lcd(dev_p, LCD_INT_ENABLE,
LCD_INT_VERT_COMP);
 
spin_lock_irq(&crtc->dev->event_lock);
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index e6aa32c..308036e 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -37,8 +37,6 @@ static irqreturn_t kmb_isr(int irq, void *arg);
 
 static struct clk *clk_lcd;
 static struct clk *clk_mipi;
-static struct clk *clk_msscam;
-static struct clk *clk_pll0out0;
 static struct clk *clk_mipi_ecfg;
 static struct clk *clk_mipi_cfg;
 
@@ -59,12 +57,6 @@ int kmb_display_clk_enable(void)
DRM_ERROR("Failed to enable MIPI clock: %d\n", ret);
return ret;
}
-/* ret = clk_prepare_enable(clk_msscam);
-   if (ret) {
-   DRM_ERROR("Failed to enable MSSCAM clock: %d\n", ret);
-   return ret;
-   }
-   */
 
ret = clk_prepare_enable(clk_mipi_ecfg);
if (ret) {
@@ -87,8 +79,6 @@ static int kmb_display_clk_disable(void)
clk_disable_unprepare(clk_lcd);
if (clk_mipi)
clk_disable_unprepare(clk_mipi);
-   if (clk_msscam)
-   clk_disable_unprepare(clk_msscam);
if (clk_mipi_ecfg)
clk_disable_unprepare(clk_mipi_ecfg);
if (clk_mipi_cfg)
@@ -180,14 +170,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
DRM_ERROR("clk_get() failed clk_mipi\n");
goto setup_fail;
}
-   clk_pll0out0 = clk_get(&pdev->dev, "clk_pll0_out0");
-   if (IS_ERR(clk_pll0out0))
-   DRM_ERROR("clk_get() failed clk_pll0_out0\n");
-
-   if (clk_pll0out0)
-   DRM_INFO("Get clk_pll0out0 = %ld\n",
-   clk_get_rate(clk_pll0out0));
-
clk_mipi_ecfg = clk_get(&pdev->dev, "clk_mipi_ecfg");
if (IS_ERR(clk_mipi_ecfg)) {
DRM_ERROR("clk_get() failed clk_mipi_ecfg\n");
@@ -394,6 +376,9 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
break;
}
}
+
+   /* clear all interrupts */
+   kmb_set_bitmask_lcd(dev->dev_private, LCD_INT_CLEAR, ~0x0);
ret

[PATCH v2 28/59] drm/kmb: Changed MMIO size

2020-07-14 Thread Anitha Chrisanthus
Also added debug messages

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c  | 16 ++--
 drivers/gpu/drm/kmb/kmb_regs.h |  6 +++---
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 4afdb9c..d13552a 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -29,6 +29,7 @@
 #include "kmb_plane.h"
 #include "kmb_regs.h"
 
+#define DEBUG
 /*IRQ handler*/
 static irqreturn_t kmb_isr(int irq, void *arg);
 
@@ -327,6 +328,7 @@ static int kmb_drm_bind(struct device *dev)
dev_set_drvdata(dev, drm);
 
kmb_setup_mode_config(drm);
+   DRM_DEBUG("kmb_bind : after kmb_setup_mode_config\n");
ret = kmb_load(drm, 0);
if (ret)
goto err_free;
@@ -439,17 +441,27 @@ static int kmb_probe(struct platform_device *pdev)
 {
struct device_node *port;
struct component_match *match = NULL;
+   int ret;
 
/* there is only one output port inside each device, find it */
+   DRM_DEBUG("%s : ENTER", __func__);
+
port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
+   DRM_DEBUG("%s : port = 0x%pOF\n", __func__, port);
if (!port)
return -ENODEV;
 
+   DRM_DEBUG("%s : after get_remote", __func__);
+   DRM_DEBUG("Adding component %pOF\n", port);
drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
+   DRM_DEBUG("%s : after get_match", __func__);
of_node_put(port);
 
-   return component_master_add_with_match(&pdev->dev, &kmb_master_ops,
-  match);
+ret = component_master_add_with_match(&pdev->dev, &kmb_master_ops,
+   match);
+
+   DRM_DEBUG("%s : EXIT ret=%d\n", __func__, ret);
+   return ret;
 }
 
 static int kmb_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index 85b55cb..e98e144 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -13,9 +13,9 @@
 /*from Data Book section 12.11.6.1 page 4972 */
 #define LCD_BASE_ADDR   (0x2093)
 #define MSS_CAM_BASE_ADDR  (MIPI_BASE_ADDR + 0x1)
-#define LCD_MMIO_SIZE  (0x1)
-#define MIPI_MMIO_SIZE (0x1)
-#define MSS_CAM_MMIO_SIZE  (0x1)
+#define LCD_MMIO_SIZE  (0x3000)
+#define MIPI_MMIO_SIZE (0x4000)
+#define MSS_CAM_MMIO_SIZE  (0x10)
 
 /***
  *LCD controller control register defines
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 20/59] drm/kmb: Register IRQ for LCD

2020-07-14 Thread Anitha Chrisanthus
This code is commented out until firmware is updated to
redirect LCD IRQ from MSSCPU to A53.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 5192040..594e64c 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -29,12 +29,16 @@
 #include "kmb_plane.h"
 #include "kmb_regs.h"
 
+/*IRQ handler*/
+static irqreturn_t kmb_isr(int irq, void *arg);
+
 static int kmb_load(struct drm_device *drm, unsigned long flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
/*struct resource *res;*/
/*u32 version;*/
+   /*int irq_lcd, irq_mipi; */
int ret;
 
/* TBD - not sure if clock_get needs to be called here */
@@ -85,6 +89,12 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
dev_p->msscam_mmio = ioremap_cache(MSS_CAM_BASE_ADDR,
MSS_CAM_MMIO_SIZE);
 
+   /*TODO - register irqs here - section 17.3 in databook
+* lists LCD at 79 under MSS CPU - firmware has to redirect it to A53
+* May be 33 for LCD and 34 for MIPI? Will wait till firmware
+* finalizes the IRQ numbers for redirection
+*/
+
 /*TBD read and check for correct product version here */
 
/* Get the optional framebuffer memory resource */
@@ -132,7 +142,7 @@ static void kmb_setup_mode_config(struct drm_device *drm)
drm->mode_config.funcs = &kmb_mode_config_funcs;
 }
 
-static irqreturn_t kmb_irq(int irq, void *arg)
+static irqreturn_t kmb_isr(int irq, void *arg)
 {
struct drm_device *dev = (struct drm_device *)arg;
unsigned long status, val;
@@ -178,8 +188,9 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
 
 static struct drm_driver kmb_driver = {
.driver_features = DRIVER_GEM |
-   DRIVER_MODESET | DRIVER_ATOMIC,
-   .irq_handler = kmb_irq,
+   DRIVER_MODESET |
+   DRIVER_ATOMIC,
+   .irq_handler = kmb_isr,
.irq_preinstall = kmb_irq_reset,
.irq_uninstall = kmb_irq_reset,
.gem_free_object_unlocked = drm_gem_cma_free_object,
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 41/59] drm/kmb: Changes for LCD to Mipi

2020-07-14 Thread Anitha Chrisanthus
Also free dsi resources on driver unload. System clock frequency change
for llp ratio calculation.

v2: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  |  25 
 drivers/gpu/drm/kmb/kmb_drv.c   |   6 +-
 drivers/gpu/drm/kmb/kmb_drv.h   |   1 +
 drivers/gpu/drm/kmb/kmb_dsi.c   | 135 +++-
 drivers/gpu/drm/kmb/kmb_dsi.h   |   2 +-
 drivers/gpu/drm/kmb/kmb_plane.c |  24 +++
 drivers/gpu/drm/kmb/kmb_regs.h  |   2 +
 7 files changed, 70 insertions(+), 125 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index f77e6f5..cbf998f 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -90,11 +90,14 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
vm.vfront_porch = 0;
 // vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
vm.vback_porch = 0;
-   vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
+// vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
+   vm.vsync_len = 1;
//vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
vm.hfront_porch = 0;
-   vm.hback_porch = m->crtc_htotal - m->crtc_hsync_end;
-   vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
+   vm.hback_porch = 0;
+   //vm.hback_porch = m->crtc_htotal - m->crtc_hsync_end;
+   vm.hsync_len = 1;
+// vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
 
vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
vsync_end_offset = m->crtc_vsync_end - m->crtc_hsync_end;
@@ -106,13 +109,13 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
vm.hback_porch, vm.hfront_porch, vm.hsync_len);
kmb_write_lcd(dev_p, LCD_V_ACTIVEHEIGHT,
m->crtc_vdisplay - 1);
-   kmb_write_lcd(dev_p, LCD_V_BACKPORCH, vm.vback_porch - 1);
-   kmb_write_lcd(dev_p, LCD_V_FRONTPORCH, vm.vfront_porch - 1);
+   kmb_write_lcd(dev_p, LCD_V_BACKPORCH, vm.vback_porch);
+   kmb_write_lcd(dev_p, LCD_V_FRONTPORCH, vm.vfront_porch);
kmb_write_lcd(dev_p, LCD_VSYNC_WIDTH, vm.vsync_len - 1);
kmb_write_lcd(dev_p, LCD_H_ACTIVEWIDTH,
m->crtc_hdisplay - 1);
-   kmb_write_lcd(dev_p, LCD_H_BACKPORCH, vm.hback_porch - 1);
-   kmb_write_lcd(dev_p, LCD_H_FRONTPORCH, vm.hfront_porch - 1);
+   kmb_write_lcd(dev_p, LCD_H_BACKPORCH, vm.hback_porch);
+   kmb_write_lcd(dev_p, LCD_H_FRONTPORCH, vm.hfront_porch);
kmb_write_lcd(dev_p, LCD_HSYNC_WIDTH, vm.hsync_len - 1);
/*this is hardcoded as 0 in the Myriadx code */
kmb_write_lcd(dev_p, LCD_VSYNC_START, 0);
@@ -122,11 +125,11 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_write_lcd(dev_p,
LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
kmb_write_lcd(dev_p,
-   LCD_V_BACKPORCH_EVEN, vm.vback_porch - 1);
+   LCD_V_BACKPORCH_EVEN, vm.vback_porch);
kmb_write_lcd(dev_p,
-   LCD_V_FRONTPORCH_EVEN, vm.vfront_porch - 1);
-   kmb_write_lcd(dev_p,
-   LCD_V_ACTIVEHEIGHT_EVEN, m->crtc_vdisplay - 1);
+   LCD_V_FRONTPORCH_EVEN, vm.vfront_porch);
+   kmb_write_lcd(dev_p, LCD_V_ACTIVEHEIGHT_EVEN,
+   m->crtc_vdisplay - 1);
/*this is hardcoded as 10 in the Myriadx code*/
kmb_write_lcd(dev_p, LCD_VSYNC_START_EVEN, 10);
kmb_write_lcd(dev_p, LCD_VSYNC_END_EVEN, 10);
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 8bd3011..039dd21 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -216,7 +216,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 #endif
/* Set MIPI clock to 24 Mhz*/
DRM_INFO("Get clk_mipi before set = %ld\n", clk_get_rate(clk_mipi));
-//#define MIPI_CLK
+#define MIPI_CLK
 #ifdef MIPI_CLK
ret = clk_set_rate(clk_mipi, KMB_MIPI_DEFAULT_CLK);
DRM_INFO("Get clk_mipi after set = %ld\n", clk_get_rate(clk_mipi));
@@ -497,7 +497,7 @@ static void kmb_drm_unload(struct device *dev)
dev_set_drvdata(dev, NULL);
 
/* Unregister DSI host */
-   dsi_host_unregister();
+   kmb_dsi_host_unregister();
 }
 
 static int kmb_probe(struct platform_device *pdev)
@@ -573,7 +573,7 @@ static int kmb_probe(struct platform_device *pdev)
drm_mode_config_cleanup(drm);
dev_set_drvdata(dev, NULL);
drm_dev_put(drm);
-   dsi_host_unregister();
+   kmb_dsi_host_unregister();
 
return ret;
 }
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 89d7845..aa77631 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ 

[PATCH v2 36/59] drm/kmb: Enable MIPI TX HS Test Pattern Generation

2020-07-14 Thread Anitha Chrisanthus
From: Edmund Dea 

Added test pattern generator function. Enable this at compile time to
test if mipi is working. mipi->hdmi section

Signed-off-by: Edmund Dea 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_dsi.c  | 31 +++
 drivers/gpu/drm/kmb/kmb_dsi.h  |  7 +++
 drivers/gpu/drm/kmb/kmb_regs.h | 11 +++
 3 files changed, 49 insertions(+)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 01fa378..960ecfa 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -744,6 +744,32 @@ static void mipi_tx_ctrl_cfg(struct kmb_drm_private 
*dev_p, u8 fg_id,
kmb_write_mipi(dev_p, MIPI_TXm_HS_CTRL(ctrl_no), ctrl);
 }
 
+#ifdef MIPI_TX_TEST_PATTERN_GENERATION
+static void mipi_tx_hs_tp_gen(struct kmb_drm_private *dev_p, int vc,
+   int tp_sel, u32 stripe_width, u32 color0, u32 color1)
+{
+   u32 ctrl_no = MIPI_CTRL6;
+
+   /* Select test pattern mode on the virtual channel */
+   kmb_write_mipi(dev_p, MIPI_TXm_HS_TEST_PAT_CTRL(ctrl_no),
+   TP_SEL_VCm(vc, tp_sel));
+
+   if (tp_sel == MIPI_TX_HS_TP_V_STRIPES ||
+   tp_sel == MIPI_TX_HS_TP_H_STRIPES) {
+   kmb_write_mipi(dev_p, MIPI_TXm_HS_TEST_PAT_CTRL(ctrl_no),
+   TP_STRIPE_WIDTH(stripe_width));
+   }
+
+   /* Configure test pattern colors */
+   kmb_write_mipi(dev_p, MIPI_TX_HS_TEST_PAT_COLOR0, color0);
+   kmb_write_mipi(dev_p, MIPI_TX_HS_TEST_PAT_COLOR1, color1);
+
+   /* Enable test pattern generation on the virtual channel */
+   kmb_write_mipi(dev_p, MIPI_TXm_HS_TEST_PAT_CTRL(ctrl_no),
+   TP_EN_VCm(vc));
+}
+#endif
+
 static u32 mipi_tx_init_cntrl(struct kmb_drm_private *dev_p,
struct mipi_ctrl_cfg *ctrl_cfg)
 {
@@ -807,6 +833,11 @@ static u32 mipi_tx_init_cntrl(struct kmb_drm_private 
*dev_p,
/*Multi-Channel FIFO Configuration*/
mipi_tx_multichannel_fifo_cfg(dev_p, ctrl_cfg->active_lanes, frame_id);
 
+#ifdef MIPI_TX_TEST_PATTERN_GENERATION
+   mipi_tx_hs_tp_gen(dev_p, 0, MIPI_TX_HS_TP_WHOLE_FRAME_COLOR0, 0,
+   0x, 0);
+#endif
+
/*Frame Generator Enable */
mipi_tx_ctrl_cfg(dev_p, frame_id, ctrl_cfg);
return ret;
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.h b/drivers/gpu/drm/kmb/kmb_dsi.h
index 811f3b8..3de68de 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.h
+++ b/drivers/gpu/drm/kmb/kmb_dsi.h
@@ -180,6 +180,13 @@ enum mipi_dsi_data_type {
DSI_LP_DT_RESERVED_3F = 0x3f
 };
 
+enum mipi_tx_hs_tp_sel {
+   MIPI_TX_HS_TP_WHOLE_FRAME_COLOR0 = 0,
+   MIPI_TX_HS_TP_WHOLE_FRAME_COLOR1,
+   MIPI_TX_HS_TP_V_STRIPES,
+   MIPI_TX_HS_TP_H_STRIPES,
+};
+
 enum dphy_mode {
MIPI_DPHY_SLAVE = 0,
MIPI_DPHY_MASTER
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index a3f1a3a..207a161 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -625,6 +625,17 @@
MIPI_TX_HS_IRQ_CLEAR \
+ HS_OFFSET(M), val)
 
+/* MIPI Test Pattern Generation */
+#define MIPI_TX_HS_TEST_PAT_CTRL   (0x230)
+#define   MIPI_TXm_HS_TEST_PAT_CTRL(M) \
+   (MIPI_TX_HS_TEST_PAT_CTRL + HS_OFFSET(M))
+#define   TP_EN_VCm(M) ((M) * 0x04)
+#define   TP_SEL_VCm(M, N) \
+   (N << (((M) * 0x04) + 1))
+#define   TP_STRIPE_WIDTH(M)   ((M) << 16)
+#define MIPI_TX_HS_TEST_PAT_COLOR0 (0x234)
+#define MIPI_TX_HS_TEST_PAT_COLOR1 (0x238)
+
 /* D-PHY regs */
 #define DPHY_ENABLE(0x100)
 #define DPHY_INIT_CTRL0(0x104)
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 44/59] drm/kmb: Mipi settings from input timings

2020-07-14 Thread Anitha Chrisanthus
Removed hardcoded timings, set timings based on the current mode's
input timings. Also calculate and set the lane rate based on the
timings.

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_crtc.c |  9 +++-
 drivers/gpu/drm/kmb/kmb_dsi.c  | 93 +++---
 drivers/gpu/drm/kmb/kmb_dsi.h  |  2 +-
 3 files changed, 61 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index a6a0444..1987185e 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -84,7 +84,14 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct kmb_drm_private *dev_p = to_kmb(dev);
 #endif
/* initialize mipi */
-   kmb_dsi_hw_init(dev);
+   kmb_dsi_hw_init(dev, m);
+   DRM_INFO("vfp= %d vbp= %d vsyc_len=%d hfp=%d hbp=%d hsync_len=%d\n",
+   m->crtc_vsync_start - m->crtc_vdisplay,
+   m->crtc_vtotal - m->crtc_vsync_end,
+   m->crtc_vsync_end - m->crtc_vsync_start,
+   m->crtc_hsync_start - m->crtc_hdisplay,
+   m->crtc_htotal - m->crtc_hsync_end,
+   m->crtc_hsync_end - m->crtc_hsync_start);
 #ifdef LCD_TEST
 // vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vfront_porch = 2;
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index e01c4f9..e9499cf 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -27,19 +27,12 @@ static int hw_initialized;
 //#define MIPI_TX_TEST_PATTERN_GENERATION
 //#define MIPI_DMA
 //#define RTL_TEST
-//#define IMG_WIDTH_PX  640
-//#define IMG_HEIGHT_LINES  10
-
-#define LCD_BYTESPP   1
 
 /*MIPI TX CFG*/
-//#define MIPI_TX_LANE_DATA_RATE_MBPS 1782
-//#define MIPI_TX_LANE_DATA_RATE_MBPS 800
 #define MIPI_TX_LANE_DATA_RATE_MBPS 891
-//#define MIPI_TX_LANE_DATA_RATE_MBPS 80
 #define MIPI_TX_REF_CLK_KHZ 24000
-//#define MIPI_TX_REF_CLK_KHZ 23809
 #define MIPI_TX_CFG_CLK_KHZ 24000
+#define MIPI_TX_BPP24
 
 /*DPHY Tx test codes*/
 #define TEST_CODE_FSM_CONTROL  0x03
@@ -78,23 +71,12 @@ static struct mipi_dsi_host *dsi_host;
 static struct mipi_dsi_device *dsi_device;
 
 /*
- * These are added here only temporarily for testing,
- * these will eventually go to the device tree sections,
- * and can be used as a refernce later for device tree additions
+ * Default setting is 1080p, 4 lanes.
  */
-#define RES_1920x1080
-#ifdef RES_1920x1080
 #define IMG_HEIGHT_LINES  1080
 #define IMG_WIDTH_PX  1920
 #define MIPI_TX_ACTIVE_LANES 4
-#endif
 
-//#define RES_1280x720
-#ifdef RES_1280x720
-#define IMG_HEIGHT_LINES  720
-#define IMG_WIDTH_PX  1280
-#define MIPI_TX_ACTIVE_LANES 2
-#endif
 struct mipi_tx_frame_section_cfg mipi_tx_frame0_sect_cfg = {
.width_pixels = IMG_WIDTH_PX,
.height_lines = IMG_HEIGHT_LINES,
@@ -104,7 +86,6 @@ struct mipi_tx_frame_section_cfg mipi_tx_frame0_sect_cfg = {
.dma_packed = 0
 };
 
-#ifdef RES_1920x1080
 struct mipi_tx_frame_cfg mipitx_frame0_cfg = {
.sections[0] = &mipi_tx_frame0_sect_cfg,
.sections[1] = NULL,
@@ -117,22 +98,6 @@ struct mipi_tx_frame_cfg mipitx_frame0_cfg = {
.h_backporch = 148,
.h_frontporch = 88
 };
-#endif
-
-#ifdef RES_1280x720
-struct mipi_tx_frame_cfg mipitx_frame0_cfg = {
-   .sections[0] = &mipi_tx_frame0_sect_cfg,
-   .sections[1] = NULL,
-   .sections[2] = NULL,
-   .sections[3] = NULL,
-   .vsync_width = 5,
-   .v_backporch = 20,
-   .v_frontporch = 5,
-   .hsync_width = 40,
-   .h_backporch = 220,
-   .h_frontporch = 110,
-};
-#endif
 
 struct mipi_tx_dsi_cfg mipitx_dsi_cfg = {
.hfp_blank_en = 0,
@@ -1720,10 +1685,58 @@ int kmb_kernel_read(struct file *file, loff_t offset,
return ret;
 }
 
-int kmb_dsi_hw_init(struct drm_device *dev)
+int kmb_dsi_hw_init(struct drm_device *dev, struct drm_display_mode *mode)
 {
struct kmb_drm_private *dev_p = to_kmb(dev);
+   u64 data_rate;
+
+   mipi_tx_init_cfg.active_lanes = MIPI_TX_ACTIVE_LANES;
+   if (mode != NULL) {
+   mipi_tx_frame0_sect_cfg.width_pixels = mode->crtc_hdisplay;
+   mipi_tx_frame0_sect_cfg.height_lines = mode->crtc_vdisplay;
+   mipitx_frame0_cfg.vsync_width =
+   mode->crtc_vsync_end - mode->crtc_vsync_start;
+   mipitx_frame0_cfg.v_backporch =
+   mode->crtc_vtotal - mode->crtc_vsync_end;
+   mipitx_frame0_cfg.v_frontporch =
+   mode->crtc_vsync_start - mode->crtc_vdisplay;
+   mipitx_frame0_cfg.hsync_width =
+   mode->crtc_hsync_end - mode->crtc_hsync_start;
+   mipitx_frame0_cfg.h_backporch =
+   mode->crtc_htotal - mode->crtc_hsync_end;
+   mipit

[PATCH v2 33/59] drm/kmb: Initialize clocks for clk_msscam, clk_mipi_ecfg, & clk_mipi_cfg.

2020-07-14 Thread Anitha Chrisanthus
From: Edmund Dea 

Note that we enable clk_msscam but do not set clk_msscam. However, we do
enable and set clk_mipi_ecfg and clk_mipi_cfg.

Verify that LCD and MIPI clocks are set successfully.

Signed-off-by: Edmund Dea 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 112 +-
 drivers/gpu/drm/kmb/kmb_drv.h |   2 +
 2 files changed, 102 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 1368770..9dc5f91 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -36,6 +36,9 @@ static irqreturn_t kmb_isr(int irq, void *arg);
 
 static struct clk *clk_lcd;
 static struct clk *clk_mipi;
+static struct clk *clk_msscam;
+static struct clk *clk_mipi_ecfg;
+static struct clk *clk_mipi_cfg;
 
 struct drm_bridge *adv_bridge;
 
@@ -54,6 +57,24 @@ static int kmb_display_clk_enable(void)
DRM_ERROR("Failed to enable MIPI clock: %d\n", ret);
return ret;
}
+
+   ret = clk_prepare_enable(clk_msscam);
+   if (ret) {
+   DRM_ERROR("Failed to enable MSSCAM clock: %d\n", ret);
+   return ret;
+   }
+
+   ret = clk_prepare_enable(clk_mipi_ecfg);
+   if (ret) {
+   DRM_ERROR("Failed to enable MIPI_ECFG clock: %d\n", ret);
+   return ret;
+   }
+
+   ret = clk_prepare_enable(clk_mipi_cfg);
+   if (ret) {
+   DRM_ERROR("Failed to enable MIPI_CFG clock: %d\n", ret);
+   return ret;
+   }
DRM_INFO("SUCCESS : enabled LCD MIPI clocks\n");
return 0;
 }
@@ -64,6 +85,12 @@ static int kmb_display_clk_disable(void)
clk_disable_unprepare(clk_lcd);
if (clk_mipi)
clk_disable_unprepare(clk_mipi);
+   if (clk_msscam)
+   clk_disable_unprepare(clk_msscam);
+   if (clk_mipi_ecfg)
+   clk_disable_unprepare(clk_mipi_ecfg);
+   if (clk_mipi_cfg)
+   clk_disable_unprepare(clk_mipi_cfg);
return 0;
 }
 
@@ -98,6 +125,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
struct platform_device *pdev = to_platform_device(drm->dev);
/*u32 version;*/
int ret = 0;
+   unsigned long clk;
 
/* Map LCD MMIO registers */
dev_p->lcd_mmio = kmb_map_mmio(pdev, "lcd_regs");
@@ -108,7 +136,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 
/* Map MIPI MMIO registers */
dev_p->mipi_mmio = kmb_map_mmio(pdev, "mipi_regs");
-
if (IS_ERR(dev_p->mipi_mmio)) {
DRM_ERROR("failed to map MIPI registers\n");
iounmap(dev_p->lcd_mmio);
@@ -126,33 +153,94 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
return -ENOMEM;
}
 
-   /* enable display clocks*/
+   /* Enable display clocks*/
clk_lcd = clk_get(&pdev->dev, "clk_lcd");
-   if (!clk_lcd) {
+   if (IS_ERR(clk_lcd)) {
DRM_ERROR("clk_get() failed clk_lcd\n");
goto setup_fail;
}
-   DRM_INFO("%s : %d\n", __func__, __LINE__);
 
clk_mipi = clk_get(&pdev->dev, "clk_mipi");
-   if (!clk_mipi) {
+   if (IS_ERR(clk_mipi)) {
DRM_ERROR("clk_get() failed clk_mipi\n");
goto setup_fail;
}
-   DRM_INFO("%s : %d\n", __func__, __LINE__);
+
+   clk_msscam = clk_get(&pdev->dev, "clk_msscam");
+   if (IS_ERR(clk_msscam)) {
+   DRM_ERROR("clk_get() failed clk_msscam\n");
+   goto setup_fail;
+   }
+
+   clk_mipi_ecfg = clk_get(&pdev->dev, "clk_mipi_ecfg");
+   if (IS_ERR(clk_mipi_ecfg)) {
+   DRM_ERROR("clk_get() failed clk_mipi_ecfg\n");
+   goto setup_fail;
+   }
+
+   clk_mipi_cfg = clk_get(&pdev->dev, "clk_mipi_cfg");
+   if (IS_ERR(clk_mipi_cfg)) {
+   DRM_ERROR("clk_get() failed clk_mipi_cfg\n");
+   goto setup_fail;
+   }
+
ret = kmb_display_clk_enable();
 
-   /* set LCD clock to 200 Mhz*/
+   /* Set LCD clock to 200 Mhz*/
DRM_INFO("Get clk_lcd before set = %ld\n", clk_get_rate(clk_lcd));
-   ret = clk_set_rate(clk_lcd, 2);
-   DRM_INFO("Setting LCD clock tp 200Mhz ret = %d\n", ret);
+   ret = clk_set_rate(clk_lcd, KMB_LCD_DEFAULT_CLK);
+   if (clk_get_rate(clk_lcd) != KMB_LCD_DEFAULT_CLK) {
+   DRM_ERROR("failed to set to clk_lcd to %d\n",
+   KMB_LCD_DEFAULT_CLK);
+   goto setup_fail;
+   }
+   DRM_INFO("Setting LCD clock to %d Mhz ret = %d\n",
+   KMB_LCD_DEFAULT_CLK/100, ret);
DRM_INFO("Get clk_lcd after set = %ld\n", clk_get_rate(clk_lcd));
-   /* set MIPI clock to 24 Mhz*/
+
+   /* Set MIPI clock to 24 Mhz*/
DRM_INFO("Get clk_mipi before set = %ld\n", clk_get_rate(clk_mipi));
-   ret = clk_set_rate(

[PATCH v2 15/59] drm/kmb: Part5 of Mipi Tx Intitialization

2020-07-14 Thread Anitha Chrisanthus
This is part1 of DPHY initialization.

v2: remove kmb_write() as the function provides no benefit over
calling writel() directly.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.h  |   5 -
 drivers/gpu/drm/kmb/kmb_dsi.c  | 346 ++---
 drivers/gpu/drm/kmb/kmb_dsi.h  |  10 ++
 drivers/gpu/drm/kmb/kmb_regs.h |  48 +-
 4 files changed, 376 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index f1d5b3a..3996c84 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -64,11 +64,6 @@ static inline void kmb_write_bits(struct kmb_drm_private 
*lcd,
 }
 #endif
 
-static inline void kmb_write(void *reg, u32 value)
-{
-   writel(value, reg);
-}
-
 static inline void kmb_write_lcd(unsigned int reg, u32 value)
 {
writel(value, (LCD_BASE_ADDR + reg));
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index a255210..d15cf6f 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -27,6 +27,13 @@
 #define MIPI_TX_REF_CLK_KHZ 24000
 #define MIPI_TX_CFG_CLK_KHZ 24000
 
+/*DPHY Tx test codes*/
+#define TEST_CODE_HS_FREQ_RANGE_CFG0x44
+#define TEST_CODE_PLL_ANALOG_PROG  0x1F
+#define TEST_CODE_SLEW_RATE_OVERRIDE_CTRL  0xA0
+#define TEST_CODE_SLEW_RATE_DDL_LOOP_CTRL  0xA3
+#define TEST_CODE_SLEW_RATE_DDL_CYCLES 0xA4
+
 /*
  * These are added here only temporarily for testing,
  * these will eventually go to the device tree sections,
@@ -87,6 +94,77 @@ struct mipi_ctrl_cfg mipi_tx_init_cfg = {
 
 };
 
+typedef struct{
+   uint16_t default_bit_rate_mbps;
+   uint8_t hsfreqrange_code;
+} mipi_hs_freq_range_cfg;
+
+static mipi_hs_freq_range_cfg
+   mipi_hs_freq_range[MIPI_DPHY_DEFAULT_BIT_RATES] = {
+   {.default_bit_rate_mbps = 80, .hsfreqrange_code = 0x00},
+   {.default_bit_rate_mbps = 90, .hsfreqrange_code = 0x10},
+   {.default_bit_rate_mbps = 100, .hsfreqrange_code = 0x20},
+   {.default_bit_rate_mbps = 110, .hsfreqrange_code = 0x30},
+   {.default_bit_rate_mbps = 120, .hsfreqrange_code = 0x01},
+   {.default_bit_rate_mbps = 130, .hsfreqrange_code = 0x11},
+   {.default_bit_rate_mbps = 140, .hsfreqrange_code = 0x21},
+   {.default_bit_rate_mbps = 150, .hsfreqrange_code = 0x31},
+   {.default_bit_rate_mbps = 160, .hsfreqrange_code = 0x02},
+   {.default_bit_rate_mbps = 170, .hsfreqrange_code = 0x12},
+   {.default_bit_rate_mbps = 180, .hsfreqrange_code = 0x22},
+   {.default_bit_rate_mbps = 190, .hsfreqrange_code = 0x32},
+   {.default_bit_rate_mbps = 205, .hsfreqrange_code = 0x03},
+   {.default_bit_rate_mbps = 220, .hsfreqrange_code = 0x13},
+   {.default_bit_rate_mbps = 235, .hsfreqrange_code = 0x23},
+   {.default_bit_rate_mbps = 250, .hsfreqrange_code = 0x33},
+   {.default_bit_rate_mbps = 275, .hsfreqrange_code = 0x04},
+   {.default_bit_rate_mbps = 300, .hsfreqrange_code = 0x14},
+   {.default_bit_rate_mbps = 325, .hsfreqrange_code = 0x25},
+   {.default_bit_rate_mbps = 350, .hsfreqrange_code = 0x35},
+   {.default_bit_rate_mbps = 400, .hsfreqrange_code = 0x05},
+   {.default_bit_rate_mbps = 450, .hsfreqrange_code = 0x16},
+   {.default_bit_rate_mbps = 500, .hsfreqrange_code = 0x26},
+   {.default_bit_rate_mbps = 550, .hsfreqrange_code = 0x37},
+   {.default_bit_rate_mbps = 600, .hsfreqrange_code = 0x07},
+   {.default_bit_rate_mbps = 650, .hsfreqrange_code = 0x18},
+   {.default_bit_rate_mbps = 700, .hsfreqrange_code = 0x28},
+   {.default_bit_rate_mbps = 750, .hsfreqrange_code = 0x39},
+   {.default_bit_rate_mbps = 800, .hsfreqrange_code = 0x09},
+   {.default_bit_rate_mbps = 850, .hsfreqrange_code = 0x19},
+   {.default_bit_rate_mbps = 900, .hsfreqrange_code = 0x29},
+   {.default_bit_rate_mbps = 1000, .hsfreqrange_code = 0x0A},
+   {.default_bit_rate_mbps = 1050, .hsfreqrange_code = 0x1A},
+   {.default_bit_rate_mbps = 1100, .hsfreqrange_code = 0x2A},
+   {.default_bit_rate_mbps = 1150, .hsfreqrange_code = 0x3B},
+   {.default_bit_rate_mbps = 1200, .hsfreqrange_code = 0x0B},
+   {.default_bit_rate_mbps = 1250, .hsfreqrange_code = 0x1B},
+   {.default_bit_rate_mbps = 1300, .hsfreqrange_code = 0x2B},
+   {.default_bit_rate_mbps = 1350, .hsfreqrange_code = 0x3C},
+   {.default_bit_rate_mbps = 1400, .hsfreqrange_code = 0x0C},
+   {.default_bit_rate_mbps = 1450, .hsfreqrange_code = 0x1C},
+   {.default_bit_rate_mbps = 1500, .hsfreqrange_code = 0x2C},
+   {.default_bit_rate_mbps = 1550, .hsfreqrange_code = 0x3D},
+   {.default_bit_rate_mbps = 1600, .hsfreqrange_code = 0x0D},
+   {.default_bit_rate_mbps = 1650, .hsfreqrange_code = 0x1D},
+   {.default_bit_rate_mbps = 1700, .hsfreqrange_code = 0x2E},
+   {.default_bit_rate_mbps = 1750, .hsfreqran

[PATCH v2 35/59] drm/kmb: Remove declaration of irq_lcd/irq_mipi

2020-07-14 Thread Anitha Chrisanthus
From: Edmund Dea 

Made it conditionally compiled.

Signed-off-by: Edmund Dea 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 90db07c..861aa97 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -123,7 +123,10 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
+#ifdef WIP
/*u32 version;*/
+   int irq_lcd, irq_mipi;
+#endif
int ret = 0;
unsigned long clk;
 
@@ -277,9 +280,9 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
pr_info("irq_mipi platform_get_irq = %d\n", irq_mipi);
ret = request_irq(irq_mipi, kmb_isr, IRQF_SHARED, "irq_mipi", dev_p);
dev_p->irq_mipi = irq_mipi;
-#endif
-   /* TBD read and check for correct product version here */
 
+   /* TBD read and check for correct product version here */
+#endif
/* Get the optional framebuffer memory resource */
ret = of_reserved_mem_device_init(drm->dev);
if (ret && ret != -ENODEV)
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 31/59] drm/kmb: Cleanup probe functions

2020-07-14 Thread Anitha Chrisanthus
From: Edmund Dea 

- Removed deprecated code blocks within probe functions
- In kmb_remove, unregister MIPI DSI host
- In kmb_probe, if kmb_load fails, then unregister MIPI DSI host
- Change kmb_dsi_host_bridge_init to return error codes using ERR_PTR
- Do clock intitialization earlier
- Rename kmb_drm_unbind to kmb_drm_unload.
- Get mmio info from device tree

v2: upclassed dev_private

Signed-off-by: Edmund Dea 
Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 332 +++---
 drivers/gpu/drm/kmb/kmb_drv.h |   1 +
 drivers/gpu/drm/kmb/kmb_dsi.c |  85 ---
 3 files changed, 218 insertions(+), 200 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 76f3c43..25daba7 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -30,18 +30,18 @@
 #include "kmb_regs.h"
 
 #define DEBUG
+
 /*IRQ handler*/
 static irqreturn_t kmb_isr(int irq, void *arg);
 
 static struct clk *clk_lcd;
 static struct clk *clk_mipi;
 
-static int probe_deferred;
 struct drm_bridge *adv_bridge;
 
 static int kmb_display_clk_enable(void)
 {
-   int ret;
+   int ret = 0;
 
ret = clk_prepare_enable(clk_lcd);
if (ret) {
@@ -67,86 +67,142 @@ static int kmb_display_clk_disable(void)
return 0;
 }
 
+static void __iomem *kmb_map_mmio(struct platform_device *pdev, char *name)
+{
+   struct resource *res;
+   u32 size;
+   void __iomem *mem;
+
+   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+   if (!res) {
+   DRM_ERROR("failed to get resource for %s\n", name);
+   return ERR_PTR(-ENOMEM);
+   }
+   size = resource_size(res);
+   if (!request_mem_region(res->start, size, name)) {
+   DRM_ERROR("failed to reserve %s registers\n", name);
+   return ERR_PTR(-ENOMEM);
+   }
+   mem = ioremap(res->start, size);
+   if (!mem) {
+   DRM_ERROR("failed to ioremap %s registers\n", name);
+   release_mem_region(res->start, size);
+   return ERR_PTR(-ENOMEM);
+   }
+   return mem;
+}
+
 static int kmb_load(struct drm_device *drm, unsigned long flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
-/* struct drm_bridge *bridge;*/
-   /*struct resource *res;*/
/*u32 version;*/
-   int ret;
-/* struct device_node *encoder_node;*/
-
-   /* TBD - not sure if clock_get needs to be called here */
-   /*
-*dev_p->clk = devm_clk_get(drm->dev, "pxlclk");
-*if (IS_ERR(dev_p->clk))
-*  return PTR_ERR(dev_p->clk);
-*/
-   /*
-* TBD call this in the future when device tree is ready,
-* use hardcoded value for now
-*/
-   /*
-* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-* dev_p->lcd_mmio = devm_ioremap_resource(drm->dev, res);
-
-*if (IS_ERR(dev_p->lcd_mmio)) {
-*  DRM_ERROR("failed to map control registers area\n");
-*  ret = PTR_ERR(dev_p->lcd_mmio);
-*  dev_p->lcd_mmio = NULL;
-*  return ret;
-*}
-*/
-   /* LCD mmio */
-   probe_deferred = 1;
+   int ret = 0;
 
-   if (!request_mem_region(LCD_BASE_ADDR, LCD_MMIO_SIZE, "kmb-lcd")) {
-   DRM_ERROR("failed to reserve LCD registers\n");
-   return -ENOMEM;
-   }
-   dev_p->lcd_mmio = ioremap_cache(LCD_BASE_ADDR, LCD_MMIO_SIZE);
-   if (!dev_p->lcd_mmio) {
+   /* Map LCD MMIO registers */
+   dev_p->lcd_mmio = kmb_map_mmio(pdev, "lcd_regs");
+   if (IS_ERR(dev_p->lcd_mmio)) {
DRM_ERROR("failed to map LCD registers\n");
return -ENOMEM;
}
-   /* Mipi mmio */
-   if (!request_mem_region(MIPI_BASE_ADDR, MIPI_MMIO_SIZE, "kmb-mipi")) {
-   DRM_ERROR("failed to reserve MIPI registers\n");
+
+   /* Map MIPI MMIO registers */
+   dev_p->mipi_mmio = kmb_map_mmio(pdev, "mipi_regs");
+
+   if (IS_ERR(dev_p->mipi_mmio)) {
+   DRM_ERROR("failed to map MIPI registers\n");
iounmap(dev_p->lcd_mmio);
return -ENOMEM;
}
-   dev_p->mipi_mmio = ioremap_cache(MIPI_BASE_ADDR, MIPI_MMIO_SIZE);
-   if (!dev_p->mipi_mmio) {
-   DRM_ERROR("failed to map MIPI registers\n");
+
+   /* This is only for MIPI_TX_MSS_LCD_MIPI_CFG and MSS_CAM_CLK_CTRL
+* register
+*/
+   dev_p->msscam_mmio = kmb_map_mmio(pdev, "msscam_regs");
+   if (IS_ERR(dev_p->msscam_mmio)) {
+   DRM_ERROR("failed to map MSSCAM registers\n");
iounmap(dev_p->lcd_mmio);
+   iounmap(dev_p->mipi_mmio);
return -ENOMEM;
}
-   /*this is only for MIPI_TX_MSS_LCD_MIPI_CFG register */
-   if (!dev_p->msscam_mmio) 

[PATCH v2 48/59] drm/kmb: SWAP R and B LCD Layer order

2020-07-14 Thread Anitha Chrisanthus
Set swap bit for the colors to display correctly
when the format is RGB and not set when its BGR.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 1582ccf..5fd1837 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -198,54 +198,55 @@ unsigned int set_pixel_format(u32 format)
val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
| LCD_LAYER_CRCB_ORDER;
break;
-   /* packed formats */
+   /* packed formats */
+   /* looks hw requires B & G to be swapped when RGB */
case DRM_FORMAT_RGB332:
-   val = LCD_LAYER_FORMAT_RGB332;
+   val = LCD_LAYER_FORMAT_RGB332 | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_XBGR:
-   val = LCD_LAYER_FORMAT_RGBX | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_RGBX;
break;
case DRM_FORMAT_ARGB:
-   val = LCD_LAYER_FORMAT_RGBA;
+   val = LCD_LAYER_FORMAT_RGBA | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_ABGR:
-   val = LCD_LAYER_FORMAT_RGBA | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_RGBA;
break;
case DRM_FORMAT_XRGB1555:
-   val = LCD_LAYER_FORMAT_XRGB1555;
+   val = LCD_LAYER_FORMAT_XRGB1555 | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_XBGR1555:
-   val = LCD_LAYER_FORMAT_XRGB1555 | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_XRGB1555;
break;
case DRM_FORMAT_ARGB1555:
-   val = LCD_LAYER_FORMAT_RGBA1555;
+   val = LCD_LAYER_FORMAT_RGBA1555 | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_ABGR1555:
-   val = LCD_LAYER_FORMAT_RGBA1555 | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_RGBA1555;
break;
case DRM_FORMAT_RGB565:
-   val = LCD_LAYER_FORMAT_RGB565;
+   val = LCD_LAYER_FORMAT_RGB565 | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_BGR565:
-   val = LCD_LAYER_FORMAT_RGB565 | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_RGB565;
break;
case DRM_FORMAT_RGB888:
-   val = LCD_LAYER_FORMAT_RGB888;
+   val = LCD_LAYER_FORMAT_RGB888 | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_BGR888:
-   val = LCD_LAYER_FORMAT_RGB888 | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_RGB888;
break;
case DRM_FORMAT_XRGB:
-   val = LCD_LAYER_FORMAT_RGBX;
+   val = LCD_LAYER_FORMAT_RGBX | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_XBGR:
-   val = LCD_LAYER_FORMAT_RGBX | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_RGBX;
break;
case DRM_FORMAT_ARGB:
-   val = LCD_LAYER_FORMAT_RGBA;
+   val = LCD_LAYER_FORMAT_RGBA | LCD_LAYER_BGR_ORDER;
break;
case DRM_FORMAT_ABGR:
-   val = LCD_LAYER_FORMAT_RGBA | LCD_LAYER_BGR_ORDER;
+   val = LCD_LAYER_FORMAT_RGBA;
break;
}
DRM_INFO("%s : %d layer format val=%d\n", __func__, __LINE__, val);
@@ -348,7 +349,6 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
val |= set_bits_per_pixel(fb->format);
/*CHECKME Leon drvr sets it to 100 try this for now */
val |= LCD_LAYER_FIFO_100;
-   val |= LCD_LAYER_BGR_ORDER;
kmb_write_lcd(dev_p, LCD_LAYERn_CFG(plane_id), val);
 
/*re-initialize interrupts */
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 22/59] drm/kmb: Set hardcoded values to LCD_VSYNC_START

2020-07-14 Thread Anitha Chrisanthus
Myriadx code has it set to these values.

v2: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index 5c1e858..eca0f3a 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -102,6 +102,9 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_write_lcd(dev_p, LCD_H_BACKPORCH, vm.hback_porch - 1);
kmb_write_lcd(dev_p, LCD_H_FRONTPORCH, vm.hfront_porch - 1);
kmb_write_lcd(dev_p, LCD_HSYNC_WIDTH, vm.hsync_len - 1);
+   /*this is hardcoded as 0 in the Myriadx code */
+   kmb_write_lcd(dev_p, LCD_VSYNC_START, 0);
+   kmb_write_lcd(dev_p, LCD_VSYNC_END, 0);
 
if (m->flags == DRM_MODE_FLAG_INTERLACE) {
kmb_write_lcd(dev_p,
@@ -112,10 +115,9 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
LCD_V_FRONTPORCH_EVEN, vm.vfront_porch - 1);
kmb_write_lcd(dev_p,
LCD_V_ACTIVEHEIGHT_EVEN, m->crtc_vdisplay - 1);
-   kmb_write_lcd(dev_p, LCD_VSYNC_START_EVEN,
-   vsync_start_offset);
-   kmb_write_lcd(dev_p, LCD_VSYNC_END_EVEN,
-   vsync_end_offset);
+   /*this is hardcoded as 10 in the Myriadx code*/
+   kmb_write_lcd(dev_p, LCD_VSYNC_START_EVEN, 10);
+   kmb_write_lcd(dev_p, LCD_VSYNC_END_EVEN, 10);
}
/* enable VL1 layer as default */
ctrl = LCD_CTRL_ENABLE | LCD_CTRL_VL1_ENABLE;
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 18/59] drm/kmb: Part8 of Mipi Tx Initialization

2020-07-14 Thread Anitha Chrisanthus
This initializes the interrupts for DSI. This is the final part of mipi
DSI initialization.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c  |  1 +
 drivers/gpu/drm/kmb/kmb_drv.h  | 30 +++-
 drivers/gpu/drm/kmb/kmb_dsi.c  | 46 
 drivers/gpu/drm/kmb/kmb_dsi.h  | 13 +++
 drivers/gpu/drm/kmb/kmb_regs.h | 81 ++
 5 files changed, 163 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 224a7f8..19f78ba 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -58,6 +58,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
if (ret && ret != -ENODEV)
return ret;
 
+   spin_lock_init(&lcd->irq_lock);
ret = kmb_setup_crtc(drm);
if (ret < 0) {
DRM_ERROR("failed to create crtc\n");
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 3996c84..14bdfc8 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -12,14 +12,15 @@
 #define KMB_MAX_HEIGHT 16384   /*max height in pixels */
 
 struct kmb_drm_private {
-   struct drm_device drm;
-   void __iomem *mmio;
-   unsigned char n_layers;
-   struct clk *clk;
-   struct drm_fbdev_cma *fbdev;
-   struct drm_crtc crtc;
-   struct kmb_plane *plane;
-   struct drm_atomic_state *state;
+   struct drm_device   drm;
+   void __iomem*mmio;
+   unsigned char   n_layers;
+   struct clk  *clk;
+   struct drm_fbdev_cma*fbdev;
+   struct drm_crtc crtc;
+   struct kmb_plane*plane;
+   struct drm_atomic_state *state;
+   spinlock_t  irq_lock;
 };
 
 static inline struct kmb_drm_private *to_kmb(const struct drm_device *dev)
@@ -111,6 +112,19 @@ static inline void kmb_clr_bit_mipi(unsigned int reg, u32 
offset)
kmb_write_mipi(reg, reg_val & (~(1 << offset)));
 }
 
+static inline void kmb_set_bitmask_mipi(unsigned int reg, u32 mask)
+{
+   u32 reg_val = kmb_read_mipi(reg);
+
+   kmb_write_mipi(reg, (reg_val | mask));
+}
+
+static inline void kmb_clr_bitmask_mipi(unsigned int reg, u32 mask)
+{
+   u32 reg_val = kmb_read_mipi(reg);
+
+   kmb_write_mipi(reg, (reg_val & (~mask)));
+}
 int kmb_setup_crtc(struct drm_device *dev);
 void kmb_set_scanout(struct kmb_drm_private *lcd);
 #endif /* __KMB_DRV_H__ */
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index f8ddb87..47456b2 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -188,6 +189,11 @@ static mipi_hs_freq_range_cfg
{.default_bit_rate_mbps = 2500, .hsfreqrange_code = 0x49}
 };
 
+union mipi_irq_cfg int_cfg = {
+   .irq_cfg.frame_done = 1,
+   .irq_cfg.ctrl_error = 1,
+};
+
 static enum drm_mode_status
 kmb_dsi_mode_valid(struct drm_connector *connector,
   struct drm_display_mode *mode)
@@ -1174,6 +1180,43 @@ static u32 mipi_tx_init_dphy(struct mipi_ctrl_cfg *cfg)
return 0;
 }
 
+static void mipi_tx_init_irqs(union mipi_irq_cfg *cfg,
+   struct kmb_drm_private *dev_priv,
+   struct  mipi_tx_ctrl_cfg *tx_ctrl_cfg)
+{
+   unsigned long irqflags;
+   uint8_t vc;
+
+   /* clear all interrupts first */
+   /*local interrupts */
+   SET_MIPI_TX_HS_IRQ_CLEAR(MIPI_CTRL6, MIPI_TX_HS_IRQ_ALL);
+   /*global interrupts */
+   SET_MIPI_CTRL_IRQ_CLEAR0(MIPI_CTRL6, MIPI_HS_IRQ);
+   SET_MIPI_CTRL_IRQ_CLEAR0(MIPI_CTRL6, MIPI_DHY_ERR_IRQ);
+   SET_MIPI_CTRL_IRQ_CLEAR1(MIPI_CTRL6, MIPI_HS_RX_EVENT_IRQ);
+
+   /*enable interrupts */
+   spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+   for (vc = 0; vc < MIPI_CTRL_VIRTUAL_CHANNELS; vc++) {
+   if (tx_ctrl_cfg->frames[vc] == NULL)
+   continue;
+   /*enable FRAME_DONE interrupt if VC is configured */
+   SET_HS_IRQ_ENABLE(MIPI_CTRL6,
+   MIPI_TX_HS_IRQ_FRAME_DONE_0 << vc);
+   break; /*only one vc for LCD interface */
+   }
+
+   /*enable user enabled interrupts */
+   if (cfg->irq_cfg.dphy_error)
+   SET_MIPI_CTRL_IRQ_ENABLE0(MIPI_CTRL6, MIPI_DHY_ERR_IRQ);
+   if (cfg->irq_cfg.line_compare)
+   SET_HS_IRQ_ENABLE(MIPI_CTRL6, MIPI_TX_HS_IRQ_LINE_COMPARE);
+   if (cfg->irq_cfg.ctrl_error)
+   SET_HS_IRQ_ENABLE(MIPI_CTRL6, MIPI_TX_HS_IRQ_ERROR);
+
+   spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
 void kmb_dsi_init(struct drm_device *dev)
 {
struct kmb_dsi *kmb_dsi;
@@ -1219,4 +1262,7 @@ void kmb_dsi_init(struct drm_dev

[PATCH v2 09/59] drm/kmb: Part 1 of Mipi Tx Initialization

2020-07-14 Thread Anitha Chrisanthus
Mipi TX frame section configuration

This is the first part in the MIPI controller initialization.
Compute and set the right values in MIPI TX frame section configuration
registers like packet header(PH), unpacked bytes and line config.

v2: added more comments to clarify assumptions
v3: improved code readability as per code review
Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.h  |  14 ++
 drivers/gpu/drm/kmb/kmb_dsi.c  | 330 +
 drivers/gpu/drm/kmb/kmb_dsi.h  | 232 +
 drivers/gpu/drm/kmb/kmb_regs.h |  25 
 4 files changed, 601 insertions(+)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 23299a5..addf5ec 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -42,6 +42,20 @@ static inline u32 kmb_read(struct kmb_drm_private *lcd, 
unsigned int reg)
return readl(lcd->mmio + reg);
 }
 
+static inline void kmb_write_bits(struct kmb_drm_private *lcd,
+ unsigned int reg, u32 offset, u32 num_bits,
+ u32 value)
+{
+   u32 reg_val = kmb_read(lcd, reg);
+   u32 mask = (1 << num_bits) - 1;
+
+   value &= mask;
+   mask <<= offset;
+   reg_val &= (~mask);
+   reg_val |= (value << offset);
+   writel(reg_val, lcd->mmio + reg);
+}
+
 int kmb_setup_crtc(struct drm_device *dev);
 void kmb_set_scanout(struct kmb_drm_private *lcd);
 #endif /* __KMB_DRV_H__ */
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index d82411e..cb6082d 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -11,9 +11,81 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "kmb_drv.h"
 #include "kmb_dsi.h"
+#include "kmb_regs.h"
+
+#define IMG_WIDTH_PX  1920
+#define IMG_HEIGHT_LINES  1080
+#define LCD_BYTESPP   1
+
+/*MIPI TX CFG*/
+#define MIPI_TX_ACTIVE_LANES4
+#define MIPI_TX_LANE_DATA_RATE_MBPS 888
+#define MIPI_TX_REF_CLK_KHZ 24000
+#define MIPI_TX_CFG_CLK_KHZ 24000
+
+/*
+ * These are added here only temporarily for testing,
+ * these will eventually go to the device tree sections,
+ * and can be used as a refernce later for device tree additions
+ */
+struct mipi_tx_frame_section_cfg mipi_tx_frame0_sect_cfg = {
+   .width_pixels = IMG_WIDTH_PX,
+   .height_lines = IMG_HEIGHT_LINES,
+   .data_type = DSI_LP_DT_PPS_RGB888_24B,
+   .data_mode = MIPI_DATA_MODE1,
+   .dma_packed = 0
+};
+
+struct mipi_tx_frame_cfg mipitx_frame0_cfg = {
+   .sections[0] = &mipi_tx_frame0_sect_cfg,
+   .sections[1] = NULL,
+   .sections[2] = NULL,
+   .sections[3] = NULL,
+   .vsync_width = 5,
+   .v_backporch = 36,
+   .v_frontporch = 4,
+   .hsync_width = 44,
+   .h_backporch = 148,
+   .h_frontporch = 88
+};
+
+struct mipi_tx_dsi_cfg mipitx_dsi_cfg = {
+   .hfp_blank_en = 0,
+   .eotp_en = 0,
+   .lpm_last_vfp_line = 0,
+   .lpm_first_vsa_line = 0,
+   .sync_pulse_eventn = DSI_VIDEO_MODE_NO_BURST_EVENT,
+   .hfp_blanking = SEND_BLANK_PACKET,
+   .hbp_blanking = SEND_BLANK_PACKET,
+   .hsa_blanking = SEND_BLANK_PACKET,
+   .v_blanking = SEND_BLANK_PACKET,
+};
+
+struct mipi_ctrl_cfg mipi_tx_init_cfg = {
+   .index = MIPI_CTRL6,
+   .type = MIPI_DSI,
+   .dir = MIPI_TX,
+   .active_lanes = MIPI_TX_ACTIVE_LANES,
+   .lane_rate_mbps = MIPI_TX_LANE_DATA_RATE_MBPS,
+   .ref_clk_khz = MIPI_TX_REF_CLK_KHZ,
+   .cfg_clk_khz = MIPI_TX_CFG_CLK_KHZ,
+   .data_if = MIPI_IF_PARALLEL,
+   .tx_ctrl_cfg = {
+   .frames[0] = &mipitx_frame0_cfg,
+   .frames[1] = NULL,
+   .frames[2] = NULL,
+   .frames[3] = NULL,
+   .tx_dsi_cfg = &mipitx_dsi_cfg,
+   .line_sync_pkt_en = 0,
+   .line_counter_active = 0,
+   .frame_counter_active = 0,
+   }
+
+};
 
 static enum drm_mode_status
 kmb_dsi_mode_valid(struct drm_connector *connector,
@@ -111,6 +183,261 @@ static struct kmb_dsi_host *kmb_dsi_host_init(struct 
kmb_dsi *kmb_dsi)
return host;
 }
 
+u32 mipi_get_datatype_params(u32 data_type, u32 data_mode,
+struct mipi_data_type_params *params)
+{
+   struct mipi_data_type_params data_type_parameters;
+
+   switch (data_type) {
+   case DSI_LP_DT_PPS_YCBCR420_12B:
+   data_type_parameters.size_constraint_pixels = 2;
+   data_type_parameters.size_constraint_bytes = 3;
+   switch (data_mode) {
+   /* case 0 not supported according to MDK */
+   case 1:
+   case 2:
+   case 3:
+   data_type_parameters.pixels_per_pclk = 2;
+   data_type_pa

[PATCH v2 54/59] drm/kmb: Initialize uninitialized variables

2020-07-14 Thread Anitha Chrisanthus
general cleaning

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 6e38f16..2599ed2 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -307,7 +307,7 @@ static struct kmb_dsi_host *kmb_dsi_host_init(struct 
drm_device *drm,
 
 struct drm_bridge *kmb_dsi_host_bridge_init(struct device *dev)
 {
-   struct drm_bridge *bridge;
+   struct drm_bridge *bridge = NULL;
 #ifndef FCCTEST
struct device_node *encoder_node;
 #endif
@@ -815,7 +815,7 @@ static void mipi_tx_hs_tp_gen(struct kmb_drm_private 
*dev_p, int vc,
 static u32 mipi_tx_init_cntrl(struct kmb_drm_private *dev_p,
  struct mipi_ctrl_cfg *ctrl_cfg)
 {
-   u32 ret;
+   u32 ret = 0;
u8 active_vchannels = 0;
u8 frame_id, sect;
u32 bits_per_pclk = 0;
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 34/59] drm/kmb: Enable MSS_CAM_CLK_CTRL for LCD and MIPI

2020-07-14 Thread Anitha Chrisanthus
Enable clocks for LCD, mipi common and mipi tx0
Renamed MSS_CAM_CLK_CTRL and also fixed bug in the
call to set this register.

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c  |  8 
 drivers/gpu/drm/kmb/kmb_drv.h  | 14 ++
 drivers/gpu/drm/kmb/kmb_dsi.c  |  6 --
 drivers/gpu/drm/kmb/kmb_regs.h |  7 ++-
 4 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 9dc5f91..90db07c 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -241,6 +241,9 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
DRM_INFO("Get clk_mipi_cfg after set = %ld\n", clk);
}
 
+   /* enable MSS_CAM_CLK_CTRL for MIPI TX and LCD */
+   kmb_set_bitmask_msscam(dev_p, MSS_CAM_CLK_CTRL, LCD | MIPI_COMMON |
+   MIPI_TX0);
 #ifdef WIP
/* Register irqs here - section 17.3 in databook
 * lists LCD at 79 and 82 for MIPI under MSS CPU -
@@ -292,10 +295,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 
/* Initialize MIPI DSI */
ret = kmb_dsi_init(drm, adv_bridge);
-   if (ret == -EPROBE_DEFER) {
-   DRM_INFO("%s: wait for external bridge driver DT", __func__);
-   return -EPROBE_DEFER;
-   } else if (ret) {
+   if (ret) {
DRM_ERROR("failed to initialize DSI\n");
goto setup_fail;
}
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 8c5ccf7..71dc883 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -88,6 +88,20 @@ static inline void kmb_write_msscam(struct kmb_drm_private 
*dev_p,
writel(value, (dev_p->msscam_mmio + reg));
 }
 
+static inline u32 kmb_read_msscam(struct kmb_drm_private *dev_p,
+   unsigned int reg)
+{
+   return readl(dev_p->msscam_mmio + reg);
+}
+
+static inline void kmb_set_bitmask_msscam(struct kmb_drm_private *dev_p,
+   unsigned int reg, u32 mask)
+{
+   u32 reg_val = kmb_read_msscam(dev_p, reg);
+
+   kmb_write_msscam(dev_p, reg, (reg_val | mask));
+}
+
 static inline u32 kmb_read_lcd(struct kmb_drm_private *dev_p, unsigned int reg)
 {
return readl(dev_p->lcd_mmio + reg);
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 4ec1753..01fa378 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -794,9 +794,11 @@ static u32 mipi_tx_init_cntrl(struct kmb_drm_private 
*dev_p,
active_vchannels++;
 
/*connect lcd to mipi */
-   kmb_write_msscam(dev_p, MSS_CAM_BASE_ADDR +
-   MIPI_TX_MSS_LCD_MIPI_CFG, 1);
+   kmb_write_msscam(dev_p, MSS_LCD_MIPI_CFG, 1);
 
+   /*stop iterating as only one virtual channel shall be used for
+* LCD connection
+*/
break;
}
 
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index e98e144..a3f1a3a 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -677,6 +677,11 @@
& (1 << (dphy - MIPI_DPHY6)))
 #define DPHY_CFG_CLK_EN(0x18c)
 
-#define MIPI_TX_MSS_LCD_MIPI_CFG   (0x04)
+#define MSS_LCD_MIPI_CFG   (0x04)
+#define MSS_CAM_CLK_CTRL   (0x10)
+#define   LCD  (1<<1)
+#define   MIPI_COMMON  (1<<2)
+#define   MIPI_TX0 (1<<9)
+
 #define BIT_MASK_16(0x)
 #endif /* __KMB_REGS_H__ */
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 39/59] drm/kmb: Fixed driver unload

2020-07-14 Thread Anitha Chrisanthus
unmap MSSCAM registers

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c  | 15 +++
 drivers/gpu/drm/kmb/kmb_drv.h  |  1 -
 drivers/gpu/drm/kmb/kmb_regs.h |  2 +-
 3 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 2a93b13..3542de7 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -159,17 +159,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
iounmap(dev_p->mipi_mmio);
return -ENOMEM;
}
-/*testing*/
-   if (!request_mem_region(CPR_BASE_ADDR, 100, "cpr")) {
-   DRM_ERROR("failed to reserve %s registers\n", "cpr");
-   return -ENOMEM;
-   }
-   dev_p->cpr_mmio = ioremap_cache(CPR_BASE_ADDR, 0x100);
-   if (!dev_p->cpr_mmio) {
-   DRM_ERROR("failed to ioremap %s registers\n", "CPR");
-   release_mem_region(CPR_BASE_ADDR, 100);
-   return -ENOMEM;
-   }
 
if (IS_ERR(dev_p->msscam_mmio)) {
DRM_ERROR("failed to map MSSCAM registers\n");
@@ -490,8 +479,10 @@ static void kmb_drm_unload(struct device *dev)
release_mem_region(MIPI_BASE_ADDR, MIPI_MMIO_SIZE);
}
 
-   if (dev_p->msscam_mmio)
+   if (dev_p->msscam_mmio) {
iounmap(dev_p->msscam_mmio);
+   release_mem_region(MSS_CAM_BASE_ADDR, MSS_CAM_MMIO_SIZE);
+   }
 
of_reserved_mem_device_release(drm->dev);
drm_mode_config_cleanup(drm);
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 0bdac1a..7e6 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -20,7 +20,6 @@ struct kmb_drm_private {
void __iomem*lcd_mmio;
void __iomem*mipi_mmio;
void __iomem*msscam_mmio;
-   void __iomem*cpr_mmio;
unsigned char   n_layers;
struct clk  *clk;
struct drm_crtc crtc;
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index d2b884c..c83740bb 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -16,7 +16,7 @@
 #define MSS_CAM_BASE_ADDR  (MIPI_BASE_ADDR + 0x1)
 #define LCD_MMIO_SIZE  (0x3000)
 #define MIPI_MMIO_SIZE (0x4000)
-#define MSS_CAM_MMIO_SIZE  (0x10)
+#define MSS_CAM_MMIO_SIZE  (0x30)
 
 /***
  *LCD controller control register defines
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 56/59] kmb/drm: Prune unsupported modes

2020-07-14 Thread Anitha Chrisanthus
KMB display pipeline is LCD->Mipi->HDMI. Mipi->HDMI converter chip only
accepts 4-lane input from mipi.
With 4-lane mipi, KMB hardware can only support 1080p resolution.
Therefore, limit supported mode to 1080p.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c   |  4 ++--
 drivers/gpu/drm/kmb/kmb_drv.h   |  8 +---
 drivers/gpu/drm/kmb/kmb_dsi.c   | 11 +++
 drivers/gpu/drm/kmb/kmb_plane.c |  2 ++
 4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 7fcab4b..b844c77 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -337,8 +337,8 @@ static const struct drm_mode_config_funcs 
kmb_mode_config_funcs = {
 static void kmb_setup_mode_config(struct drm_device *drm)
 {
drm_mode_config_init(drm);
-   drm->mode_config.min_width = 0;
-   drm->mode_config.min_height = 0;
+   drm->mode_config.min_width = KMB_MIN_WIDTH;
+   drm->mode_config.min_height = KMB_MIN_HEIGHT;
drm->mode_config.max_width = KMB_MAX_WIDTH;
drm->mode_config.max_height = KMB_MAX_HEIGHT;
drm->mode_config.funcs = &kmb_mode_config_funcs;
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 94b62b9..373a059 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -8,10 +8,12 @@
 
 #include "kmb_regs.h"
 
-#define FCCTEST
+//#define FCCTEST
 #define LCD_TEST
-#define KMB_MAX_WIDTH  1920/*max width in pixels */
-#define KMB_MAX_HEIGHT 1080/*max height in pixels */
+#define KMB_MAX_WIDTH  1920 /*max width in pixels */
+#define KMB_MAX_HEIGHT 1080 /*max height in pixels */
+#define KMB_MIN_WIDTH   1920 /*max width in pixels */
+#define KMB_MIN_HEIGHT  1080 /*max height in pixels */
 #define KMB_LCD_DEFAULT_CLK25000
 #define KMB_MIPI_DEFAULT_CLK   2400
 #define KMB_MIPI_DEFAULT_CFG_CLK   2400
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 2599ed2..47798ed 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -193,6 +193,17 @@ static enum drm_mode_status
 kmb_dsi_mode_valid(struct drm_connector *connector,
   struct drm_display_mode *mode)
 {
+   struct drm_device *dev = connector->dev;
+   struct drm_mode_config *mode_config = &dev->mode_config;
+
+   if (mode->hdisplay < mode_config->min_width ||
+   mode->hdisplay > mode_config->max_width)
+   return MODE_BAD_HVALUE;
+
+   if (mode->vdisplay < mode_config->min_height ||
+   mode->vdisplay > mode_config->max_height)
+   return MODE_BAD_VVALUE;
+
return MODE_OK;
 }
 
diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 8b2b202..a6b5969 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -57,6 +57,8 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
 
if (state->crtc_w > KMB_MAX_WIDTH || state->crtc_h > KMB_MAX_HEIGHT)
return -EINVAL;
+   if (state->crtc_w < KMB_MIN_WIDTH || state->crtc_h < KMB_MIN_HEIGHT)
+   return -EINVAL;
return 0;
 }
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 32/59] drm/kmb: Revert dsi_host back to a static variable

2020-07-14 Thread Anitha Chrisanthus
From: Edmund Dea 

revert dsi_host to static and instead add dsi_host_unregister.

Signed-off-by: Edmund Dea 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 6 +++---
 drivers/gpu/drm/kmb/kmb_drv.h | 1 -
 drivers/gpu/drm/kmb/kmb_dsi.c | 9 +++--
 drivers/gpu/drm/kmb/kmb_dsi.h | 1 +
 4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 25daba7..1368770 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -379,7 +379,7 @@ static void kmb_drm_unload(struct device *dev)
dev_set_drvdata(dev, NULL);
 
/* Unregister DSI host */
-   mipi_dsi_host_unregister(dsi_host);
+   dsi_host_unregister();
 }
 
 static int kmb_probe(struct platform_device *pdev)
@@ -420,7 +420,7 @@ static int kmb_probe(struct platform_device *pdev)
dev_set_drvdata(dev, drm);
 
kmb_setup_mode_config(drm);
-   dev_set_drvdata(dev, drm);
+   dev_set_drvdata(dev, drm);
 
/* Load driver */
ret = kmb_load(drm, 0);
@@ -461,7 +461,7 @@ static int kmb_probe(struct platform_device *pdev)
drm_mode_config_cleanup(drm);
dev_set_drvdata(dev, NULL);
drm_dev_put(drm);
-   mipi_dsi_host_unregister(dsi_host);
+   dsi_host_unregister();
 
return ret;
 }
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 54780ec..1150505 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -11,7 +11,6 @@
 #define KMB_MAX_WIDTH  16384   /*max width in pixels */
 #define KMB_MAX_HEIGHT 16384   /*max height in pixels */
 
-extern struct mipi_dsi_host *dsi_host;
 struct kmb_drm_private {
struct drm_device   drm;
void __iomem*lcd_mmio;
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 70bb231..4ec1753 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -59,7 +59,7 @@
 #define PLL_M_MAX  623
 #define PLL_FVCO_MAX   1250
 
-struct mipi_dsi_host *dsi_host;
+static struct mipi_dsi_host *dsi_host;
 static struct mipi_dsi_device *dsi_device;
 
 /*
@@ -337,8 +337,13 @@ struct drm_bridge *kmb_dsi_host_bridge_init(struct device 
*dev)
return bridge;
 }
 
+void dsi_host_unregister(void)
+{
+   mipi_dsi_host_unregister(dsi_host);
+}
+
 u32 mipi_get_datatype_params(u32 data_type, u32 data_mode,
-struct mipi_data_type_params *params)
+   struct mipi_data_type_params *params)
 {
struct mipi_data_type_params data_type_parameters;
 
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.h b/drivers/gpu/drm/kmb/kmb_dsi.h
index e9bcc7e..811f3b8 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.h
+++ b/drivers/gpu/drm/kmb/kmb_dsi.h
@@ -313,6 +313,7 @@ struct drm_bridge *kmb_dsi_host_bridge_init(struct device 
*dev);
 int kmb_dsi_init(struct drm_device *dev, struct drm_bridge *bridge);
 void kmb_plane_destroy(struct drm_plane *plane);
 void mipi_tx_handle_irqs(struct kmb_drm_private *dev_p);
+void dsi_host_unregister(void);
 
 #define to_kmb_connector(x) container_of(x, struct kmb_connector, base)
 #define to_kmb_host(x) container_of(x, struct kmb_dsi_host, base)
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 19/59] drm/kmb: Added ioremap/iounmap for register access

2020-07-14 Thread Anitha Chrisanthus
Register physical addresses are remapped and the register mmio
addresses for lcd,mipi and msscam are saved in drm_private.
All register reads/writes are updated to get the mmio offset
from this structure. We are using hardcoded values for register
physical addresses and this will be modified to read from device
tree in the future.

v2: minor code review changes
v3: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  |  59 +++---
 drivers/gpu/drm/kmb/kmb_drv.c   | 104 ---
 drivers/gpu/drm/kmb/kmb_drv.h   |  64 ---
 drivers/gpu/drm/kmb/kmb_dsi.c   | 401 +---
 drivers/gpu/drm/kmb/kmb_plane.c |  35 ++--
 drivers/gpu/drm/kmb/kmb_regs.h  | 106 ++-
 6 files changed, 441 insertions(+), 328 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index 984f21a..5c1e858 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -31,21 +31,28 @@ static void kmb_crtc_cleanup(struct drm_crtc *crtc)
 
 static int kmb_crtc_enable_vblank(struct drm_crtc *crtc)
 {
+   struct drm_device *dev = crtc->dev;
+   struct kmb_drm_private *dev_p = to_kmb(dev);
+
/*clear interrupt */
-   kmb_write_lcd(LCD_INT_CLEAR, LCD_INT_VERT_COMP);
+   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
/*set which interval to generate vertical interrupt */
-   kmb_write_lcd(LCD_VSTATUS_COMPARE, LCD_VSTATUS_COMPARE_VSYNC);
+   kmb_write_lcd(dev_p, LCD_VSTATUS_COMPARE,
+   LCD_VSTATUS_COMPARE_VSYNC);
/* enable vertical interrupt */
-   kmb_write_lcd(LCD_INT_ENABLE, LCD_INT_VERT_COMP);
+   kmb_write_lcd(dev_p, LCD_INT_ENABLE, LCD_INT_VERT_COMP);
return 0;
 }
 
 static void kmb_crtc_disable_vblank(struct drm_crtc *crtc)
 {
+   struct drm_device *dev = crtc->dev;
+   struct kmb_drm_private *dev_p = to_kmb(dev);
+
/*clear interrupt */
-   kmb_write_lcd(LCD_INT_CLEAR, LCD_INT_VERT_COMP);
+   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
/* disable vertical interrupt */
-   kmb_write_lcd(LCD_INT_ENABLE, 0);
+   kmb_write_lcd(dev_p, LCD_INT_ENABLE, 0);
 
 /* TBD
  *  set the BIT2 (VERTICAL_COMPARE_INTERRUPT) of the LCD_INT_ENABLE register
@@ -68,10 +75,12 @@ static const struct drm_crtc_funcs kmb_crtc_funcs = {
 static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
struct drm_display_mode *m = &crtc->state->adjusted_mode;
+   struct drm_device *dev = crtc->dev;
struct videomode vm;
int vsync_start_offset;
int vsync_end_offset;
unsigned int ctrl = 0;
+   struct kmb_drm_private *dev_p = to_kmb(dev);
 
vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -83,30 +92,38 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
vsync_end_offset = m->crtc_vsync_end - m->crtc_hsync_end;
 
-   kmb_write_lcd(LCD_V_ACTIVEHEIGHT, m->crtc_vdisplay - 1);
-   kmb_write_lcd(LCD_V_BACKPORCH, vm.vback_porch - 1);
-   kmb_write_lcd(LCD_V_FRONTPORCH, vm.vfront_porch - 1);
-   kmb_write_lcd(LCD_VSYNC_WIDTH, vm.vsync_len - 1);
-   kmb_write_lcd(LCD_H_ACTIVEWIDTH, m->crtc_hdisplay - 1);
-   kmb_write_lcd(LCD_H_BACKPORCH, vm.hback_porch - 1);
-   kmb_write_lcd(LCD_H_FRONTPORCH, vm.hfront_porch - 1);
-   kmb_write_lcd(LCD_HSYNC_WIDTH, vm.hsync_len - 1);
+   kmb_write_lcd(dev_p, LCD_V_ACTIVEHEIGHT,
+   m->crtc_vdisplay - 1);
+   kmb_write_lcd(dev_p, LCD_V_BACKPORCH, vm.vback_porch - 1);
+   kmb_write_lcd(dev_p, LCD_V_FRONTPORCH, vm.vfront_porch - 1);
+   kmb_write_lcd(dev_p, LCD_VSYNC_WIDTH, vm.vsync_len - 1);
+   kmb_write_lcd(dev_p, LCD_H_ACTIVEWIDTH,
+   m->crtc_hdisplay - 1);
+   kmb_write_lcd(dev_p, LCD_H_BACKPORCH, vm.hback_porch - 1);
+   kmb_write_lcd(dev_p, LCD_H_FRONTPORCH, vm.hfront_porch - 1);
+   kmb_write_lcd(dev_p, LCD_HSYNC_WIDTH, vm.hsync_len - 1);
 
if (m->flags == DRM_MODE_FLAG_INTERLACE) {
-   kmb_write_lcd(LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
-   kmb_write_lcd(LCD_V_BACKPORCH_EVEN, vm.vback_porch - 1);
-   kmb_write_lcd(LCD_V_FRONTPORCH_EVEN, vm.vfront_porch - 1);
-   kmb_write_lcd(LCD_V_ACTIVEHEIGHT_EVEN,  m->crtc_vdisplay - 1);
-   kmb_write_lcd(LCD_VSYNC_START_EVEN, vsync_start_offset);
-   kmb_write_lcd(LCD_VSYNC_END_EVEN, vsync_end_offset);
+   kmb_write_lcd(dev_p,
+   LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
+   kmb_write_lcd(dev_p,
+   LCD_V_BACKPORCH_EVEN, vm.vback_porch - 1);
+   kmb_write_lcd(dev_p,
+   LCD_V_FRONTPORCH_

[PATCH v2 13/59] drm/kmb: Part4 of Mipi Tx Initialization

2020-07-14 Thread Anitha Chrisanthus
This initializes the mipi high speed transmitter CTRL and SYNC
configuration registers.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_dsi.c  | 55 --
 drivers/gpu/drm/kmb/kmb_regs.h | 29 +-
 2 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index a5b9681..a685a7a 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -533,6 +533,55 @@ static void mipi_tx_multichannel_fifo_cfg(u8 active_lanes, 
u8 vchannel_id)
kmb_set_bit_mipi(MIPI_TXm_HS_MC_FIFO_CTRL_EN(ctrl_no), vchannel_id);
 }
 
+static void mipi_tx_ctrl_cfg(u8 fg_id, struct mipi_ctrl_cfg *ctrl_cfg)
+{
+   u32 sync_cfg = 0, ctrl = 0, fg_en;
+   u32 ctrl_no = MIPI_CTRL6;
+
+   /*MIPI_TX_HS_SYNC_CFG*/
+   if (ctrl_cfg->tx_ctrl_cfg.line_sync_pkt_en)
+   sync_cfg |= LINE_SYNC_PKT_ENABLE;
+   if (ctrl_cfg->tx_ctrl_cfg.frame_counter_active)
+   sync_cfg |= FRAME_COUNTER_ACTIVE;
+   if (ctrl_cfg->tx_ctrl_cfg.line_counter_active)
+   sync_cfg |= LINE_COUNTER_ACTIVE;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->v_blanking)
+   sync_cfg |= DSI_V_BLANKING;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->hsa_blanking)
+   sync_cfg |= DSI_HSA_BLANKING;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->hbp_blanking)
+   sync_cfg |= DSI_HBP_BLANKING;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->hfp_blanking)
+   sync_cfg |= DSI_HFP_BLANKING;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->sync_pulse_eventn)
+   sync_cfg |= DSI_SYNC_PULSE_EVENTN;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->lpm_first_vsa_line)
+   sync_cfg |= DSI_LPM_FIRST_VSA_LINE;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->lpm_last_vfp_line)
+   sync_cfg |= DSI_LPM_LAST_VFP_LINE;
+   /* enable frame generator */
+   fg_en = 1 << fg_id;
+   sync_cfg |= FRAME_GEN_EN(fg_en);
+   if (ctrl_cfg->tx_ctrl_cfg.tx_always_use_hact)
+   sync_cfg |= ALWAYS_USE_HACT(fg_en);
+   if (ctrl_cfg->tx_ctrl_cfg.tx_hact_wait_stop)
+   sync_cfg |= HACT_WAIT_STOP(fg_en);
+
+   /* MIPI_TX_HS_CTRL*/
+   ctrl = HS_CTRL_EN | TX_SOURCE; /* type:DSI,source:LCD */
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->eotp_en)
+   ctrl |= DSI_EOTP_EN;
+   if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->hfp_blank_en)
+   ctrl |= DSI_CMD_HFP_EN;
+   ctrl |= LCD_VC(fg_id);
+   ctrl |= ACTIVE_LANES(ctrl_cfg->active_lanes - 1);
+   /*67 ns stop time*/
+   ctrl |= HSEXIT_CNT(0x43);
+
+   kmb_write_mipi(MIPI_TXm_HS_SYNC_CFG(ctrl_no), sync_cfg);
+   kmb_write_mipi(MIPI_TXm_HS_CTRL(ctrl_no), ctrl);
+}
+
 static u32 mipi_tx_init_cntrl(struct kmb_drm_private *dev_priv,
struct mipi_ctrl_cfg *ctrl_cfg)
 {
@@ -576,8 +625,7 @@ static u32 mipi_tx_init_cntrl(struct kmb_drm_private 
*dev_priv,
/* set frame specific parameters */
mipi_tx_fg_cfg(dev_priv, frame_id, ctrl_cfg->active_lanes,
bits_per_pclk,
-   word_count,
-   ctrl_cfg->lane_rate_mbps,
+   word_count, ctrl_cfg->lane_rate_mbps,
ctrl_cfg->tx_ctrl_cfg.frames[frame_id]);
 
active_vchannels++;
@@ -592,6 +640,9 @@ static u32 mipi_tx_init_cntrl(struct kmb_drm_private 
*dev_priv,
return -EINVAL;
/*Multi-Channel FIFO Configuration*/
mipi_tx_multichannel_fifo_cfg(ctrl_cfg->active_lanes, frame_id);
+
+   /*Frame Generator Enable */
+   mipi_tx_ctrl_cfg(frame_id, ctrl_cfg);
return ret;
 }
 
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index ef6b4ee..2d25c50 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -378,7 +378,35 @@
 #define MIPI_CTRL_HS_BASE_ADDR (0x400)
 
 #define MIPI_TX_HS_CTRL(0x0)
+#define   MIPI_TXm_HS_CTRL(M)  (MIPI_TX_HS_CTRL + (0x400*M))
+#define   HS_CTRL_EN   (1 << 0)
+#define   HS_CTRL_CSIDSIN  (1 << 2) /*1:CSI 0:DSI*/
+#define   TX_SOURCE(1 << 3) /*1:LCD, 0:DMA*/
+#define   ACTIVE_LANES(n)  ((n) << 4)
+#define   LCD_VC(ch)   ((ch) << 8)
+#define   DSI_EOTP_EN  (1 << 11)
+#define   DSI_CMD_HFP_EN   (1 << 12)
+#define   CRC_EN   (1 << 14)
+#define   HSEXIT_CNT(n)((n) << 16)
+#define   HSCLKIDLE_CNT(1 << 24)
 #define MIPI_TX_HS_SYNC_CFG(0x8)
+#define   MIPI_TXm_HS_SYNC_CFG(M)  (MIPI_TX_HS

[PATCH v2 52/59] drm/kmb: Cleaned up code

2020-07-14 Thread Anitha Chrisanthus
From: Edmund Dea 

to remove compiler warnings and general clean up

v2: minor code review changes
v3: upclassed dev_private, corrected spelling

Signed-off-by: Edmund Dea 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  |   46 +-
 drivers/gpu/drm/kmb/kmb_crtc.h  |6 +-
 drivers/gpu/drm/kmb/kmb_drv.c   |  111 ++--
 drivers/gpu/drm/kmb/kmb_drv.h   |  107 ++--
 drivers/gpu/drm/kmb/kmb_dsi.c   | 1074 +--
 drivers/gpu/drm/kmb/kmb_dsi.h   |   84 ++-
 drivers/gpu/drm/kmb/kmb_plane.c |  155 ++
 drivers/gpu/drm/kmb/kmb_plane.h |   74 ++-
 drivers/gpu/drm/kmb/kmb_regs.h  |   29 +-
 9 files changed, 894 insertions(+), 792 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index c390bbe..aceca94 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -39,10 +39,10 @@ static int kmb_crtc_enable_vblank(struct drm_crtc *crtc)
kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
/*set which interval to generate vertical interrupt */
kmb_write_lcd(dev_p, LCD_VSTATUS_COMPARE,
-   LCD_VSTATUS_COMPARE_VSYNC);
+ LCD_VSTATUS_COMPARE_VSYNC);
/* enable vertical interrupt */
kmb_set_bitmask_lcd(dev_p, LCD_INT_ENABLE,
-   LCD_INT_VERT_COMP);
+   LCD_INT_VERT_COMP);
return 0;
 }
 
@@ -83,38 +83,38 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
/* initialize mipi */
kmb_dsi_hw_init(dev, m);
DRM_INFO("vfp= %d vbp= %d vsyc_len=%d hfp=%d hbp=%d hsync_len=%d\n",
-   m->crtc_vsync_start - m->crtc_vdisplay,
-   m->crtc_vtotal - m->crtc_vsync_end,
-   m->crtc_vsync_end - m->crtc_vsync_start,
-   m->crtc_hsync_start - m->crtc_hdisplay,
-   m->crtc_htotal - m->crtc_hsync_end,
-   m->crtc_hsync_end - m->crtc_hsync_start);
+m->crtc_vsync_start - m->crtc_vdisplay,
+m->crtc_vtotal - m->crtc_vsync_end,
+m->crtc_vsync_end - m->crtc_vsync_start,
+m->crtc_hsync_start - m->crtc_hdisplay,
+m->crtc_htotal - m->crtc_hsync_end,
+m->crtc_hsync_end - m->crtc_hsync_start);
val = kmb_read_lcd(dev_p, LCD_INT_ENABLE);
kmb_clr_bitmask_lcd(dev_p, LCD_INT_ENABLE, val);
kmb_set_bitmask_lcd(dev_p, LCD_INT_CLEAR, ~0x0);
-// vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
+//  vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vfront_porch = 2;
-// vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
+//  vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
vm.vback_porch = 2;
-// vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
+//  vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
vm.vsync_len = 1;
//vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
vm.hfront_porch = 0;
vm.hback_porch = 0;
//vm.hback_porch = m->crtc_htotal - m->crtc_hsync_end;
vm.hsync_len = 7;
-// vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
+//  vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
 
vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
vsync_end_offset = m->crtc_vsync_end - m->crtc_hsync_end;
 
-   DRM_INFO("%s : %dactive height= %d vbp=%d vfp=%d vsync-w=%d h-active=%d 
h-bp=%d h-fp=%d hysnc-l=%d\n",
-   __func__, __LINE__, m->crtc_vdisplay,
-   vm.vback_porch, vm.vfront_porch,
-   vm.vsync_len, m->crtc_hdisplay,
-   vm.hback_porch, vm.hfront_porch, vm.hsync_len);
+   DRM_DEBUG
+   ("%s : %dactive height= %d vbp=%d vfp=%d vsync-w=%d h-active=%d 
h-bp=%d h-fp=%d hysnc-l=%d",
+__func__, __LINE__, m->crtc_vdisplay, vm.vback_porch,
+vm.vfront_porch, vm.vsync_len, m->crtc_hdisplay, vm.hback_porch,
+vm.hfront_porch, vm.hsync_len);
kmb_write_lcd(dev_p, LCD_V_ACTIVEHEIGHT,
-   m->crtc_vdisplay - 1);
+ m->crtc_vdisplay - 1);
kmb_write_lcd(dev_p, LCD_V_BACKPORCH, vm.vback_porch);
kmb_write_lcd(dev_p, LCD_V_FRONTPORCH, vm.vfront_porch);
kmb_write_lcd(dev_p, LCD_VSYNC_WIDTH, vm.vsync_len - 1);
@@ -129,14 +129,14 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
 
if (m->flags == DRM_MODE_FLAG_INTERLACE) {
kmb_write_lcd(dev_p,
-   LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
+ LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
kmb_write_lcd(dev_p,
LCD_V_BACKPORCH_EVEN, vm.vback_porch);
kmb_write_lcd(dev_p,
LCD_V_FRONTPORCH_EVEN, vm.vfront_porch);

[PATCH v2 53/59] drm/kmb: disable the LCD layer in EOF irq handler

2020-07-14 Thread Anitha Chrisanthus
When disabling/enabling LCD layers, the change takes effect
immediately and does not wait for EOF (end of frame). If we
disable an LCD layer in kmb_plane_atomic_disable, then the frame
reappears with incorrect display offsets.

The solution is to mark the plane as disabled when
kmb_plane_atomic_disable is called but actually disable the LCD
layer when EOF irq is being handled.

Also only enable one plane (video plane0) as there is no use case for
multiple planes.

v2: Moved extern to .h, removed license text, upclassed dev_private.

Signed-off-by: Anitha Chrisanthus 
Signed-off-by: Edmund Dea 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c   | 36 +---
 drivers/gpu/drm/kmb/kmb_drv.h   |  1 +
 drivers/gpu/drm/kmb/kmb_plane.c | 24 
 drivers/gpu/drm/kmb/kmb_plane.h | 11 ++-
 4 files changed, 48 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index f5e1def..55574c1 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -347,25 +347,47 @@ static void kmb_setup_mode_config(struct drm_device *drm)
 static irqreturn_t handle_lcd_irq(struct drm_device *dev)
 {
unsigned long status, val;
+   int plane_id;
struct kmb_drm_private *dev_p = to_kmb(dev);
 
status = kmb_read_lcd(dev_p, LCD_INT_STATUS);
if (status & LCD_INT_EOF) {
-   /*To DO - handle EOF interrupt? */
-   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_EOF);
+   /* TODO - handle EOF interrupt? */
+   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_EOF);
+
+   /* When disabling/enabling LCD layers, the change takes effect
+* immediately and does not wait for EOF (end of frame).
+* When kmb_plane_atomic_disable is called, mark the plane as
+* disabled but actually disable the plane when EOF irq is
+* being handled.
+*/
+   for (plane_id = LAYER_0; plane_id < KMB_MAX_PLANES;
+   plane_id++) {
+   if (plane_status[plane_id].disable) {
+   kmb_clr_bitmask_lcd(dev_p,
+   LCD_LAYERn_DMA_CFG(plane_id),
+   LCD_DMA_LAYER_ENABLE);
+
+   kmb_clr_bitmask_lcd(dev_p, LCD_CONTROL,
+   plane_status[plane_id].ctrl);
+
+   plane_status[plane_id].disable = false;
+   }
+   }
}
+
if (status & LCD_INT_LINE_CMP) {
/* clear line compare interrupt */
-   kmb_write_lcd(dev_p, LCD_INT_CLEAR,
-   LCD_INT_LINE_CMP);
+   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_LINE_CMP);
}
+
if (status & LCD_INT_LAYER) {
/* Clear layer interrupts */
-   kmb_write_lcd(dev->dev_private, LCD_INT_CLEAR, LCD_INT_LAYER);
+   kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_LAYER);
}
 
if (status & LCD_INT_VERT_COMP) {
-   /* read VSTATUS */
+   /* Read VSTATUS */
val = kmb_read_lcd(dev_p, LCD_VSTATUS);
val = (val & LCD_VSTATUS_VERTICAL_STATUS_MASK);
switch (val) {
@@ -382,7 +404,7 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
}
 
/* Clear all interrupts */
-   kmb_set_bitmask_lcd(dev->dev_private, LCD_INT_CLEAR, ~0x0);
+   kmb_set_bitmask_lcd(dev_p, LCD_INT_CLEAR, 1);
return IRQ_HANDLED;
 }
 
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 4b97a3d..94b62b9 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -19,6 +19,7 @@
 
 #define crtc_to_kmb_priv(x)container_of(x, struct kmb_drm_private, crtc)
 
+
 struct kmb_drm_private {
struct drm_device drm;
void __iomem *lcd_mmio;
diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index f92e191..8b2b202 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -21,6 +21,8 @@
 #include "kmb_plane.h"
 #include "kmb_regs.h"
 
+struct layer_status plane_status[KMB_MAX_PLANES];
+
 const uint32_t layer_irqs[] = {
LCD_INT_VL0,
LCD_INT_VL1,
@@ -62,34 +64,24 @@ static void kmb_plane_atomic_disable(struct drm_plane 
*plane,
 struct drm_plane_state *state)
 {
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
-   int ctrl = 0;
-   struct kmb_drm_private *dev_p;
-   int plane_id;
-
-   dev_p = to_kmb(plane->dev);
-   plane_id = kmb_plane->id;
+   int plane_id = kmb_plane->id;
 
switch (plane_id) {
case LAYER_0:
-   ctrl = LCD_CTRL_VL1_ENABLE;
+   plane_status[plan

[PATCH v2 29/59] drm/kmb: Defer Probe

2020-07-14 Thread Anitha Chrisanthus
Register DSI host first and then defer probe until ADV bridge is
initialized.

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_drv.c | 144 ++
 drivers/gpu/drm/kmb/kmb_dsi.c |  46 --
 drivers/gpu/drm/kmb/kmb_dsi.h |   3 +-
 3 files changed, 89 insertions(+), 104 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index d13552a..36edfbf 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -36,6 +36,8 @@ static irqreturn_t kmb_isr(int irq, void *arg);
 static struct clk *clk_lcd;
 static struct clk *clk_mipi;
 
+static int probe_deferred;
+
 static int kmb_display_clk_enable(void)
 {
clk_prepare_enable(clk_lcd);
@@ -56,12 +58,11 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 {
struct kmb_drm_private *dev_p = to_kmb(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
-   struct drm_bridge *bridge;
+/* struct drm_bridge *bridge;*/
/*struct resource *res;*/
/*u32 version;*/
-   int irq_lcd, irq_mipi;
int ret;
-   struct device_node *encoder_node;
+/* struct device_node *encoder_node;*/
 
/* TBD - not sure if clock_get needs to be called here */
/*
@@ -73,9 +74,10 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 * TBD call this in the future when device tree is ready,
 * use hardcoded value for now
 */
-   /*res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-*dev_p->lcd_mmio = devm_ioremap_resource(drm->dev, res);
-*
+   /*
+* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+* dev_p->lcd_mmio = devm_ioremap_resource(drm->dev, res);
+
 *if (IS_ERR(dev_p->lcd_mmio)) {
 *  DRM_ERROR("failed to map control registers area\n");
 *  ret = PTR_ERR(dev_p->lcd_mmio);
@@ -83,7 +85,10 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 *  return ret;
 *}
 */
-/* LCD mmio */
+   /* LCD mmio */
+   if (!probe_deferred) {
+   probe_deferred = 1;
+
if (!request_mem_region(LCD_BASE_ADDR, LCD_MMIO_SIZE, "kmb-lcd")) {
DRM_ERROR("failed to reserve LCD registers\n");
return -ENOMEM;
@@ -93,7 +98,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
DRM_ERROR("failed to map LCD registers\n");
return -ENOMEM;
}
-
/* Mipi mmio */
if (!request_mem_region(MIPI_BASE_ADDR, MIPI_MMIO_SIZE, "kmb-mipi")) {
DRM_ERROR("failed to reserve MIPI registers\n");
@@ -106,35 +110,16 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
iounmap(dev_p->lcd_mmio);
return -ENOMEM;
}
-
/*this is only for MIPI_TX_MSS_LCD_MIPI_CFG register */
-   dev_p->msscam_mmio = ioremap_cache(MSS_CAM_BASE_ADDR,
+   if (!dev_p->msscam_mmio) {
+   dev_p->msscam_mmio = ioremap_cache(MSS_CAM_BASE_ADDR,
MSS_CAM_MMIO_SIZE);
+   }
 
/* register irqs here - section 17.3 in databook
 * lists LCD at 79 and 82 for MIPI under MSS CPU -
 * firmware has to redirect it to A53
 */
-   irq_lcd = platform_get_irq_byname(pdev, "irq_lcd");
-   if (irq_lcd < 0) {
-   DRM_ERROR("irq_lcd not found");
-   return irq_lcd;
-   }
-   pr_info("irq_lcd platform_get_irq = %d\n", irq_lcd);
-   ret = request_irq(irq_lcd, kmb_isr, IRQF_SHARED, "irq_lcd", dev_p);
-   dev_p->irq_lcd = irq_lcd;
-
-   irq_mipi = platform_get_irq_byname(pdev, "irq_mipi");
-   if (irq_mipi < 0) {
-   DRM_ERROR("irq_mipi not found");
-   return irq_mipi;
-   }
-   pr_info("irq_mipi platform_get_irq = %d\n", irq_mipi);
-   ret = request_irq(irq_mipi, kmb_isr, IRQF_SHARED, "irq_mipi", dev_p);
-   dev_p->irq_mipi = irq_mipi;
-
-
-
 /*TBD read and check for correct product version here */
 
/* Get the optional framebuffer memory resource */
@@ -149,52 +134,35 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}
 
-   /* find ADV7535 node and initialize it */
-   encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
-   if (!encoder_node) {
-   DRM_ERROR("failed to get bridge info from DT\n");
-   ret = -EPROBE_DEFER;
-   goto setup_fail;
-   }
-
-   /* Locate drm bridge from the hdmi encoder DT node */
-   bridge = of_drm_find_bridge(encoder_node);
-   if (!bridge) {
-   DRM_ERROR("failed to get bridge driver from DT\n");
-   ret = -EPROBE_DEFER;
-   goto setup_fail;
-   }
-
-   of_node_put(encoder_node);
-
-   ret = kmb_dsi_init

[PATCH v2 51/59] drm/kmb: Write to LCD_LAYERn_CFG only once

2020-07-14 Thread Anitha Chrisanthus
From: Edmund Dea 

Video artifacts appear during playback as horizontal lines that
sporadically appear every few frames. Issue was caused by writing to
LCD_LAYERn_CFG register twice during plane updates. Issue is fixed by
writing to LCD_LAYERn_CFG only once.

Removed plane_init_status so that there are no initialization
dependencies during plane updates.

Signed-off-by: Edmund Dea 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 81 +++--
 1 file changed, 38 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 6be0997..bf93986 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -98,7 +98,6 @@ static const u32 csc_coef_lcd[] = {
 };
 
 /*plane initialization status */
-static int plane_init_status[KMB_MAX_PLANES] = { 0, 0, 0, 0 };
 
 static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
 {
@@ -301,7 +300,6 @@ static void config_csc(struct kmb_drm_private *dev_p, int 
plane_id)
kmb_write_lcd(dev_p, LCD_LAYERn_CSC_OFF1(plane_id), csc_coef_lcd[9]);
kmb_write_lcd(dev_p, LCD_LAYERn_CSC_OFF2(plane_id), csc_coef_lcd[10]);
kmb_write_lcd(dev_p, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]);
-   kmb_set_bitmask_lcd(dev_p, LCD_LAYERn_CFG(plane_id), LCD_LAYER_CSC_EN);
 }
 #endif
 
@@ -390,19 +388,27 @@ static void kmb_plane_atomic_update(struct drm_plane 
*plane,
  addr[V_PLANE]);
}
}
-   if (plane_init_status[plane_id] != INITIALIZED) {
-   kmb_write_lcd(dev_p, LCD_LAYERn_WIDTH(plane_id), src_w - 1);
-   kmb_write_lcd(dev_p, LCD_LAYERn_HEIGHT(plane_id), src_h - 1);
-   kmb_write_lcd(dev_p, LCD_LAYERn_COL_START(plane_id), crtc_x);
-   kmb_write_lcd(dev_p, LCD_LAYERn_ROW_START(plane_id), crtc_y);
-
-   val = set_pixel_format(fb->format->format);
-   val |= set_bits_per_pixel(fb->format);
-   /*CHECKME Leon drvr sets it to 100 try this for now */
-   val |= LCD_LAYER_FIFO_100;
-   kmb_write_lcd(dev_p, LCD_LAYERn_CFG(plane_id), val);
-
-   switch (plane_id) {
+
+   kmb_write_lcd(dev_p, LCD_LAYERn_WIDTH(plane_id), src_w-1);
+   kmb_write_lcd(dev_p, LCD_LAYERn_HEIGHT(plane_id), src_h-1);
+   kmb_write_lcd(dev_p, LCD_LAYERn_COL_START(plane_id), crtc_x);
+   kmb_write_lcd(dev_p, LCD_LAYERn_ROW_START(plane_id), crtc_y);
+
+   val = set_pixel_format(fb->format->format);
+   val |= set_bits_per_pixel(fb->format);
+   /*CHECKME Leon drvr sets it to 100 try this for now */
+   val |= LCD_LAYER_FIFO_100;
+
+   if (val & LCD_LAYER_PLANAR_STORAGE) {
+   val |= LCD_LAYER_CSC_EN;
+
+   /*enable CSC if input is planar and output is RGB */
+   config_csc(dev_p, plane_id);
+   }
+
+   kmb_write_lcd(dev_p, LCD_LAYERn_CFG(plane_id), val);
+
+   switch (plane_id) {
case LAYER_0:
ctrl = LCD_CTRL_VL1_ENABLE;
break;
@@ -415,36 +421,28 @@ static void kmb_plane_atomic_update(struct drm_plane 
*plane,
case LAYER_3:
ctrl = LCD_CTRL_GL2_ENABLE;
break;
-   }
+   }
 
-   ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
-   | LCD_CTRL_CONTINUOUS | LCD_CTRL_OUTPUT_ENABLED;
+   ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
+   | LCD_CTRL_CONTINUOUS | LCD_CTRL_OUTPUT_ENABLED;
 
-   /*LCD is connected to MIPI on kmb
-* Therefore this bit is required for DSI Tx
-*/
-   ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
+   /*LCD is connected to MIPI on kmb
+* Therefore this bit is required for DSI Tx
+*/
+   ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
 
-   kmb_set_bitmask_lcd(dev_p, LCD_CONTROL, ctrl);
+   kmb_set_bitmask_lcd(dev_p, LCD_CONTROL, ctrl);
 
-   /* FIXME no doc on how to set output format,these values are
-* taken from the Myriadx tests
-*/
-   out_format |= LCD_OUTF_FORMAT_RGB888;
+   /* FIXME no doc on how to set output format,these values are
+* taken from the Myriadx tests
+*/
+   out_format |= LCD_OUTF_FORMAT_RGB888;
 
-   if (val & LCD_LAYER_PLANAR_STORAGE) {
-   /*enable CSC if input is planar and output is RGB */
-   config_csc(dev_p, plane_id);
-   }
-
-   /*set background color to white */
-   //  kmb_write_lcd(dev_p, LCD_BG_COLOUR_LS, 0xff);
-   /*leave RGB order,conversion mode and clip mode to default */
-   /* do not interleave RGB channels for mipi Tx compatibility */
-   out_format |= LCD_OUTF_MI

[PATCH v2 59/59] drm/kmb: work around for planar formats

2020-07-14 Thread Anitha Chrisanthus
Set the DMA Vstride and Line width for U and V planes to the same as the
Y plane and not the actual pitch.
Bit18 of layer config does not have any effect when U and V planes are
swapped, so swap it in the driver.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Edmund Dea 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 50 -
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index de225a8..e35d732 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -170,6 +170,8 @@ unsigned int set_pixel_format(u32 format)
val = LCD_LAYER_FORMAT_RGBA;
break;
}
+   DRM_INFO_ONCE("%s : %d format=0x%x val=0x%x\n",
+__func__, __LINE__, format, val);
return val;
 }
 
@@ -280,38 +282,48 @@ static void kmb_plane_atomic_update(struct drm_plane 
*plane,
dev_p->fb_addr = addr[Y_PLANE];
kmb_write_lcd(dev_p, LCD_LAYERn_DMA_START_ADDR(plane_id),
  addr[Y_PLANE] + fb->offsets[0]);
+   val = set_pixel_format(fb->format->format);
+   val |= set_bits_per_pixel(fb->format);
/* Program Cb/Cr for planar formats */
if (num_planes > 1) {
-   if (fb->format->format == DRM_FORMAT_YUV420 ||
-   fb->format->format == DRM_FORMAT_YVU420)
-   width /= 2;
-
kmb_write_lcd(dev_p, LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
- fb->pitches[LAYER_1]);
-
+   width*fb->format->cpp[0]);
kmb_write_lcd(dev_p, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
  (width * fb->format->cpp[0]));
 
addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, plane->state,
-   U_PLANE);
-   kmb_write_lcd(dev_p, LCD_LAYERn_DMA_START_CB_ADR(plane_id),
- addr[U_PLANE]);
+   U_PLANE);
+   /* check if Cb/Cr is swapped*/
+   if ((num_planes == 3) && (val & LCD_LAYER_CRCB_ORDER))
+   kmb_write_lcd(dev_p,
+   LCD_LAYERn_DMA_START_CR_ADR(plane_id),
+   addr[U_PLANE]);
+   else
+   kmb_write_lcd(dev_p,
+   LCD_LAYERn_DMA_START_CB_ADR(plane_id),
+   addr[U_PLANE]);
 
if (num_planes == 3) {
kmb_write_lcd(dev_p,
- LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
- fb->pitches[LAYER_2]);
+   LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
+   ((width)*fb->format->cpp[0]));
 
kmb_write_lcd(dev_p,
- LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
- (width * fb->format->cpp[0]));
+   LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
+   ((width)*fb->format->cpp[0]));
 
addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb,
-   plane->state,
-   V_PLANE);
-   kmb_write_lcd(dev_p,
- LCD_LAYERn_DMA_START_CR_ADR(plane_id),
- addr[V_PLANE]);
+   plane->state, V_PLANE);
+
+   /* check if Cb/Cr is swapped*/
+   if (val & LCD_LAYER_CRCB_ORDER)
+   kmb_write_lcd(dev_p,
+   LCD_LAYERn_DMA_START_CB_ADR(plane_id),
+   addr[V_PLANE]);
+   else
+   kmb_write_lcd(dev_p,
+   LCD_LAYERn_DMA_START_CR_ADR(plane_id),
+   addr[V_PLANE]);
}
}
 
@@ -320,8 +332,6 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
kmb_write_lcd(dev_p, LCD_LAYERn_COL_START(plane_id), crtc_x);
kmb_write_lcd(dev_p, LCD_LAYERn_ROW_START(plane_id), crtc_y);
 
-   val = set_pixel_format(fb->format->format);
-   val |= set_bits_per_pixel(fb->format);
/*CHECKME Leon drvr sets it to 100 try this for now */
val |= LCD_LAYER_FIFO_100;
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 42/59] drm/kmb: Update LCD programming to match MIPI

2020-07-14 Thread Anitha Chrisanthus
Mipi input expects the memory layout to be unpacked with 8 bits per
pixel in RGB (BRG) order. If the LCD is not configured properly,
corrupted output results, changed dma_unpacked to 0 in mipi FG.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  |  6 +++---
 drivers/gpu/drm/kmb/kmb_drv.h   |  1 +
 drivers/gpu/drm/kmb/kmb_dsi.c   | 27 +--
 drivers/gpu/drm/kmb/kmb_dsi.h   |  1 +
 drivers/gpu/drm/kmb/kmb_plane.c | 37 +++--
 drivers/gpu/drm/kmb/kmb_regs.h  |  1 +
 6 files changed, 50 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index cbf998f..a6a0444 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -87,16 +87,16 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_dsi_hw_init(dev);
 #ifdef LCD_TEST
 // vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
-   vm.vfront_porch = 0;
+   vm.vfront_porch = 2;
 // vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
-   vm.vback_porch = 0;
+   vm.vback_porch = 2;
 // vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
vm.vsync_len = 1;
//vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
vm.hfront_porch = 0;
vm.hback_porch = 0;
//vm.hback_porch = m->crtc_htotal - m->crtc_hsync_end;
-   vm.hsync_len = 1;
+   vm.hsync_len = 7;
 // vm.hsync_len = m->crtc_hsync_end - m->crtc_hsync_start;
 
vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index aa77631..3a1b66c 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -30,6 +30,7 @@ struct kmb_drm_private {
spinlock_t  irq_lock;
int irq_lcd;
int irq_mipi;
+   dma_addr_t  fb_addr;
 };
 
 static inline struct kmb_drm_private *to_kmb(const struct drm_device *dev)
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index a9f2d78..e01c4f9 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -25,6 +25,7 @@
 static int hw_initialized;
 #define IMAGE_PATH "/home/root/1280x720.pnm"
 //#define MIPI_TX_TEST_PATTERN_GENERATION
+//#define MIPI_DMA
 //#define RTL_TEST
 //#define IMG_WIDTH_PX  640
 //#define IMG_HEIGHT_LINES  10
@@ -33,6 +34,7 @@ static int hw_initialized;
 
 /*MIPI TX CFG*/
 //#define MIPI_TX_LANE_DATA_RATE_MBPS 1782
+//#define MIPI_TX_LANE_DATA_RATE_MBPS 800
 #define MIPI_TX_LANE_DATA_RATE_MBPS 891
 //#define MIPI_TX_LANE_DATA_RATE_MBPS 80
 #define MIPI_TX_REF_CLK_KHZ 24000
@@ -80,14 +82,14 @@ static struct mipi_dsi_device *dsi_device;
  * these will eventually go to the device tree sections,
  * and can be used as a refernce later for device tree additions
  */
-//#define RES_1920x1080
+#define RES_1920x1080
 #ifdef RES_1920x1080
 #define IMG_HEIGHT_LINES  1080
 #define IMG_WIDTH_PX  1920
 #define MIPI_TX_ACTIVE_LANES 4
 #endif
 
-#define RES_1280x720
+//#define RES_1280x720
 #ifdef RES_1280x720
 #define IMG_HEIGHT_LINES  720
 #define IMG_WIDTH_PX  1280
@@ -97,9 +99,9 @@ struct mipi_tx_frame_section_cfg mipi_tx_frame0_sect_cfg = {
.width_pixels = IMG_WIDTH_PX,
.height_lines = IMG_HEIGHT_LINES,
.data_type = DSI_LP_DT_PPS_RGB888_24B,
-   //.data_mode = MIPI_DATA_MODE1,
-   .data_mode = MIPI_DATA_MODE0,
-   .dma_packed = 1
+   .data_mode = MIPI_DATA_MODE1,
+// .data_mode = MIPI_DATA_MODE0,
+   .dma_packed = 0
 };
 
 #ifdef RES_1920x1080
@@ -544,12 +546,15 @@ static u32 mipi_tx_fg_section_cfg_regs(struct 
kmb_drm_private *dev_p,
<< MIPI_TX_SECT_VC_SHIFT);  /* bits [23:22] */
/* data mode */
cfg |= ((ph_cfg->data_mode & MIPI_TX_SECT_DM_MASK)
-   << MIPI_TX_SECT_DM_SHIFT);  /* bits [24:25] */
-   cfg |= MIPI_TX_SECT_DMA_PACKED;
-   DRM_INFO("%s : %d ctrl=%d frame_id=%d section=%d cfg=%x\n",
-__func__, __LINE__, ctrl_no, frame_id, section, cfg);
+   << MIPI_TX_SECT_DM_SHIFT); /* bits [24:25]*/
+   if (ph_cfg->dma_packed)
+   cfg |= MIPI_TX_SECT_DMA_PACKED;
+   DRM_INFO("%s : %d ctrl=%d frame_id=%d section=%d cfg=%x packed=%d\n",
+   __func__, __LINE__, ctrl_no, frame_id, section, cfg,
+   ph_cfg->dma_packed);
kmb_write_mipi(dev_p, (MIPI_TXm_HS_FGn_SECTo_PH(ctrl_no, frame_id,
-   section)), cfg);
+   section)), cfg);
+
/*unpacked bytes */
/*there are 4 frame generators and each fg has 4 sections
 *there are 2 registers for unpacked bytes -
@@ -601,6 +606,7 @@ static u32 mipi_tx_fg_

[PATCH v2 47/59] drm/kmb: Don’t inadvertantly disable LCD controller

2020-07-14 Thread Anitha Chrisanthus
setbits instead of write dword for LCD_CONTROL register
this was inadvertantly disabling the LCD controller.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 3245ec7..1582ccf 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -158,6 +158,9 @@ static void kmb_plane_atomic_disable(struct drm_plane 
*plane,
kmb_clr_bitmask_lcd(dev_p, LCD_LAYERn_DMA_CFG(plane_id),
LCD_DMA_LAYER_ENABLE);
kmb_clr_bitmask_lcd(dev_p, LCD_CONTROL, ctrl);
+   DRM_INFO("%s : %d lcd_ctrl = 0x%x lcd_int_enable=0x%x\n",
+   __func__, __LINE__, kmb_read_lcd(dev_p, LCD_CONTROL),
+   kmb_read_lcd(dev_p, LCD_INT_ENABLE));
 }
 
 
@@ -454,7 +457,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
 */
ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
 
-   kmb_write_lcd(dev_p, LCD_CONTROL, ctrl);
+   kmb_set_bitmask_lcd(dev_p, LCD_CONTROL, ctrl);
 
/* FIXME no doc on how to set output format,these values are taken
 * from the Myriadx tests
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 40/59] drm/kmb: Added LCD_TEST config

2020-07-14 Thread Anitha Chrisanthus
To run modetest without ADV driver, enable LCD_TEST and FCC_TEST.
Also made front porches 0, and some changes in the plane init.

v2: upclassed dev_private

Signed-off-by: Anitha Chrisanthus 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  | 13 +++
 drivers/gpu/drm/kmb/kmb_drv.c   |  6 +--
 drivers/gpu/drm/kmb/kmb_drv.h   |  3 +-
 drivers/gpu/drm/kmb/kmb_dsi.c   | 85 +++--
 drivers/gpu/drm/kmb/kmb_plane.c | 15 ++--
 5 files changed, 78 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index 21b2d7f..f77e6f5 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -81,14 +81,15 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct videomode vm;
int vsync_start_offset;
int vsync_end_offset;
-   unsigned int ctrl = 0;
struct kmb_drm_private *dev_p = to_kmb(dev);
 #endif
/* initialize mipi */
kmb_dsi_hw_init(dev);
 #ifdef LCD_TEST
-   vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
-   vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
+// vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
+   vm.vfront_porch = 0;
+// vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
+   vm.vback_porch = 0;
vm.vsync_len = m->crtc_vsync_end - m->crtc_vsync_start;
//vm.hfront_porch = m->crtc_hsync_start - m->crtc_hdisplay;
vm.hfront_porch = 0;
@@ -131,12 +132,8 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
kmb_write_lcd(dev_p, LCD_VSYNC_END_EVEN, 10);
}
/* enable VL1 layer as default */
-   ctrl = LCD_CTRL_ENABLE | LCD_CTRL_VL1_ENABLE;
-   ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
-   | LCD_CTRL_OUTPUT_ENABLED;
-   kmb_write_lcd(dev_p, LCD_CONTROL, ctrl);
-
kmb_write_lcd(dev_p, LCD_TIMING_GEN_TRIG, ENABLE);
+   kmb_set_bitmask_lcd(dev_p, LCD_CONTROL, LCD_CTRL_ENABLE);
 #endif
/* TBD */
/* set clocks here */
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 3542de7..8bd3011 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -216,6 +216,8 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
 #endif
/* Set MIPI clock to 24 Mhz*/
DRM_INFO("Get clk_mipi before set = %ld\n", clk_get_rate(clk_mipi));
+//#define MIPI_CLK
+#ifdef MIPI_CLK
ret = clk_set_rate(clk_mipi, KMB_MIPI_DEFAULT_CLK);
DRM_INFO("Get clk_mipi after set = %ld\n", clk_get_rate(clk_mipi));
if (clk_get_rate(clk_mipi) != KMB_MIPI_DEFAULT_CLK) {
@@ -223,6 +225,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
KMB_MIPI_DEFAULT_CLK);
goto setup_fail;
}
+#endif
DRM_INFO("Setting MIPI clock to %d Mhz ret = %d\n",
KMB_MIPI_DEFAULT_CLK/100, ret);
DRM_INFO("Get clk_mipi after set = %ld\n", clk_get_rate(clk_mipi));
@@ -319,8 +322,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
DRM_ERROR("failed to initialize DSI\n");
goto setup_fail;
}
-
-   DRM_INFO("%s : %d\n", __func__, __LINE__);
 #ifdef WIP
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
if (ret < 0) {
@@ -335,7 +336,6 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
drm_crtc_cleanup(&dev_p->crtc);
 #endif
 setup_fail:
-   DRM_INFO("%s : %d\n", __func__, __LINE__);
of_reserved_mem_device_release(drm->dev);
 
return ret;
diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index 7e6..89d7845 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -8,7 +8,8 @@
 
 #include "kmb_regs.h"
 
-/*#define FCCTEST*/
+#define FCCTEST
+#define LCD_TEST
 #define KMB_MAX_WIDTH  1920 /*max width in pixels */
 #define KMB_MAX_HEIGHT 1080 /*max height in pixels */
 #define KMB_LCD_DEFAULT_CLK25000
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 9da9d9f..c23719c 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -24,18 +24,19 @@
 
 static int hw_initialized;
 #define IMAGE_PATH "/home/root/1280x720.pnm"
-#define MIPI_TX_TEST_PATTERN_GENERATION
+//#define MIPI_TX_TEST_PATTERN_GENERATION
+//#define RTL_TEST
+//#define IMG_WIDTH_PX  640
+//#define IMG_HEIGHT_LINES  10
 
-#define IMG_HEIGHT_LINES  720
-#define IMG_WIDTH_PX  1280
 #define LCD_BYTESPP   1
 
 /*MIPI TX CFG*/
-#define MIPI_TX_ACTIVE_LANES  2
 //#define MIPI_TX_LANE_DATA_RATE_MBPS 1782
 #define MIPI_TX_LANE_DATA_RATE_MBPS 891
 //#define MIPI_TX_LANE_DATA_RATE_MBPS 80
 #define MIPI_TX_REF_CLK_KHZ 24000
+//#define MIPI_TX_REF_CLK_KHZ 23809
 #define MIPI_TX_CFG_CLK_KHZ

[PATCH v2 50/59] drm/kmb: Do the layer initializations only once

2020-07-14 Thread Anitha Chrisanthus
The issue was video starts fine, but towards the end, the color disappers.
Do the layer initializations only once, but update the DMA registers
for every frame. Also changed DRM_INFO to DRM_DEBUG.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 150 ++--
 1 file changed, 66 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index a1d616a..6be0997 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -97,6 +97,9 @@ static const u32 csc_coef_lcd[] = {
-179, 125, -226
 };
 
+/*plane initialization status */
+static int plane_init_status[KMB_MAX_PLANES] = { 0, 0, 0, 0 };
+
 static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
 {
int i;
@@ -157,9 +160,9 @@ static void kmb_plane_atomic_disable(struct drm_plane 
*plane,
kmb_clr_bitmask_lcd(dev_p, LCD_LAYERn_DMA_CFG(plane_id),
LCD_DMA_LAYER_ENABLE);
kmb_clr_bitmask_lcd(dev_p, LCD_CONTROL, ctrl);
-   DRM_INFO("%s : %d lcd_ctrl = 0x%x lcd_int_enable=0x%x\n",
-__func__, __LINE__, kmb_read_lcd(dev_p, LCD_CONTROL),
-kmb_read_lcd(dev_p, LCD_INT_ENABLE));
+   DRM_DEBUG("%s : %d lcd_ctrl = 0x%x lcd_int_enable=0x%x\n",
+ __func__, __LINE__, kmb_read_lcd(dev_p, LCD_CONTROL),
+ kmb_read_lcd(dev_p, LCD_INT_ENABLE));
 }
 
 unsigned int set_pixel_format(u32 format)
@@ -317,8 +320,6 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
unsigned int src_w, src_h, crtc_x, crtc_y;
unsigned char plane_id;
int num_planes;
-   /*plane initialization status */
-   static int plane_init_status[KMB_MAX_PLANES] = { 0, 0, 0, 0 };
static dma_addr_t addr[MAX_SUB_PLANES] = { 0, 0, 0 };
 
if (!plane || !plane->state || !state)
@@ -339,9 +340,56 @@ static void kmb_plane_atomic_update(struct drm_plane 
*plane,
crtc_x = plane->state->crtc_x;
crtc_y = plane->state->crtc_y;
 
-   DRM_INFO
+   DRM_DEBUG
("%s : %d src_w=%d src_h=%d, fb->format->format=0x%x 
fb->flags=0x%x",
 __func__, __LINE__, src_w, src_h, fb->format->format, fb->flags);
+
+   width = fb->width;
+   height = fb->height;
+   dma_len = (width * height * fb->format->cpp[0]);
+   DRM_DEBUG("%s : %d dma_len=%d ", __func__, __LINE__, dma_len);
+   kmb_write_lcd(dev_p, LCD_LAYERn_DMA_LEN(plane_id), dma_len);
+   kmb_write_lcd(dev_p, LCD_LAYERn_DMA_LEN_SHADOW(plane_id), dma_len);
+
+   kmb_write_lcd(dev_p, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
+ fb->pitches[0]);
+   kmb_write_lcd(dev_p, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),
+ (width * fb->format->cpp[0]));
+
+   addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, plane->state, 0);
+   dev_p->fb_addr = (dma_addr_t) addr;
+   kmb_write_lcd(dev_p, LCD_LAYERn_DMA_START_ADDR(plane_id),
+ addr[Y_PLANE] + fb->offsets[0]);
+   /*program Cb/Cr for planar formats */
+   if (num_planes > 1) {
+   if (fb->format->format == DRM_FORMAT_YUV420 ||
+   fb->format->format == DRM_FORMAT_YVU420)
+   width /= 2;
+   kmb_write_lcd(dev_p,
+ LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
+ fb->pitches[LAYER_1]);
+   kmb_write_lcd(dev_p,
+ LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
+ (width * fb->format->cpp[0]));
+   addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, plane->state,
+   U_PLANE);
+   kmb_write_lcd(dev_p, LCD_LAYERn_DMA_START_CB_ADR(plane_id),
+ addr[U_PLANE]);
+   if (num_planes == 3) {
+   kmb_write_lcd(dev_p,
+ LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
+ fb->pitches[LAYER_2]);
+   kmb_write_lcd(dev_p,
+ LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
+ (width * fb->format->cpp[0]));
+   addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb,
+   plane->state,
+   V_PLANE);
+   kmb_write_lcd(dev_p,
+ LCD_LAYERn_DMA_START_CR_ADR(plane_id),
+ addr[V_PLANE]);
+   }
+   }
if (plane_init_status[plane_id] != INITIALIZED) {
kmb_write_lcd(dev_p, LCD_LAYERn_WIDTH(plane_id), src_w - 1);
kmb_write_lcd(dev_p, LCD_LAYERn_HEIGHT(plane_id), src_h - 1);
@@ 

[PATCH v2 00/59] Add support for KeemBay DRM driver

2020-07-14 Thread Anitha Chrisanthus
This is a new DRM driver for Intel's KeemBay SOC.
The SoC couples an ARM Cortex A53 CPU with an Intel
Movidius VPU.

This driver is tested with the KMB EVM board which is the refernce baord
for Keem Bay SOC. The SOC's display pipeline is as follows

+--++-++---+
|LCD controller| -> |Mipi DSI | -> |Mipi to HDMI Converter |
+--++-++---+

LCD controller and Mipi DSI transmitter are part of the SOC and
mipi to HDMI converter is ADV7535 for KMB EVM board.

The DRM driver is a basic KMS atomic modesetting display driver and
has no 2D or 3D graphics.It calls into the ADV bridge driver at
the connector level.

Only 1080p resolution and single plane is supported at this time.
The usecase is for debugging video and camera outputs.

Device tree patches are under review here
https://lore.kernel.org/linux-arm-kernel/20200708175020.194436-1-daniele.alessandre...@linux.intel.com/T/

Changes since v1:
- Removed redundant license text, updated license
- Rearranged include blocks
- renamed global vars and removed extern in c
- Used upclassing for dev_private
- Used drm_dev_init in drm device create (will be updated to use
  devm_drm_dev_alloc() in a separate patch later as kmb driver is currently
  developed on 5.4 kernel)
- minor cleanups

Anitha Chrisanthus (52):
  drm/kmb: Add support for KeemBay Display
  drm/kmb: Added id to kmb_plane
  drm/kmb: Set correct values in the LAYERn_CFG register
  drm/kmb: Use biwise operators for register definitions
  drm/kmb: Updated kmb_plane_atomic_check
  drm/kmb: Initial check-in for Mipi DSI
  drm/kmb: Set OUT_FORMAT_CFG register
  drm/kmb: Added mipi_dsi_host initialization
  drm/kmb: Part 1 of Mipi Tx Initialization
  drm/kmb: Part 2 of Mipi Tx Initialization
  drm/kmb: Use correct mmio offset from data book
  drm/kmb: Part3 of Mipi Tx initialization
  drm/kmb: Part4 of Mipi Tx Initialization
  drm/kmb: Correct address offsets for mipi registers
  drm/kmb: Part5 of Mipi Tx Intitialization
  drm/kmb: Part6 of Mipi Tx Initialization
  drm/kmb: Part7 of Mipi Tx Initialization
  drm/kmb: Part8 of Mipi Tx Initialization
  drm/kmb: Added ioremap/iounmap for register access
  drm/kmb: Register IRQ for LCD
  drm/kmb: IRQ handlers for LCD and mipi dsi
  drm/kmb: Set hardcoded values to LCD_VSYNC_START
  drm/kmb: Additional register programming to update_plane
  drm/kmb: Add ADV7535 bridge
  drm/kmb: Display clock enable/disable
  drm/kmb: rebase to newer kernel version
  drm/kmb: minor name change to match device tree
  drm/kmb: Changed MMIO size
  drm/kmb: Defer Probe
  drm/kmb: call bridge init in the very beginning
  drm/kmb: Enable MSS_CAM_CLK_CTRL for LCD and MIPI
  drm/kmb: Set MSS_CAM_RSTN_CTRL along with enable
  drm/kmb: Mipi DPHY initialization changes
  drm/kmb: Fixed driver unload
  drm/kmb: Added LCD_TEST config
  drm/kmb: Changes for LCD to Mipi
  drm/kmb: Update LCD programming to match MIPI
  drm/kmb: Changed name of driver to kmb-drm
  drm/kmb: Mipi settings from input timings
  drm/kmb: Enable LCD interrupts
  drm/kmb: Enable LCD interrupts during modeset
  drm/kmb: Don’t inadvertantly disable LCD controller
  drm/kmb: SWAP R and B LCD Layer order
  drm/kmb: Disable ping pong mode
  drm/kmb: Do the layer initializations only once
  drm/kmb: disable the LCD layer in EOF irq handler
  drm/kmb: Initialize uninitialized variables
  drm/kmb: Added useful messages in LCD ISR
  kmb/drm: Prune unsupported modes
  drm/kmb: workaround for dma undeflow issue
  drm/kmb: Get System Clock from SCMI
  drm/kmb: work around for planar formats

Edmund Dea (7):
  drm/kmb: Cleanup probe functions
  drm/kmb: Revert dsi_host back to a static variable
  drm/kmb: Initialize clocks for clk_msscam, clk_mipi_ecfg, &
clk_mipi_cfg.
  drm/kmb: Remove declaration of irq_lcd/irq_mipi
  drm/kmb: Enable MIPI TX HS Test Pattern Generation
  drm/kmb: Write to LCD_LAYERn_CFG only once
  drm/kmb: Cleaned up code

 drivers/gpu/drm/Kconfig |2 +
 drivers/gpu/drm/Makefile|1 +
 drivers/gpu/drm/kmb/Kconfig |   12 +
 drivers/gpu/drm/kmb/Makefile|2 +
 drivers/gpu/drm/kmb/kmb_crtc.c  |  226 +
 drivers/gpu/drm/kmb/kmb_crtc.h  |   41 +
 drivers/gpu/drm/kmb/kmb_drv.c   |  809 
 drivers/gpu/drm/kmb/kmb_drv.h   |  176 
 drivers/gpu/drm/kmb/kmb_dsi.c   | 1927 +++
 drivers/gpu/drm/kmb/kmb_dsi.h   |  370 
 drivers/gpu/drm/kmb/kmb_plane.c |  518 +++
 drivers/gpu/drm/kmb/kmb_plane.h |  124 +++
 drivers/gpu/drm/kmb/kmb_regs.h  |  738 +++
 13 files changed, 4946 insertions(+)
 create mode 100644 drivers/gpu/drm/kmb/Kconfig
 create mode 100644 drivers/gpu/drm/kmb/Makefile
 create mode 100644 drivers/gpu/drm/kmb/kmb_crtc.c
 create mode 100644 drivers/gpu/drm/kmb/kmb_crtc.h
 create mode 100644 drivers/gpu/drm/kmb/kmb_drv.c
 create mode 100644 drivers/gpu/drm/kmb/kmb_drv.h
 create mode 100644 drivers/gpu/drm/kmb/k

[PATCH v2 10/59] drm/kmb: Part 2 of Mipi Tx Initialization

2020-07-14 Thread Anitha Chrisanthus
Mipi TX Frame generator timing configuration

Compute and set frame generator timings like hactive, front porch,
back porch etc.

v2: minor code review changes
Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_dsi.c  | 132 -
 drivers/gpu/drm/kmb/kmb_regs.h |  37 
 2 files changed, 166 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index cb6082d..951a742 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -391,6 +391,123 @@ static u32 mipi_tx_fg_section_cfg(struct kmb_drm_private 
*dev_priv,
return 0;
 }
 
+static void mipi_tx_fg_cfg_regs(struct kmb_drm_private *dev_priv,
+   u8 frame_gen,
+   struct mipi_tx_frame_timing_cfg *fg_cfg)
+{
+   u32 sysclk;
+   /*float ppl_llp_ratio; */
+   u32 ppl_llp_ratio;
+   u32 ctrl_no = MIPI_CTRL6, reg_adr, val, offset;
+
+   /*Get system clock for blanking period cnfigurations */
+   /*TODO need to get system clock from clock driver */
+   /* Assume 700 Mhz system clock for now */
+   sysclk = 700;
+
+   /*ppl-pixel packing layer, llp-low level protocol
+* frame genartor timing parameters are clocked on the system clock
+* whereas as the equivalent parameters in the LLP blocks are clocked
+* on LLP Tx clock from the D-PHY - BYTE clock
+*/
+
+   /*multiply by 1000 to keep the precision */
+   ppl_llp_ratio = ((fg_cfg->bpp / 8) * sysclk * 1000) /
+   ((fg_cfg->lane_rate_mbps / 8) * fg_cfg->active_lanes);
+
+   /*frame generator number of lines */
+   reg_adr = MIPI_TXm_HS_FGn_NUM_LINES(ctrl_no, frame_gen);
+   kmb_write(dev_priv, reg_adr, fg_cfg->v_active);
+
+   /*vsync width */
+   /*
+*there are 2 registers for vsync width -VSA in lines for channels 0-3
+*REG_VSYNC_WIDTH0: [15:0]-VSA for channel0, [31:16]-VSA for channel1
+*REG_VSYNC_WIDTH1: [15:0]-VSA for channel2, [31:16]-VSA for channel3
+*/
+   offset = (frame_gen % 2) * 16;
+   reg_adr = MIPI_TXm_HS_VSYNC_WIDTHn(ctrl_no, frame_gen);
+   kmb_write_bits(dev_priv, reg_adr, offset, 16, fg_cfg->vsync_width);
+
+   /*v backporch - same register config like vsync width */
+   reg_adr = MIPI_TXm_HS_V_BACKPORCHESn(ctrl_no, frame_gen);
+   kmb_write_bits(dev_priv, reg_adr, offset, 16, fg_cfg->v_backporch);
+
+   /*v frontporch - same register config like vsync width */
+   reg_adr = MIPI_TXm_HS_V_FRONTPORCHESn(ctrl_no, frame_gen);
+   kmb_write_bits(dev_priv, reg_adr, offset, 16, fg_cfg->v_frontporch);
+
+   /*v active - same register config like vsync width */
+   reg_adr = MIPI_TXm_HS_V_ACTIVEn(ctrl_no, frame_gen);
+   kmb_write_bits(dev_priv, reg_adr, offset, 16, fg_cfg->v_active);
+
+   /*hsyc width */
+   reg_adr = MIPI_TXm_HS_HSYNC_WIDTHn(ctrl_no, frame_gen);
+   kmb_write(dev_priv, reg_adr,
+ (fg_cfg->hsync_width * ppl_llp_ratio) / 1000);
+
+   /*h backporch */
+   reg_adr = MIPI_TXm_HS_H_BACKPORCHn(ctrl_no, frame_gen);
+   kmb_write(dev_priv, reg_adr,
+ (fg_cfg->h_backporch * ppl_llp_ratio) / 1000);
+
+   /*h frontporch */
+   reg_adr = MIPI_TXm_HS_H_FRONTPORCHn(ctrl_no, frame_gen);
+   kmb_write(dev_priv, reg_adr,
+ (fg_cfg->h_frontporch * ppl_llp_ratio) / 1000);
+
+   /*h active */
+   reg_adr = MIPI_TXm_HS_H_ACTIVEn(ctrl_no, frame_gen);
+   /*convert h_active which is wc in bytes to cycles */
+   val = (fg_cfg->h_active * sysclk * 1000) /
+   ((fg_cfg->lane_rate_mbps / 8) * fg_cfg->active_lanes);
+   val /= 1000;
+   kmb_write(dev_priv, reg_adr, val);
+
+   /* llp hsync width */
+   reg_adr = MIPI_TXm_HS_LLP_HSYNC_WIDTHn(ctrl_no, frame_gen);
+   kmb_write(dev_priv, reg_adr, fg_cfg->hsync_width * (fg_cfg->bpp / 8));
+
+   /* llp h backporch */
+   reg_adr = MIPI_TXm_HS_LLP_H_BACKPORCHn(ctrl_no, frame_gen);
+   kmb_write(dev_priv, reg_adr, fg_cfg->h_backporch * (fg_cfg->bpp / 8));
+
+   /* llp h frontporch */
+   reg_adr = MIPI_TXm_HS_LLP_H_FRONTPORCHn(ctrl_no, frame_gen);
+   kmb_write(dev_priv, reg_adr, fg_cfg->h_frontporch * (fg_cfg->bpp / 8));
+}
+
+static void mipi_tx_fg_cfg(struct kmb_drm_private *dev_priv, u8 frame_gen,
+  u8 active_lanes, u32 bpp, u32 wc,
+  u32 lane_rate_mbps, struct mipi_tx_frame_cfg *fg_cfg)
+{
+   u32 i, fg_num_lines = 0;
+   struct mipi_tx_frame_timing_cfg fg_t_cfg;
+
+   /*calculate the total frame generator number of lines based on it's
+* active sections
+*/
+   for (i = 0; i < MIPI_TX_FRAME_GEN_SECTIONS; i++) {
+   if (fg_cfg->sections[i] != NULL)
+   fg_num_lines += fg_cfg->sections[i]->height_lines;
+ 

[PATCH v2 04/59] drm/kmb: Use biwise operators for register definitions

2020-07-14 Thread Anitha Chrisanthus
Did some general clean up and organization.

v2: corrected spelling

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_drv.c  |   3 +-
 drivers/gpu/drm/kmb/kmb_regs.h | 852 +++--
 2 files changed, 307 insertions(+), 548 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 28aa625..11f8d1f 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -113,8 +113,7 @@ static irqreturn_t kmb_irq(int irq, void *arg)
if (status & LCD_INT_VERT_COMP) {
/* read VSTATUS */
val = kmb_read(lcd, LCD_VSTATUS);
-   /* BITS 13 and 14 */
-   val = (val & LCD_VSTATUS_VERTICAL_STATUS_MASK) >> 12;
+   val = (val & LCD_VSTATUS_VERTICAL_STATUS_MASK);
switch (val) {
case LCD_VSTATUS_COMPARE_VSYNC:
case LCD_VSTATUS_COMPARE_BACKPORCH:
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index 0f879b9..8346a04 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -6,35 +6,181 @@
 #ifndef __KMB_REGS_H__
 #define __KMB_REGS_H__
 
-/*LCD CONTROLLER REGISTERS */
-#define LCD_CONTROL(0x4 * 0x000)
-#define LCD_INT_STATUS (0x4 * 0x001)
-#define LCD_INT_ENABLE (0x4 * 0x002)
-#define LCD_INT_CLEAR  (0x4 * 0x003)
-#define LCD_LINE_COUNT (0x4 * 0x004)
-#define LCD_LINE_COMPARE   (0x4 * 0x005)
-#define LCD_VSTATUS(0x4 * 0x006)
-#define LCD_VSTATUS_COMPARE(0x4 * 0x007)
-#define LCD_SCREEN_WIDTH   (0x4 * 0x008)
-#define LCD_SCREEN_HEIGHT  (0x4 * 0x009)
-#define LCD_FIELD_INT_CFG  (0x4 * 0x00a)
-#define LCD_FIFO_FLUSH (0x4 * 0x00b)
-#define LCD_BG_COLOUR_LS   (0x4 * 0x00c)
-#define LCD_BG_COLOUR_MS   (0x4 * 0x00d)
-#define LCD_RAM_CFG(0x4 * 0x00e)
+#define ENABLE  1
+/***
+ *LCD controller control register defines
+ ***/
+#define LCD_CONTROL(0x4 * 0x000)
+#define LCD_CTRL_PROGRESSIVE (0<<0)
+#define LCD_CTRL_INTERLACED  (1<<0)
+#define LCD_CTRL_ENABLE  (1<<1)
+#define LCD_CTRL_VL1_ENABLE  (1<<2)
+#define LCD_CTRL_VL2_ENABLE  (1<<3)
+#define LCD_CTRL_GL1_ENABLE  (1<<4)
+#define LCD_CTRL_GL2_ENABLE  (1<<5)
+#define LCD_CTRL_ALPHA_BLEND_VL1 (0<<6)
+#define LCD_CTRL_ALPHA_BLEND_VL2 (1<<6)
+#define LCD_CTRL_ALPHA_BLEND_GL1 (2<<6)
+#define LCD_CTRL_ALPHA_BLEND_GL2 (3<<6)
+#define LCD_CTRL_ALPHA_TOP_VL1   (0<<8)
+#define LCD_CTRL_ALPHA_TOP_VL2   (1<<8)
+#define LCD_CTRL_ALPHA_TOP_GL1   (2<<8)
+#define LCD_CTRL_ALPHA_TOP_GL2   (3<<8)
+#define LCD_CTRL_ALPHA_MIDDLE_VL1(0<<10)
+#define LCD_CTRL_ALPHA_MIDDLE_VL2(1<<10)
+#define LCD_CTRL_ALPHA_MIDDLE_GL1(2<<10)
+#define LCD_CTRL_ALPHA_MIDDLE_GL2(3<<10)
+#define LCD_CTRL_ALPHA_BOTTOM_VL1(0<<12)
+#define LCD_CTRL_ALPHA_BOTTOM_VL2(1<<12)
+#define LCD_CTRL_ALPHA_BOTTOM_GL1(2<<12)
+#define LCD_CTRL_ALPHA_BOTTOM_GL2(3<<12)
+#define LCD_CTRL_TIM_GEN_ENABLE  (1<<14)
+#define LCD_CTRL_DISPLAY_MODE_ONE_SHOT   (1<<15)
+#define LCD_CTRL_PWM0_EN (1<<16)
+#define LCD_CTRL_PWM1_EN (1<<17)
+#define LCD_CTRL_PWM2_EN (1<<18)
+#define LCD_CTRL_OUTPUT_DISABLED (0<<19)
+#define LCD_CTRL_OUTPUT_ENABLED  (1<<19)
+#define LCD_CTRL_BPORCH_ENABLE   (1<<21)
+#define LCD_CTRL_FPORCH_ENABLE   (1<<22)
+#define LCD_CTRL_PIPELINE_DMA(1<<28)
+
+/*interrupts */
+#define LCD_INT_STATUS (0x4 * 0x001)
+#define LCD_INT_EOF  (1<<0)
+#define LCD_INT_LINE_CMP (1<<1)
+#define LCD_INT_VERT_COMP(1<<2)
+#define LAYER0_DMA_DONE_BIT  (1<<3)
+#define LAYER0_DMA_IDLE_BIT  (1<<4)
+#define LAYER0_DMA_OVERFLOW_BIT  (1<<5)
+#define LAYER0_DMA_FIFO_UNDERFLOW_BIT(1<<6)
+#define LAYER0_DMA_CB_FIFO_OVERFLOW_BIT  (1<<7)
+#define LAYER0_DMA_CB_FIFO_UNDERFLOW_BIT (1<<8)
+#define LAYER0_DMA_CR_FIFO_OVERFLOW_BIT  (1<<9)

[PATCH v2 11/59] drm/kmb: Use correct mmio offset from data book

2020-07-14 Thread Anitha Chrisanthus
Also added separate macros for lcd and mipi register accesses that
use the corrected mmio offset. mmio oofset will be read from the device
tree in the future.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_crtc.c  | 49 ++---
 drivers/gpu/drm/kmb/kmb_drv.c   | 17 ++
 drivers/gpu/drm/kmb/kmb_drv.h   | 47 ---
 drivers/gpu/drm/kmb/kmb_dsi.c   | 41 +++---
 drivers/gpu/drm/kmb/kmb_plane.c | 34 ++--
 drivers/gpu/drm/kmb/kmb_regs.h  |  6 -
 6 files changed, 113 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
index 63821ed..984f21a 100644
--- a/drivers/gpu/drm/kmb/kmb_crtc.c
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -31,25 +31,21 @@ static void kmb_crtc_cleanup(struct drm_crtc *crtc)
 
 static int kmb_crtc_enable_vblank(struct drm_crtc *crtc)
 {
-   struct kmb_drm_private *lcd = crtc_to_kmb_priv(crtc);
-
/*clear interrupt */
-   kmb_write(lcd, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
+   kmb_write_lcd(LCD_INT_CLEAR, LCD_INT_VERT_COMP);
/*set which interval to generate vertical interrupt */
-   kmb_write(lcd, LCD_VSTATUS_COMPARE, LCD_VSTATUS_COMPARE_VSYNC);
+   kmb_write_lcd(LCD_VSTATUS_COMPARE, LCD_VSTATUS_COMPARE_VSYNC);
/* enable vertical interrupt */
-   kmb_write(lcd, LCD_INT_ENABLE, LCD_INT_VERT_COMP);
+   kmb_write_lcd(LCD_INT_ENABLE, LCD_INT_VERT_COMP);
return 0;
 }
 
 static void kmb_crtc_disable_vblank(struct drm_crtc *crtc)
 {
-   struct kmb_drm_private *lcd = crtc_to_kmb_priv(crtc);
-
/*clear interrupt */
-   kmb_write(lcd, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
+   kmb_write_lcd(LCD_INT_CLEAR, LCD_INT_VERT_COMP);
/* disable vertical interrupt */
-   kmb_write(lcd, LCD_INT_ENABLE, 0);
+   kmb_write_lcd(LCD_INT_ENABLE, 0);
 
 /* TBD
  *  set the BIT2 (VERTICAL_COMPARE_INTERRUPT) of the LCD_INT_ENABLE register
@@ -71,7 +67,6 @@ static const struct drm_crtc_funcs kmb_crtc_funcs = {
 
 static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
-   struct kmb_drm_private *lcd = crtc_to_kmb_priv(crtc);
struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct videomode vm;
int vsync_start_offset;
@@ -88,30 +83,30 @@ static void kmb_crtc_mode_set_nofb(struct drm_crtc *crtc)
vsync_start_offset = m->crtc_vsync_start - m->crtc_hsync_start;
vsync_end_offset = m->crtc_vsync_end - m->crtc_hsync_end;
 
-   kmb_write(lcd, LCD_V_ACTIVEHEIGHT, m->crtc_vdisplay - 1);
-   kmb_write(lcd, LCD_V_BACKPORCH, vm.vback_porch - 1);
-   kmb_write(lcd, LCD_V_FRONTPORCH, vm.vfront_porch - 1);
-   kmb_write(lcd, LCD_VSYNC_WIDTH, vm.vsync_len - 1);
-   kmb_write(lcd, LCD_H_ACTIVEWIDTH, m->crtc_hdisplay - 1);
-   kmb_write(lcd, LCD_H_BACKPORCH, vm.hback_porch - 1);
-   kmb_write(lcd, LCD_H_FRONTPORCH, vm.hfront_porch - 1);
-   kmb_write(lcd, LCD_HSYNC_WIDTH, vm.hsync_len - 1);
+   kmb_write_lcd(LCD_V_ACTIVEHEIGHT, m->crtc_vdisplay - 1);
+   kmb_write_lcd(LCD_V_BACKPORCH, vm.vback_porch - 1);
+   kmb_write_lcd(LCD_V_FRONTPORCH, vm.vfront_porch - 1);
+   kmb_write_lcd(LCD_VSYNC_WIDTH, vm.vsync_len - 1);
+   kmb_write_lcd(LCD_H_ACTIVEWIDTH, m->crtc_hdisplay - 1);
+   kmb_write_lcd(LCD_H_BACKPORCH, vm.hback_porch - 1);
+   kmb_write_lcd(LCD_H_FRONTPORCH, vm.hfront_porch - 1);
+   kmb_write_lcd(LCD_HSYNC_WIDTH, vm.hsync_len - 1);
 
if (m->flags == DRM_MODE_FLAG_INTERLACE) {
-   kmb_write(lcd, LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
-   kmb_write(lcd, LCD_V_BACKPORCH_EVEN, vm.vback_porch - 1);
-   kmb_write(lcd, LCD_V_FRONTPORCH_EVEN, vm.vfront_porch - 1);
-   kmb_write(lcd, LCD_V_ACTIVEHEIGHT_EVEN, m->crtc_vdisplay - 1);
-   kmb_write(lcd, LCD_VSYNC_START_EVEN, vsync_start_offset);
-   kmb_write(lcd, LCD_VSYNC_END_EVEN, vsync_end_offset);
+   kmb_write_lcd(LCD_VSYNC_WIDTH_EVEN, vm.vsync_len - 1);
+   kmb_write_lcd(LCD_V_BACKPORCH_EVEN, vm.vback_porch - 1);
+   kmb_write_lcd(LCD_V_FRONTPORCH_EVEN, vm.vfront_porch - 1);
+   kmb_write_lcd(LCD_V_ACTIVEHEIGHT_EVEN,  m->crtc_vdisplay - 1);
+   kmb_write_lcd(LCD_VSYNC_START_EVEN, vsync_start_offset);
+   kmb_write_lcd(LCD_VSYNC_END_EVEN, vsync_end_offset);
}
/* enable VL1 layer as default */
ctrl = LCD_CTRL_ENABLE | LCD_CTRL_VL1_ENABLE;
ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
-   | LCD_CTRL_OUTPUT_ENABLED;
-   kmb_write(lcd, LCD_CONTROL, ctrl);
+   | LCD_CTRL_OUTPUT_ENABLED;
+   kmb_write_lcd(LCD_CONTROL, ctrl);
 
-   kmb_write(lcd, LCD_TIMING_GEN_TRIG, ENABLE);
+   kmb_write_lcd(LCD_TIMING_GEN_TRIG, ENABLE);
 
/* TBD */
 

[PATCH v2 01/59] drm/kmb: Add support for KeemBay Display

2020-07-14 Thread Anitha Chrisanthus
Initial check-in for basic display driver for KeemBay family of SOCs.
This is not tested and does not work and also there are many TBDs in the
code which will be implemented in future commits.

v2: moved extern to .h, removed license text
use drm_dev_init, upclassed dev_private, removed HAVE_IRQ.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/Kconfig |   2 +
 drivers/gpu/drm/Makefile|   1 +
 drivers/gpu/drm/kmb/Kconfig |  12 ++
 drivers/gpu/drm/kmb/Makefile|   2 +
 drivers/gpu/drm/kmb/kmb_crtc.c  | 194 ++
 drivers/gpu/drm/kmb/kmb_crtc.h  |  39 
 drivers/gpu/drm/kmb/kmb_drv.c   | 355 
 drivers/gpu/drm/kmb/kmb_drv.h   |  47 +
 drivers/gpu/drm/kmb/kmb_plane.c | 232 +
 drivers/gpu/drm/kmb/kmb_plane.h |  32 +++
 drivers/gpu/drm/kmb/kmb_regs.h  | 440 
 11 files changed, 1356 insertions(+)
 create mode 100644 drivers/gpu/drm/kmb/Kconfig
 create mode 100644 drivers/gpu/drm/kmb/Makefile
 create mode 100644 drivers/gpu/drm/kmb/kmb_crtc.c
 create mode 100644 drivers/gpu/drm/kmb/kmb_crtc.h
 create mode 100644 drivers/gpu/drm/kmb/kmb_drv.c
 create mode 100644 drivers/gpu/drm/kmb/kmb_drv.h
 create mode 100644 drivers/gpu/drm/kmb/kmb_plane.c
 create mode 100644 drivers/gpu/drm/kmb/kmb_plane.h
 create mode 100644 drivers/gpu/drm/kmb/kmb_regs.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c4fd57d..5292574 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -275,6 +275,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
 
 source "drivers/gpu/drm/i915/Kconfig"
 
+source "drivers/gpu/drm/kmb/Kconfig"
+
 config DRM_VGEM
tristate "Virtual GEM provider"
depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 2c0e5a7..bdbdc63 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
 obj-$(CONFIG_DRM_MGA)  += mga/
 obj-$(CONFIG_DRM_I810) += i810/
 obj-$(CONFIG_DRM_I915) += i915/
+obj-$(CONFIG_DRM_KMB_DISPLAY)  += kmb/
 obj-$(CONFIG_DRM_MGAG200) += mgag200/
 obj-$(CONFIG_DRM_V3D)  += v3d/
 obj-$(CONFIG_DRM_VC4)  += vc4/
diff --git a/drivers/gpu/drm/kmb/Kconfig b/drivers/gpu/drm/kmb/Kconfig
new file mode 100644
index 000..005a9962
--- /dev/null
+++ b/drivers/gpu/drm/kmb/Kconfig
@@ -0,0 +1,12 @@
+config DRM_KMB_DISPLAY
+   tristate "KEEMBAY DISPLAY"
+   depends on DRM && OF && (ARM || ARM64)
+   depends on COMMON_CLK
+   select DRM_KMS_HELPER
+   select DRM_KMS_CMA_HELPER
+   select DRM_GEM_CMA_HELPER
+   select VIDEOMODE_HELPERS
+   help
+   Choose this option if you have an KEEMBAY DISPLAY controller.
+
+   If M is selected the module will be called kmb-display.
diff --git a/drivers/gpu/drm/kmb/Makefile b/drivers/gpu/drm/kmb/Makefile
new file mode 100644
index 000..be9f19c
--- /dev/null
+++ b/drivers/gpu/drm/kmb/Makefile
@@ -0,0 +1,2 @@
+kmb-display-y := kmb_crtc.o kmb_drv.o kmb_plane.o
+obj-$(CONFIG_DRM_KMB_DISPLAY)  += kmb-display.o
diff --git a/drivers/gpu/drm/kmb/kmb_crtc.c b/drivers/gpu/drm/kmb/kmb_crtc.c
new file mode 100644
index 000..1a00015
--- /dev/null
+++ b/drivers/gpu/drm/kmb/kmb_crtc.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright © 2018-2020 Intel Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "kmb_crtc.h"
+#include "kmb_drv.h"
+#include "kmb_plane.h"
+#include "kmb_regs.h"
+
+static void kmb_crtc_cleanup(struct drm_crtc *crtc)
+{
+   struct kmb_crtc *l_crtc = to_kmb_crtc(crtc);
+
+   drm_crtc_cleanup(crtc);
+   kfree(l_crtc);
+}
+
+static int kmb_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+   struct kmb_drm_private *lcd = crtc_to_kmb_priv(crtc);
+
+   /*clear interrupt */
+   kmb_write(lcd, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
+   /*set which interval to generate vertical interrupt */
+   kmb_write(lcd, LCD_VSTATUS_COMPARE, LCD_VSTATUS_COMPARE_VSYNC);
+   /* enable vertical interrupt */
+   kmb_write(lcd, LCD_INT_ENABLE, LCD_INT_VERT_COMP);
+   return 0;
+}
+
+static void kmb_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+   struct kmb_drm_private *lcd = crtc_to_kmb_priv(crtc);
+
+   /*clear interrupt */
+   kmb_write(lcd, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
+   /* disable vertical interrupt */
+   kmb_write(lcd, LCD_INT_ENABLE, 0);
+
+/* TBD
+ *  set the BIT2 (VERTICAL_COMPARE_INTERRUPT) of the LCD_INT_ENABLE register
+ *  set the required bit LCD_VSTATUS_COMPARE register
+ *  Not sure if anything needs to be done in the ICB
+ */
+}
+
+static const struct drm_crtc_funcs kmb_crtc_funcs = {
+   .destroy = kmb_crtc_cleanup,
+   .set_config = drm_atomic_helper_set_config,
+   .page_flip = drm_atomic_helper_page_fli

[PATCH v2 03/59] drm/kmb: Set correct values in the LAYERn_CFG register

2020-07-14 Thread Anitha Chrisanthus
During update plane, set the layer format, bpp, fifo level,
RGB order, Cb/Cr order etc. in the LAYER_CFG register.

v2: Return val in set_pixel and set_bpp instead of passing in pointer,

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_plane.c | 145 ++
 drivers/gpu/drm/kmb/kmb_regs.h  | 167 
 2 files changed, 298 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index 7077a4c..877314a 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -33,6 +33,119 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
return 0;
 }
 
+unsigned int set_pixel_format(u32 format)
+{
+   unsigned int val = 0;
+
+   switch (format) {
+   /*planar formats */
+   case DRM_FORMAT_YUV444:
+   val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE;
+   break;
+   case DRM_FORMAT_YVU444:
+   val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE
+   | LCD_LAYER_CRCB_ORDER;
+   break;
+   case DRM_FORMAT_YUV422:
+   val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE;
+   break;
+   case DRM_FORMAT_YVU422:
+   val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE
+  | LCD_LAYER_CRCB_ORDER;
+   break;
+   case DRM_FORMAT_YUV420:
+   val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE;
+   break;
+   case DRM_FORMAT_YVU420:
+   val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE
+  | LCD_LAYER_CRCB_ORDER;
+   break;
+   case DRM_FORMAT_NV12:
+   val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE;
+   break;
+   case DRM_FORMAT_NV21:
+   val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
+  | LCD_LAYER_CRCB_ORDER;
+   break;
+   /* packed formats */
+   case DRM_FORMAT_RGB332:
+   val = LCD_LAYER_FORMAT_RGB332;
+   break;
+   case DRM_FORMAT_XBGR:
+   val = LCD_LAYER_FORMAT_RGBX | LCD_LAYER_BGR_ORDER;
+   break;
+   case DRM_FORMAT_ARGB:
+   val = LCD_LAYER_FORMAT_RGBA;
+   break;
+   case DRM_FORMAT_ABGR:
+   val = LCD_LAYER_FORMAT_RGBA | LCD_LAYER_BGR_ORDER;
+   break;
+   case DRM_FORMAT_XRGB1555:
+   val = LCD_LAYER_FORMAT_XRGB1555;
+   break;
+   case DRM_FORMAT_XBGR1555:
+   val = LCD_LAYER_FORMAT_XRGB1555 | LCD_LAYER_BGR_ORDER;
+   break;
+   case DRM_FORMAT_ARGB1555:
+   val = LCD_LAYER_FORMAT_RGBA1555;
+   break;
+   case DRM_FORMAT_ABGR1555:
+   val = LCD_LAYER_FORMAT_RGBA1555 | LCD_LAYER_BGR_ORDER;
+   break;
+   case DRM_FORMAT_RGB565:
+   val = LCD_LAYER_FORMAT_RGB565;
+   break;
+   case DRM_FORMAT_BGR565:
+   val = LCD_LAYER_FORMAT_RGB565 | LCD_LAYER_BGR_ORDER;
+   break;
+   case DRM_FORMAT_RGB888:
+   val = LCD_LAYER_FORMAT_RGB888;
+   break;
+   case DRM_FORMAT_BGR888:
+   val = LCD_LAYER_FORMAT_RGB888 | LCD_LAYER_BGR_ORDER;
+   break;
+   case DRM_FORMAT_XRGB:
+   val = LCD_LAYER_FORMAT_RGBX;
+   break;
+   case DRM_FORMAT_XBGR:
+   val = LCD_LAYER_FORMAT_RGBX | LCD_LAYER_BGR_ORDER;
+   break;
+   case DRM_FORMAT_ARGB:
+   val = LCD_LAYER_FORMAT_RGBA;
+   break;
+   case DRM_FORMAT_ABGR:
+   val = LCD_LAYER_FORMAT_RGBA | LCD_LAYER_BGR_ORDER;
+   break;
+   }
+   return val;
+}
+
+unsigned int set_bits_per_pixel(const struct drm_format_info *format)
+{
+   int i;
+   u32 bpp = 0;
+   unsigned int val = 0;
+
+   for (i = 0; i < format->num_planes; i++)
+   bpp += 8*format->cpp[i];
+
+   switch (bpp) {
+   case 8:
+   val = LCD_LAYER_8BPP;
+   break;
+   case 16:
+   val = LCD_LAYER_16BPP;
+   break;
+   case 24:
+   val = LCD_LAYER_24BPP;
+   break;
+   case 32:
+   val = LCD_LAYER_32BPP;
+   break;
+   }
+   return val;
+}
+
 static void kmb_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *state)
 {
@@ -44,7 +157,8 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
unsigned int dma_len;
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
unsigned int dma_cfg;
-   unsigned int c

[PATCH v2 14/59] drm/kmb: Correct address offsets for mipi registers

2020-07-14 Thread Anitha Chrisanthus
Mipi HS registers start at an additional offset of 0x400 which needs to be
added at the register macro definition and not at the read/write function
level.

v2: replaced calculations with macro to make code simpler
Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_dsi.c  |  16 +++---
 drivers/gpu/drm/kmb/kmb_regs.h | 116 -
 2 files changed, 75 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index a685a7a..a255210 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -423,20 +423,20 @@ static void mipi_tx_fg_cfg_regs(struct kmb_drm_private 
*dev_priv,
 *REG_VSYNC_WIDTH0: [15:0]-VSA for channel0, [31:16]-VSA for channel1
 *REG_VSYNC_WIDTH1: [15:0]-VSA for channel2, [31:16]-VSA for channel3
 */
-   offset = (frame_gen % 2) * 16;
-   reg_adr = MIPI_TXm_HS_VSYNC_WIDTHn(ctrl_no, frame_gen);
+   offset = (frame_gen % 2)*16;
+   reg_adr = MIPI_TXm_HS_VSYNC_WIDTHn(ctrl_no, frame_gen/2);
kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->vsync_width);
 
-   /*v backporch - same register config like vsync width */
-   reg_adr = MIPI_TXm_HS_V_BACKPORCHESn(ctrl_no, frame_gen);
+   /*v backporch - same register config like vsync width*/
+   reg_adr = MIPI_TXm_HS_V_BACKPORCHESn(ctrl_no, frame_gen/2);
kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->v_backporch);
 
-   /*v frontporch - same register config like vsync width */
-   reg_adr = MIPI_TXm_HS_V_FRONTPORCHESn(ctrl_no, frame_gen);
+   /*v frontporch - same register config like vsync width*/
+   reg_adr = MIPI_TXm_HS_V_FRONTPORCHESn(ctrl_no, frame_gen/2);
kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->v_frontporch);
 
-   /*v active - same register config like vsync width */
-   reg_adr = MIPI_TXm_HS_V_ACTIVEn(ctrl_no, frame_gen);
+   /*v active - same register config like vsync width*/
+   reg_adr = MIPI_TXm_HS_V_ACTIVEn(ctrl_no, frame_gen/2);
kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->v_active);
 
/*hsyc width */
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index 2d25c50..381e255 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -375,10 +375,10 @@
  *MIPI controller control register defines
  ***i/
 #define MIPI0_HS_BASE_ADDR (MIPI_BASE_ADDR + 0x400)
-#define MIPI_CTRL_HS_BASE_ADDR (0x400)
+#define HS_OFFSET(M)   ((M + 1) * 0x400)
 
 #define MIPI_TX_HS_CTRL(0x0)
-#define   MIPI_TXm_HS_CTRL(M)  (MIPI_TX_HS_CTRL + (0x400*M))
+#define   MIPI_TXm_HS_CTRL(M)  (MIPI_TX_HS_CTRL + HS_OFFSET(M))
 #define   HS_CTRL_EN   (1 << 0)
 #define   HS_CTRL_CSIDSIN  (1 << 2) /*1:CSI 0:DSI*/
 #define   TX_SOURCE(1 << 3) /*1:LCD, 0:DMA*/
@@ -391,7 +391,7 @@
 #define   HSCLKIDLE_CNT(1 << 24)
 #define MIPI_TX_HS_SYNC_CFG(0x8)
 #define   MIPI_TXm_HS_SYNC_CFG(M)  (MIPI_TX_HS_SYNC_CFG \
-   + (0x400*M))
+   + HS_OFFSET(M))
 #define   LINE_SYNC_PKT_ENABLE (1 << 0)
 #define   FRAME_COUNTER_ACTIVE (1 << 1)
 #define   LINE_COUNTER_ACTIVE  (1 << 2)
@@ -408,75 +408,93 @@
 #define   FRAME_GEN_EN(f)  ((f) << 23)
 #define   HACT_WAIT_STOP(f)((f) << 28)
 #define MIPI_TX0_HS_FG0_SECT0_PH   (0x40)
-#define MIPI_TXm_HS_FGn_SECTo_PH(M, N, O)  (MIPI_TX0_HS_FG0_SECT0_PH + \
-   (0x400*M) + (0x2C*N) + (8*O))
-#define MIPI_TX_SECT_WC_MASK (0x)
-#defineMIPI_TX_SECT_VC_MASK  (3)
-#define MIPI_TX_SECT_VC_SHIFT(22)
-#define MIPI_TX_SECT_DT_MASK (0x3f)
-#define MIPI_TX_SECT_DT_SHIFT(16)
-#define MIPI_TX_SECT_DM_MASK (3)
-#define MIPI_TX_SECT_DM_SHIFT(24)
-#define MIPI_TX_SECT_DMA_PACKED  (1<<26)
+#define   MIPI_TXm_HS_FGn_SECTo_PH(M, N, O)(MIPI_TX0_HS_FG0_SECT0_PH + \
+   HS_OFFSET(M) + (0x2C*N) + (8*O))
+#define   MIPI_TX_SECT_WC_MASK (0x)
+#define  MIPI_TX_SECT_VC_MASK  (3)
+#define   MIPI_TX_SECT_VC_SHIFT(22)
+#define   MIPI_TX_SECT_DT_MASK (0x3f)
+#define   MIPI_TX_SECT_DT_SHIFT(16)
+#define   MIPI_TX_SECT_DM_MASK (3)
+#define   MIPI_TX

[PATCH v2 08/59] drm/kmb: Added mipi_dsi_host initialization

2020-07-14 Thread Anitha Chrisanthus
Added mipi DSI host initialization functions

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/kmb_dsi.c | 59 +++
 drivers/gpu/drm/kmb/kmb_dsi.h |  4 +++
 2 files changed, 63 insertions(+)

diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 654fae8..d82411e 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -65,12 +65,59 @@ static const struct drm_connector_funcs 
kmb_dsi_connector_funcs = {
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 };
 
+static ssize_t kmb_dsi_host_transfer(struct mipi_dsi_host *host,
+const struct mipi_dsi_msg *msg)
+{
+   return 0;
+}
+
+static int kmb_dsi_host_attach(struct mipi_dsi_host *host,
+  struct mipi_dsi_device *dev)
+{
+   return 0;
+}
+
+static int kmb_dsi_host_detach(struct mipi_dsi_host *host,
+  struct mipi_dsi_device *dev)
+{
+   return 0;
+}
+
+static const struct mipi_dsi_host_ops kmb_dsi_host_ops = {
+   .attach = kmb_dsi_host_attach,
+   .detach = kmb_dsi_host_detach,
+   .transfer = kmb_dsi_host_transfer,
+};
+
+static struct kmb_dsi_host *kmb_dsi_host_init(struct kmb_dsi *kmb_dsi)
+{
+   struct kmb_dsi_host *host;
+   struct mipi_dsi_device *device;
+
+   host = kzalloc(sizeof(*host), GFP_KERNEL);
+   if (!host)
+   return NULL;
+
+   host->base.ops = &kmb_dsi_host_ops;
+   host->kmb_dsi = kmb_dsi;
+
+   device = kzalloc(sizeof(*device), GFP_KERNEL);
+   if (!device) {
+   kfree(host);
+   return NULL;
+   }
+   device->host = &host->base;
+   host->device = device;
+   return host;
+}
+
 void kmb_dsi_init(struct drm_device *dev)
 {
struct kmb_dsi *kmb_dsi;
struct drm_encoder *encoder;
struct kmb_connector *kmb_connector;
struct drm_connector *connector;
+   struct kmb_dsi_host *host;
 
kmb_dsi = kzalloc(sizeof(*kmb_dsi), GFP_KERNEL);
if (!kmb_dsi)
@@ -88,7 +135,19 @@ void kmb_dsi_init(struct drm_device *dev)
encoder = &kmb_dsi->base;
drm_encoder_init(dev, encoder, &kmb_dsi_funcs, DRM_MODE_ENCODER_DSI,
 "MIPI-DSI");
+
+   host = kmb_dsi_host_init(kmb_dsi);
+   if (!host) {
+   drm_encoder_cleanup(encoder);
+   kfree(kmb_dsi);
+   kfree(kmb_connector);
+   }
+
drm_connector_init(dev, connector, &kmb_dsi_connector_funcs,
   DRM_MODE_CONNECTOR_DSI);
drm_connector_helper_add(connector, &kmb_dsi_connector_helper_funcs);
+
+   connector->encoder = encoder;
+   drm_connector_attach_encoder(connector, encoder);
+
 }
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.h b/drivers/gpu/drm/kmb/kmb_dsi.h
index 9a6b0b7..0f5da87 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.h
+++ b/drivers/gpu/drm/kmb/kmb_dsi.h
@@ -12,19 +12,23 @@
 #include "kmb_drv.h"
 
 struct kmb_connector;
+struct kmb_dsi_host;
 
 struct kmb_dsi {
struct drm_encoder base;
struct kmb_connector *attached_connector;
+   struct kmb_dsi_host *dsi_host;
 };
 
 struct kmb_dsi_host {
struct mipi_dsi_host base;
struct kmb_dsi *kmb_dsi;
+   struct mipi_dsi_device *device;
 };
 
 struct kmb_connector {
struct drm_connector base;
+   struct drm_encoder *encoder;
struct drm_display_mode *fixed_mode;
 };
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 06/59] drm/kmb: Initial check-in for Mipi DSI

2020-07-14 Thread Anitha Chrisanthus
Basic frame work for mipi encoder and connector.
More hardware specific details will be added in the future commits.

Signed-off-by: Anitha Chrisanthus 
Reviewed-by: Bob Paauwe 
---
 drivers/gpu/drm/kmb/Makefile  |  2 +-
 drivers/gpu/drm/kmb/kmb_drv.c |  2 +
 drivers/gpu/drm/kmb/kmb_dsi.c | 94 +++
 drivers/gpu/drm/kmb/kmb_dsi.h | 38 +
 4 files changed, 135 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/kmb/kmb_dsi.c
 create mode 100644 drivers/gpu/drm/kmb/kmb_dsi.h

diff --git a/drivers/gpu/drm/kmb/Makefile b/drivers/gpu/drm/kmb/Makefile
index be9f19c..8102bc9 100644
--- a/drivers/gpu/drm/kmb/Makefile
+++ b/drivers/gpu/drm/kmb/Makefile
@@ -1,2 +1,2 @@
-kmb-display-y := kmb_crtc.o kmb_drv.o kmb_plane.o
+kmb-display-y := kmb_crtc.o kmb_drv.o kmb_plane.o kmb_dsi.o
 obj-$(CONFIG_DRM_KMB_DISPLAY)  += kmb-display.o
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 11f8d1f..aec8a5b 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -25,6 +25,7 @@
 #include 
 #include "kmb_crtc.h"
 #include "kmb_drv.h"
+#include "kmb_dsi.h"
 #include "kmb_plane.h"
 #include "kmb_regs.h"
 
@@ -63,6 +64,7 @@ static int kmb_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}
 
+   kmb_dsi_init(drm);
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n");
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
new file mode 100644
index 000..654fae8
--- /dev/null
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright © 2019-2020 Intel Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "kmb_drv.h"
+#include "kmb_dsi.h"
+
+static enum drm_mode_status
+kmb_dsi_mode_valid(struct drm_connector *connector,
+  struct drm_display_mode *mode)
+{
+   return MODE_OK;
+}
+
+static int kmb_dsi_get_modes(struct drm_connector *connector)
+{
+   struct drm_display_mode *mode;
+   struct kmb_connector *kmb_connector = to_kmb_connector(connector);
+
+   mode = drm_mode_duplicate(connector->dev, kmb_connector->fixed_mode);
+   drm_mode_probed_add(connector, mode);
+   return 1;
+}
+
+static void kmb_dsi_connector_destroy(struct drm_connector *connector)
+{
+   struct kmb_connector *kmb_connector = to_kmb_connector(connector);
+
+   drm_connector_cleanup(connector);
+   kfree(kmb_connector);
+}
+
+static void kmb_dsi_encoder_destroy(struct drm_encoder *encoder)
+{
+   struct kmb_dsi *kmb_dsi = to_kmb_dsi(encoder);
+
+   drm_encoder_cleanup(encoder);
+   kfree(kmb_dsi);
+}
+
+static const struct drm_encoder_funcs kmb_dsi_funcs = {
+   .destroy = kmb_dsi_encoder_destroy,
+};
+
+static const struct
+drm_connector_helper_funcs kmb_dsi_connector_helper_funcs = {
+   .get_modes = kmb_dsi_get_modes,
+   .mode_valid = kmb_dsi_mode_valid,
+};
+
+static const struct drm_connector_funcs kmb_dsi_connector_funcs = {
+   .destroy = kmb_dsi_connector_destroy,
+   .fill_modes = drm_helper_probe_single_connector_modes,
+   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+};
+
+void kmb_dsi_init(struct drm_device *dev)
+{
+   struct kmb_dsi *kmb_dsi;
+   struct drm_encoder *encoder;
+   struct kmb_connector *kmb_connector;
+   struct drm_connector *connector;
+
+   kmb_dsi = kzalloc(sizeof(*kmb_dsi), GFP_KERNEL);
+   if (!kmb_dsi)
+   return;
+
+   kmb_connector = kzalloc(sizeof(*kmb_connector), GFP_KERNEL);
+   if (!kmb_connector) {
+   kfree(kmb_dsi);
+   return;
+   }
+
+   kmb_dsi->attached_connector = kmb_connector;
+
+   connector = &kmb_connector->base;
+   encoder = &kmb_dsi->base;
+   drm_encoder_init(dev, encoder, &kmb_dsi_funcs, DRM_MODE_ENCODER_DSI,
+"MIPI-DSI");
+   drm_connector_init(dev, connector, &kmb_dsi_connector_funcs,
+  DRM_MODE_CONNECTOR_DSI);
+   drm_connector_helper_add(connector, &kmb_dsi_connector_helper_funcs);
+}
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.h b/drivers/gpu/drm/kmb/kmb_dsi.h
new file mode 100644
index 000..9a6b0b7
--- /dev/null
+++ b/drivers/gpu/drm/kmb/kmb_dsi.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright © 2019-2020 Intel Corporation
+ */
+
+#ifndef __KMB_DSI_H__
+#define __KMB_DSI_H__
+
+#include 
+#include 
+#include 
+#include "kmb_drv.h"
+
+struct kmb_connector;
+
+struct kmb_dsi {
+   struct drm_encoder base;
+   struct kmb_connector *attached_connector;
+};
+
+struct kmb_dsi_host {
+   struct mipi_dsi_host base;
+   struct k

Re: [PATCH 3/3] dma-buf/selftests: Add locking selftests for sw_sync

2020-07-14 Thread Bas Nieuwenhuizen
Awsome, thanks for adding the tests!

Got to say I'm not that familiar with the self-test framework idioms,
but from my perspective patches 2 and 3 are

Reviewed-by: Bas Nieuwenhuizen 

as well.

On Tue, Jul 14, 2020 at 10:06 PM Chris Wilson  wrote:
>
> While sw_sync is purely a debug facility for userspace to create fences
> and timelines it can control, nevertheless it has some tricky locking
> semantics of its own. In particular, Bas Nieuwenhuize reported that we
> had reintroduced a deadlock if a signal callback attempted to destroy
> the fence. So let's add a few trivial selftests to make sure that once
> fixed again, it stays fixed.
>
> Signed-off-by: Chris Wilson 
> Cc: Bas Nieuwenhuizen 
> ---
>  drivers/dma-buf/Makefile |   3 +-
>  drivers/dma-buf/selftests.h  |   1 +
>  drivers/dma-buf/st-sw_sync.c | 279 +++
>  drivers/dma-buf/sw_sync.c|  39 +
>  drivers/dma-buf/sync_debug.h |   8 +
>  5 files changed, 329 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/dma-buf/st-sw_sync.c
>
> diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> index 995e05f609ff..9be4d4611609 100644
> --- a/drivers/dma-buf/Makefile
> +++ b/drivers/dma-buf/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_UDMABUF) += udmabuf.o
>  dmabuf_selftests-y := \
> selftest.o \
> st-dma-fence.o \
> -   st-dma-fence-chain.o
> +   st-dma-fence-chain.o \
> +   st-sw_sync.o
>
>  obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
> diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
> index bc8cea67bf1e..232499a24872 100644
> --- a/drivers/dma-buf/selftests.h
> +++ b/drivers/dma-buf/selftests.h
> @@ -12,3 +12,4 @@
>  selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
>  selftest(dma_fence, dma_fence)
>  selftest(dma_fence_chain, dma_fence_chain)
> +selftest(sw_sync, sw_sync)
> diff --git a/drivers/dma-buf/st-sw_sync.c b/drivers/dma-buf/st-sw_sync.c
> new file mode 100644
> index ..3a21e7717df7
> --- /dev/null
> +++ b/drivers/dma-buf/st-sw_sync.c
> @@ -0,0 +1,279 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "sync_debug.h"
> +#include "selftest.h"
> +
> +static int sanitycheck(void *arg)
> +{
> +   struct sync_timeline *tl;
> +   struct dma_fence *f;
> +   int err = -ENOMEM;
> +
> +   /* Quick check we can create the timeline and syncpt */
> +
> +   tl = st_sync_timeline_create("mock");
> +   if (!tl)
> +   return -ENOMEM;
> +
> +   f = st_sync_pt_create(tl, 1);
> +   if (!f)
> +   goto out;
> +
> +   dma_fence_signal(f);
> +   dma_fence_put(f);
> +
> +   err = 0;
> +out:
> +   st_sync_timeline_put(tl);
> +   return 0;
> +}
> +
> +static int signal(void *arg)
> +{
> +   struct sync_timeline *tl;
> +   struct dma_fence *f;
> +   int err = -EINVAL;
> +
> +   /* Check that the syncpt fence is signaled when the timeline advances 
> */
> +
> +   tl = st_sync_timeline_create("mock");
> +   if (!tl)
> +   return -ENOMEM;
> +
> +   f = st_sync_pt_create(tl, 1);
> +   if (!f) {
> +   err = -ENOMEM;
> +   goto out;
> +   }
> +
> +   if (dma_fence_is_signaled(f)) {
> +   pr_err("syncpt:%lld signaled too early\n", f->seqno);
> +   goto out_fence;
> +   }
> +
> +   st_sync_timeline_signal(tl, 1);
> +
> +   if (!dma_fence_is_signaled(f)) {
> +   pr_err("syncpt:%lld not signaled after increment\n", 
> f->seqno);
> +   goto out_fence;
> +   }
> +
> +   err = 0;
> +out_fence:
> +   dma_fence_signal(f);
> +   dma_fence_put(f);
> +out:
> +   st_sync_timeline_put(tl);
> +   return 0;
> +}
> +
> +struct cb_destroy {
> +   struct dma_fence_cb cb;
> +   struct dma_fence *f;
> +};
> +
> +static void cb_destroy(struct dma_fence *fence, struct dma_fence_cb *_cb)
> +{
> +   struct cb_destroy *cb = container_of(_cb, typeof(*cb), cb);
> +
> +   pr_info("syncpt:%llx destroying syncpt:%llx\n",
> +   fence->seqno, cb->f->seqno);
> +   dma_fence_put(cb->f);
> +   cb->f = NULL;
> +}
> +
> +static int cb_autodestroy(void *arg)
> +{
> +   struct sync_timeline *tl;
> +   struct cb_destroy cb;
> +   int err = -EINVAL;
> +
> +   /* Check that we can drop the final syncpt reference from a callback 
> */
> +
> +   tl = st_sync_timeline_create("mock");
> +   if (!tl)
> +   return -ENOMEM;
> +
> +   cb.f = st_sync_pt_create(tl, 1);
> +   if (!cb.f) {
> +   err = -ENOMEM;
> +   goto out;
> +   }
> +
> +   if (dma_fence_add_callback(cb.f, &cb.cb, cb_destroy)) {
> +   pr_err("syncpt:%lld signaled before increment\n", 
> cb.f->seqn

Re: [PATCH 1/3] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Bas Nieuwenhuizen
Thanks for updating the patch. LGTM

On Tue, Jul 14, 2020 at 10:07 PM Chris Wilson  wrote:
>
> From: Bas Nieuwenhuizen 
>
> Calltree:
>   timeline_fence_release
>   drm_sched_entity_wakeup
>   dma_fence_signal_locked
>   sync_timeline_signal
>   sw_sync_ioctl
>
> Releasing the reference to the fence in the fence signal callback
> seems reasonable to me, so this patch avoids the locking issue in
> sw_sync.
>
> d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
> fixed the recursive locking issue but caused an use-after-free. Later
> d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> fixed the use-after-free but reintroduced the recursive locking issue.
>
> In this attempt we avoid the use-after-free still because the release
> function still always locks, and outside of the locking region in the
> signal function we have properly refcounted references.
>
> We furthermore also avoid the recurive lock by making sure that either:
>
> 1) We have a properly refcounted reference, preventing the signal from
>triggering the release function inside the locked region.
> 2) The refcount was already zero, and hence nobody will be able to trigger
>the release function from the signal function.
>
> v2: Move dma_fence_signal() into second loop in preparation to moving
> the callback out of the timeline obj->lock.
>
> Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> Cc: Sumit Semwal 
> Cc: Chris Wilson 
> Cc: Gustavo Padovan 
> Cc: Christian König 
> Cc: 
> Signed-off-by: Bas Nieuwenhuizen 
> Signed-off-by: Chris Wilson 
> ---
>  drivers/dma-buf/sw_sync.c | 32 ++--
>  1 file changed, 22 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
> index 348b3a9170fa..807c82148062 100644
> --- a/drivers/dma-buf/sw_sync.c
> +++ b/drivers/dma-buf/sw_sync.c
> @@ -192,6 +192,7 @@ static const struct dma_fence_ops timeline_fence_ops = {
>  static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
>  {
> struct sync_pt *pt, *next;
> +   LIST_HEAD(signal);
>
> trace_sync_timeline(obj);
>
> @@ -203,21 +204,32 @@ static void sync_timeline_signal(struct sync_timeline 
> *obj, unsigned int inc)
> if (!timeline_fence_signaled(&pt->base))
> break;
>
> -   list_del_init(&pt->link);
> -   rb_erase(&pt->node, &obj->pt_tree);
> -
> /*
> -* A signal callback may release the last reference to this
> -* fence, causing it to be freed. That operation has to be
> -* last to avoid a use after free inside this loop, and must
> -* be after we remove the fence from the timeline in order to
> -* prevent deadlocking on timeline->lock inside
> -* timeline_fence_release().
> +* We need to take a reference to avoid a release during
> +* signalling (which can cause a recursive lock of obj->lock).
> +* If refcount was already zero, another thread is already
> +* taking care of destroying the fence.
>  */
> -   dma_fence_signal_locked(&pt->base);
> +   if (!dma_fence_get_rcu(&pt->base))
> +   continue;
> +
> +   list_move_tail(&pt->link, &signal);
> +   rb_erase(&pt->node, &obj->pt_tree);
> }
>
> spin_unlock_irq(&obj->lock);
> +
> +   list_for_each_entry_safe(pt, next, &signal, link) {
> +   /*
> +* This needs to be cleared before release, otherwise the
> +* timeline_fence_release function gets confused about also
> +* removing the fence from the pt_tree.
> +*/
> +   list_del_init(&pt->link);
> +
> +   dma_fence_signal(&pt->base);
> +   dma_fence_put(&pt->base);
> +   }
>  }
>
>  /**
> --
> 2.20.1
>
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2] dma-buf/sw_sync: Separate signal/timeline locks

2020-07-14 Thread Chris Wilson
Since we decouple the sync_pt from the timeline tree upon release, in
order to allow releasing the sync_pt from a signal callback we need to
separate the sync_pt signaling lock from the timeline tree lock.

v2: Mark up the unlocked read of the current timeline value.

Suggested-by: Bas Nieuwenhuizen 
Signed-off-by: Chris Wilson 
Cc: Bas Nieuwenhuizen 
---
 drivers/dma-buf/sw_sync.c| 33 -
 drivers/dma-buf/sync_debug.h |  2 ++
 2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 807c82148062..5851bf7076d0 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -132,24 +132,32 @@ static void timeline_fence_release(struct dma_fence 
*fence)
 {
struct sync_pt *pt = dma_fence_to_sync_pt(fence);
struct sync_timeline *parent = dma_fence_parent(fence);
-   unsigned long flags;
 
-   spin_lock_irqsave(fence->lock, flags);
if (!list_empty(&pt->link)) {
-   list_del(&pt->link);
-   rb_erase(&pt->node, &parent->pt_tree);
+   unsigned long flags;
+
+   spin_lock_irqsave(&parent->lock, flags);
+   if (!list_empty(&pt->link)) {
+   list_del(&pt->link);
+   rb_erase(&pt->node, &parent->pt_tree);
+   }
+   spin_unlock_irqrestore(&parent->lock, flags);
}
-   spin_unlock_irqrestore(fence->lock, flags);
 
sync_timeline_put(parent);
dma_fence_free(fence);
 }
 
-static bool timeline_fence_signaled(struct dma_fence *fence)
+static int timeline_value(struct dma_fence *fence)
 {
-   struct sync_timeline *parent = dma_fence_parent(fence);
+   return READ_ONCE(dma_fence_parent(fence)->value);
+}
 
-   return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops);
+static bool timeline_fence_signaled(struct dma_fence *fence)
+{
+   return !__dma_fence_is_later(fence->seqno,
+timeline_value(fence),
+fence->ops);
 }
 
 static bool timeline_fence_enable_signaling(struct dma_fence *fence)
@@ -166,9 +174,7 @@ static void timeline_fence_value_str(struct dma_fence 
*fence,
 static void timeline_fence_timeline_value_str(struct dma_fence *fence,
 char *str, int size)
 {
-   struct sync_timeline *parent = dma_fence_parent(fence);
-
-   snprintf(str, size, "%d", parent->value);
+   snprintf(str, size, "%d", timeline_value(fence));
 }
 
 static const struct dma_fence_ops timeline_fence_ops = {
@@ -252,12 +258,13 @@ static struct sync_pt *sync_pt_create(struct 
sync_timeline *obj,
return NULL;
 
sync_timeline_get(obj);
-   dma_fence_init(&pt->base, &timeline_fence_ops, &obj->lock,
+   spin_lock_init(&pt->lock);
+   dma_fence_init(&pt->base, &timeline_fence_ops, &pt->lock,
   obj->context, value);
INIT_LIST_HEAD(&pt->link);
 
spin_lock_irq(&obj->lock);
-   if (!dma_fence_is_signaled_locked(&pt->base)) {
+   if (!dma_fence_is_signaled(&pt->base)) {
struct rb_node **p = &obj->pt_tree.rb_node;
struct rb_node *parent = NULL;
 
diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h
index 6176e52ba2d7..fd073fc32329 100644
--- a/drivers/dma-buf/sync_debug.h
+++ b/drivers/dma-buf/sync_debug.h
@@ -55,11 +55,13 @@ static inline struct sync_timeline *dma_fence_parent(struct 
dma_fence *fence)
  * @base: base fence object
  * @link: link on the sync timeline's list
  * @node: node in the sync timeline's tree
+ * @lock: fence signaling lock
  */
 struct sync_pt {
struct dma_fence base;
struct list_head link;
struct rb_node node;
+   spinlock_t lock;
 };
 
 extern const struct file_operations sw_sync_debugfs_fops;
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 3/3] dma-buf/selftests: Add locking selftests for sw_sync

2020-07-14 Thread Chris Wilson
While sw_sync is purely a debug facility for userspace to create fences
and timelines it can control, nevertheless it has some tricky locking
semantics of its own. In particular, Bas Nieuwenhuize reported that we
had reintroduced a deadlock if a signal callback attempted to destroy
the fence. So let's add a few trivial selftests to make sure that once
fixed again, it stays fixed.

Signed-off-by: Chris Wilson 
Cc: Bas Nieuwenhuizen 
---
 drivers/dma-buf/Makefile |   3 +-
 drivers/dma-buf/selftests.h  |   1 +
 drivers/dma-buf/st-sw_sync.c | 279 +++
 drivers/dma-buf/sw_sync.c|  39 +
 drivers/dma-buf/sync_debug.h |   8 +
 5 files changed, 329 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma-buf/st-sw_sync.c

diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 995e05f609ff..9be4d4611609 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_UDMABUF) += udmabuf.o
 dmabuf_selftests-y := \
selftest.o \
st-dma-fence.o \
-   st-dma-fence-chain.o
+   st-dma-fence-chain.o \
+   st-sw_sync.o
 
 obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
index bc8cea67bf1e..232499a24872 100644
--- a/drivers/dma-buf/selftests.h
+++ b/drivers/dma-buf/selftests.h
@@ -12,3 +12,4 @@
 selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
 selftest(dma_fence, dma_fence)
 selftest(dma_fence_chain, dma_fence_chain)
+selftest(sw_sync, sw_sync)
diff --git a/drivers/dma-buf/st-sw_sync.c b/drivers/dma-buf/st-sw_sync.c
new file mode 100644
index ..3a21e7717df7
--- /dev/null
+++ b/drivers/dma-buf/st-sw_sync.c
@@ -0,0 +1,279 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "sync_debug.h"
+#include "selftest.h"
+
+static int sanitycheck(void *arg)
+{
+   struct sync_timeline *tl;
+   struct dma_fence *f;
+   int err = -ENOMEM;
+
+   /* Quick check we can create the timeline and syncpt */
+
+   tl = st_sync_timeline_create("mock");
+   if (!tl)
+   return -ENOMEM;
+
+   f = st_sync_pt_create(tl, 1);
+   if (!f)
+   goto out;
+
+   dma_fence_signal(f);
+   dma_fence_put(f);
+
+   err = 0;
+out:
+   st_sync_timeline_put(tl);
+   return 0;
+}
+
+static int signal(void *arg)
+{
+   struct sync_timeline *tl;
+   struct dma_fence *f;
+   int err = -EINVAL;
+
+   /* Check that the syncpt fence is signaled when the timeline advances */
+
+   tl = st_sync_timeline_create("mock");
+   if (!tl)
+   return -ENOMEM;
+
+   f = st_sync_pt_create(tl, 1);
+   if (!f) {
+   err = -ENOMEM;
+   goto out;
+   }
+
+   if (dma_fence_is_signaled(f)) {
+   pr_err("syncpt:%lld signaled too early\n", f->seqno);
+   goto out_fence;
+   }
+
+   st_sync_timeline_signal(tl, 1);
+
+   if (!dma_fence_is_signaled(f)) {
+   pr_err("syncpt:%lld not signaled after increment\n", f->seqno);
+   goto out_fence;
+   }
+
+   err = 0;
+out_fence:
+   dma_fence_signal(f);
+   dma_fence_put(f);
+out:
+   st_sync_timeline_put(tl);
+   return 0;
+}
+
+struct cb_destroy {
+   struct dma_fence_cb cb;
+   struct dma_fence *f;
+};
+
+static void cb_destroy(struct dma_fence *fence, struct dma_fence_cb *_cb)
+{
+   struct cb_destroy *cb = container_of(_cb, typeof(*cb), cb);
+
+   pr_info("syncpt:%llx destroying syncpt:%llx\n",
+   fence->seqno, cb->f->seqno);
+   dma_fence_put(cb->f);
+   cb->f = NULL;
+}
+
+static int cb_autodestroy(void *arg)
+{
+   struct sync_timeline *tl;
+   struct cb_destroy cb;
+   int err = -EINVAL;
+
+   /* Check that we can drop the final syncpt reference from a callback */
+
+   tl = st_sync_timeline_create("mock");
+   if (!tl)
+   return -ENOMEM;
+
+   cb.f = st_sync_pt_create(tl, 1);
+   if (!cb.f) {
+   err = -ENOMEM;
+   goto out;
+   }
+
+   if (dma_fence_add_callback(cb.f, &cb.cb, cb_destroy)) {
+   pr_err("syncpt:%lld signaled before increment\n", cb.f->seqno);
+   goto out;
+   }
+
+   st_sync_timeline_signal(tl, 1);
+   if (cb.f) {
+   pr_err("syncpt:%lld callback not run\n", cb.f->seqno);
+   dma_fence_put(cb.f);
+   goto out;
+   }
+
+   err = 0;
+out:
+   st_sync_timeline_put(tl);
+   return 0;
+}
+
+static int cb_destroy_12(void *arg)
+{
+   struct sync_timeline *tl;
+   struct cb_destroy cb;
+   struct dma_fence *f;
+   int err = -EINVAL;
+
+   /* Check that we can drop some other syncpt reference from a callback */
+
+   t

[PATCH 2/3] dma-buf/sw_sync: Separate signal/timeline locks

2020-07-14 Thread Chris Wilson
Since we decouple the sync_pt from the timeline tree upon release, in
order to allow releasing the sync_pt from a signal callback we need to
separate the sync_pt signaling lock from the timeline tree lock.

Suggested-by: Bas Nieuwenhuizen 
Signed-off-by: Chris Wilson 
Cc: Bas Nieuwenhuizen 
---
 drivers/dma-buf/sw_sync.c| 18 +++---
 drivers/dma-buf/sync_debug.h |  2 ++
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 807c82148062..116dad6c7905 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -132,14 +132,17 @@ static void timeline_fence_release(struct dma_fence 
*fence)
 {
struct sync_pt *pt = dma_fence_to_sync_pt(fence);
struct sync_timeline *parent = dma_fence_parent(fence);
-   unsigned long flags;
 
-   spin_lock_irqsave(fence->lock, flags);
if (!list_empty(&pt->link)) {
-   list_del(&pt->link);
-   rb_erase(&pt->node, &parent->pt_tree);
+   unsigned long flags;
+
+   spin_lock_irqsave(&parent->lock, flags);
+   if (!list_empty(&pt->link)) {
+   list_del(&pt->link);
+   rb_erase(&pt->node, &parent->pt_tree);
+   }
+   spin_unlock_irqrestore(&parent->lock, flags);
}
-   spin_unlock_irqrestore(fence->lock, flags);
 
sync_timeline_put(parent);
dma_fence_free(fence);
@@ -252,12 +255,13 @@ static struct sync_pt *sync_pt_create(struct 
sync_timeline *obj,
return NULL;
 
sync_timeline_get(obj);
-   dma_fence_init(&pt->base, &timeline_fence_ops, &obj->lock,
+   spin_lock_init(&pt->lock);
+   dma_fence_init(&pt->base, &timeline_fence_ops, &pt->lock,
   obj->context, value);
INIT_LIST_HEAD(&pt->link);
 
spin_lock_irq(&obj->lock);
-   if (!dma_fence_is_signaled_locked(&pt->base)) {
+   if (!dma_fence_is_signaled(&pt->base)) {
struct rb_node **p = &obj->pt_tree.rb_node;
struct rb_node *parent = NULL;
 
diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h
index 6176e52ba2d7..fd073fc32329 100644
--- a/drivers/dma-buf/sync_debug.h
+++ b/drivers/dma-buf/sync_debug.h
@@ -55,11 +55,13 @@ static inline struct sync_timeline *dma_fence_parent(struct 
dma_fence *fence)
  * @base: base fence object
  * @link: link on the sync timeline's list
  * @node: node in the sync timeline's tree
+ * @lock: fence signaling lock
  */
 struct sync_pt {
struct dma_fence base;
struct list_head link;
struct rb_node node;
+   spinlock_t lock;
 };
 
 extern const struct file_operations sw_sync_debugfs_fops;
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/3] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Chris Wilson
From: Bas Nieuwenhuizen 

Calltree:
  timeline_fence_release
  drm_sched_entity_wakeup
  dma_fence_signal_locked
  sync_timeline_signal
  sw_sync_ioctl

Releasing the reference to the fence in the fence signal callback
seems reasonable to me, so this patch avoids the locking issue in
sw_sync.

d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
fixed the recursive locking issue but caused an use-after-free. Later
d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
fixed the use-after-free but reintroduced the recursive locking issue.

In this attempt we avoid the use-after-free still because the release
function still always locks, and outside of the locking region in the
signal function we have properly refcounted references.

We furthermore also avoid the recurive lock by making sure that either:

1) We have a properly refcounted reference, preventing the signal from
   triggering the release function inside the locked region.
2) The refcount was already zero, and hence nobody will be able to trigger
   the release function from the signal function.

v2: Move dma_fence_signal() into second loop in preparation to moving
the callback out of the timeline obj->lock.

Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
Cc: Sumit Semwal 
Cc: Chris Wilson 
Cc: Gustavo Padovan 
Cc: Christian König 
Cc: 
Signed-off-by: Bas Nieuwenhuizen 
Signed-off-by: Chris Wilson 
---
 drivers/dma-buf/sw_sync.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 348b3a9170fa..807c82148062 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -192,6 +192,7 @@ static const struct dma_fence_ops timeline_fence_ops = {
 static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
 {
struct sync_pt *pt, *next;
+   LIST_HEAD(signal);
 
trace_sync_timeline(obj);
 
@@ -203,21 +204,32 @@ static void sync_timeline_signal(struct sync_timeline 
*obj, unsigned int inc)
if (!timeline_fence_signaled(&pt->base))
break;
 
-   list_del_init(&pt->link);
-   rb_erase(&pt->node, &obj->pt_tree);
-
/*
-* A signal callback may release the last reference to this
-* fence, causing it to be freed. That operation has to be
-* last to avoid a use after free inside this loop, and must
-* be after we remove the fence from the timeline in order to
-* prevent deadlocking on timeline->lock inside
-* timeline_fence_release().
+* We need to take a reference to avoid a release during
+* signalling (which can cause a recursive lock of obj->lock).
+* If refcount was already zero, another thread is already
+* taking care of destroying the fence.
 */
-   dma_fence_signal_locked(&pt->base);
+   if (!dma_fence_get_rcu(&pt->base))
+   continue;
+
+   list_move_tail(&pt->link, &signal);
+   rb_erase(&pt->node, &obj->pt_tree);
}
 
spin_unlock_irq(&obj->lock);
+
+   list_for_each_entry_safe(pt, next, &signal, link) {
+   /*
+* This needs to be cleared before release, otherwise the
+* timeline_fence_release function gets confused about also
+* removing the fence from the pt_tree.
+*/
+   list_del_init(&pt->link);
+
+   dma_fence_signal(&pt->base);
+   dma_fence_put(&pt->base);
+   }
 }
 
 /**
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Chris Wilson
Quoting Chris Wilson (2020-07-14 19:30:39)
> Quoting Bas Nieuwenhuizen (2020-07-14 19:17:21)
> > On Tue, Jul 14, 2020 at 6:26 PM Chris Wilson  
> > wrote:
> > >
> > > Quoting Bas Nieuwenhuizen (2020-07-14 16:41:02)
> > > > Calltree:
> > > >   timeline_fence_release
> > > >   drm_sched_entity_wakeup
> > > >   dma_fence_signal_locked
> > > >   sync_timeline_signal
> > > >   sw_sync_ioctl
> > > >
> > > > Releasing the reference to the fence in the fence signal callback
> > > > seems reasonable to me, so this patch avoids the locking issue in
> > > > sw_sync.
> > > >
> > > > d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
> > > > fixed the recursive locking issue but caused an use-after-free. Later
> > > > d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> > > > fixed the use-after-free but reintroduced the recursive locking issue.
> > > >
> > > > In this attempt we avoid the use-after-free still because the release
> > > > function still always locks, and outside of the locking region in the
> > > > signal function we have properly refcounted references.
> > > >
> > > > We furthermore also avoid the recurive lock by making sure that either:
> > > >
> > > > 1) We have a properly refcounted reference, preventing the signal from
> > > >triggering the release function inside the locked region.
> > > > 2) The refcount was already zero, and hence nobody will be able to 
> > > > trigger
> > > >the release function from the signal function.
> > > >
> > > > Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt 
> > > > free")
> > > > Cc: Sumit Semwal 
> > > > Cc: Chris Wilson 
> > > > Cc: Gustavo Padovan 
> > > > Cc: Christian König 
> > > > Cc: 
> > > > Signed-off-by: Bas Nieuwenhuizen 
> > > > ---
> > > >  drivers/dma-buf/sw_sync.c | 28 
> > > >  1 file changed, 20 insertions(+), 8 deletions(-)
> > > >
> > > > diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
> > > > index 348b3a9170fa..30a482f75d56 100644
> > > > --- a/drivers/dma-buf/sw_sync.c
> > > > +++ b/drivers/dma-buf/sw_sync.c
> > > > @@ -192,9 +192,12 @@ static const struct dma_fence_ops 
> > > > timeline_fence_ops = {
> > > >  static void sync_timeline_signal(struct sync_timeline *obj, unsigned 
> > > > int inc)
> > > >  {
> > > > struct sync_pt *pt, *next;
> > > > +   struct list_head ref_list;
> > > >
> > > > trace_sync_timeline(obj);
> > > >
> > > > +   INIT_LIST_HEAD(&ref_list);
> > > > +
> > > > spin_lock_irq(&obj->lock);
> > > >
> > > > obj->value += inc;
> > > > @@ -206,18 +209,27 @@ static void sync_timeline_signal(struct 
> > > > sync_timeline *obj, unsigned int inc)
> > > > list_del_init(&pt->link);
> > > > rb_erase(&pt->node, &obj->pt_tree);
> > > >
> > > > -   /*
> > > > -* A signal callback may release the last reference to 
> > > > this
> > > > -* fence, causing it to be freed. That operation has to 
> > > > be
> > > > -* last to avoid a use after free inside this loop, and 
> > > > must
> > > > -* be after we remove the fence from the timeline in 
> > > > order to
> > > > -* prevent deadlocking on timeline->lock inside
> > > > -* timeline_fence_release().
> > > > -*/
> > > > +   /* We need to take a reference to avoid a release during
> > > > +* signalling (which can cause a recursive lock of 
> > > > obj->lock).
> > > > +* If refcount was already zero, another thread is 
> > > > already taking
> > > > +* care of destructing the fence, so the signal cannot 
> > > > release
> > > > +* it again and we hence will not have the recursive 
> > > > lock. */
> > >
> > > /*
> > >  * Block commentary style:
> > >  * 
> > > https://www.kernel.org/doc/html/latest/process/coding-style.html#commenting
> > >  */
> > >
> > > > +   if (dma_fence_get_rcu(&pt->base))
> > > > +   list_add_tail(&pt->link, &ref_list);
> > >
> > > Ok.
> > >
> > > > +
> > > > dma_fence_signal_locked(&pt->base);
> > > > }
> > > >
> > > > spin_unlock_irq(&obj->lock);
> > > > +
> > > > +   list_for_each_entry_safe(pt, next, &ref_list, link) {
> > > > +   /* This needs to be cleared before release, otherwise 
> > > > the
> > > > +* timeline_fence_release function gets confused about 
> > > > also
> > > > +* removing the fence from the pt_tree. */
> > > > +   list_del_init(&pt->link);
> > > > +
> > > > +   dma_fence_put(&pt->base);
> > > > +   }
> > >
> > > How serious is the problem of one fence callback freeing another pt?
> > >
> > > Following the pattern here
> > >
> > > spin_lock(&obj->lock);
> > > list_for_each_entry_safe(pt, next, &obj->pt_list, link)

Re: [PATCH v3 0/6] Generic USB Display driver

2020-07-14 Thread Peter Stuge
Noralf Trønnes wrote:
> > In all cases, the driver on the host knows/has available how many bytes
> > were successfully transfered.
> 
> I was thinking about the device, that it could get out of sync. Let's
> say the host sends a 1k framebuffer and half of it gets transferred and
> the rest fails for some reason. Lubomir's MCU implementation has an
> endpoint max size of 64 bytes and a callback is called for each packet.
> If the 1k transfer fails at some point, will the device be able to
> detect this and know that the next time the rx callback is called that
> this is the start of a new framebuffer update?

Ah! No, a device can not detect that the host intended to send more (bulk)
packets but e.g. timed out.

I can't immediately think of other reasons for a larger transfer to fail,
which still allow communication to continue.

When the host recognizes a timeout with partial data transfer it could
simply send the remaining data in a new transfer.


While the device can not detect host intent, the protocol could allow
devices to specify requirements, e.g. that the host always sends full frames.

In any case, please avoid making a control request mandatory for frame
transfer.

Because control requests are scheduled differently onto the wire and
because they consist of more packets than bulk data, a control request
will interrupt a bulk data stream and likely introduce unneccessary latency.

If synchronization is always required then I'd suggest to place it inline
with frame data, e.g. in the first packet byte.

If synchronization is only required in rare cases then a control transfer
is probably the better choice, to not waste any inline bytes.

But the optimum would be that the device can describe its needs to the host
and the host driver ensures that the device always receives the data it needs.

Do you think this is possible?


Kind regards

//Peter
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3 0/6] Generic USB Display driver

2020-07-14 Thread Noralf Trønnes


Den 14.07.2020 19.40, skrev Peter Stuge:
> Hi Noralf,
> 
> Noralf Trønnes wrote:
>> I would like to keep the SET_BUFFER request since it will serve as a
>> syncing point between the host and the device. I'm no USB expert but I
>> assume that a bulk transfer can fail halfway through and result in the
>> next update starting where the previous one failed and thus writing
>> beyond the end of the display buffer.
> 
> Transfers either succeed completely (possibly after many retries),
> time out (after zero or more transfered bytes) or fail catastrophically
> (e.g. from device disconnect).
> 
> In all cases, the driver on the host knows/has available how many bytes
> were successfully transfered.
> 

I was thinking about the device, that it could get out of sync. Let's
say the host sends a 1k framebuffer and half of it gets transferred and
the rest fails for some reason. Lubomir's MCU implementation has an
endpoint max size of 64 bytes and a callback is called for each packet.
If the 1k transfer fails at some point, will the device be able to
detect this and know that the next time the rx callback is called that
this is the start of a new framebuffer update?

Noralf.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/vkms: add wait_for_vblanks in atomic_commit_tail

2020-07-14 Thread Melissa Wen
On 07/14, Daniel Vetter wrote:
> On Tue, Jul 14, 2020 at 07:39:42AM -0300, Melissa Wen wrote:
> > On Tue, Jul 14, 2020 at 7:20 AM Melissa Wen  wrote:
> > >
> > > On 07/13, Daniel Vetter wrote:
> > > > On Fri, Jul 10, 2020 at 02:05:33PM -0300, Melissa Wen wrote:
> > > > > On 07/02, Daniel Vetter wrote:
> > > > > > On Wed, Jul 01, 2020 at 03:31:34PM +, Sidong Yang wrote:
> > > > > > > there is an error when igt test is run continuously. 
> > > > > > > vkms_atomic_commit_tail()
> > > > > > > need to call drm_atomic_helper_wait_for_vblanks() for give up 
> > > > > > > ownership of
> > > > > > > vblank events. without this code, next atomic commit will not 
> > > > > > > enable vblank
> > > > > > > and raise timeout error.
> > > > > > >
> > > > > > > Signed-off-by: Sidong Yang 
> > > > > > > ---
> > > > > > >  drivers/gpu/drm/vkms/vkms_drv.c | 2 ++
> > > > > > >  1 file changed, 2 insertions(+)
> > > > > > >
> > > > > > > diff --git a/drivers/gpu/drm/vkms/vkms_drv.c 
> > > > > > > b/drivers/gpu/drm/vkms/vkms_drv.c
> > > > > > > index 1e8b2169d834..10b9be67a068 100644
> > > > > > > --- a/drivers/gpu/drm/vkms/vkms_drv.c
> > > > > > > +++ b/drivers/gpu/drm/vkms/vkms_drv.c
> > > > > > > @@ -93,6 +93,8 @@ static void vkms_atomic_commit_tail(struct 
> > > > > > > drm_atomic_state *old_state)
> > > > > > > flush_work(&vkms_state->composer_work);
> > > > > > > }
> > > > > > >
> > > > > > > +   drm_atomic_helper_wait_for_vblanks(dev, old_state);
> > > > > >
> > > > > > Uh, we have a wait_for_flip_done right above, which should be doing
> > > > > > exactly the same, but more precisely: Instead of just waiting for 
> > > > > > any
> > > > > > vblank to happen, we wait for exactly the vblank corresponding to 
> > > > > > this
> > > > > > atomic commit. So no races possible. If this is papering over some 
> > > > > > issue,
> > > > > > then I think more debugging is needed.
> > > > > >
> > > > > > What exactly is going wrong here for you?
> > > > >
> > > > > Hi Daniel and Sidong,
> > > > >
> > > > > I noticed a similar issue when running the IGT test kms_cursor_crc. 
> > > > > For
> > > > > example, a subtest that passes on the first run (alpha-opaque) fails 
> > > > > on
> > > > > the second due to a kind of busy waiting in subtest preparation (the
> > > > > subtest fails before actually running).
> > > > >
> > > > > In addition, in the same test, the dpms subtest started to fail since
> > > > > the commit that change from wait_for_vblanks to wait_for_flip_done. By
> > > > > reverting this commit, the dpms subtest passes again and the 
> > > > > sequential
> > > > > subtests return to normal.
> > > > >
> > > > > I am trying to figure out what's missing from using flip_done op on
> > > > > vkms, since I am also interested in solving this problem and I
> > > > > understand that the change for flip_done has been discussed in the 
> > > > > past.
> > > > >
> > > > > Do you have any idea?
> > > >
> > > > Uh, not at all. This is indeed rather surprising ...
> > > >
> > > > What exactly is the failure mode when running a test the 2nd time? Full
> > > > igt logs might give me an idea. But yeah this is kinda surprising.
> > >
> > > Hi Daniel,
> > >
> > > This is the IGT log of the 2nd run of kms_cursor_crc/alpha-opaque:
> > >
> > > IGT-Version: 1.25-NO-GIT (x86_64) (Linux: 5.8.0-rc2-DRM+ x86_64)
> > > Force option used: Using driver vkms
> > > Starting subtest: pipe-A-cursor-alpha-opaque
> > > Timed out: Opening crc fd, and poll for first CRC.
> > > Subtest pipe-A-cursor-alpha-opaque failed.
> > >  DEBUG 
> > > (kms_cursor_crc:2317) igt_kms-DEBUG: display: Virtual-1: set_pipe(A)
> > > (kms_cursor_crc:2317) igt_kms-DEBUG: display: Virtual-1: Selecting pipe A
> > > (kms_cursor_crc:2317) igt_fb-DEBUG: 
> > > igt_create_fb_with_bo_size(width=1024, height=768, 
> > > format=XR24(0x34325258), modifier=0x0, size=0)
> > > (kms_cursor_crc:2317) igt_fb-DEBUG: igt_create_fb_with_bo_size(handle=1, 
> > > pitch=4096)
> > > (kms_cursor_crc:2317) igt_fb-DEBUG: Test requirement passed: 
> > > cairo_surface_status(fb->cairo_surface) == CAIRO_STATUS_SUCCESS
> > > (kms_cursor_crc:2317) igt_fb-DEBUG: 
> > > igt_create_fb_with_bo_size(width=1024, height=768, 
> > > format=XR24(0x34325258), modifier=0x0, size=0)
> > > (kms_cursor_crc:2317) igt_fb-DEBUG: igt_create_fb_with_bo_size(handle=2, 
> > > pitch=4096)
> > > (kms_cursor_crc:2317) igt_fb-DEBUG: Test requirement passed: 
> > > cairo_surface_status(fb->cairo_surface) == CAIRO_STATUS_SUCCESS
> > > (kms_cursor_crc:2317) igt_kms-DEBUG: Test requirement passed: plane_idx 
> > > >= 0 && plane_idx < pipe->n_planes
> > > (kms_cursor_crc:2317) igt_kms-DEBUG: Test requirement passed: plane_idx 
> > > >= 0 && plane_idx < pipe->n_planes
> > > (kms_cursor_crc:2317) igt_kms-DEBUG: display: A.0: plane_set_fb(37)
> > > (kms_cursor_crc:2317) igt_kms-DEBUG: display: A.0: plane_set_size 
> > > (1024x768)
> > > (kms_cursor_crc:2317) igt_kms-DEBUG: display: A.0: fb_set_position(0,

[PATCH][next] drm/rockchip: lvds: ensure ret is assigned before checking for an error

2020-07-14 Thread Colin King
From: Colin Ian King 

Currently there are two places where the return status in ret is being
checked for an error however the assignment of ret has been omitted
making the checks redundant.  Fix this by adding in the missing assignments
of ret.

Addresses-Coverity: ("Logically dead code")
Fixes: cca1705c3d89 ("drm/rockchip: lvds: Add PX30 support")
Signed-off-by: Colin Ian King 
---
 drivers/gpu/drm/rockchip/rockchip_lvds.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c 
b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 63f967902c2d..b45c618b9793 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -499,11 +499,11 @@ static int px30_lvds_probe(struct platform_device *pdev,
if (IS_ERR(lvds->dphy))
return PTR_ERR(lvds->dphy);
 
-   phy_init(lvds->dphy);
+   ret = phy_init(lvds->dphy);
if (ret)
return ret;
 
-   phy_set_mode(lvds->dphy, PHY_MODE_LVDS);
+   ret = phy_set_mode(lvds->dphy, PHY_MODE_LVDS);
if (ret)
return ret;
 
-- 
2.27.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 1/2] dma-buf.rst: Document why indefinite fences are a bad idea

2020-07-14 Thread Jason Ekstrand
This matches my understanding for what it's worth.  In my little bit
of synchronization work in drm, I've gone out of my way to ensure we
can maintain this constraint.

Acked-by: Jason Ekstrand 

On Thu, Jul 9, 2020 at 7:33 AM Daniel Vetter  wrote:
>
> Comes up every few years, gets somewhat tedious to discuss, let's
> write this down once and for all.
>
> What I'm not sure about is whether the text should be more explicit in
> flat out mandating the amdkfd eviction fences for long running compute
> workloads or workloads where userspace fencing is allowed.
>
> v2: Now with dot graph!
>
> v3: Typo (Dave Airlie)
>
> Acked-by: Christian König 
> Acked-by: Daniel Stone 
> Cc: Jesse Natalie 
> Cc: Steve Pronovost 
> Cc: Jason Ekstrand 
> Cc: Felix Kuehling 
> Cc: Mika Kuoppala 
> Cc: Thomas Hellstrom 
> Cc: linux-me...@vger.kernel.org
> Cc: linaro-mm-...@lists.linaro.org
> Cc: linux-r...@vger.kernel.org
> Cc: amd-...@lists.freedesktop.org
> Cc: intel-...@lists.freedesktop.org
> Cc: Chris Wilson 
> Cc: Maarten Lankhorst 
> Cc: Christian König 
> Signed-off-by: Daniel Vetter 
> ---
>  Documentation/driver-api/dma-buf.rst | 70 
>  1 file changed, 70 insertions(+)
>
> diff --git a/Documentation/driver-api/dma-buf.rst 
> b/Documentation/driver-api/dma-buf.rst
> index f8f6decde359..100bfd227265 100644
> --- a/Documentation/driver-api/dma-buf.rst
> +++ b/Documentation/driver-api/dma-buf.rst
> @@ -178,3 +178,73 @@ DMA Fence uABI/Sync File
>  .. kernel-doc:: include/linux/sync_file.h
> :internal:
>
> +Indefinite DMA Fences
> +
> +
> +At various times &dma_fence with an indefinite time until dma_fence_wait()
> +finishes have been proposed. Examples include:
> +
> +* Future fences, used in HWC1 to signal when a buffer isn't used by the 
> display
> +  any longer, and created with the screen update that makes the buffer 
> visible.
> +  The time this fence completes is entirely under userspace's control.
> +
> +* Proxy fences, proposed to handle &drm_syncobj for which the fence has not 
> yet
> +  been set. Used to asynchronously delay command submission.
> +
> +* Userspace fences or gpu futexes, fine-grained locking within a command 
> buffer
> +  that userspace uses for synchronization across engines or with the CPU, 
> which
> +  are then imported as a DMA fence for integration into existing winsys
> +  protocols.
> +
> +* Long-running compute command buffers, while still using traditional end of
> +  batch DMA fences for memory management instead of context preemption DMA
> +  fences which get reattached when the compute job is rescheduled.
> +
> +Common to all these schemes is that userspace controls the dependencies of 
> these
> +fences and controls when they fire. Mixing indefinite fences with normal
> +in-kernel DMA fences does not work, even when a fallback timeout is included 
> to
> +protect against malicious userspace:
> +
> +* Only the kernel knows about all DMA fence dependencies, userspace is not 
> aware
> +  of dependencies injected due to memory management or scheduler decisions.
> +
> +* Only userspace knows about all dependencies in indefinite fences and when
> +  exactly they will complete, the kernel has no visibility.
> +
> +Furthermore the kernel has to be able to hold up userspace command submission
> +for memory management needs, which means we must support indefinite fences 
> being
> +dependent upon DMA fences. If the kernel also support indefinite fences in 
> the
> +kernel like a DMA fence, like any of the above proposal would, there is the
> +potential for deadlocks.
> +
> +.. kernel-render:: DOT
> +   :alt: Indefinite Fencing Dependency Cycle
> +   :caption: Indefinite Fencing Dependency Cycle
> +
> +   digraph "Fencing Cycle" {
> +  node [shape=box bgcolor=grey style=filled]
> +  kernel [label="Kernel DMA Fences"]
> +  userspace [label="userspace controlled fences"]
> +  kernel -> userspace [label="memory management"]
> +  userspace -> kernel [label="Future fence, fence proxy, ..."]
> +
> +  { rank=same; kernel userspace }
> +   }
> +
> +This means that the kernel might accidentally create deadlocks
> +through memory management dependencies which userspace is unaware of, which
> +randomly hangs workloads until the timeout kicks in. Workloads, which from
> +userspace's perspective, do not contain a deadlock.  In such a mixed fencing
> +architecture there is no single entity with knowledge of all dependencies.
> +Thefore preventing such deadlocks from within the kernel is not possible.
> +
> +The only solution to avoid dependencies loops is by not allowing indefinite
> +fences in the kernel. This means:
> +
> +* No future fences, proxy fences or userspace fences imported as DMA fences,
> +  with or without a timeout.
> +
> +* No DMA fences that signal end of batchbuffer for command submission where
> +  userspace is allowed to use userspace fencing or long running compute
> +  workloads. This also means no implicit 

Re: [PATCH] drm: msm: a6xx: fix gpu failure after system resume

2020-07-14 Thread Rob Clark
On Tue, Jul 14, 2020 at 10:10 AM Matthias Kaehlcke  wrote:
>
> On Tue, Jul 14, 2020 at 06:55:30PM +0530, Akhil P Oommen wrote:
> > On targets where GMU is available, GMU takes over the ownership of GX GDSC
> > during its initialization. So, take a refcount on the GX PD on behalf of
> > GMU before we initialize it. This makes sure that nobody can collapse the
> > GX GDSC once GMU owns the GX GDSC. This patch fixes some weird failures
> > during GPU wake up during system resume.
> >
> > Signed-off-by: Akhil P Oommen 
>
> I went through a few dozen suspend/resume cycles on SC7180 and didn't run
> into the kernel panic that typically occurs after a few iterations without
> this patch.
>
> Reported-by: Matthias Kaehlcke 
> Tested-by: Matthias Kaehlcke 
>
> On which tree is this patch based on? I had to apply it manually because
> 'git am' is unhappy when I try to apply it:
>
>   error: sha1 information is lacking or useless 
> (drivers/gpu/drm/msm/adreno/a6xx_gmu.c).
>   error: could not build fake ancestor
>
> Both upstream and drm-msm are in my remotes and synced, so I suspect it's
> some private tree. Please make sure to base patches on the corresponding
> maintainer tree or upstream, whichs makes life easier for maintainers,
> testers and reviewers.

I've run into the same issue frequently :-(

BR,
-R
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Chris Wilson
Quoting Bas Nieuwenhuizen (2020-07-14 19:17:21)
> On Tue, Jul 14, 2020 at 6:26 PM Chris Wilson  wrote:
> >
> > Quoting Bas Nieuwenhuizen (2020-07-14 16:41:02)
> > > Calltree:
> > >   timeline_fence_release
> > >   drm_sched_entity_wakeup
> > >   dma_fence_signal_locked
> > >   sync_timeline_signal
> > >   sw_sync_ioctl
> > >
> > > Releasing the reference to the fence in the fence signal callback
> > > seems reasonable to me, so this patch avoids the locking issue in
> > > sw_sync.
> > >
> > > d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
> > > fixed the recursive locking issue but caused an use-after-free. Later
> > > d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> > > fixed the use-after-free but reintroduced the recursive locking issue.
> > >
> > > In this attempt we avoid the use-after-free still because the release
> > > function still always locks, and outside of the locking region in the
> > > signal function we have properly refcounted references.
> > >
> > > We furthermore also avoid the recurive lock by making sure that either:
> > >
> > > 1) We have a properly refcounted reference, preventing the signal from
> > >triggering the release function inside the locked region.
> > > 2) The refcount was already zero, and hence nobody will be able to trigger
> > >the release function from the signal function.
> > >
> > > Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> > > Cc: Sumit Semwal 
> > > Cc: Chris Wilson 
> > > Cc: Gustavo Padovan 
> > > Cc: Christian König 
> > > Cc: 
> > > Signed-off-by: Bas Nieuwenhuizen 
> > > ---
> > >  drivers/dma-buf/sw_sync.c | 28 
> > >  1 file changed, 20 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
> > > index 348b3a9170fa..30a482f75d56 100644
> > > --- a/drivers/dma-buf/sw_sync.c
> > > +++ b/drivers/dma-buf/sw_sync.c
> > > @@ -192,9 +192,12 @@ static const struct dma_fence_ops timeline_fence_ops 
> > > = {
> > >  static void sync_timeline_signal(struct sync_timeline *obj, unsigned int 
> > > inc)
> > >  {
> > > struct sync_pt *pt, *next;
> > > +   struct list_head ref_list;
> > >
> > > trace_sync_timeline(obj);
> > >
> > > +   INIT_LIST_HEAD(&ref_list);
> > > +
> > > spin_lock_irq(&obj->lock);
> > >
> > > obj->value += inc;
> > > @@ -206,18 +209,27 @@ static void sync_timeline_signal(struct 
> > > sync_timeline *obj, unsigned int inc)
> > > list_del_init(&pt->link);
> > > rb_erase(&pt->node, &obj->pt_tree);
> > >
> > > -   /*
> > > -* A signal callback may release the last reference to 
> > > this
> > > -* fence, causing it to be freed. That operation has to be
> > > -* last to avoid a use after free inside this loop, and 
> > > must
> > > -* be after we remove the fence from the timeline in 
> > > order to
> > > -* prevent deadlocking on timeline->lock inside
> > > -* timeline_fence_release().
> > > -*/
> > > +   /* We need to take a reference to avoid a release during
> > > +* signalling (which can cause a recursive lock of 
> > > obj->lock).
> > > +* If refcount was already zero, another thread is 
> > > already taking
> > > +* care of destructing the fence, so the signal cannot 
> > > release
> > > +* it again and we hence will not have the recursive 
> > > lock. */
> >
> > /*
> >  * Block commentary style:
> >  * 
> > https://www.kernel.org/doc/html/latest/process/coding-style.html#commenting
> >  */
> >
> > > +   if (dma_fence_get_rcu(&pt->base))
> > > +   list_add_tail(&pt->link, &ref_list);
> >
> > Ok.
> >
> > > +
> > > dma_fence_signal_locked(&pt->base);
> > > }
> > >
> > > spin_unlock_irq(&obj->lock);
> > > +
> > > +   list_for_each_entry_safe(pt, next, &ref_list, link) {
> > > +   /* This needs to be cleared before release, otherwise the
> > > +* timeline_fence_release function gets confused about 
> > > also
> > > +* removing the fence from the pt_tree. */
> > > +   list_del_init(&pt->link);
> > > +
> > > +   dma_fence_put(&pt->base);
> > > +   }
> >
> > How serious is the problem of one fence callback freeing another pt?
> >
> > Following the pattern here
> >
> > spin_lock(&obj->lock);
> > list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
> > if (!timeline_fence_signaled(&pt->base))
> > break;
> >
> > if (!dma_fence_get_rcu(&pt->base))
> > continue; /* too late! */
> >
> > rb_erase(&pt->node, &obj->pt_tree);
> > list_move_tail(&pt->link, &ref_l

Re: [PATCH] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Bas Nieuwenhuizen
On Tue, Jul 14, 2020 at 6:26 PM Chris Wilson  wrote:
>
> Quoting Bas Nieuwenhuizen (2020-07-14 16:41:02)
> > Calltree:
> >   timeline_fence_release
> >   drm_sched_entity_wakeup
> >   dma_fence_signal_locked
> >   sync_timeline_signal
> >   sw_sync_ioctl
> >
> > Releasing the reference to the fence in the fence signal callback
> > seems reasonable to me, so this patch avoids the locking issue in
> > sw_sync.
> >
> > d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
> > fixed the recursive locking issue but caused an use-after-free. Later
> > d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> > fixed the use-after-free but reintroduced the recursive locking issue.
> >
> > In this attempt we avoid the use-after-free still because the release
> > function still always locks, and outside of the locking region in the
> > signal function we have properly refcounted references.
> >
> > We furthermore also avoid the recurive lock by making sure that either:
> >
> > 1) We have a properly refcounted reference, preventing the signal from
> >triggering the release function inside the locked region.
> > 2) The refcount was already zero, and hence nobody will be able to trigger
> >the release function from the signal function.
> >
> > Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> > Cc: Sumit Semwal 
> > Cc: Chris Wilson 
> > Cc: Gustavo Padovan 
> > Cc: Christian König 
> > Cc: 
> > Signed-off-by: Bas Nieuwenhuizen 
> > ---
> >  drivers/dma-buf/sw_sync.c | 28 
> >  1 file changed, 20 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
> > index 348b3a9170fa..30a482f75d56 100644
> > --- a/drivers/dma-buf/sw_sync.c
> > +++ b/drivers/dma-buf/sw_sync.c
> > @@ -192,9 +192,12 @@ static const struct dma_fence_ops timeline_fence_ops = 
> > {
> >  static void sync_timeline_signal(struct sync_timeline *obj, unsigned int 
> > inc)
> >  {
> > struct sync_pt *pt, *next;
> > +   struct list_head ref_list;
> >
> > trace_sync_timeline(obj);
> >
> > +   INIT_LIST_HEAD(&ref_list);
> > +
> > spin_lock_irq(&obj->lock);
> >
> > obj->value += inc;
> > @@ -206,18 +209,27 @@ static void sync_timeline_signal(struct sync_timeline 
> > *obj, unsigned int inc)
> > list_del_init(&pt->link);
> > rb_erase(&pt->node, &obj->pt_tree);
> >
> > -   /*
> > -* A signal callback may release the last reference to this
> > -* fence, causing it to be freed. That operation has to be
> > -* last to avoid a use after free inside this loop, and must
> > -* be after we remove the fence from the timeline in order 
> > to
> > -* prevent deadlocking on timeline->lock inside
> > -* timeline_fence_release().
> > -*/
> > +   /* We need to take a reference to avoid a release during
> > +* signalling (which can cause a recursive lock of 
> > obj->lock).
> > +* If refcount was already zero, another thread is already 
> > taking
> > +* care of destructing the fence, so the signal cannot 
> > release
> > +* it again and we hence will not have the recursive lock. 
> > */
>
> /*
>  * Block commentary style:
>  * https://www.kernel.org/doc/html/latest/process/coding-style.html#commenting
>  */
>
> > +   if (dma_fence_get_rcu(&pt->base))
> > +   list_add_tail(&pt->link, &ref_list);
>
> Ok.
>
> > +
> > dma_fence_signal_locked(&pt->base);
> > }
> >
> > spin_unlock_irq(&obj->lock);
> > +
> > +   list_for_each_entry_safe(pt, next, &ref_list, link) {
> > +   /* This needs to be cleared before release, otherwise the
> > +* timeline_fence_release function gets confused about also
> > +* removing the fence from the pt_tree. */
> > +   list_del_init(&pt->link);
> > +
> > +   dma_fence_put(&pt->base);
> > +   }
>
> How serious is the problem of one fence callback freeing another pt?
>
> Following the pattern here
>
> spin_lock(&obj->lock);
> list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
> if (!timeline_fence_signaled(&pt->base))
> break;
>
> if (!dma_fence_get_rcu(&pt->base))
> continue; /* too late! */
>
> rb_erase(&pt->node, &obj->pt_tree);
> list_move_tail(&pt->link, &ref_list);
> }
> spin_unlock(&obj->lock);
>
> list_for_each_entry_safe(pt, next, &ref_list, link) {
> list_del_init(&pt->link);
> dma_fence_signal(&pt->base);

Question is what the scope should be. Using this method we only take a
reference and avoid releasing the fenc

Re: [PATCH v3 0/6] Generic USB Display driver

2020-07-14 Thread Peter Stuge
Hi Noralf,

Noralf Trønnes wrote:
> I would like to keep the SET_BUFFER request since it will serve as a
> syncing point between the host and the device. I'm no USB expert but I
> assume that a bulk transfer can fail halfway through and result in the
> next update starting where the previous one failed and thus writing
> beyond the end of the display buffer.

Transfers either succeed completely (possibly after many retries),
time out (after zero or more transfered bytes) or fail catastrophically
(e.g. from device disconnect).

In all cases, the driver on the host knows/has available how many bytes
were successfully transfered.


//Peter
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm: msm: a6xx: fix gpu failure after system resume

2020-07-14 Thread Matthias Kaehlcke
On Tue, Jul 14, 2020 at 06:55:30PM +0530, Akhil P Oommen wrote:
> On targets where GMU is available, GMU takes over the ownership of GX GDSC
> during its initialization. So, take a refcount on the GX PD on behalf of
> GMU before we initialize it. This makes sure that nobody can collapse the
> GX GDSC once GMU owns the GX GDSC. This patch fixes some weird failures
> during GPU wake up during system resume.
> 
> Signed-off-by: Akhil P Oommen 

I went through a few dozen suspend/resume cycles on SC7180 and didn't run
into the kernel panic that typically occurs after a few iterations without
this patch.

Reported-by: Matthias Kaehlcke 
Tested-by: Matthias Kaehlcke 

On which tree is this patch based on? I had to apply it manually because
'git am' is unhappy when I try to apply it:

  error: sha1 information is lacking or useless 
(drivers/gpu/drm/msm/adreno/a6xx_gmu.c).
  error: could not build fake ancestor

Both upstream and drm-msm are in my remotes and synced, so I suspect it's
some private tree. Please make sure to base patches on the corresponding
maintainer tree or upstream, whichs makes life easier for maintainers,
testers and reviewers.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[RFC PATCH] drm/i915: g4x_get_flip_counter() can be static

2020-07-14 Thread kernel test robot


Signed-off-by: kernel test robot 
---
 i915_irq.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9812a8051c5ea..79a3118f918a1 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -697,7 +697,7 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc)
return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xff;
 }
 
-u32 g4x_get_flip_counter(struct drm_crtc *crtc)
+static u32 g4x_get_flip_counter(struct drm_crtc *crtc)
 {
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v4 1/5] drm/i915: Add enable/disable flip done and flip done handler

2020-07-14 Thread kernel test robot
Hi Karthik,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on drm-tip/drm-tip drm-exynos/exynos-drm-next 
tegra-drm/drm/tegra/for-next v5.8-rc5 next-20200714]
[cannot apply to drm/drm-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use  as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Karthik-B-S/Asynchronous-flip-implementation-for-i915/20200714-095304
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-s032-20200714 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.2-41-g14e84ffc-dirty
# save the attached .config to linux build tree
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 


sparse warnings: (new ones prefixed by >>)

>> drivers/gpu/drm/i915/i915_irq.c:700:5: sparse: sparse: symbol 
>> 'g4x_get_flip_counter' was not declared. Should it be static?

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


.config.gz
Description: application/gzip
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Chris Wilson
Quoting Bas Nieuwenhuizen (2020-07-14 16:41:02)
> Calltree:
>   timeline_fence_release
>   drm_sched_entity_wakeup
>   dma_fence_signal_locked
>   sync_timeline_signal
>   sw_sync_ioctl
> 
> Releasing the reference to the fence in the fence signal callback
> seems reasonable to me, so this patch avoids the locking issue in
> sw_sync.
> 
> d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
> fixed the recursive locking issue but caused an use-after-free. Later
> d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> fixed the use-after-free but reintroduced the recursive locking issue.
> 
> In this attempt we avoid the use-after-free still because the release
> function still always locks, and outside of the locking region in the
> signal function we have properly refcounted references.
> 
> We furthermore also avoid the recurive lock by making sure that either:
> 
> 1) We have a properly refcounted reference, preventing the signal from
>triggering the release function inside the locked region.
> 2) The refcount was already zero, and hence nobody will be able to trigger
>the release function from the signal function.
> 
> Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
> Cc: Sumit Semwal 
> Cc: Chris Wilson 
> Cc: Gustavo Padovan 
> Cc: Christian König 
> Cc: 
> Signed-off-by: Bas Nieuwenhuizen 
> ---
>  drivers/dma-buf/sw_sync.c | 28 
>  1 file changed, 20 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
> index 348b3a9170fa..30a482f75d56 100644
> --- a/drivers/dma-buf/sw_sync.c
> +++ b/drivers/dma-buf/sw_sync.c
> @@ -192,9 +192,12 @@ static const struct dma_fence_ops timeline_fence_ops = {
>  static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
>  {
> struct sync_pt *pt, *next;
> +   struct list_head ref_list;
>  
> trace_sync_timeline(obj);
>  
> +   INIT_LIST_HEAD(&ref_list);
> +
> spin_lock_irq(&obj->lock);
>  
> obj->value += inc;
> @@ -206,18 +209,27 @@ static void sync_timeline_signal(struct sync_timeline 
> *obj, unsigned int inc)
> list_del_init(&pt->link);
> rb_erase(&pt->node, &obj->pt_tree);
>  
> -   /*
> -* A signal callback may release the last reference to this
> -* fence, causing it to be freed. That operation has to be
> -* last to avoid a use after free inside this loop, and must
> -* be after we remove the fence from the timeline in order to
> -* prevent deadlocking on timeline->lock inside
> -* timeline_fence_release().
> -*/
> +   /* We need to take a reference to avoid a release during
> +* signalling (which can cause a recursive lock of obj->lock).
> +* If refcount was already zero, another thread is already 
> taking
> +* care of destructing the fence, so the signal cannot release
> +* it again and we hence will not have the recursive lock. */

/*
 * Block commentary style:
 * https://www.kernel.org/doc/html/latest/process/coding-style.html#commenting
 */

> +   if (dma_fence_get_rcu(&pt->base))
> +   list_add_tail(&pt->link, &ref_list);

Ok.

> +
> dma_fence_signal_locked(&pt->base);
> }
>  
> spin_unlock_irq(&obj->lock);
> +
> +   list_for_each_entry_safe(pt, next, &ref_list, link) {
> +   /* This needs to be cleared before release, otherwise the
> +* timeline_fence_release function gets confused about also
> +* removing the fence from the pt_tree. */
> +   list_del_init(&pt->link);
> +
> +   dma_fence_put(&pt->base);
> +   }

How serious is the problem of one fence callback freeing another pt?

Following the pattern here

spin_lock(&obj->lock);
list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
if (!timeline_fence_signaled(&pt->base))
break;

if (!dma_fence_get_rcu(&pt->base))
continue; /* too late! */

rb_erase(&pt->node, &obj->pt_tree);
list_move_tail(&pt->link, &ref_list);
}
spin_unlock(&obj->lock);

list_for_each_entry_safe(pt, next, &ref_list, link) {
list_del_init(&pt->link);
dma_fence_signal(&pt->base);
dma_fence_put(&pt->base);
}

Marginal extra cost for signaling along the debug sw_timeline for total
peace of mind.
-Chris
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [v1] drm/msm/dpu: add support for clk and bw scaling for display

2020-07-14 Thread Matthias Kaehlcke
On Tue, Jul 14, 2020 at 04:39:47PM +0530, kalya...@codeaurora.org wrote:
> On 2020-07-14 06:42, Matthias Kaehlcke wrote:
> > On Thu, Jun 18, 2020 at 07:38:41PM +0530, Kalyan Thota wrote:
> > > This change adds support to scale src clk and bandwidth as
> > > per composition requirements.
> > > 
> > > Interconnect registration for bw has been moved to mdp
> > > device node from mdss to facilitate the scaling.
> > > 
> > > Changes in v1:
> > >  - Address armv7 compilation issues with the patch (Rob)
> > > 
> > > Signed-off-by: Kalyan Thota 
> > 
> > It seems this is an evolution of this series:
> > https://patchwork.kernel.org/project/linux-arm-msm/list/?series=265351
> > 
> > Are the DT bits of the series still valid? If so please include them in
> > the
> > series, otherwise please add DT patches to allow folks to test and
> > review,
> > and get them landed in Bjorn's tree after the driver changes have
> > landed.
> 
> Hi,
> 
> Yes the patch is dependent on the DT changes, should i add them with depends
> tag in the commit text ?
> https://patchwork.kernel.org/patch/11470785/
> https://patchwork.kernel.org/patch/11470789/

This patch doesn't really depend on the DT changes. I would suggest to
make this a series of 3 patches, just like the original series linked
above.

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/i915: Avoid modeset when content protection changes

2020-07-14 Thread Sean Paul
From: Sean Paul 

Instead of doing a full modeset to enable/disable content protection,
simply go through the update_pipe flow which was introduced in the
related patch below. This avoids flashing the screen every time the user
starts viewing protected content.

Related: 634852d1f468 ("drm/i915: HDCP state handling in ddi_update_pipe")
Cc: Ramalingam C 
Cc: Daniel Vetter 
Cc: Jani Nikula 
Cc: Joonas Lahtinen 
Cc: Rodrigo Vivi 
Cc: intel-...@lists.freedesktop.org
Signed-off-by: Sean Paul 
---
 drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_hdcp.c
index 89a4d294822d..839ce1715253 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -2191,7 +2191,7 @@ void intel_hdcp_atomic_check(struct drm_connector 
*connector,
return;
}
 
-   crtc_state->mode_changed = true;
+   to_intel_crtc_state(crtc_state)->update_pipe = true;
 }
 
 /* Handles the CP_IRQ raised from the DP HDCP sink */
-- 
Sean Paul, Software Engineer, Google / Chromium OS

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [Freedreno] [v1] drm/msm/dpu: add support for clk and bw scaling for display

2020-07-14 Thread Rob Clark
On Tue, Jul 14, 2020 at 4:20 AM  wrote:
>
> On 2020-07-13 22:50, Rob Clark wrote:
> > On Mon, Jul 13, 2020 at 8:59 AM  wrote:
> >>
> >> On 2020-07-10 22:38, Rob Clark wrote:
> >> > On Thu, Jun 18, 2020 at 7:09 AM Kalyan Thota 
> >> > wrote:
> >> >>
> >> >> This change adds support to scale src clk and bandwidth as
> >> >> per composition requirements.
> >> >>
> >> >> Interconnect registration for bw has been moved to mdp
> >> >> device node from mdss to facilitate the scaling.
> >> >>
> >> >> Changes in v1:
> >> >>  - Address armv7 compilation issues with the patch (Rob)
> >> >>
> >> >> Signed-off-by: Kalyan Thota 
> >> >> ---
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c  | 109
> >> >> +
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |   5 +-
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |   4 +
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|  37 -
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h|   4 +
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c   |   9 +-
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  |  84
> >> >> +++
> >> >>  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h  |   4 +
> >> >>  8 files changed, 233 insertions(+), 23 deletions(-)
> >> >>
> >> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
> >> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
> >> >> index 7c230f7..e52bc44 100644
> >> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
> >> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
> >> >> @@ -29,6 +29,74 @@ enum dpu_perf_mode {
> >> >> DPU_PERF_MODE_MAX
> >> >>  };
> >> >>
> >> >> +/**
> >> >> + * @_dpu_core_perf_calc_bw() - to calculate BW per crtc
> >> >> + * @kms -  pointer to the dpu_kms
> >> >> + * @crtc - pointer to a crtc
> >> >> + * Return: returns aggregated BW for all planes in crtc.
> >> >> + */
> >> >> +static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms,
> >> >> +   struct drm_crtc *crtc)
> >> >> +{
> >> >> +   struct drm_plane *plane;
> >> >> +   struct dpu_plane_state *pstate;
> >> >> +   u64 crtc_plane_bw = 0;
> >> >> +   u32 bw_factor;
> >> >> +
> >> >> +   drm_atomic_crtc_for_each_plane(plane, crtc) {
> >> >> +   pstate = to_dpu_plane_state(plane->state);
> >> >> +   if (!pstate)
> >> >> +   continue;
> >> >> +
> >> >> +   crtc_plane_bw += pstate->plane_fetch_bw;
> >> >> +   }
> >> >> +
> >> >> +   bw_factor = kms->catalog->perf.bw_inefficiency_factor;
> >> >> +   if (bw_factor) {
> >> >> +   crtc_plane_bw *= bw_factor;
> >> >> +   do_div(crtc_plane_bw, 100);
> >> >> +   }
> >> >> +
> >> >> +   return crtc_plane_bw;
> >> >> +}
> >> >> +
> >> >> +/**
> >> >> + * _dpu_core_perf_calc_clk() - to calculate clock per crtc
> >> >> + * @kms -  pointer to the dpu_kms
> >> >> + * @crtc - pointer to a crtc
> >> >> + * @state - pointer to a crtc state
> >> >> + * Return: returns max clk for all planes in crtc.
> >> >> + */
> >> >> +static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms,
> >> >> +   struct drm_crtc *crtc, struct drm_crtc_state *state)
> >> >> +{
> >> >> +   struct drm_plane *plane;
> >> >> +   struct dpu_plane_state *pstate;
> >> >> +   struct drm_display_mode *mode;
> >> >> +   u64 crtc_clk;
> >> >> +   u32 clk_factor;
> >> >> +
> >> >> +   mode = &state->adjusted_mode;
> >> >> +
> >> >> +   crtc_clk = mode->vtotal * mode->hdisplay *
> >> >> drm_mode_vrefresh(mode);
> >> >> +
> >> >> +   drm_atomic_crtc_for_each_plane(plane, crtc) {
> >> >> +   pstate = to_dpu_plane_state(plane->state);
> >> >> +   if (!pstate)
> >> >> +   continue;
> >> >> +
> >> >> +   crtc_clk = max(pstate->plane_clk, crtc_clk);
> >> >> +   }
> >> >> +
> >> >> +   clk_factor = kms->catalog->perf.clk_inefficiency_factor;
> >> >> +   if (clk_factor) {
> >> >> +   crtc_clk *= clk_factor;
> >> >> +   do_div(crtc_clk, 100);
> >> >> +   }
> >> >> +
> >> >> +   return crtc_clk;
> >> >> +}
> >> >> +
> >> >>  static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
> >> >>  {
> >> >> struct msm_drm_private *priv;
> >> >> @@ -51,12 +119,7 @@ static void _dpu_core_perf_calc_crtc(struct
> >> >> dpu_kms *kms,
> >> >> dpu_cstate = to_dpu_crtc_state(state);
> >> >> memset(perf, 0, sizeof(struct dpu_core_perf_params));
> >> >>
> >> >> -   if (!dpu_cstate->bw_control) {
> >> >> -   perf->bw_ctl = kms->catalog->perf.max_bw_high *
> >> >> -   1000ULL;
> >> >> -   perf->max_per_pipe_ib = perf->bw_ctl;
> >> >> -   perf->core_clk_rate = kms->perf.max_core_clk_rate;
> >> >> -   } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM)
> >> >> {
> >> >> +   if (kms->perf.perf_tune.m

[PATCH] dma-buf/sw_sync: Avoid recursive lock during fence signal.

2020-07-14 Thread Bas Nieuwenhuizen
Calltree:
  timeline_fence_release
  drm_sched_entity_wakeup
  dma_fence_signal_locked
  sync_timeline_signal
  sw_sync_ioctl

Releasing the reference to the fence in the fence signal callback
seems reasonable to me, so this patch avoids the locking issue in
sw_sync.

d3862e44daa7 ("dma-buf/sw-sync: Fix locking around sync_timeline lists")
fixed the recursive locking issue but caused an use-after-free. Later
d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
fixed the use-after-free but reintroduced the recursive locking issue.

In this attempt we avoid the use-after-free still because the release
function still always locks, and outside of the locking region in the
signal function we have properly refcounted references.

We furthermore also avoid the recurive lock by making sure that either:

1) We have a properly refcounted reference, preventing the signal from
   triggering the release function inside the locked region.
2) The refcount was already zero, and hence nobody will be able to trigger
   the release function from the signal function.

Fixes: d3c6dd1fb30d ("dma-buf/sw_sync: Synchronize signal vs syncpt free")
Cc: Sumit Semwal 
Cc: Chris Wilson 
Cc: Gustavo Padovan 
Cc: Christian König 
Cc: 
Signed-off-by: Bas Nieuwenhuizen 
---
 drivers/dma-buf/sw_sync.c | 28 
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 348b3a9170fa..30a482f75d56 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -192,9 +192,12 @@ static const struct dma_fence_ops timeline_fence_ops = {
 static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
 {
struct sync_pt *pt, *next;
+   struct list_head ref_list;
 
trace_sync_timeline(obj);
 
+   INIT_LIST_HEAD(&ref_list);
+
spin_lock_irq(&obj->lock);
 
obj->value += inc;
@@ -206,18 +209,27 @@ static void sync_timeline_signal(struct sync_timeline 
*obj, unsigned int inc)
list_del_init(&pt->link);
rb_erase(&pt->node, &obj->pt_tree);
 
-   /*
-* A signal callback may release the last reference to this
-* fence, causing it to be freed. That operation has to be
-* last to avoid a use after free inside this loop, and must
-* be after we remove the fence from the timeline in order to
-* prevent deadlocking on timeline->lock inside
-* timeline_fence_release().
-*/
+   /* We need to take a reference to avoid a release during
+* signalling (which can cause a recursive lock of obj->lock).
+* If refcount was already zero, another thread is already 
taking
+* care of destructing the fence, so the signal cannot release
+* it again and we hence will not have the recursive lock. */
+   if (dma_fence_get_rcu(&pt->base))
+   list_add_tail(&pt->link, &ref_list);
+
dma_fence_signal_locked(&pt->base);
}
 
spin_unlock_irq(&obj->lock);
+
+   list_for_each_entry_safe(pt, next, &ref_list, link) {
+   /* This needs to be cleared before release, otherwise the
+* timeline_fence_release function gets confused about also
+* removing the fence from the pt_tree. */
+   list_del_init(&pt->link);
+
+   dma_fence_put(&pt->base);
+   }
 }
 
 /**
-- 
2.27.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3 6/9] drm/bridge: ti-sn65dsi86: Use 18-bit DP if we can

2020-07-14 Thread Doug Anderson
Hi,

On Fri, Jul 10, 2020 at 10:11 AM Steev Klimaszewski  wrote:
>
>
> On 7/10/20 9:47 AM, Doug Anderson wrote:
> > Hi,
> >
> >
> > But should I continue on this path,
> > It's probably worth getting dithering working on your sdm845 anyway in
> > case anyone actually does put a 6bpp panel on this SoC.
> >
> >
> >> or should we be finding others who
> >> have an N61 and see what their EDID reports?
> > I have an email out to BOE, but it might take a little while to get a
> > response.  I'll see what they say.  If they say that the panel
> > actually supports 8bpp then it's a no-brainer and we should just
> > switch to 8bpp and be done.
> >
> > ...but if they say it's a 6bpp panel that has its own dither logic
> > then it gets more complicated.  Initially one would think there should
> > be very little downside in defining the panel as an 8bpp panel and
> > calling it done.  ...except that it conflicts with some other work
> > that I have in progress.  :-P  Specifically if you treat the panel as
> > 6bpp and then reduce the blanking a tiny bit you can actually save 75
> > mW of total system power on my board (probably similar on your board
> > since you have the same bridge chip).  You can see a patch to do that
> > here:
> >
> > https://crrev.com/c/2276384
> >
> > ...so I'm hoping to get some clarity from BOE both on the true bits
> > per pixel and whether my proposed timings are valid before moving
> > forward.  Is that OK?
> >
> >
> > -Doug
>
>
> It's fine by me - testing Rob's suggestion of changing
> MAX_HDISPLAY_SPLIT 1080->1920 along with the change to adding IS_SDM845
> does give me a full screen that looks nicer, I'm fine with using the
> hack locally until a proper solution is found.  And I'm always a fan of
> using less power on a laptop.
>
>
> I'll give the patch a spin here if you want as well.
>
>
> Hopefully BOE gets back to you soon, and there's no rush, I'm just an
> end user who is extremely appreciative of all the work everyone on the
> list and the kernel in general put in to make my machines usable.

Just FYI that I got confirmation that the panel is truly 6 bpp but it
will do FRC dithering if given an 8 bpp input.  That means that you
should be getting just as good picture quality (and possibly more
tunable) by using the dithering in the display pipeline and leaving
the panel as 6bpp.  Thus I'm going to assume that's the route we'll go
down.  If ever we find someone that wants to use this panel on a
display controller that can't do its own dithering then I guess we'll
have to figure out what to do then...

In terms of the more optimal pixel clock for saving power, my proposal
is still being analyzed and I'll report back when I hear more.  I'm
seeing if BOE can confirm that my proposal will work both for my panel
(the -n62 variant) and the one you have (the -n61 variant).

-Doug
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3 4/6] drm: Add Generic USB Display driver

2020-07-14 Thread Noralf Trønnes


Den 02.06.2020 13.46, skrev Noralf Trønnes:
> 
> 
> Den 02.06.2020 04.32, skrev Alan Stern:
>> On Tue, Jun 02, 2020 at 12:12:07AM +, Peter Stuge wrote:
>>
>> ...
>>
>>> The way I read composite_setup() after try_fun_setup: it calls f->setup()
>>> when available, and that can return < 0 to stall.
>>>
>>> I expect that composite_setup() and thus f->setup() run when the
>>> SETUP packet has arrived, thus before the data packet arrives, and if
>>> composite_setup() stalls then the device/function should never see the
>>> data packet.
>>>
>>> For an OUT transaction I think the host controller might still send
>>> the DATA packet, but the device controllers that I know don't make it
>>> visible to the application in that case.
>>
>> ...
>>
>> Are you guys interested in comments from other people who know more
>> about the kernel and how it works with USB?
> 
> Absolutely, I want something thats works well in the kernel and doesn't
> look odd to kernel USB people.
> 
>> Your messages have been
>> far too long to go into in any detail, but I will address this one issue.
>>
>> The USB protocol forbids a device from sending a STALL response to a
>> SETUP packet.  The only valid response is ACK.  Thus, there is no way
>> to prevent the host from sending its DATA packet for a control-OUT
>> transfer.
>>
>> A gadget driver can STALL in response to a control-OUT data packet,
>> but only before it has seen the packet.  Once the driver knows what
>> the data packet contains, the gadget API doesn't provide any way to
>> STALL the status stage.  There has been a proposal to change the API
>> to make this possible, but so far it hasn't gone forward.
>>
> 
> This confirms what I have seen in the kernel and the reason I added a
> status request so I can know the result of the operation the device has
> performed.
> 
> I have a problem that I've encountered with this status request.
> In my first version the gadget would usb_ep_queue() the status value
> when the operation was done and as long as this happended within the
> host timeout (5s) everything worked fine.
> 
> Then I hit a 10s timeout in the gadget when performing a display modeset
> operation (wait on missing vblank). The result of this was that the host
> timed out and moved on. The gadget however didn't know that the host
> gave up, so it queued up the status value. The result of this was that
> all further requests from the host would time out.
> Do you know a solution to this?
> My work around is to just poll on the status request, which returns a
> value immediately, until there's a result. The udc driver I use is dwc2.
> 

I have now tried this on a Beaglebone Black (musb udc driver) and it
works just fine there (it displays an error message on the next
request). So it has to be a dwc2 driver problem. I will try and chase
down this problem when I get the time.

This means I don't need this status request polling in my host driver.

Noralf.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 04/25] drm/vkms: Annotate vblank timer

2020-07-14 Thread Daniel Vetter
On Tue, Jul 14, 2020 at 4:56 PM Melissa Wen  wrote:
>
> Hi,
>
> On 07/14, Daniel Vetter wrote:
> > On Tue, Jul 14, 2020 at 11:57 AM Melissa Wen  wrote:
> > >
> > > On 07/12, Rodrigo Siqueira wrote:
> > > > Hi,
> > > >
> > > > Everything looks fine to me, I just noticed that the amdgpu patches did
> > > > not apply smoothly, however it was trivial to fix the issues.
> > > >
> > > > Reviewed-by: Rodrigo Siqueira 
> > > >
> > > > Melissa,
> > > > Since you are using vkms regularly, could you test this patch and review
> > > > it? Remember to add your Tested-by when you finish.
> > > >
> > > Hi,
> > >
> > > I've applied the patch series, ran some tests on vkms, and found no
> > > issues. I mean, things have remained stable.
> > >
> > > Tested-by: Melissa Wen 
> >
> > Did you test with CONFIG_PROVE_LOCKING enabled in the kernel .config?
> > Without that enabled, there's not really any change here, but with
> > that enabled there might be some lockdep splats in dmesg indicating a
> > problem.
> >
>
> Even with the lock debugging config enabled, no new issue arose in dmesg
> during my tests using vkms.

Excellent, thanks a lot for confirming this.
-Daniel

>
> Melissa
>
> > Thanks, Daniel
> > >
> > > > Thanks
> > > >
> > > > On 07/07, Daniel Vetter wrote:
> > > > > This is needed to signal the fences from page flips, annotate it
> > > > > accordingly. We need to annotate entire timer callback since if we get
> > > > > stuck anywhere in there, then the timer stops, and hence fences stop.
> > > > > Just annotating the top part that does the vblank handling isn't
> > > > > enough.
> > > > >
> > > > > Cc: linux-me...@vger.kernel.org
> > > > > Cc: linaro-mm-...@lists.linaro.org
> > > > > Cc: linux-r...@vger.kernel.org
> > > > > Cc: amd-...@lists.freedesktop.org
> > > > > Cc: intel-...@lists.freedesktop.org
> > > > > Cc: Chris Wilson 
> > > > > Cc: Maarten Lankhorst 
> > > > > Cc: Christian König 
> > > > > Signed-off-by: Daniel Vetter 
> > > > > Cc: Rodrigo Siqueira 
> > > > > Cc: Haneen Mohammed 
> > > > > Cc: Daniel Vetter 
> > > > > ---
> > > > >  drivers/gpu/drm/vkms/vkms_crtc.c | 8 +++-
> > > > >  1 file changed, 7 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> > > > > b/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > > index ac85e17428f8..a53a40848a72 100644
> > > > > --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > > +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > > @@ -1,5 +1,7 @@
> > > > >  // SPDX-License-Identifier: GPL-2.0+
> > > > >
> > > > > +#include 
> > > > > +
> > > > >  #include 
> > > > >  #include 
> > > > >  #include 
> > > > > @@ -14,7 +16,9 @@ static enum hrtimer_restart 
> > > > > vkms_vblank_simulate(struct hrtimer *timer)
> > > > > struct drm_crtc *crtc = &output->crtc;
> > > > > struct vkms_crtc_state *state;
> > > > > u64 ret_overrun;
> > > > > -   bool ret;
> > > > > +   bool ret, fence_cookie;
> > > > > +
> > > > > +   fence_cookie = dma_fence_begin_signalling();
> > > > >
> > > > > ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > > > >   output->period_ns);
> > > > > @@ -49,6 +53,8 @@ static enum hrtimer_restart 
> > > > > vkms_vblank_simulate(struct hrtimer *timer)
> > > > > DRM_DEBUG_DRIVER("Composer worker already 
> > > > > queued\n");
> > > > > }
> > > > >
> > > > > +   dma_fence_end_signalling(fence_cookie);
> > > > > +
> > > > > return HRTIMER_RESTART;
> > > > >  }
> > > > >
> > > > > --
> > > > > 2.27.0
> > > > >
> > > >
> > > > --
> > > > Rodrigo Siqueira
> > > > https://siqueira.tech
> > >
> > >
> >
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v4 1/5] drm/i915: Add enable/disable flip done and flip done handler

2020-07-14 Thread kernel test robot
Hi Karthik,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on drm-tip/drm-tip drm-exynos/exynos-drm-next 
tegra-drm/drm/tegra/for-next v5.8-rc5 next-20200713]
[cannot apply to drm/drm-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use  as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Karthik-B-S/Asynchronous-flip-implementation-for-i915/20200714-095304
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-a002-20200714 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
reproduce (this is a W=1 build):
# save the attached .config to linux build tree
make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/i915/i915_irq.c:700:5: error: no previous prototype for 
>> 'g4x_get_flip_counter' [-Werror=missing-prototypes]
 700 | u32 g4x_get_flip_counter(struct drm_crtc *crtc)
 | ^~~~
   cc1: all warnings being treated as errors

vim +/g4x_get_flip_counter +700 drivers/gpu/drm/i915/i915_irq.c

   699  
 > 700  u32 g4x_get_flip_counter(struct drm_crtc *crtc)
   701  {
   702  struct drm_i915_private *dev_priv = to_i915(crtc->dev);
   703  enum pipe pipe = to_intel_crtc(crtc)->pipe;
   704  
   705  return I915_READ(PIPE_FLIPCOUNT_G4X(pipe));
   706  }
   707  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


.config.gz
Description: application/gzip
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 0/9] drm: Add privacy-screen class and connector properties

2020-07-14 Thread Alex Deucher
On Thu, Jul 9, 2020 at 8:48 AM Hans de Goede  wrote:
>
> Hi,
>
> On 7/8/20 11:25 PM, Alex Deucher wrote:
> > On Wed, Jul 8, 2020 at 12:43 PM Hans de Goede  wrote:
> >>
> >> Hi All,
> >>
> >> Here is the privacy-screen related code which we discussed a while ago.
> >> This series consists of a number of different parts:
> >>
> >> 1. A new version of Rajat's privacy-screen connector properties patch,
> >> this adds new userspace API in the form of new properties
> >>
> >> 2. Since on most devices the privacy screen is actually controlled by
> >> some vendor specific ACPI/WMI interface which has a driver under
> >> drivers/platform/x86, we need some "glue" code to make this functionality
> >> available to KMS drivers. Patches 3-5 add a new privacy-screen class for
> >> this, which allows non KMS drivers (and possibly KMS drivers too) to
> >> register a privacy-screen device and also adds an interface for KMS drivers
> >> to get access to the privacy-screen associated with a specific connector.
> >> This is modelled similar to how we deal with e.g. PWMs and GPIOs in the
> >> kernel, including separate includes for consumers and providers(drivers).
> >>
> >> 3. Some drm_connector helper functions to keep the actual changes needed
> >> for this in individual KMS drivers as small as possible (patch 6).
> >>
> >> 4. Make the thinkpad_acpi code register a privacy-screen device on
> >> ThinkPads with a privacy-screen (patches 7-8)
> >>
> >> 5. Make the i915 driver export the privacy-screen functionality through
> >> the connector properties on the eDP connector.
> >
> > Care to create a patch 10 for amdgpu?  Lenovo sells AMD thinkpads with
> > a privacy screen as well, presumably it works
> > the same way.
>
> Yes the AMD based Thinkpads should work the same way.
>
> We will need similar changes for amdgpu and very likely also for
> nouveau. The problem is I don't really have hw to test this.
>
> Do you have access to a recent thinkpad with amdgpu ? It does not need
> to have a privacy screen, as long as it is new enough that the ACPI
> tables have the GSSS and  methods you can test by ignoring
> the presence bit for the privacy-screen, I use this little change for
> that:

Thanks for the hints Hans.  If I can find some time, I will give it a try.

Alex

>
>  From 9438bababe77dfccbade5c2377bdc7d6a777a6c6 Mon Sep 17 00:00:00 2001
> From: Hans de Goede 
> Date: Wed, 27 May 2020 14:38:42 +0200
> Subject: [PATCH] platform/x86: thinkpad_acpi: Hack to allow testing
>   on devices without a privacy-screen
>
> Hack to allow testing on devices without a privacy-screen.
>
> Signed-off-by: Hans de Goede 
> ---
>   drivers/gpu/drm/drm_privacy_screen_x86.c | 4 
>   drivers/platform/x86/thinkpad_acpi.c | 4 ++--
>   2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_privacy_screen_x86.c 
> b/drivers/gpu/drm/drm_privacy_screen_x86.c
> index f486d9087819..87725766a90d 100644
> --- a/drivers/gpu/drm/drm_privacy_screen_x86.c
> +++ b/drivers/gpu/drm/drm_privacy_screen_x86.c
> @@ -41,7 +41,11 @@ static bool __init detect_thinkpad_privacy_screen(void)
> if (ACPI_FAILURE(status))
> return false;
>
> +#if 1
> +   return true;
> +#else
> return (output & 0x1) ? true : false;
> +#endif
>   }
>
>   static const struct arch_init_data arch_init_data[] __initconst = {
> diff --git a/drivers/platform/x86/thinkpad_acpi.c 
> b/drivers/platform/x86/thinkpad_acpi.c
> index 1583c18f7f77..92aad746d1f8 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -9747,8 +9747,8 @@ static int tpacpi_lcdshadow_init(struct ibm_init_struct 
> *iibm)
> if (!acpi_evalf(lcdshadow_get_handle, &output, NULL, "dd", 0))
> return -EIO;
>
> -   if (!(output & 0x1))
> -   return 0;
> +// if (!(output & 0x1))
> +// return 0;
>
> lcdshadow_dev = drm_privacy_screen_register(&tpacpi_pdev->dev,
> &lcdshadow_ops);
> --
> 2.26.2
>
>
> So if you have a machine with an AMDGPU and with the mentioned ACPI methods,
> then you should be able to implement this yourself. You can read/write the new
> props under X11 with xrandr. And you monitor if the changes make it to the
> hardware by doing:
>
> cat /proc/acpi/ibm/lcdshadow
>
> And you can simulate external changes (like through a hotkey handled by the 
> embedded-controller) by doing:
>
> echo 0 > /proc/acpi/ibm/lcdshadow
> echo 1 > /proc/acpi/ibm/lcdshadow
>
> When you do this you should see udev change events for the properties, you
> can test for those by doing:
>
> sudo udevadm monitor -u -p
>
> ###
>
> With all that said, I can take a shot at blindly implementing this for amdgpu
> but I would greatly prefer an actually tested patch, even if it is tested in
> the way described above. When the patch is ready you can just send it to me
> and I'll add my s-o-b and add it as patch 

Re: [PATCH] drm: msm: a6xx: fix gpu failure after system resume

2020-07-14 Thread Jordan Crouse
On Tue, Jul 14, 2020 at 06:55:30PM +0530, Akhil P Oommen wrote:
> On targets where GMU is available, GMU takes over the ownership of GX GDSC
> during its initialization. So, take a refcount on the GX PD on behalf of
> GMU before we initialize it. This makes sure that nobody can collapse the
> GX GDSC once GMU owns the GX GDSC. This patch fixes some weird failures
> during GPU wake up during system resume.

The change looks fine but this explanation is confusing. When I read it I
thought "oh, man, we weren't taking a reference to the GX PD during resume???"
but that's not really the case. We *are* taking a reference, just not soon
enough to avoid possible issues. It would be helpful if you reworded this to
explain that you are moving the reference and perhaps to shine a bit more light
on what the "weird" failures are.

Jordan

> Signed-off-by: Akhil P Oommen 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 18 ++
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index a6f43ff..5b2df7d 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -873,10 +873,19 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
>   /* Turn on the resources */
>   pm_runtime_get_sync(gmu->dev);
>  
> + /*
> +  * "enable" the GX power domain which won't actually do anything but it
> +  * will make sure that the refcounting is correct in case we need to
> +  * bring down the GX after a GMU failure
> +  */
> + if (!IS_ERR_OR_NULL(gmu->gxpd))
> + pm_runtime_get_sync(gmu->gxpd);
> +
>   /* Use a known rate to bring up the GMU */
>   clk_set_rate(gmu->core_clk, 2);
>   ret = clk_bulk_prepare_enable(gmu->nr_clocks, gmu->clocks);
>   if (ret) {
> + pm_runtime_put(gmu->gxpd);
>   pm_runtime_put(gmu->dev);
>   return ret;
>   }
> @@ -919,19 +928,12 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
>   /* Set the GPU to the current freq */
>   a6xx_gmu_set_initial_freq(gpu, gmu);
>  
> - /*
> -  * "enable" the GX power domain which won't actually do anything but it
> -  * will make sure that the refcounting is correct in case we need to
> -  * bring down the GX after a GMU failure
> -  */
> - if (!IS_ERR_OR_NULL(gmu->gxpd))
> - pm_runtime_get(gmu->gxpd);
> -
>  out:
>   /* On failure, shut down the GMU to leave it in a good state */
>   if (ret) {
>   disable_irq(gmu->gmu_irq);
>   a6xx_rpmh_stop(gmu);
> + pm_runtime_put(gmu->gxpd);
>   pm_runtime_put(gmu->dev);
>   }
>  
> -- 
> 2.7.4
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 04/25] drm/vkms: Annotate vblank timer

2020-07-14 Thread Melissa Wen
Hi,

On 07/14, Daniel Vetter wrote:
> On Tue, Jul 14, 2020 at 11:57 AM Melissa Wen  wrote:
> >
> > On 07/12, Rodrigo Siqueira wrote:
> > > Hi,
> > >
> > > Everything looks fine to me, I just noticed that the amdgpu patches did
> > > not apply smoothly, however it was trivial to fix the issues.
> > >
> > > Reviewed-by: Rodrigo Siqueira 
> > >
> > > Melissa,
> > > Since you are using vkms regularly, could you test this patch and review
> > > it? Remember to add your Tested-by when you finish.
> > >
> > Hi,
> >
> > I've applied the patch series, ran some tests on vkms, and found no
> > issues. I mean, things have remained stable.
> >
> > Tested-by: Melissa Wen 
> 
> Did you test with CONFIG_PROVE_LOCKING enabled in the kernel .config?
> Without that enabled, there's not really any change here, but with
> that enabled there might be some lockdep splats in dmesg indicating a
> problem.
>

Even with the lock debugging config enabled, no new issue arose in dmesg
during my tests using vkms.

Melissa

> Thanks, Daniel
> >
> > > Thanks
> > >
> > > On 07/07, Daniel Vetter wrote:
> > > > This is needed to signal the fences from page flips, annotate it
> > > > accordingly. We need to annotate entire timer callback since if we get
> > > > stuck anywhere in there, then the timer stops, and hence fences stop.
> > > > Just annotating the top part that does the vblank handling isn't
> > > > enough.
> > > >
> > > > Cc: linux-me...@vger.kernel.org
> > > > Cc: linaro-mm-...@lists.linaro.org
> > > > Cc: linux-r...@vger.kernel.org
> > > > Cc: amd-...@lists.freedesktop.org
> > > > Cc: intel-...@lists.freedesktop.org
> > > > Cc: Chris Wilson 
> > > > Cc: Maarten Lankhorst 
> > > > Cc: Christian König 
> > > > Signed-off-by: Daniel Vetter 
> > > > Cc: Rodrigo Siqueira 
> > > > Cc: Haneen Mohammed 
> > > > Cc: Daniel Vetter 
> > > > ---
> > > >  drivers/gpu/drm/vkms/vkms_crtc.c | 8 +++-
> > > >  1 file changed, 7 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> > > > b/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > index ac85e17428f8..a53a40848a72 100644
> > > > --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > @@ -1,5 +1,7 @@
> > > >  // SPDX-License-Identifier: GPL-2.0+
> > > >
> > > > +#include 
> > > > +
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > @@ -14,7 +16,9 @@ static enum hrtimer_restart 
> > > > vkms_vblank_simulate(struct hrtimer *timer)
> > > > struct drm_crtc *crtc = &output->crtc;
> > > > struct vkms_crtc_state *state;
> > > > u64 ret_overrun;
> > > > -   bool ret;
> > > > +   bool ret, fence_cookie;
> > > > +
> > > > +   fence_cookie = dma_fence_begin_signalling();
> > > >
> > > > ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > > >   output->period_ns);
> > > > @@ -49,6 +53,8 @@ static enum hrtimer_restart 
> > > > vkms_vblank_simulate(struct hrtimer *timer)
> > > > DRM_DEBUG_DRIVER("Composer worker already 
> > > > queued\n");
> > > > }
> > > >
> > > > +   dma_fence_end_signalling(fence_cookie);
> > > > +
> > > > return HRTIMER_RESTART;
> > > >  }
> > > >
> > > > --
> > > > 2.27.0
> > > >
> > >
> > > --
> > > Rodrigo Siqueira
> > > https://siqueira.tech
> >
> >
> 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


  1   2   3   >