* Re: [PATCH] iommu/mediatek: Use totalram_pages to setup enable_4GB
From: David Hildenbrand @ 2020-06-04 11:32 UTC (permalink / raw)
To: Miles Chen
Cc: wsd_upstream, Joerg Roedel, linux-kernel, Chao Hao, iommu,
linux-mediatek, Yong Wu, Matthias Brugger, yingjoe.chen,
linux-arm-kernel
In-Reply-To: <1591264174.12661.17.camel@mtkswgap22>
On 04.06.20 11:49, Miles Chen wrote:
> On Thu, 2020-06-04 at 10:25 +0200, David Hildenbrand wrote:
>> On 04.06.20 10:01, Miles Chen wrote:
>>> To build this driver as a kernel module, we cannot use
>>> the unexported symbol "max_pfn" to setup enable_4GB.
>>>
>>> Use totalram_pages() instead to setup enable_4GB.
>>>
>>> Suggested-by: Mike Rapoport <rppt@linux.ibm.com>
>>> Signed-off-by: Miles Chen <miles.chen@mediatek.com>
>>> Cc: David Hildenbrand <david@redhat.com>
>>> Cc: Yong Wu <yong.wu@mediatek.com>
>>> Cc: Chao Hao <chao.hao@mediatek.com>
>>> ---
>>> drivers/iommu/mtk_iommu.c | 5 ++---
>>> 1 file changed, 2 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
>>> index 5f4d6df59cf6..c2798a6e0e38 100644
>>> --- a/drivers/iommu/mtk_iommu.c
>>> +++ b/drivers/iommu/mtk_iommu.c
>>> @@ -3,7 +3,6 @@
>>> * Copyright (c) 2015-2016 MediaTek Inc.
>>> * Author: Yong Wu <yong.wu@mediatek.com>
>>> */
>>> -#include <linux/memblock.h>
>>> #include <linux/bug.h>
>>> #include <linux/clk.h>
>>> #include <linux/component.h>
>>> @@ -626,8 +625,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
>>> return -ENOMEM;
>>> data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
>>>
>>> - /* Whether the current dram is over 4GB */
>>> - data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
>>> + /* Whether the current dram is over 4GB, note: DRAM start at 1GB */
>>> + data->enable_4GB = !!(totalram_pages() > ((SZ_2G + SZ_1G) >> PAGE_SHIFT));
>>
>> A similar thing seems to be done by
>> drivers/media/platform/mtk-vpu/mtk_vpu.c:
>> vpu->enable_4GB = !!(totalram_pages() > (SZ_2G >> PAGE_SHIFT));
>>
>> I do wonder if some weird memory hotplug setups might give you false
>> negatives.
>>
>> E.g., start a VM with 1GB and hotplug 1GB - it will be hotplugged on
>> x86-64 above 4GB, turning max_pfn into 5GB. totalram_pages() should
>> return something < 2GB.
>>
>> Same can happen when you have a VM and use ballooning to fake-unplug
>> memory, making totalram_pages() return something < 4GB, but leaving
>> usable pfns >= 4GB
>
> Yes. Yingjoe also told me that this patch is not correct.
>
> Thanks for pointing this out. totalram_pages() does not work
> for some cases:
>
Just a thought: If memory hotplug is applicable as well, you might
either want to always assume data->enable_4GB, or handle memory hotplug
events from the memory notifier, when new memory gets onlined (not sure
how tricky that is).
--
Thanks,
David / dhildenb
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 0/5 v2] KASan for ARM
From: Ard Biesheuvel @ 2020-06-04 11:26 UTC (permalink / raw)
To: Linus Walleij
Cc: Rob Herring, Florian Fainelli, Abbott Liu, Russell King,
Andrey Ryabinin, Linux ARM
In-Reply-To: <CACRpkdYnXCfUxbd8PxM5N9=xHDi6-55VcmkEzMNpUGR0k5snag@mail.gmail.com>
On Thu, 4 Jun 2020 at 11:24, Linus Walleij <linus.walleij@linaro.org> wrote:
>
> On Wed, Jun 3, 2020 at 10:45 AM Linus Walleij <linus.walleij@linaro.org> wrote:
> > On Mon, Jun 1, 2020 at 6:37 PM Florian Fainelli <f.fainelli@gmail.com> wrote:
> >
> > > This branch got me a bit further,
> >
> > Thanks, at least we get improvements. :)
> >
> > > but still failed to fully initialize
> > > (see attached kasan.log), on another platform with a slightly different
> > > memory map, I ended up getting a different error (kasan2.log).
> >
> > I have this error too on a Qualcomm board, it is what I report
> > in the cover letter, that if I load the kernel into 0x40200000
> > this happens but when I load it into 0x50000000 it does not
> > happen.
>
> So this is what happens to me, even after I try to de-instrument
> the DT parsing code (maybe I do it all wrong...)
> This is done with that patch:
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/commit/?h=kasan-apq8060-test&id=1cd83357f3c35b037400f6ec2547eeff074c578c
>
> If I boot from physical memory at 0x40200000
> fastboot --base 40200000 --cmdline "console=ttyMSM0,115200,n8" boot zImage
>
> kasan: populating shadow for b7040000, b75c0000
> kasan: populating shadow for b8000000, bb000000
> kasan: populating shadow for b6e00000, b7000000
> kasan: Kernel address sanitizer initialized
> 8<--- cut here ---
> Unable to handle kernel paging request at virtual address c30050b0
> pgd = (ptrval)
> [c30050b0] *pgd=00000000c
> Internal error: Oops: 5 [#1] PREEMPT SMP ARM
> Modules linked in:c
> CPU: 0 PID: 0 Comm: swapper Not tainted 5.7.0-00011-g1cd83357f3c3 #34
> Hardware name: Generic DT based system
> PC is at fdt_check_header+0x0/0x168
> LR is at __unflatten_device_tree+0x6c/0x338
> pc : [<c08e6968>] lr : [<c0d698a8>] psr: 60000093
> sp : c1e03db8 ip : cffffee0 fp : fffff000
> r10: 00000000 r9 : c2646000 r8 : 00000000
> r7 : c30050b0 r6 : c192e9e4 r5 : c19492e8 r4 : c21d7448
> r3 : 00000000 r2 : c2646000 r1 : 00000000 r0 : c30050b0
> (...)
> [<c08e6968>] (fdt_check_header) from [<c192e9e4>]
> (early_init_dt_alloc_memory_arch+0x0/0x64)
> [<c192e9e4>] (early_init_dt_alloc_memory_arch) from [<c1930264>]
> (unflatten_device_tree+0x34/0x44)
> [<c1930264>] (unflatten_device_tree) from [<c1905794>] (setup_arch+0xac4/0xde8)
> [<c1905794>] (setup_arch) from [<c1900b98>] (start_kernel+0xd8/0x634)
> [<c1900b98>] (start_kernel) from [<00000000>] (0x0)
> Code: e3a00020 e12fff1e e3a0001c e12fff1e (e5901000)
> random: get_random_bytes called from print_oops_end_marker+0x38/0x50
> with crng_init=0
> ---[ end trace 0000000000000000 ]---
> Kernel panic - not syncing: Attempted to kill the idle task!
> ---[ end Kernel panic - not syncing: Attempted to kill the idle task! ]---
>
I don't think we ever check whether the ATAGS/DTB pointer points into
memory that is described to the kernel as unreserved lowmem. We simply
call phys_to_virt() on it [in setup_machine_fdt()], and assume that by
the time we call unflatten_device_tree(), the same virtual address
still points to the DT contents.
On arm64, we have a special fixmap slot for the DT, so there this
doesn't happen.
Could you try whether the following makes the issues go away?
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d8e18cdd96d3..b00867a026ed 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -1076,6 +1076,7 @@ void __init hyp_mode_check(void)
void __init setup_arch(char **cmdline_p)
{
const struct machine_desc *mdesc;
+ void *fdt;
setup_processor();
mdesc = setup_machine_fdt(__atags_pointer);
@@ -1135,6 +1136,8 @@ void __init setup_arch(char **cmdline_p)
if (mdesc->restart)
arm_pm_restart = mdesc->restart;
+ fdt = memremap(__atags_pointer, SZ_1M, MEMREMAP_WB);
+ early_init_dt_verify(fdt);
unflatten_device_tree();
arm_dt_init_cpu_maps();
(Not saying this is the right fix, just testing a hypothesis)
> But if I instead boot from 0x50000000 I just get this lesser error and
> the platform actually comes up:
> fastboot --base 50000000 --cmdline "console=ttyMSM0,115200,n8" boot zImage
>
> [ 0.000000] kasan: populating shadow for b7000000, b9000000
> [ 0.000000] kasan: populating shadow for b6e00000, b7000000
> [ 0.000000] kasan: Kernel address sanitizer initialized
> [ 0.000000] ==================================================================
> [ 0.000000] BUG: KASAN: stack-out-of-bounds in
> memblock_alloc_try_nid+0x9c/0xac
> [ 0.000000] Write of size 61920 at addr cdbd6e20 by task swapper/0
> [ 0.000000]
> [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted
> 5.7.0-00011-g1cd83357f3c3 #34
> [ 0.000000] Hardware name: Generic DT based system
> [ 0.000000] [<c0317844>] (unwind_backtrace) from [<c0310544>]
> (show_stack+0x10/0x14)
> [ 0.000000] [<c0310544>] (show_stack) from [<c08e6374>]
> (dump_stack+0x80/0x98)
> [ 0.000000] [<c08e6374>] (dump_stack) from [<c050eed0>]
> (print_address_description.constprop.3+0x50/0x478)
> [ 0.000000] [<c050eed0>] (print_address_description.constprop.3)
> from [<c050f508>] (__kasan_report+0xf0/0x12c)
> [ 0.000000] [<c050f508>] (__kasan_report) from [<c050e95c>]
> (kasan_report+0x34/0x3c)
> [ 0.000000] [<c050e95c>] (kasan_report) from [<c050fed0>]
> (check_memory_region+0x14c/0x1b0)
> [ 0.000000] [<c050fed0>] (check_memory_region) from [<c050e100>]
> (memset+0x20/0x3c)
> [ 0.000000] [<c050e100>] (memset) from [<c1918898>]
> (memblock_alloc_try_nid+0x9c/0xac)
> [ 0.000000] [<c1918898>] (memblock_alloc_try_nid) from [<c192ea14>]
> (early_init_dt_alloc_memory_arch+0x30/0x64)
> [ 0.000000] [<c192ea14>] (early_init_dt_alloc_memory_arch) from
> [<c0d698f0>] (__unflatten_device_tree+0xb4/0x338)
> [ 0.000000] [<c0d698f0>] (__unflatten_device_tree) from
> [<c1930264>] (unflatten_device_tree+0x34/0x44)
> [ 0.000000] [<c1930264>] (unflatten_device_tree) from [<c1905794>]
> (setup_arch+0xac4/0xde8)
> [ 0.000000] [<c1905794>] (setup_arch) from [<c1900b98>]
> (start_kernel+0xd8/0x634)
> [ 0.000000] [<c1900b98>] (start_kernel) from [<00000000>] (0x0)
> [ 0.000000]
> [ 0.000000] The buggy address belongs to the page:
> [ 0.000000] page:cffafac0 refcount:1 mapcount:0 mapping:00000000 index:0x0
> [ 0.000000] flags: 0x0()
> [ 0.000000] raw: 00000000 cffafac4 cffafac4 00000000 00000000
> 00000000 ffffffff 00000001
> [ 0.000000] page dumped because: kasan: bad access detected
> [ 0.000000]
> [ 0.000000] Memory state around the buggy address:
> [ 0.000000] cdbe3d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> [ 0.000000] cdbe3d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> [ 0.000000] >cdbe3e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> [ 0.000000] ^
> [ 0.000000] cdbe3e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> [ 0.000000] cdbe3f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> [ 0.000000] ==================================================================
>
> There is something really funky going on with how devicetree is unflattened
> in this platform I think, I just need to figure it out.
>
> I do not think it is a KASan bug per se, more of a DT parser issue, like it is
> doing stuff that need to be properly de-instrumented.
>
> Any hints welcome!
>
> Yours,
> Linus Walleij
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH 2/3] ARM: dts: bcm2711: Update SPI nodes compatible strings
From: Mark Brown @ 2020-06-04 11:13 UTC (permalink / raw)
To: Lukas Wunner
Cc: moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Florian Fainelli, Scott Branden, Ray Jui, linux-kernel,
open list:SPI SUBSYSTEM, Rob Herring,
maintainer:BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITE...,
moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
Martin Sperl, Nicolas Saenz Julienne
In-Reply-To: <20200604042038.jzolu6k7q3d6bsvq@wunner.de>
[-- Attachment #1.1: Type: text/plain, Size: 883 bytes --]
On Thu, Jun 04, 2020 at 06:20:38AM +0200, Lukas Wunner wrote:
> On Wed, Jun 03, 2020 at 08:46:54PM -0700, Florian Fainelli wrote:
> > The BCM2711 SoC features 5 SPI controllers which all share the same
> > interrupt line, the SPI driver needs to support interrupt sharing,
> > therefore use the chip specific compatible string to help with that.
> You're saying above that the 5 controllers all share the interrupt
> but below you're only changing the compatible string of 4 controllers.
> So I assume spi0 still has its own interrupt and only the additional
> 4 controllers present on the BCM2711/BCM7211 share their interrupt?
Regardless of what's going on with the interrupts the compatible string
should reflect the IP version so unless for some reason someone taped
out two different versions of the IP it seems odd that the compatible
strings would vary within a given SoC.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] pinctrl: pxa: pxa2xx: Remove 'pxa2xx_pinctrl_exit()' which is unused and broken
From: Joe Perches @ 2020-06-04 11:08 UTC (permalink / raw)
To: Julia Lawall
Cc: Linux ARM, Linus Walleij, kernel-janitors,
linux-kernel@vger.kernel.org, Haojian Zhuang,
open list:GPIO SUBSYSTEM, Christophe JAILLET, Dan Carpenter,
Robert Jarzmik, Daniel Mack
In-Reply-To: <alpine.DEB.2.21.2006041228520.2577@hadrien>
On Thu, 2020-06-04 at 12:33 +0200, Julia Lawall wrote:
>
> On Thu, 4 Jun 2020, Joe Perches wrote:
>
> > On Thu, 2020-06-04 at 11:52 +0200, Julia Lawall wrote:
> > > Should Fixes also be used when the change will make it hard to port other
> > > fixes over it?
> >
> > If it's a logic defect or regression that's being fixed,
> > shouldn't the logic defect or regression be fixed as
> > reasonably soon as possible?
>
> Sure, but I recall seeing some patches that mentioned that the problem had
> existed since the beginning of git. Of course, it should be rare.
git history goes back 15 years already.
There are scant few bugs that old.
There is a tree with even older history that Rob Landley
still has here: https://landley.net/kdocs/fullhist/
It does make git blame research a bit easier for those
rare and extremely old defects.
> > The nature of the fix should ideally be optimal for
> > backporting, but I believe that should not stop any
> > consideration for the standalone fix itself.
>
> I'm not sure to follow this.
I think it comes down to defects in current need to be
fixed. Describing
the base commit that is being fixed
is useful for backporting.
I believe it's not reasonable to ask the author of a
fix to research how it could or should be backported.
> Sometimes non-bug fixes that block
> backporting a bug fix have to be backported as well. So the fixes would
> again highlight the range of versions affected by the issue.
Sure, but the non-bug fixes that may also need backporting
to enable easy backports of the actual fix should not be
described in the Fixes: <commit> as those are generally
easily researched from a command like:
$ git log <commit>.. <files in fix>
by whoever needs to backport.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] pinctrl: pxa: pxa2xx: Remove 'pxa2xx_pinctrl_exit()' which is unused and broken
From: Julia Lawall @ 2020-06-04 10:33 UTC (permalink / raw)
To: Joe Perches
Cc: Linux ARM, Linus Walleij, kernel-janitors,
linux-kernel@vger.kernel.org, Haojian Zhuang,
open list:GPIO SUBSYSTEM, Christophe JAILLET, Dan Carpenter,
Robert Jarzmik, Daniel Mack
In-Reply-To: <32232229031e02edcc268b1074c9bac44012ee35.camel@perches.com>
On Thu, 4 Jun 2020, Joe Perches wrote:
> On Thu, 2020-06-04 at 11:52 +0200, Julia Lawall wrote:
> > Should Fixes also be used when the change will make it hard to port other
> > fixes over it?
>
> If it's a logic defect or regression that's being fixed,
> shouldn't the logic defect or regression be fixed as
> reasonably soon as possible?
Sure, but I recall seeing some patches that mentioned that the problem had
existed since the beginning of git. Of course, it should be rare.
>
> The nature of the fix should ideally be optimal for
> backporting, but I believe that should not stop any
> consideration for the standalone fix itself.
I'm not sure to follow this. Sometimes non-bug fixes that block
backporting a bug fix have to be backported as well. So the fixes would
again highlight the range of versions affected by the issue.
julia
> What do you think?
>
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v3 2/6] PCI: uniphier: Add misc interrupt handler to invoke PME and AER
From: Marc Zyngier @ 2020-06-04 10:11 UTC (permalink / raw)
To: Kunihiko Hayashi
Cc: devicetree, Lorenzo Pieralisi, Masami Hiramatsu, Jassi Brar,
Jingoo Han, linux-pci, linux-kernel, Masahiro Yamada, Rob Herring,
Gustavo Pimentel, Bjorn Helgaas, linux-arm-kernel
In-Reply-To: <2e07d3d3-515b-57e1-0a36-8892bc38bb7b@socionext.com>
On 2020-06-04 10:43, Kunihiko Hayashi wrote:
[...]
>>> -static void uniphier_pcie_irq_handler(struct irq_desc *desc)
>>> +static void uniphier_pcie_misc_isr(struct pcie_port *pp)
>>> {
>>> - struct pcie_port *pp = irq_desc_get_handler_data(desc);
>>> struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>>> struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
>>> - struct irq_chip *chip = irq_desc_get_chip(desc);
>>> - unsigned long reg;
>>> - u32 val, bit, virq;
>>> + u32 val, virq;
>>>
>>> - /* INT for debug */
>>> val = readl(priv->base + PCL_RCV_INT);
>>>
>>> if (val & PCL_CFG_BW_MGT_STATUS)
>>> dev_dbg(pci->dev, "Link Bandwidth Management Event\n");
>>> +
>>> if (val & PCL_CFG_LINK_AUTO_BW_STATUS)
>>> dev_dbg(pci->dev, "Link Autonomous Bandwidth Event\n");
>>> - if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS)
>>> - dev_dbg(pci->dev, "Root Error\n");
>>> - if (val & PCL_CFG_PME_MSI_STATUS)
>>> - dev_dbg(pci->dev, "PME Interrupt\n");
>>> +
>>> + if (pci_msi_enabled()) {
>>
>> This checks whether the kernel supports MSIs. Not that they are
>> enabled in your controller. Is that really what you want to do?
>
> The below two status bits are valid when the interrupt for MSI is
> asserted.
> That is, pci_msi_enabled() is wrong.
>
> I'll modify the function to check the two bits only if this function is
> called from MSI handler.
>
>>
>>> + if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS) {
>>> + dev_dbg(pci->dev, "Root Error Status\n");
>>> + virq = irq_linear_revmap(pp->irq_domain, 0);
>>> + generic_handle_irq(virq);
>>> + }
>>> +
>>> + if (val & PCL_CFG_PME_MSI_STATUS) {
>>> + dev_dbg(pci->dev, "PME Interrupt\n");
>>> + virq = irq_linear_revmap(pp->irq_domain, 0);
>>> + generic_handle_irq(virq);
>>> + }
>>
>> These two cases do the exact same thing, calling the same interrupt.
>> What is the point of dealing with them independently?
>
> Both PME and AER are asserted from MSI-0, and each handler checks its
> own
> status bit in the PCIe register (aer_irq() in pcie/aer.c and
> pcie_pme_irq()
> in pcie/pme.c).
> So I think this handler calls generic_handle_irq() for the same MSI-0.
So what is wrong with
if (val & (PCL_CFG_AER_RC_ERR_MSI_STATUS |
PCL_CFG_PME_MSI_STATUS)) {
// handle interrupt
}
?
If you have two handlers for the same interrupt, this is a shared
interrupt and each handler will be called in turn.
M.
--
Jazz is not dead. It just smells funny...
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] pinctrl: pxa: pxa2xx: Remove 'pxa2xx_pinctrl_exit()' which is unused and broken
From: Joe Perches @ 2020-06-04 10:00 UTC (permalink / raw)
To: Julia Lawall
Cc: Linux ARM, Linus Walleij, kernel-janitors,
linux-kernel@vger.kernel.org, Haojian Zhuang,
open list:GPIO SUBSYSTEM, Christophe JAILLET, Dan Carpenter,
Robert Jarzmik, Daniel Mack
In-Reply-To: <alpine.DEB.2.21.2006041147360.2577@hadrien>
On Thu, 2020-06-04 at 11:52 +0200, Julia Lawall wrote:
> Should Fixes also be used when the change will make it hard to port other
> fixes over it?
If it's a logic defect or regression that's being fixed,
shouldn't the logic defect or regression be fixed as
reasonably soon as possible?
The nature of the fix should ideally be optimal for
backporting, but I believe that should not stop any
consideration for the standalone fix itself.
What do you think?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] pinctrl: pxa: pxa2xx: Remove 'pxa2xx_pinctrl_exit()' which is unused and broken
From: Julia Lawall @ 2020-06-04 9:52 UTC (permalink / raw)
To: Joe Perches
Cc: Linux ARM, Linus Walleij, kernel-janitors,
linux-kernel@vger.kernel.org, Haojian Zhuang,
open list:GPIO SUBSYSTEM, Christophe JAILLET, Dan Carpenter,
Robert Jarzmik, Daniel Mack
In-Reply-To: <2aa49a543e6f48a6f428a37b63a06f9149870225.camel@perches.com>
On Thu, 4 Jun 2020, Joe Perches wrote:
> On Thu, 2020-06-04 at 11:31 +0300, Dan Carpenter wrote:
> > On Thu, Jun 04, 2020 at 12:08:49AM +0200, Linus Walleij wrote:
> []
> > > Fixes means it fixes something that was wrong in that commit.
> > > That's all. Whether syntactic or semantic or regression or
> > > serious or not does not matter. It is also not compulsory to
> > > add it is just helpful.
> >
> > Fixes tag should be compulsory for actual bug fixes. We had a the
> > Bad Binder exploit last year because commit f5cb779ba163
> > ("ANDROID: binder: remove waitqueue when thread exits.") had no Fixes
> > tag and wasn't backported to Android kernels.
>
> Fixes tags IMO should be exclusively for actual bug fixes
> and should be mandatory.
I'm not sure that it is always possible to determine the specific commit
that a patch fixes. Some bugs are too old. Some bugs may arise from an
interaction of issues. I don't have a concrete example, but I feel uneasy
about mandator and compulsory. Neither word is in the proposed text,
though.
Should Fixes also be used when the change will make it hard to port other
fixes over it?
julia
>
> Perhaps:
> ---
> Documentation/process/submitting-patches.rst | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst
> index 1699b7f8e63a..285a84ae79de 100644
> --- a/Documentation/process/submitting-patches.rst
> +++ b/Documentation/process/submitting-patches.rst
> @@ -636,12 +636,14 @@ idea was not posted in a public forum. That said, if we diligently credit our
> idea reporters, they will, hopefully, be inspired to help us again in the
> future.
>
> -A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
> -is used to make it easy to determine where a bug originated, which can help
> -review a bug fix. This tag also assists the stable kernel team in determining
> -which stable kernel versions should receive your fix. This is the preferred
> -method for indicating a bug fixed by the patch. See :ref:`describe_changes`
> -for more details.
> +A Fixes: tag indicates that the patch fixes a "bug". i.e.: a logic defect or
> +regression in a previous commit. A Fixes: tag should not be used to indicate
> +that a previous commit had some trivial defect in spelling in the commit log or
> +some whitespace defect. The Fixes: tag is used to make it easy to determine
> +where a bug originated, which can help review a bug fix. The Fixes: tag also
> +assists the stable kernel team in determining which stable kernel versions
> +should receive your fix. This is the preferred method for indicating a bug is
> +fixed by the patch. See :ref:`describe_changes` for more details.
>
> .. _the_canonical_patch_format:
>
>
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 08/14] powerpc: add support for folded p4d page tables
From: Qian Cai @ 2020-06-04 9:50 UTC (permalink / raw)
To: Andrew Morton
Cc: Rich Felker, linux-ia64, Geert Uytterhoeven, linux-sh,
Benjamin Herrenschmidt, linux-mm, Paul Mackerras, linux-hexagon,
Will Deacon, kvmarm, Jonas Bonn, linux-arch, Brian Cain,
Marc Zyngier, Russell King, Ley Foon Tan, Mike Rapoport,
Catalin Marinas, Julien Thierry, uclinux-h8-devel, Fenghua Yu,
Arnd Bergmann, Suzuki K Poulose, kvm-ppc, Stefan Kristiansson,
openrisc, Stafford Horne, Guan Xuetao, linux-arm-kernel,
Christophe Leroy, Tony Luck, Yoshinori Sato, linux-kernel,
James Morse, Michael Ellerman, nios2-dev, linuxppc-dev,
Mike Rapoport
In-Reply-To: <20200603120522.7646d56a23088416a7d3fc1a@linux-foundation.org>
> On Jun 3, 2020, at 3:05 PM, Andrew Morton <akpm@linux-foundation.org> wrote:
>
> A bunch of new material just landed in linux-next/powerpc.
>
> The timing is awkward! I trust this will be going into mainline during
> this merge window? If not, please drop it and repull after -rc1.
I have noticed the same pattern over and over again, i.e., many powerpc new material has only shown up in linux-next for only a few days before sending for a pull request to Linus.
There are absolutely no safe net for this kind of practice. The main problem is that Linus seems totally fine with it.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] iommu/mediatek: Use totalram_pages to setup enable_4GB
From: Miles Chen @ 2020-06-04 9:49 UTC (permalink / raw)
To: David Hildenbrand
Cc: wsd_upstream, Joerg Roedel, linux-kernel, Chao Hao, iommu,
linux-mediatek, Yong Wu, Matthias Brugger, yingjoe.chen,
linux-arm-kernel
In-Reply-To: <55820901-430b-14c4-9426-7a4991ca0eed@redhat.com>
On Thu, 2020-06-04 at 10:25 +0200, David Hildenbrand wrote:
> On 04.06.20 10:01, Miles Chen wrote:
> > To build this driver as a kernel module, we cannot use
> > the unexported symbol "max_pfn" to setup enable_4GB.
> >
> > Use totalram_pages() instead to setup enable_4GB.
> >
> > Suggested-by: Mike Rapoport <rppt@linux.ibm.com>
> > Signed-off-by: Miles Chen <miles.chen@mediatek.com>
> > Cc: David Hildenbrand <david@redhat.com>
> > Cc: Yong Wu <yong.wu@mediatek.com>
> > Cc: Chao Hao <chao.hao@mediatek.com>
> > ---
> > drivers/iommu/mtk_iommu.c | 5 ++---
> > 1 file changed, 2 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index 5f4d6df59cf6..c2798a6e0e38 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -3,7 +3,6 @@
> > * Copyright (c) 2015-2016 MediaTek Inc.
> > * Author: Yong Wu <yong.wu@mediatek.com>
> > */
> > -#include <linux/memblock.h>
> > #include <linux/bug.h>
> > #include <linux/clk.h>
> > #include <linux/component.h>
> > @@ -626,8 +625,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> > return -ENOMEM;
> > data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
> >
> > - /* Whether the current dram is over 4GB */
> > - data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> > + /* Whether the current dram is over 4GB, note: DRAM start at 1GB */
> > + data->enable_4GB = !!(totalram_pages() > ((SZ_2G + SZ_1G) >> PAGE_SHIFT));
>
> A similar thing seems to be done by
> drivers/media/platform/mtk-vpu/mtk_vpu.c:
> vpu->enable_4GB = !!(totalram_pages() > (SZ_2G >> PAGE_SHIFT));
>
> I do wonder if some weird memory hotplug setups might give you false
> negatives.
>
> E.g., start a VM with 1GB and hotplug 1GB - it will be hotplugged on
> x86-64 above 4GB, turning max_pfn into 5GB. totalram_pages() should
> return something < 2GB.
>
> Same can happen when you have a VM and use ballooning to fake-unplug
> memory, making totalram_pages() return something < 4GB, but leaving
> usable pfns >= 4GB
Yes. Yingjoe also told me that this patch is not correct.
Thanks for pointing this out. totalram_pages() does not work
for some cases:
e.g., DRAM start @0x4000_0000 and DRAM size is 0x1_0000_0000 but we
reserve large amount of memory, which makes totalram_pages() < 3GB but
it is possible to allocate a pfn >= 4GB.
I will discuss this internally.
Miles
> .
>
> but
> ... I don't know if I understood what "enable_4GB" needs/implies
> ... I don't know if this is applicable to VMs
> at all (on real HW such
> memory hotplug setups should not exist)
> ... I don't know how this code would react to memory hotplug, so if the
> condition changes after the driver loaded and enable_4GB would
> suddenly apply. Again, most probably not relevant on real HW, only
> for VMs.
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v3 2/6] PCI: uniphier: Add misc interrupt handler to invoke PME and AER
From: Kunihiko Hayashi @ 2020-06-04 9:43 UTC (permalink / raw)
To: Marc Zyngier
Cc: devicetree, Lorenzo Pieralisi, Masami Hiramatsu, Jassi Brar,
Jingoo Han, linux-pci, linux-kernel, Masahiro Yamada, Rob Herring,
Gustavo Pimentel, Bjorn Helgaas, linux-arm-kernel
In-Reply-To: <78af3b11de9c513f9be2a1f42f273f27@kernel.org>
Hi Marc,
On 2020/06/03 20:22, Marc Zyngier wrote:
> On 2020-06-03 09:54, Kunihiko Hayashi wrote:
>> The misc interrupts consisting of PME, AER, and Link event, is handled
>> by INTx handler, however, these interrupts should be also handled by
>> MSI handler.
>>
>> This adds the function uniphier_pcie_misc_isr() that handles misc
>> intterupts, which is called from both INTx and MSI handlers.
>
> interrupts
Okay, I'll fix it.
>> This function detects PME and AER interrupts with the status register,
>> and invoke PME and AER drivers related to INTx or MSI.
>>
>> And this sets the mask for misc interrupts from INTx if MSI is enabled
>> and sets the mask for misc interrupts from MSI if MSI is disabled.
>>
>> Cc: Marc Zyngier <maz@kernel.org>
>> Cc: Jingoo Han <jingoohan1@gmail.com>
>> Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
>> Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
>> ---
>> drivers/pci/controller/dwc/pcie-uniphier.c | 53 +++++++++++++++++++++++-------
>> 1 file changed, 42 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c
>> b/drivers/pci/controller/dwc/pcie-uniphier.c
>> index a5401a0..a8dda39 100644
>> --- a/drivers/pci/controller/dwc/pcie-uniphier.c
>> +++ b/drivers/pci/controller/dwc/pcie-uniphier.c
>> @@ -44,7 +44,9 @@
>> #define PCL_SYS_AUX_PWR_DET BIT(8)
>>
>> #define PCL_RCV_INT 0x8108
>> +#define PCL_RCV_INT_ALL_INT_MASK GENMASK(28, 25)
>> #define PCL_RCV_INT_ALL_ENABLE GENMASK(20, 17)
>> +#define PCL_RCV_INT_ALL_MSI_MASK GENMASK(12, 9)
>> #define PCL_CFG_BW_MGT_STATUS BIT(4)
>> #define PCL_CFG_LINK_AUTO_BW_STATUS BIT(3)
>> #define PCL_CFG_AER_RC_ERR_MSI_STATUS BIT(2)
>> @@ -167,7 +169,15 @@ static void uniphier_pcie_stop_link(struct dw_pcie *pci)
>>
>> static void uniphier_pcie_irq_enable(struct uniphier_pcie_priv *priv)
>> {
>> - writel(PCL_RCV_INT_ALL_ENABLE, priv->base + PCL_RCV_INT);
>> + u32 val;
>> +
>> + val = PCL_RCV_INT_ALL_ENABLE;
>> + if (pci_msi_enabled())
>> + val |= PCL_RCV_INT_ALL_INT_MASK;
>> + else
>> + val |= PCL_RCV_INT_ALL_MSI_MASK;
>> +
>> + writel(val, priv->base + PCL_RCV_INT);
>> writel(PCL_RCV_INTX_ALL_ENABLE, priv->base + PCL_RCV_INTX);
>> }
>>
>> @@ -231,28 +241,48 @@ static const struct irq_domain_ops
>> uniphier_intx_domain_ops = {
>> .map = uniphier_pcie_intx_map,
>> };
>>
>> -static void uniphier_pcie_irq_handler(struct irq_desc *desc)
>> +static void uniphier_pcie_misc_isr(struct pcie_port *pp)
>> {
>> - struct pcie_port *pp = irq_desc_get_handler_data(desc);
>> struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>> struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
>> - struct irq_chip *chip = irq_desc_get_chip(desc);
>> - unsigned long reg;
>> - u32 val, bit, virq;
>> + u32 val, virq;
>>
>> - /* INT for debug */
>> val = readl(priv->base + PCL_RCV_INT);
>>
>> if (val & PCL_CFG_BW_MGT_STATUS)
>> dev_dbg(pci->dev, "Link Bandwidth Management Event\n");
>> +
>> if (val & PCL_CFG_LINK_AUTO_BW_STATUS)
>> dev_dbg(pci->dev, "Link Autonomous Bandwidth Event\n");
>> - if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS)
>> - dev_dbg(pci->dev, "Root Error\n");
>> - if (val & PCL_CFG_PME_MSI_STATUS)
>> - dev_dbg(pci->dev, "PME Interrupt\n");
>> +
>> + if (pci_msi_enabled()) {
>
> This checks whether the kernel supports MSIs. Not that they are
> enabled in your controller. Is that really what you want to do?
The below two status bits are valid when the interrupt for MSI is asserted.
That is, pci_msi_enabled() is wrong.
I'll modify the function to check the two bits only if this function is
called from MSI handler.
>
>> + if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS) {
>> + dev_dbg(pci->dev, "Root Error Status\n");
>> + virq = irq_linear_revmap(pp->irq_domain, 0);
>> + generic_handle_irq(virq);
>> + }
>> +
>> + if (val & PCL_CFG_PME_MSI_STATUS) {
>> + dev_dbg(pci->dev, "PME Interrupt\n");
>> + virq = irq_linear_revmap(pp->irq_domain, 0);
>> + generic_handle_irq(virq);
>> + }
>
> These two cases do the exact same thing, calling the same interrupt.
> What is the point of dealing with them independently?
Both PME and AER are asserted from MSI-0, and each handler checks its own
status bit in the PCIe register (aer_irq() in pcie/aer.c and pcie_pme_irq()
in pcie/pme.c).
So I think this handler calls generic_handle_irq() for the same MSI-0.
>
>> + }
>>
>> writel(val, priv->base + PCL_RCV_INT);
>> +}
>> +
>> +static void uniphier_pcie_irq_handler(struct irq_desc *desc)
>> +{
>> + struct pcie_port *pp = irq_desc_get_handler_data(desc);
>> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
>> + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
>> + struct irq_chip *chip = irq_desc_get_chip(desc);
>> + unsigned long reg;
>> + u32 val, bit, virq;
>> +
>> + /* misc interrupt */
>> + uniphier_pcie_misc_isr(pp);
>
> This is a chained handler called outside of a chained_irq_enter/exit
> block. It isn't acceptable.
I got it.
This call should be called in the block.
Thank you,
---
Best Regards
Kunihiko Hayashi
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v3 1/6] PCI: dwc: Add msi_host_isr() callback
From: Kunihiko Hayashi @ 2020-06-04 9:43 UTC (permalink / raw)
To: Marc Zyngier
Cc: devicetree, Lorenzo Pieralisi, Masami Hiramatsu, Jassi Brar,
Jingoo Han, linux-pci, linux-kernel, Masahiro Yamada, Rob Herring,
Gustavo Pimentel, Bjorn Helgaas, linux-arm-kernel
In-Reply-To: <95bb3ffbfab4923854e20266c6b0b098@kernel.org>
Hi Marc,
On 2020/06/03 20:15, Marc Zyngier wrote:
> On 2020-06-03 09:54, Kunihiko Hayashi wrote:
>> This adds msi_host_isr() callback function support to describe
>> SoC-dependent service triggered by MSI.
>>
>> For example, when AER interrupt is triggered by MSI, the callback function
>> reads SoC-dependent registers and detects that the interrupt is from AER,
>> and invoke AER interrupts related to MSI.
>>
>> Cc: Marc Zyngier <maz@kernel.org>
>> Cc: Jingoo Han <jingoohan1@gmail.com>
>> Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
>> Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
>> ---
>> drivers/pci/controller/dwc/pcie-designware-host.c | 8 ++++----
>> drivers/pci/controller/dwc/pcie-designware.h | 1 +
>> 2 files changed, 5 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c
>> b/drivers/pci/controller/dwc/pcie-designware-host.c
>> index 0a4a5aa..9b628a2 100644
>> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
>> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
>> @@ -112,13 +112,13 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
>> static void dw_chained_msi_isr(struct irq_desc *desc)
>> {
>> struct irq_chip *chip = irq_desc_get_chip(desc);
>> - struct pcie_port *pp;
>> + struct pcie_port *pp = irq_desc_get_handler_data(desc);
>>
>> - chained_irq_enter(chip, desc);
>> + if (pp->ops->msi_host_isr)
>> + pp->ops->msi_host_isr(pp);
>
> Why is this call outside of the enter/exit guards?
> Do you still need to execute the standard handler?
I assume that the msi_host_isr() contains chained interrupts in
the second patch and no need to treat as the standard handler,
so this should be called in the guards.
I'll move this call to the top of dw_chained_msi_isr().
Thank you,
---
Best Regards
Kunihiko Hayashi
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
From: Mike Rapoport @ 2020-06-04 9:41 UTC (permalink / raw)
To: Guenter Roeck
Cc: Peter Zijlstra, Benjamin Herrenschmidt, Dave Hansen, dri-devel,
linux-mips, James E.J. Bottomley, Max Filippov, Paul Mackerras,
H. Peter Anvin, sparclinux, Ira Weiny, Dan Williams, Helge Deller,
x86, linux-csky, Christoph Hellwig, Ingo Molnar, linux-snps-arc,
linux-xtensa, Borislav Petkov, Al Viro, Andy Lutomirski,
Thomas Gleixner, linux-arm-kernel, Chris Zankel,
Thomas Bogendoerfer, linux-parisc, linux-kernel, Christian Koenig,
Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <3538c8ad-674e-d310-d870-4ef6888092ed@roeck-us.net>
On Wed, Jun 03, 2020 at 04:44:17PM -0700, Guenter Roeck wrote:
>
> sparc32 smp images in next-20200603 still crash for me with a spinlock
> recursion. s390 images hang early in boot. Several others (alpha, arm64,
> various ppc) don't even compile. I can run some more bisects over time,
> but this is becoming a full-time job :-(.
I've been able to bisect s390 hang to commit b614345f52bc ("x86/entry:
Clarify irq_{enter,exit}_rcu()").
After this commit, lockdep_hardirq_exit() is called twice on s390 (and
others) - one time in irq_exit_rcu() and another one in irq_exit():
/**
* irq_exit_rcu() - Exit an interrupt context without updating RCU
*
* Also processes softirqs if needed and possible.
*/
void irq_exit_rcu(void)
{
__irq_exit_rcu();
/* must be last! */
lockdep_hardirq_exit();
}
/**
* irq_exit - Exit an interrupt context, update RCU and lockdep
*
* Also processes softirqs if needed and possible.
*/
void irq_exit(void)
{
irq_exit_rcu();
rcu_irq_exit();
/* must be last! */
lockdep_hardirq_exit();
}
Removing the call in irq_exit() make s390 boot again, and judgung by the
x86 entry code, the comment /* must be last! */ is stale...
@Peter, @Thomas, can you comment please?
From e51d50ee6f4d1f446decf91c2c67230da14ff82c Mon Sep 17 00:00:00 2001
From: Mike Rapoport <rppt@linux.ibm.com>
Date: Thu, 4 Jun 2020 12:37:03 +0300
Subject: [PATCH] softirq: don't call lockdep_hardirq_exit() twice
After commit b614345f52bc ("x86/entry: Clarify irq_{enter,exit}_rcu()")
lockdep_hardirq_exit() is called twice on every architecture that uses
irq_exit(): one time in irq_exit_rcu() and another one in irq_exit().
Remove the extra call in irq_exit().
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
---
kernel/softirq.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/kernel/softirq.c b/kernel/softirq.c
index a3eb6eba8c41..7523f4ce4c1d 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -427,7 +427,6 @@ static inline void __irq_exit_rcu(void)
void irq_exit_rcu(void)
{
__irq_exit_rcu();
- /* must be last! */
lockdep_hardirq_exit();
}
@@ -440,8 +439,6 @@ void irq_exit(void)
{
irq_exit_rcu();
rcu_irq_exit();
- /* must be last! */
- lockdep_hardirq_exit();
}
/*
--
2.26.2
> Guenter
--
Sincerely yours,
Mike.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
From: Guenter Roeck @ 2020-06-04 9:38 UTC (permalink / raw)
To: Ira Weiny
Cc: Peter Zijlstra, Benjamin Herrenschmidt, Dave Hansen, dri-devel,
linux-mips, James E.J. Bottomley, Max Filippov, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Christoph Hellwig, Ingo Molnar, linux-snps-arc,
linux-xtensa, Borislav Petkov, Al Viro, Andy Lutomirski,
Thomas Gleixner, linux-arm-kernel, Chris Zankel,
Thomas Bogendoerfer, linux-parisc, linux-kernel, Christian Koenig,
Andrew Morton, linuxppc-dev, David S. Miller, Mike Rapoport
In-Reply-To: <20200604062226.GA1740345@iweiny-DESK2.sc.intel.com>
On 6/3/20 11:22 PM, Ira Weiny wrote:
[ ... ]
>
> s390: (does not compile)
>
> <stdin>:1511:2: warning: #warning syscall clone3 not implemented [-Wcpp]
> In file included from ./arch/sparc/include/asm/bug.h:6:0,
> from ./include/linux/bug.h:5,
> from ./include/linux/mmdebug.h:5,
> from ./include/linux/mm.h:9,
> from mm/huge_memory.c:8:
> mm/huge_memory.c: In function 'hugepage_init':
> ./include/linux/compiler.h:403:38: error: call to '__compiletime_assert_127' declared with attribute error: BUILD_BUG_ON failed: ((13 + (13-3))-13) >= 9
> _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
> ^
> ./include/linux/compiler.h:384:4: note: in definition of macro '__compiletime_assert'
> prefix ## suffix(); \
> ^~~~~~
> ./include/linux/compiler.h:403:2: note: in expansion of macro '_compiletime_assert'
> _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
> ^~~~~~~~~~~~~~~~~~~
> ./include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
> #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
> ^~~~~~~~~~~~~~~~~~
> ./include/linux/build_bug.h:50:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
> BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
> ^~~~~~~~~~~~~~~~
> ./include/linux/bug.h:24:4: note: in expansion of macro 'BUILD_BUG_ON'
> BUILD_BUG_ON(cond); \
> ^~~~~~~~~~~~
> mm/huge_memory.c:403:2: note: in expansion of macro 'MAYBE_BUILD_BUG_ON'
> MAYBE_BUILD_BUG_ON(HPAGE_PMD_ORDER >= MAX_ORDER);
> ^~~~~~~~~~~~~~~~~~
> make[1]: *** [scripts/Makefile.build:267: mm/huge_memory.o] Error 1
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:1735: mm] Error 2
> make: *** Waiting for unfinished jobs....
> ------------
>
>
> The s390 error is the same on Linus' master and linux-next. So whatever is
> causing that has slipped into mainline and/or is something I've broken in the
> test scripts.
>
Compiler version related. gcc version 8.x and later no longer work.
Bisect points to commit a148866489f ("sched: Replace rq::wake_list").
Oddly enough x86 images are broken as well. You'll have to use an
older version of gcc (or presumably clang) until this is fixed.
Guenter
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dmaengine: stm32-dmamux: Fix pm_runtime_get_sync() failure cases
From: Markus Elfring @ 2020-06-04 9:36 UTC (permalink / raw)
To: Navid Emamdoost, dmaengine, linux-arm-kernel, linux-stm32
Cc: Maxime Coquelin, Alexandre Torgue, kernel-janitors, Kangjie Lu,
LKML, Vinod Koul, Navid Emamdoost, Qiushi Wu, Stephen McCamant,
Dan Williams
In-Reply-To: <CAEkB2ET_gfNUAuoZHxiGWZX7d3CQaJYJJqS2Fspif5mFq4-xfA@mail.gmail.com>
> Please stop proposing rewording on my patches!
I find it interesting that you got into the mood to choose
another patch subject variant.
https://lore.kernel.org/patchwork/patch/1252131/
https://lore.kernel.org/dmaengine/20200603193648.19190-1-navid.emamdoost@gmail.com/
> I will consider updating my patches only if a maintainer asks for it.
Now I am curious if you would like take my patch review request into account
to avoid a typo there.
How will the quality evolve for such commit messages?
Regards,
Markus
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [EXT] Re: [PATCH 7/7] dt-bindings: display: Document Cadence MHDP HDMI/DP bindings
From: Sandor Yu @ 2020-06-04 9:32 UTC (permalink / raw)
To: Laurent Pinchart
Cc: jernej.skrabec@siol.net, heiko@sntech.de, jonas@kwiboo.se,
narmstrong@baylibre.com, hjc@rock-chips.com,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
a.hajda@samsung.com, dl-linux-imx,
linux-rockchip@lists.infradead.org, dkos@cadence.com,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20200602234422.GR6547@pendragon.ideasonboard.com>
Hi Laurent,
Thanks your review comments.
> -----Original Message-----
> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Sent: Wednesday, June 3, 2020 7:44 AM
> To: Sandor Yu <sandor.yu@nxp.com>
> Cc: a.hajda@samsung.com; narmstrong@baylibre.com; jonas@kwiboo.se;
> jernej.skrabec@siol.net; heiko@sntech.de; hjc@rock-chips.com;
> dkos@cadence.com; dri-devel@lists.freedesktop.org;
> linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> linux-rockchip@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>
> Subject: [EXT] Re: [PATCH 7/7] dt-bindings: display: Document Cadence MHDP
> HDMI/DP bindings
>
> Caution: EXT Email
>
> Hi Sandor,
>
> Thank you for the patch.
>
> On Mon, Jun 01, 2020 at 02:17:37PM +0800, sandor.yu@nxp.com wrote:
> > From: Sandor Yu <Sandor.yu@nxp.com>
> >
> > Document the bindings used for the Cadence MHDP HDMI/DP bridge.
> >
> > Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
> > ---
> > .../bindings/display/bridge/cdns,mhdp.yaml | 46 +++++++++++++++
> > .../devicetree/bindings/display/imx/mhdp.yaml | 59
> > +++++++++++++++++++
>
> Please split the patch in two.
OK, I will split it later.
>
> > 2 files changed, 105 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > create mode 100644
> > Documentation/devicetree/bindings/display/imx/mhdp.yaml
> >
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > new file mode 100644
> > index 000000000000..aa23feba744a
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > @@ -0,0 +1,46 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)) %YAML 1.2
> > +---
> > +$id:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fschemas%2Fdisplay%2Fbridge%2Fcdns%2Cmhdp.yaml%23&a
> mp;dat
> >
> +a=02%7C01%7Csandor.yu%40nxp.com%7C7862af2fa05b490b6fe908d8074eea
> 14%7C
> >
> +686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637267382802978543&
> amp;sda
> >
> +ta=1AoEDe9F2v7fy0RRWkn%2BgEXWgvt78E1D8DqmCf8AsnU%3D&reser
> ved=0
> > +$schema:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fmeta-schemas%2Fcore.yaml%23&data=02%7C01%7Csand
> or.yu
> >
> +%40nxp.com%7C7862af2fa05b490b6fe908d8074eea14%7C686ea1d3bc2b4c6f
> a92cd
> >
> +99c5c301635%7C0%7C0%7C637267382802988539&sdata=X5HtTsR2roO
> %2FyqOI
> > +JbaLy3hEcxjmU5QL5b1UHXOdbLg%3D&reserved=0
> > +
> > +title: Cadence MHDP TX Encoder
> > +
> > +maintainers:
> > + - Sandor Yu <Sandoryu@nxp.com>
> > +
> > +description: |
> > + Cadence MHDP Controller supports one or more of the protocols,
> > + such as HDMI and DisplayPort.
> > + Each protocol requires a different FW binaries.
> > +
> > + This document defines device tree properties for the Cadence MHDP
> > + Encoder (CDNS MHDP TX). It doesn't constitue a device tree binding
> > + specification by itself but is meant to be referenced by
> > + platform-specific device tree bindings.
> > +
> > + When referenced from platform device tree bindings the properties
> > + defined in this document are defined as follows. The platform
> > + device tree bindings are responsible for defining whether each property
> is required or optional.
> > +
> > +properties:
> > + reg:
> > + maxItems: 1
> > + description: Memory mapped base address and length of the MHDP TX
> registers.
> > +
> > + interrupts:
> > + maxItems: 2
> > +
> > + interrupt-names:
> > + - const: plug_in
> > + description: Hotplug detect interrupter for cable plugin event.
> > + - const: plug_out
> > + description: Hotplug detect interrupter for cable plugout event.
>
> Does the IP core really have two different interrupt lines, one for hot-plug and
> one for hot-unplug ? That's a very unusual design.
>
These two interrupter generated by SOC.
The IP Core haven't provide interrupt lines to SOC, it only provide HPD status in Firmware.
> > +
> > + port:
> > + type: object
> > + description: |
> > + The connectivity of the MHDP TX with the rest of the system is
> > + expressed in using ports as specified in the device graph bindings
> defined
> > + in Documentation/devicetree/bindings/graph.txt. The numbering of
> the ports
> > + is platform-specific.
> > diff --git a/Documentation/devicetree/bindings/display/imx/mhdp.yaml
> > b/Documentation/devicetree/bindings/display/imx/mhdp.yaml
> > new file mode 100644
> > index 000000000000..17850cfd1cb1
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/imx/mhdp.yaml
> > @@ -0,0 +1,59 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2
> > +---
> > +$id:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fschemas%2Fdisplay%2Fbridge%2Fmhdp.yaml%23&data=0
> 2%7C
> >
> +01%7Csandor.yu%40nxp.com%7C7862af2fa05b490b6fe908d8074eea14%7C68
> 6ea1d
> >
> +3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637267382802988539&sdat
> a=88VM
> > +M6TP6Sd%2FwGnKsZ7REO1S5FNY5UJ6ll0H5pecNrY%3D&reserved=0
> > +$schema:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fmeta-schemas%2Fcore.yaml%23&data=02%7C01%7Csand
> or.yu
> >
> +%40nxp.com%7C7862af2fa05b490b6fe908d8074eea14%7C686ea1d3bc2b4c6f
> a92cd
> >
> +99c5c301635%7C0%7C0%7C637267382802988539&sdata=X5HtTsR2roO
> %2FyqOI
> > +JbaLy3hEcxjmU5QL5b1UHXOdbLg%3D&reserved=0
> > +
> > +title: Cadence MHDP Encoder
> > +
> > +maintainers:
> > + - Sandor Yu <Sandoryu@nxp.com>
> > +
> > +description: |
> > + The MHDP transmitter is a Cadence HD Display TX controller IP
> > + with a companion PHY IP.
> > + The MHDP supports one or more of the protocols,
> > + such as HDMI(1.4 & 2.0), DisplayPort(1.2).
> > + switching between the two modes (HDMI and DisplayPort)
> > + requires reloading the appropriate FW
>
> Does the IP core integrated in the imx8mp SoCs (as that is what this binding
> targets) support both HDMI and DP ? If not this should be reworded to be
> more specific to the SoC.
>
Yes, the IP core have one MCU, it could run different firmware to support HDMI or DP.
> > +
> > + These DT bindings follow the Cadence MHDP TX bindings defined in
> > + Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml with
> > + the following device-specific properties.
> > +
> > +Properties:
>
> Have you tried validating this with make dt_binding_check ? See
> Documentation/devicetree/writing-schema.rst for more information.
>
I have run the online yaml checker, I will check it with make dt_binding_check, thanks.
> > + compatible:
> > + enum:
> > + - nxp,imx8mq-cdns-hdmi
> > + - nxp,imx8mq-cdns-dp
> > +
> > + reg: See cdns,mhdp.yaml.
>
> This isn't how bindings are referenced. You need to reference the parent
> binding with $ref, either globally, or on an individual property basis.
OK
>
> > +
> > + interrupts: See cdns,mhdp.yaml.
> > +
> > + interrupt-names: See cdns,mhdp.yaml.
>
> That's it ? No clocks, no power domains, no resets, no PHYs (especially given
> that you mention a PHY companion IP above) ?
>
Yes, iMX8MQ HDMI/DP firmware loaded by ROM code for security check,
IP core clock and power will management by ROM code, it will keep in ON status when device bootup.
The PHY configurated in platform files, it will generate pixel clock for HDMI controller.
So no clocks, power, reset and PHY.
> > +
> > + ports: See cdns,mhdp.yaml.
>
> This isn't correct. Please soo of-graph.txt. If can have either one port node, or
> one ports node that contains one of more port subnodes. In this case you
> need at least two ports, one for the input to the HDMI encoder, and one for
> the HDMI output. The latter should be connected to a DT node representing
> the HDMI connector. Yuo can search for "hdmi-connector" in the .dts files in
> the kernel for plenty of examples.
OK, I will add more information later.
>
> > +
> > +Required:
> > + - compatible
> > + - reg
> > + - interrupts
> > + - interrupt-names
> > + - ports
> > +
> > +Example:
> > + - |
> > + mhdp: mhdp@32c00000 {
> > + compatible = "nxp,imx8mq-cdns-hdmi";
> > + reg = <0x32c00000 0x100000>;
> > + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
> > + <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
> > + interrupt-names = "plug_in", "plug_out";
> > +
> > + ports {
> > + mhdp_in: endpoint {
> > + remote-endpoint = <&dcss_out>;
> > + };
> > + };
> > + };
>
> --
> Regards,
>
> Laurent Pinchart
Regards,
Sandor
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [EXT] Re: [PATCH 3/7] drm: bridge: cadence: initial support for MHDP DP bridge driver
From: Sandor Yu @ 2020-06-04 9:29 UTC (permalink / raw)
To: Laurent Pinchart
Cc: jernej.skrabec@siol.net, heiko@sntech.de, jonas@kwiboo.se,
narmstrong@baylibre.com, hjc@rock-chips.com,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
a.hajda@samsung.com, dl-linux-imx,
linux-rockchip@lists.infradead.org, dkos@cadence.com,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20200602233524.GQ6547@pendragon.ideasonboard.com>
> -----Original Message-----
> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Sent: Wednesday, June 3, 2020 7:35 AM
> To: Sandor Yu <sandor.yu@nxp.com>
> Cc: a.hajda@samsung.com; narmstrong@baylibre.com; jonas@kwiboo.se;
> jernej.skrabec@siol.net; heiko@sntech.de; hjc@rock-chips.com;
> dkos@cadence.com; dri-devel@lists.freedesktop.org;
> linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> linux-rockchip@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>
> Subject: [EXT] Re: [PATCH 3/7] drm: bridge: cadence: initial support for MHDP
> DP bridge driver
>
> Caution: EXT Email
>
> Hi Sandor,
>
> Thank you for the patch.
>
> On Mon, Jun 01, 2020 at 02:17:33PM +0800, sandor.yu@nxp.com wrote:
> > From: Sandor Yu <Sandor.yu@nxp.com>
> >
> > This adds initial support for MHDP DP bridge driver.
> > Basic DP functions are supported, that include:
> > -Video mode set on-the-fly
> > -Cable hotplug detect
> > -MAX support resolution to 3096x2160@60fps -Support DP audio
> -EDID
> > read via AUX
> >
> > Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
> > ---
> > drivers/gpu/drm/bridge/cadence/Kconfig | 4 +
> > drivers/gpu/drm/bridge/cadence/Makefile | 1 +
> > drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 530
> > ++++++++++++++++++ .../gpu/drm/bridge/cadence/cdns-mhdp-audio.c
> |
> > 100 ++++ .../gpu/drm/bridge/cadence/cdns-mhdp-common.c | 42 +-
> > .../gpu/drm/bridge/cadence/cdns-mhdp-common.h | 3 +
> > drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c | 34 +-
> > drivers/gpu/drm/rockchip/cdn-dp-core.c | 7 +-
> > include/drm/bridge/cdns-mhdp.h | 52 +-
> > 9 files changed, 740 insertions(+), 33 deletions(-) create mode
> > 100644 drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
> >
> > diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig
> > b/drivers/gpu/drm/bridge/cadence/Kconfig
> > index 48c1b0f77dc6..b7b8d30b18b6 100644
> > --- a/drivers/gpu/drm/bridge/cadence/Kconfig
> > +++ b/drivers/gpu/drm/bridge/cadence/Kconfig
> > @@ -5,3 +5,7 @@ config DRM_CDNS_MHDP
> > depends on OF
> > help
> > Support Cadence MHDP API library.
> > +
> > +config DRM_CDNS_DP
> > + tristate "Cadence DP DRM driver"
> > + depends on DRM_CDNS_MHDP
> > diff --git a/drivers/gpu/drm/bridge/cadence/Makefile
> > b/drivers/gpu/drm/bridge/cadence/Makefile
> > index ddb2ba4fb852..cb3c88311a64 100644
> > --- a/drivers/gpu/drm/bridge/cadence/Makefile
> > +++ b/drivers/gpu/drm/bridge/cadence/Makefile
> > @@ -1,3 +1,4 @@
> > # SPDX-License-Identifier: GPL-2.0-only cdns_mhdp_drmcore-y :=
> > cdns-mhdp-common.o cdns-mhdp-audio.o cdns-mhdp-dp.o
> > +cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_DP) += cdns-dp-core.o
> > obj-$(CONFIG_DRM_CDNS_MHDP) += cdns_mhdp_drmcore.o
> > diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
> > b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
> > new file mode 100644
> > index 000000000000..b2fe8fdc64ed
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
> > @@ -0,0 +1,530 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Cadence Display Port Interface (DP) driver
> > + *
> > + * Copyright (C) 2019-2020 NXP Semiconductor, Inc.
> > + *
> > + */
> > +#include <drm/bridge/cdns-mhdp.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_edid.h>
> > +#include <drm/drm_encoder_slave.h>
> > +#include <drm/drm_of.h>
> > +#include <drm/drm_probe_helper.h>
> > +#include <drm/drm_vblank.h>
> > +#include <drm/drm_print.h>
> > +#include <linux/delay.h>
> > +#include <linux/err.h>
> > +#include <linux/irq.h>
> > +#include <linux/module.h>
> > +#include <linux/mutex.h>
> > +#include <linux/of_device.h>
> > +
> > +#include "cdns-mhdp-common.h"
> > +
> > +/*
> > + * This function only implements native DPDC reads and writes */
> > +static ssize_t dp_aux_transfer(struct drm_dp_aux *aux,
> > + struct drm_dp_aux_msg *msg) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(aux->dev);
> > + bool native = msg->request & (DP_AUX_NATIVE_WRITE &
> DP_AUX_NATIVE_READ);
> > + int ret;
> > +
> > + /* Ignore address only message */
> > + if ((msg->size == 0) || (msg->buffer == NULL)) {
> > + msg->reply = native ?
> > + DP_AUX_NATIVE_REPLY_ACK :
> DP_AUX_I2C_REPLY_ACK;
> > + return msg->size;
> > + }
> > +
> > + if (!native) {
> > + dev_err(mhdp->dev, "%s: only native messages
> supported\n", __func__);
> > + return -EINVAL;
> > + }
> > +
> > + /* msg sanity check */
> > + if (msg->size > DP_AUX_MAX_PAYLOAD_BYTES) {
> > + dev_err(mhdp->dev, "%s: invalid msg: size(%zu),
> request(%x)\n",
> > + __func__, msg->size,
> (unsigned int)msg->request);
> > + return -EINVAL;
> > + }
> > +
> > + if (msg->request == DP_AUX_NATIVE_WRITE) {
> > + const u8 *buf = msg->buffer;
> > + int i;
> > + for (i = 0; i < msg->size; ++i) {
> > + ret = cdns_mhdp_dpcd_write(mhdp,
> > + msg->address + i,
> buf[i]);
> > + if (!ret)
> > + continue;
> > +
> > + DRM_DEV_ERROR(mhdp->dev, "Failed to write
> > + DPCD\n");
> > +
> > + return ret;
> > + }
> > + msg->reply = DP_AUX_NATIVE_REPLY_ACK;
> > + return msg->size;
> > + }
> > +
> > + if (msg->request == DP_AUX_NATIVE_READ) {
> > + ret = cdns_mhdp_dpcd_read(mhdp, msg->address,
> msg->buffer, msg->size);
> > + if (ret < 0)
> > + return -EIO;
> > + msg->reply = DP_AUX_NATIVE_REPLY_ACK;
> > + return msg->size;
> > + }
> > + return 0;
> > +}
> > +
> > +static int dp_aux_init(struct cdns_mhdp_device *mhdp,
> > + struct device *dev)
> > +{
> > + int ret;
> > +
> > + mhdp->dp.aux.name = "imx_dp_aux";
> > + mhdp->dp.aux.dev = dev;
> > + mhdp->dp.aux.transfer = dp_aux_transfer;
> > +
> > + ret = drm_dp_aux_register(&mhdp->dp.aux);
> > +
> > + return ret;
> > +}
> > +
> > +static int dp_aux_destroy(struct cdns_mhdp_device *mhdp) {
> > + drm_dp_aux_unregister(&mhdp->dp.aux);
> > + return 0;
> > +}
> > +
> > +static void dp_pixel_clk_reset(struct cdns_mhdp_device *mhdp) {
> > + u32 val;
> > +
> > + /* reset pixel clk */
> > + val = cdns_mhdp_reg_read(mhdp, SOURCE_HDTX_CAR);
> > + cdns_mhdp_reg_write(mhdp, SOURCE_HDTX_CAR, val & 0xFD);
> > + cdns_mhdp_reg_write(mhdp, SOURCE_HDTX_CAR, val); }
> > +
> > +static void cdns_dp_mode_set(struct cdns_mhdp_device *mhdp) {
> > + int ret;
> > +
> > + cdns_mhdp_plat_call(mhdp, pclk_rate);
> > +
> > + /* delay for DP FW stable after pixel clock relock */
> > + msleep(50);
> > +
> > + dp_pixel_clk_reset(mhdp);
> > +
> > + /* Get DP Caps */
> > + ret = drm_dp_dpcd_read(&mhdp->dp.aux, DP_DPCD_REV,
> mhdp->dp.dpcd,
> > + DP_RECEIVER_CAP_SIZE);
> > + if (ret < 0) {
> > + DRM_ERROR("Failed to get caps %d\n", ret);
> > + return;
> > + }
> > +
> > + mhdp->dp.rate = drm_dp_max_link_rate(mhdp->dp.dpcd);
> > + mhdp->dp.num_lanes = drm_dp_max_lane_count(mhdp->dp.dpcd);
> > +
> > + /* check the max link rate */
> > + if (mhdp->dp.rate > CDNS_DP_MAX_LINK_RATE)
> > + mhdp->dp.rate = CDNS_DP_MAX_LINK_RATE;
> > +
> > + /* Initialize link rate/num_lanes as panel max link
> rate/max_num_lanes */
> > + cdns_mhdp_plat_call(mhdp, phy_set);
> > +
> > + /* Video off */
> > + ret = cdns_mhdp_set_video_status(mhdp, CONTROL_VIDEO_IDLE);
> > + if (ret) {
> > + DRM_DEV_ERROR(mhdp->dev, "Failed to valid video %d\n",
> ret);
> > + return;
> > + }
> > +
> > + /* Line swaping */
> > + mhdp->lane_mapping = mhdp->plat_data->lane_mapping;
> > + cdns_mhdp_reg_write(mhdp, LANES_CONFIG, 0x00400000 |
> > + mhdp->lane_mapping);
> > +
> > + /* Set DP host capability */
> > + ret = cdns_mhdp_set_host_cap(mhdp);
> > + if (ret) {
> > + DRM_DEV_ERROR(mhdp->dev, "Failed to set host cap %d\n",
> ret);
> > + return;
> > + }
> > +
> > + ret = cdns_mhdp_config_video(mhdp);
> > + if (ret) {
> > + DRM_DEV_ERROR(mhdp->dev, "Failed to config video %d\n",
> ret);
> > + return;
> > + }
> > +
> > + return;
> > +}
> > +
> > +/*
> > +---------------------------------------------------------------------
> > +--------
> > + * DP TX Setup
> > + */
> > +static enum drm_connector_status
> > +cdns_dp_connector_detect(struct drm_connector *connector, bool force)
> > +{
> > + struct cdns_mhdp_device *mhdp = container_of(connector,
> > + struct cdns_mhdp_device,
> connector.base);
> > + u8 hpd = 0xf;
> > +
> > + hpd = cdns_mhdp_read_hpd(mhdp);
> > + if (hpd == 1)
> > + /* Cable Connected */
> > + return connector_status_connected;
> > + else if (hpd == 0)
> > + /* Cable Disconnedted */
> > + return connector_status_disconnected;
> > + else {
> > + /* Cable status unknown */
> > + DRM_INFO("Unknow cable status, hdp=%u\n", hpd);
> > + return connector_status_unknown;
> > + }
> > +}
> > +
> > +static int cdns_dp_connector_get_modes(struct drm_connector
> > +*connector) {
> > + struct cdns_mhdp_device *mhdp = container_of(connector,
> > + struct cdns_mhdp_device,
> connector.base);
> > + int num_modes = 0;
> > + struct edid *edid;
> > +
> > + edid = drm_do_get_edid(&mhdp->connector.base,
> > + cdns_mhdp_get_edid_block, mhdp);
> > + if (edid) {
> > + dev_info(mhdp->dev, "%x,%x,%x,%x,%x,%x,%x,%x\n",
> > + edid->header[0], edid->header[1],
> > + edid->header[2], edid->header[3],
> > + edid->header[4], edid->header[5],
> > + edid->header[6], edid->header[7]);
> > + drm_connector_update_edid_property(connector, edid);
> > + num_modes = drm_add_edid_modes(connector, edid);
> > + kfree(edid);
> > + }
> > +
> > + if (num_modes == 0)
> > + DRM_ERROR("Invalid edid\n");
> > + return num_modes;
> > +}
> > +
> > +static const struct drm_connector_funcs cdns_dp_connector_funcs = {
> > + .fill_modes = drm_helper_probe_single_connector_modes,
> > + .detect = cdns_dp_connector_detect,
> > + .destroy = drm_connector_cleanup,
> > + .reset = drm_atomic_helper_connector_reset,
> > + .atomic_duplicate_state =
> drm_atomic_helper_connector_duplicate_state,
> > + .atomic_destroy_state =
> > +drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static const struct drm_connector_helper_funcs
> cdns_dp_connector_helper_funcs = {
> > + .get_modes = cdns_dp_connector_get_modes, };
> > +
> > +static int cdns_dp_bridge_attach(struct drm_bridge *bridge,
> > + enum drm_bridge_attach_flags flags) {
> > + struct cdns_mhdp_device *mhdp = bridge->driver_private;
> > + struct drm_encoder *encoder = bridge->encoder;
> > + struct drm_connector *connector = &mhdp->connector.base;
>
> New bridge drivers need to support operation without creating a connector
> when the DRM_BRIDGE_ATTACH_NO_CONNECTOR flag is set in the flags
> argument. For an example of how this is done, please see
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.ke
> rnel.org%2Fdri-devel%2F20200526011505.31884-23-laurent.pinchart%2Bren
> esas%40ideasonboard.com%2F&data=02%7C01%7Csandor.yu%40nxp.co
> m%7C3bcd86069c2f4203291408d8074da940%7C686ea1d3bc2b4c6fa92cd9
> 9c5c301635%7C0%7C0%7C637267377438245998&sdata=BYg3bd0%2F
> KZYHqTTaHGHxkRMDpqwzNCjxFYpo3%2BTa2r4%3D&reserved=0
>
I will followed the new bridge drivers later, thanks.
> > +
> > + connector->interlace_allowed = 1;
> > +
> > + connector->polled = DRM_CONNECTOR_POLL_HPD;
> > +
> > + drm_connector_helper_add(connector,
> > + &cdns_dp_connector_helper_funcs);
> > +
> > + drm_connector_init(bridge->dev, connector,
> &cdns_dp_connector_funcs,
> > + DRM_MODE_CONNECTOR_DisplayPort);
> > +
> > + drm_connector_attach_encoder(connector, encoder);
> > +
> > + return 0;
> > +}
> > +
> > +static enum drm_mode_status
> > +cdns_dp_bridge_mode_valid(struct drm_bridge *bridge,
> > + const struct drm_display_mode *mode) {
> > + enum drm_mode_status mode_status = MODE_OK;
> > +
> > + /* We don't support double-clocked modes */
> > + if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
> > + mode->flags & DRM_MODE_FLAG_INTERLACE)
> > + return MODE_BAD;
> > +
> > + /* MAX support pixel clock rate 594MHz */
> > + if (mode->clock > 594000)
> > + return MODE_CLOCK_HIGH;
> > +
> > + /* 4096x2160 is not supported */
> > + if (mode->hdisplay > 3840)
> > + return MODE_BAD_HVALUE;
> > +
> > + if (mode->vdisplay > 2160)
> > + return MODE_BAD_VVALUE;
> > +
> > + return mode_status;
> > +}
> > +
> > +static void cdns_dp_bridge_mode_set(struct drm_bridge *bridge,
> > + const struct drm_display_mode
> *orig_mode,
> > + const struct drm_display_mode
> *mode)
> > +{
> > + struct cdns_mhdp_device *mhdp = bridge->driver_private;
> > + struct drm_display_info *display_info =
> &mhdp->connector.base.display_info;
> > + struct video_info *video = &mhdp->video_info;
> > +
> > + switch (display_info->bpc) {
> > + case 10:
> > + video->color_depth = 10;
> > + break;
> > + case 6:
> > + video->color_depth = 6;
> > + break;
> > + default:
> > + video->color_depth = 8;
> > + break;
> > + }
> > +
> > + video->color_fmt = PXL_RGB;
> > + video->v_sync_polarity = !!(mode->flags &
> DRM_MODE_FLAG_NVSYNC);
> > + video->h_sync_polarity = !!(mode->flags &
> DRM_MODE_FLAG_NHSYNC);
> > +
> > + DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay,
> mode->clock);
> > + memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode));
> > +
> > + mutex_lock(&mhdp->lock);
> > + cdns_dp_mode_set(mhdp);
> > + mutex_unlock(&mhdp->lock);
> > +}
> > +
> > +static void cdn_dp_bridge_enable(struct drm_bridge *bridge) {
> > + struct cdns_mhdp_device *mhdp = bridge->driver_private;
> > + int ret;
> > +
> > + /* Link trainning */
> > + ret = cdns_mhdp_train_link(mhdp);
> > + if (ret) {
> > + DRM_DEV_ERROR(mhdp->dev, "Failed link train %d\n", ret);
> > + return;
> > + }
> > +
> > + ret = cdns_mhdp_set_video_status(mhdp, CONTROL_VIDEO_VALID);
> > + if (ret) {
> > + DRM_DEV_ERROR(mhdp->dev, "Failed to valid video %d\n",
> ret);
> > + return;
> > + }
> > +}
> > +
> > +static void cdn_dp_bridge_disable(struct drm_bridge *bridge) {
> > + struct cdns_mhdp_device *mhdp = bridge->driver_private;
> > +
> > + cdns_mhdp_set_video_status(mhdp, CONTROL_VIDEO_IDLE); }
> > +
> > +static const struct drm_bridge_funcs cdns_dp_bridge_funcs = {
> > + .attach = cdns_dp_bridge_attach,
> > + .enable = cdn_dp_bridge_enable,
> > + .disable = cdn_dp_bridge_disable,
> > + .mode_set = cdns_dp_bridge_mode_set,
> > + .mode_valid = cdns_dp_bridge_mode_valid, };
> > +
> > +static void hotplug_work_func(struct work_struct *work) {
> > + struct cdns_mhdp_device *mhdp = container_of(work,
> > + struct cdns_mhdp_device,
> hotplug_work.work);
> > + struct drm_connector *connector = &mhdp->connector.base;
> > +
> > + drm_helper_hpd_irq_event(connector->dev);
> > +
> > + if (connector->status == connector_status_connected) {
> > + /* Cable connedted */
> > + DRM_INFO("HDMI/DP Cable Plug In\n");
> > + enable_irq(mhdp->irq[IRQ_OUT]);
> > + } else if (connector->status == connector_status_disconnected) {
> > + /* Cable Disconnedted */
> > + DRM_INFO("HDMI/DP Cable Plug Out\n");
> > + enable_irq(mhdp->irq[IRQ_IN]);
> > + }
> > +}
> > +
> > +static irqreturn_t cdns_dp_irq_thread(int irq, void *data) {
> > + struct cdns_mhdp_device *mhdp = data;
> > +
> > + disable_irq_nosync(irq);
> > +
> > + mod_delayed_work(system_wq, &mhdp->hotplug_work,
> > + msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int __cdns_dp_probe(struct platform_device *pdev,
> > + struct cdns_mhdp_device *mhdp) {
> > + struct device *dev = &pdev->dev;
> > + struct resource *iores = NULL;
> > + int ret;
> > +
> > + mutex_init(&mhdp->lock);
> > +
> > + INIT_DELAYED_WORK(&mhdp->hotplug_work, hotplug_work_func);
> > +
> > + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + if (iores) {
> > + mhdp->regs_base = devm_ioremap(dev, iores->start,
> > + resource_size(iores));
> > + if (IS_ERR(mhdp->regs_base))
> > + return -ENOMEM;
> > + }
> > +
> > + mhdp->irq[IRQ_IN] = platform_get_irq_byname(pdev, "plug_in");
> > + if (mhdp->irq[IRQ_IN] < 0) {
> > + dev_info(dev, "No plug_in irq number\n");
> > + }
> > +
> > + mhdp->irq[IRQ_OUT] = platform_get_irq_byname(pdev, "plug_out");
> > + if (mhdp->irq[IRQ_OUT] < 0) {
> > + dev_info(dev, "No plug_out irq number\n");
> > + }
> > +
> > + cdns_mhdp_plat_call(mhdp, power_on);
> > +
> > + cdns_mhdp_plat_call(mhdp, firmware_init);
> > +
> > + /* DP FW alive check */
> > + ret = cdns_mhdp_check_alive(mhdp);
> > + if (ret == false) {
> > + DRM_ERROR("NO dp FW running\n");
> > + return -ENXIO;
> > + }
> > +
> > + /* DP PHY init before AUX init */
> > + cdns_mhdp_plat_call(mhdp, phy_set);
> > +
> > + /* Enable Hotplug Detect IRQ thread */
> > + irq_set_status_flags(mhdp->irq[IRQ_IN], IRQ_NOAUTOEN);
> > + ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_IN],
> > + NULL, cdns_dp_irq_thread,
> > + IRQF_ONESHOT,
> dev_name(dev),
> > + mhdp);
> > +
> > + if (ret) {
> > + dev_err(dev, "can't claim irq %d\n",
> > + mhdp->irq[IRQ_IN]);
> > + return -EINVAL;
> > + }
> > +
> > + irq_set_status_flags(mhdp->irq[IRQ_OUT], IRQ_NOAUTOEN);
> > + ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_OUT],
> > + NULL, cdns_dp_irq_thread,
> > + IRQF_ONESHOT,
> dev_name(dev),
> > + mhdp);
> > +
> > + if (ret) {
> > + dev_err(dev, "can't claim irq %d\n",
> > + mhdp->irq[IRQ_OUT]);
> > + return -EINVAL;
> > + }
> > +
> > + if (cdns_mhdp_read_hpd(mhdp))
> > + enable_irq(mhdp->irq[IRQ_OUT]);
> > + else
> > + enable_irq(mhdp->irq[IRQ_IN]);
> > +
> > + mhdp->bridge.base.driver_private = mhdp;
> > + mhdp->bridge.base.funcs = &cdns_dp_bridge_funcs; #ifdef
> > +CONFIG_OF
> > + mhdp->bridge.base.of_node = dev->of_node; #endif
> > +
> > + dev_set_drvdata(dev, mhdp);
> > +
> > + /* register audio driver */
> > + cdns_mhdp_register_audio_driver(dev);
> > +
> > + dp_aux_init(mhdp, dev);
> > +
> > + return 0;
> > +}
> > +
> > +static void __cdns_dp_remove(struct cdns_mhdp_device *mhdp) {
> > + dp_aux_destroy(mhdp);
> > + cdns_mhdp_unregister_audio_driver(mhdp->dev);
> > +}
> > +
> > +/*
> > +---------------------------------------------------------------------
> > +--------
> > + * Probe/remove API, used from platforms based on the DRM bridge API.
> > + */
> > +int cdns_dp_probe(struct platform_device *pdev,
> > + struct cdns_mhdp_device *mhdp) {
> > + int ret;
> > +
> > + ret = __cdns_dp_probe(pdev, mhdp);
> > + if (ret)
> > + return ret;
> > +
> > + drm_bridge_add(&mhdp->bridge.base);
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(cdns_dp_probe);
> > +
> > +void cdns_dp_remove(struct platform_device *pdev) {
> > + struct cdns_mhdp_device *mhdp = platform_get_drvdata(pdev);
> > +
> > + drm_bridge_remove(&mhdp->bridge.base);
> > +
> > + __cdns_dp_remove(mhdp);
> > +}
> > +EXPORT_SYMBOL_GPL(cdns_dp_remove);
> > +
> > +/*
> > +---------------------------------------------------------------------
> > +--------
> > + * Bind/unbind API, used from platforms based on the component
> framework.
> > + */
> > +int cdns_dp_bind(struct platform_device *pdev, struct drm_encoder
> *encoder,
> > + struct cdns_mhdp_device *mhdp) {
> > + int ret;
> > +
> > + ret = __cdns_dp_probe(pdev, mhdp);
> > + if (ret < 0)
> > + return ret;
> > +
> > + ret = drm_bridge_attach(encoder, &mhdp->bridge.base, NULL, 0);
> > + if (ret) {
> > + cdns_dp_remove(pdev);
> > + DRM_ERROR("Failed to initialize bridge with drm\n");
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(cdns_dp_bind);
> > +
> > +void cdns_dp_unbind(struct device *dev) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
> > +
> > + __cdns_dp_remove(mhdp);
> > +}
> > +EXPORT_SYMBOL_GPL(cdns_dp_unbind);
>
> Do we really need to support the component framework, can't we just support
> the DRM bridge API ?
>
> > +
> > +MODULE_AUTHOR("Sandor Yu <sandor.yu@nxp.com>");
> > +MODULE_DESCRIPTION("Cadence Display Port transmitter driver");
> > +MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:cdns-dp");
> > diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c
> > b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c
> > index 8f51de0672ab..fdd4bcd0d33c 100644
> > --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c
> > +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c
> > @@ -2,6 +2,9 @@
> > /*
> > * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> > * Author: Chris Zhong <zyw@rock-chips.com>
> > + *
> > + * Cadence MHDP Audio driver
> > + *
> > */
> > #include <linux/clk.h>
> > #include <linux/reset.h>
> > @@ -196,3 +199,100 @@ int cdns_mhdp_audio_config(struct
> cdns_mhdp_device *mhdp,
> > return ret;
> > }
> > EXPORT_SYMBOL(cdns_mhdp_audio_config);
> > +
> > +static int audio_hw_params(struct device *dev, void *data,
> > + struct hdmi_codec_daifmt *daifmt,
> > + struct hdmi_codec_params *params) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
> > + struct audio_info audio = {
> > + .sample_width = params->sample_width,
> > + .sample_rate = params->sample_rate,
> > + .channels = params->channels,
> > + .connector_type = mhdp->connector.base.connector_type,
> > + };
> > + int ret;
> > +
> > + switch (daifmt->fmt) {
> > + case HDMI_I2S:
> > + audio.format = AFMT_I2S;
> > + break;
> > + case HDMI_SPDIF:
> > + audio.format = AFMT_SPDIF_EXT;
> > + break;
> > + default:
> > + DRM_DEV_ERROR(dev, "Invalid format %d\n", daifmt->fmt);
> > + ret = -EINVAL;
> > + goto out;
> > + }
> > +
> > + ret = cdns_mhdp_audio_config(mhdp, &audio);
> > + if (!ret)
> > + mhdp->audio_info = audio;
> > +
> > +out:
> > + return ret;
> > +}
> > +
> > +static void audio_shutdown(struct device *dev, void *data) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
> > + int ret;
> > +
> > + ret = cdns_mhdp_audio_stop(mhdp, &mhdp->audio_info);
> > + if (!ret)
> > + mhdp->audio_info.format = AFMT_UNUSED; }
> > +
> > +static int audio_digital_mute(struct device *dev, void *data,
> > + bool enable) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
> > + int ret;
> > +
> > + ret = cdns_mhdp_audio_mute(mhdp, enable);
> > +
> > + return ret;
> > +}
> > +
> > +static int audio_get_eld(struct device *dev, void *data,
> > + u8 *buf, size_t len) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
> > +
> > + memcpy(buf, mhdp->connector.base.eld,
> > + min(sizeof(mhdp->connector.base.eld), len));
> > +
> > + return 0;
> > +}
> > +
> > +static const struct hdmi_codec_ops audio_codec_ops = {
> > + .hw_params = audio_hw_params,
> > + .audio_shutdown = audio_shutdown,
> > + .digital_mute = audio_digital_mute,
> > + .get_eld = audio_get_eld,
> > +};
> > +
> > +int cdns_mhdp_register_audio_driver(struct device *dev) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
> > + struct hdmi_codec_pdata codec_data = {
> > + .i2s = 1,
> > + .spdif = 1,
> > + .ops = &audio_codec_ops,
> > + .max_i2s_channels = 8,
> > + };
> > +
> > + mhdp->audio_pdev = platform_device_register_data(
> > + dev, HDMI_CODEC_DRV_NAME, 1,
> > + &codec_data, sizeof(codec_data));
> > +
> > + return PTR_ERR_OR_ZERO(mhdp->audio_pdev);
> > +}
> > +
> > +void cdns_mhdp_unregister_audio_driver(struct device *dev) {
> > + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
> > +
> > + platform_device_unregister(mhdp->audio_pdev);
> > +}
> > diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
> > b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
> > index efb39cf5f48b..9fd4546c6914 100644
> > --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
> > +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
> > @@ -357,36 +357,6 @@ int cdns_mhdp_set_firmware_active(struct
> > cdns_mhdp_device *mhdp, bool enable) }
> > EXPORT_SYMBOL(cdns_mhdp_set_firmware_active);
> >
> > -int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp, bool flip)
> > -{
> > - u8 msg[8];
> > - int ret;
> > -
> > - msg[0] = drm_dp_link_rate_to_bw_code(mhdp->dp.rate);
> > - msg[1] = mhdp->dp.num_lanes | SCRAMBLER_EN;
> > - msg[2] = VOLTAGE_LEVEL_2;
> > - msg[3] = PRE_EMPHASIS_LEVEL_3;
> > - msg[4] = PTS1 | PTS2 | PTS3 | PTS4;
> > - msg[5] = FAST_LT_NOT_SUPPORT;
> > - msg[6] = flip ? LANE_MAPPING_FLIPPED : LANE_MAPPING_NORMAL;
> > - msg[7] = ENHANCED;
> > -
> > - ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
> > - DPTX_SET_HOST_CAPABILITIES,
> > - sizeof(msg), msg);
> > - if (ret)
> > - goto err_set_host_cap;
> > -
> > - ret = cdns_mhdp_reg_write(mhdp,
> DP_AUX_SWAP_INVERSION_CONTROL,
> > - AUX_HOST_INVERT);
> > -
> > -err_set_host_cap:
> > - if (ret)
> > - DRM_DEV_ERROR(mhdp->dev, "set host cap failed: %d\n",
> ret);
> > - return ret;
> > -}
> > -EXPORT_SYMBOL(cdns_mhdp_set_host_cap);
> > -
> > int cdns_mhdp_event_config(struct cdns_mhdp_device *mhdp) {
> > u8 msg[5];
> > @@ -698,3 +668,15 @@ int cdns_mhdp_config_video(struct
> cdns_mhdp_device *mhdp)
> > return ret;
> > }
> > EXPORT_SYMBOL(cdns_mhdp_config_video);
> > +
> > +int cdns_phy_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32
> > +val) {
> > + return cdns_mhdp_reg_write(mhdp, ADDR_PHY_AFE + (addr << 2),
> > +val); } EXPORT_SYMBOL(cdns_phy_reg_write);
> > +
> > +u32 cdns_phy_reg_read(struct cdns_mhdp_device *mhdp, u32 addr) {
> > + return cdns_mhdp_reg_read(mhdp, ADDR_PHY_AFE + (addr << 2)); }
> > +EXPORT_SYMBOL(cdns_phy_reg_read);
> > diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.h
> > b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.h
> > index 1f093a2deaa7..b122bf5f0bdf 100644
> > --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.h
> > +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.h
> > @@ -20,4 +20,7 @@ int cdns_mhdp_reg_write(struct cdns_mhdp_device
> > *mhdp, u32 addr, u32 val); int cdns_mhdp_reg_write_bit(struct
> cdns_mhdp_device *mhdp, u16 addr,
> > u8 start_bit, u8 bits_no, u32 val);
> >
> > +/* Audio */
> > +int cdns_mhdp_register_audio_driver(struct device *dev); void
> > +cdns_mhdp_unregister_audio_driver(struct device *dev);
> > #endif
> > diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c
> > b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c
> > index c8160f321aca..8fea072a5568 100644
> > --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c
> > +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c
> > @@ -108,7 +108,9 @@ static int cdns_mhdp_training_start(struct
> cdns_mhdp_device *mhdp)
> > if (ret)
> > goto err_training_start;
> >
> > - if (event[1] & EQ_PHASE_FINISHED)
> > + if (event[1] & CLK_RECOVERY_FAILED)
> > + DRM_DEV_ERROR(mhdp->dev, "clock recovery
> failed\n");
> > + else if (event[1] & EQ_PHASE_FINISHED)
> > return 0;
> > }
> >
> > @@ -172,3 +174,33 @@ int cdns_mhdp_train_link(struct
> cdns_mhdp_device *mhdp)
> > return ret;
> > }
> > EXPORT_SYMBOL(cdns_mhdp_train_link);
> > +
> > +int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp) {
> > + u8 msg[8];
> > + int ret;
> > +
> > + msg[0] = drm_dp_link_rate_to_bw_code(mhdp->dp.rate);
> > + msg[1] = mhdp->dp.num_lanes | SCRAMBLER_EN;
> > + msg[2] = VOLTAGE_LEVEL_2;
> > + msg[3] = PRE_EMPHASIS_LEVEL_3;
> > + msg[4] = PTS1 | PTS2 | PTS3 | PTS4;
> > + msg[5] = FAST_LT_NOT_SUPPORT;
> > + msg[6] = mhdp->lane_mapping;
> > + msg[7] = ENHANCED;
> > +
> > + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
> > + DPTX_SET_HOST_CAPABILITIES,
> > + sizeof(msg), msg);
> > + if (ret)
> > + goto err_set_host_cap;
> > +
> > + ret = cdns_mhdp_reg_write(mhdp,
> DP_AUX_SWAP_INVERSION_CONTROL,
> > + AUX_HOST_INVERT);
> > +
> > +err_set_host_cap:
> > + if (ret)
> > + DRM_DEV_ERROR(mhdp->dev, "set host cap failed: %d\n",
> ret);
> > + return ret;
> > +}
> > +EXPORT_SYMBOL(cdns_mhdp_set_host_cap);
> > diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c
> > b/drivers/gpu/drm/rockchip/cdn-dp-core.c
> > index 06fd82b217b6..d94d22650899 100644
> > --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
> > +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
> > @@ -423,7 +423,12 @@ static int cdn_dp_enable_phy(struct
> cdn_dp_device *dp, struct cdn_dp_port *port)
> > }
> >
> > port->lanes = cdn_dp_get_port_lanes(port);
> > - ret = cdns_mhdp_set_host_cap(&dp->mhdp, property.intval);
> > +
> > + if (property.intval)
> > + dp->mhdp.lane_mapping = LANE_MAPPING_FLIPPED;
> > + else
> > + dp->mhdp.lane_mapping = LANE_MAPPING_NORMAL;
> > + ret = cdns_mhdp_set_host_cap(&dp->mhdp);
> > if (ret) {
> > DRM_DEV_ERROR(dev, "set host capabilities failed: %d\n",
> > ret);
> > diff --git a/include/drm/bridge/cdns-mhdp.h
> > b/include/drm/bridge/cdns-mhdp.h index c8170e6048f7..6ffb97e17fae
> > 100644
> > --- a/include/drm/bridge/cdns-mhdp.h
> > +++ b/include/drm/bridge/cdns-mhdp.h
> > @@ -14,6 +14,7 @@
> >
> > #define ADDR_IMEM 0x10000
> > #define ADDR_DMEM 0x20000
> > +#define ADDR_PHY_AFE 0x80000
> >
> > /* APB CFG addr */
> > #define APB_CTRL 0
> > @@ -81,6 +82,10 @@
> > #define SOURCE_PIF_SW_RESET 0x30834
> >
> > /* bellow registers need access by mailbox */
> > +
> > +/* source phy comp */
> > +#define LANES_CONFIG 0x0814
> > +
> > /* source car addr */
> > #define SOURCE_HDTX_CAR 0x0900
> > #define SOURCE_DPTX_CAR 0x0904
> > @@ -424,6 +429,16 @@
> > /* Reference cycles when using lane clock as reference */
> > #define LANE_REF_CYC 0x8000
> >
> > +#define HOTPLUG_DEBOUNCE_MS 200
> > +
> > +#define IRQ_IN 0
> > +#define IRQ_OUT 1
> > +#define IRQ_NUM 2
> > +
> > +#define cdns_mhdp_plat_call(mhdp, operation) \
> > + (!(mhdp) ? -ENODEV : (((mhdp)->plat_data &&
> (mhdp)->plat_data->operation) ? \
> > + (mhdp)->plat_data->operation(mhdp) : ENOIOCTLCMD))
> > +
> > enum voltage_swing_level {
> > VOLTAGE_LEVEL_0,
> > VOLTAGE_LEVEL_1,
> > @@ -504,9 +519,29 @@ struct cdns_mhdp_connector {
> > struct cdns_mhdp_bridge *bridge; };
> >
> > +struct cdns_plat_data {
> > + /* Vendor PHY support */
> > + int (*bind)(struct platform_device *pdev,
> > + struct drm_encoder *encoder,
> > + struct cdns_mhdp_device *mhdp);
> > + void (*unbind)(struct device *dev);
> > +
> > + int (*phy_set)(struct cdns_mhdp_device *mhdp);
> > + bool (*phy_video_valid)(struct cdns_mhdp_device *mhdp);
> > + int (*firmware_init)(struct cdns_mhdp_device *mhdp);
> > + void (*pclk_rate)(struct cdns_mhdp_device *mhdp);
> > +
> > + int (*power_on)(struct cdns_mhdp_device *mhdp);
> > + int (*power_off)(struct cdns_mhdp_device *mhdp);
> > +
> > + char *plat_name;
> > + int lane_mapping;
> > +};
> > +
> > struct cdns_mhdp_device {
> > struct device *dev;
> > struct cdns_mhdp_connector connector;
> > + struct cdns_mhdp_bridge bridge;
> >
> > void __iomem *regs_base;
> > struct reset_control *spdif_rst; @@ -520,6 +555,11 @@ struct
> > cdns_mhdp_device {
> >
> > unsigned int fw_version;
> >
> > + struct delayed_work hotplug_work;
> > + u32 lane_mapping;
> > + bool power_up;
> > + struct mutex lock;
> > + int irq[IRQ_NUM];
> > union {
> > struct _dp_data {
> > u32 rate;
> > @@ -528,6 +568,8 @@ struct cdns_mhdp_device {
> > u8 dpcd[DP_RECEIVER_CAP_SIZE];
> > } dp;
> > };
> > + const struct cdns_plat_data *plat_data;
> > +
> > };
> >
> > void cdns_mhdp_clock_reset(struct cdns_mhdp_device *mhdp); @@
> -535,7
> > +577,7 @@ void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp,
> > unsigned long clk); int cdns_mhdp_load_firmware(struct
> cdns_mhdp_device *mhdp, const u32 *i_mem,
> > u32 i_size, const u32 *d_mem, u32 d_size);
> > int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool
> > enable); -int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp,
> > bool flip);
> > +int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp);
> > int cdns_mhdp_event_config(struct cdns_mhdp_device *mhdp);
> > u32 cdns_mhdp_get_event(struct cdns_mhdp_device *mhdp); int
> > cdns_mhdp_read_hpd(struct cdns_mhdp_device *mhdp); @@ -547,10
> +589,18
> > @@ int cdns_mhdp_get_edid_block(void *mhdp, u8 *edid, int
> > cdns_mhdp_train_link(struct cdns_mhdp_device *mhdp); int
> > cdns_mhdp_set_video_status(struct cdns_mhdp_device *mhdp, int active);
> > int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp);
> > +bool cdns_mhdp_check_alive(struct cdns_mhdp_device *mhdp);
> > int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp,
> > struct audio_info *audio); int
> > cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable);
> int
> > cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp,
> > struct audio_info *audio);
> >
> > +int cdns_phy_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32
> > +val);
> > +u32 cdns_phy_reg_read(struct cdns_mhdp_device *mhdp, u32 addr);
> > +
> > +/* DP */
> > +int cdns_dp_bind(struct platform_device *pdev, struct drm_encoder
> *encoder,
> > + struct cdns_mhdp_device *mhdp); void
> > +cdns_dp_unbind(struct device *dev);
> > #endif /* CDNS_MHDP_H_ */
>
> --
> Regards,
>
> Laurent Pinchart
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [EXT] Re: [PATCH 1/7] drm/rockchip: prepare common code for cdns and rk dpi/dp driver
From: Sandor Yu @ 2020-06-04 9:28 UTC (permalink / raw)
To: Laurent Pinchart, Emil Velikov
Cc: Jernej Skrabec, Heiko Stübner, Jonas Karlman, Neil Armstrong,
Sandy Huang, ML dri-devel, Linux-Kernel@Vger. Kernel. Org,
Andrzej Hajda, dl-linux-imx, linux-rockchip, dkos@cadence.com,
LAKML
In-Reply-To: <20200602232840.GP6547@pendragon.ideasonboard.com>
> -----Original Message-----
> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Sent: Wednesday, June 3, 2020 7:29 AM
> To: Emil Velikov <emil.l.velikov@gmail.com>
> Cc: Sandor Yu <sandor.yu@nxp.com>; Andrzej Hajda <a.hajda@samsung.com>;
> Neil Armstrong <narmstrong@baylibre.com>; Jonas Karlman
> <jonas@kwiboo.se>; Jernej Skrabec <jernej.skrabec@siol.net>; Heiko Stübner
> <heiko@sntech.de>; Sandy Huang <hjc@rock-chips.com>;
> dkos@cadence.com; ML dri-devel <dri-devel@lists.freedesktop.org>;
> linux-rockchip <linux-rockchip@lists.infradead.org>; Linux-Kernel@Vger.
> Kernel. Org <linux-kernel@vger.kernel.org>; LAKML
> <linux-arm-kernel@lists.infradead.org>; dl-linux-imx <linux-imx@nxp.com>
> Subject: [EXT] Re: [PATCH 1/7] drm/rockchip: prepare common code for cdns
> and rk dpi/dp driver
>
> Caution: EXT Email
>
> On Tue, Jun 02, 2020 at 02:55:52PM +0100, Emil Velikov wrote:
> > On Mon, 1 Jun 2020 at 07:29, <sandor.yu@nxp.com> wrote:
> > >
> > > From: Sandor Yu <Sandor.yu@nxp.com>
> > >
> > > - Extracted common fields from cdn_dp_device to a new
> cdns_mhdp_device
> > > structure which will be used by two separate drivers later on.
> > > - Moved some datatypes (audio_format, audio_info,
> vic_pxl_encoding_format,
> > > video_info) from cdn-dp-core.c to cdn-dp-reg.h.
> > > - Changed prefixes from cdn_dp to cdns_mhdp
> > > cdn -> cdns to match the other Cadence's drivers
> > > dp -> mhdp to distinguish it from a "just a DP" as the IP underneath
> > > this registers map can be a HDMI (which is internally different,
> > > but the interface for commands, events is pretty much the same).
> > > - Modified cdn-dp-core.c to use the new driver structure and new function
> > > names.
> > > - writel and readl are replaced by cdns_mhdp_bus_write and
> > > cdns_mhdp_bus_read.
> > >
> > The high-level idea is great - split, refactor and reuse the existing drivers.
> >
> > Although looking at the patches themselves - they seems to be doing
> > multiple things at once.
> > As indicated by the extensive list in the commit log.
> >
> > I would suggest splitting those up a bit, roughly in line of the
> > itemisation as per the commit message.
> >
> > Here is one hand wavy way to chunk this patch:
> > 1) use put_unalligned*
> > 2) 'use local variable dev' style of changes (as seem in
> > cdn_dp_clk_enable)
> > 3) add writel/readl wrappers
> > 4) hookup struct cdns_mhdp_device, keep dp->mhdp detail internal.
> > The cdn-dp-reg.h function names/signatures will stay the same.
> > 5) finalize the helpers - use mhdp directly, rename
>
> I second this, otherwise review is very hard.
>
I will split the patch later, thanks.
> > Examples:
> > 4)
> > static int cdn_dp_mailbox_read(struct cdn_dp_device *dp) {
> > +" struct cdns_mhdp_device *mhdp = dp->mhdp;
> > int val, ret;
> >
> > - ret = readx_poll_timeout(readl, dp->regs + MAILBOX_EMPTY_ADDR,
> > + ret = readx_poll_timeout(readl, mhdp->regs_base +
> > + MAILBOX_EMPTY_ADDR,
> > ...
> > return fancy_readl(dp, MAILBOX0_RD_DATA) & 0xff; }
> >
> > 5)
> > -static int cdn_dp_mailbox_read(struct cdn_dp_device *dp)
> > +static int mhdp_mailbox_read(struct cdns_mhdp_device *mhdp)
> > {
> > - struct cdns_mhdp_device *mhdp = dp->mhdp;
> > int val, ret;
> > ...
> > - return fancy_readl(dp, MAILBOX0_RD_DATA) & 0xff;
> > + return cdns_mhdp_bus_read(mhdp, MAILBOX0_RD_DATA) & 0xff;
> > }
>
> --
> Regards,
>
> Laurent Pinchart
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [V9, 2/2] media: i2c: ov02a10: Add OV02A10 image sensor driver
From: Sakari Ailus @ 2020-06-04 9:26 UTC (permalink / raw)
To: Dongchun Zhu
Cc: mark.rutland, drinkcat, andriy.shevchenko, srv_heupstream,
devicetree, linus.walleij, shengnan.wang, tfiga, bgolaszewski,
sj.huang, robh+dt, linux-mediatek, louis.kuo, matthias.bgg,
bingbu.cao, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <1591236845.8804.547.camel@mhfsdcap03>
Hi Dongchun,
On Thu, Jun 04, 2020 at 10:14:05AM +0800, Dongchun Zhu wrote:
> Hi Tomasz, Sakari, and sirs,
>
> Could anyone help to review this patch?
>
> On Sat, 2020-05-23 at 16:41 +0800, Dongchun Zhu wrote:
> > Add a V4L2 sub-device driver for OV02A10 image sensor.
> >
> > Signed-off-by: Dongchun Zhu <dongchun.zhu@mediatek.com>
> > ---
> > MAINTAINERS | 1 +
> > drivers/media/i2c/Kconfig | 13 +
> > drivers/media/i2c/Makefile | 1 +
> > drivers/media/i2c/ov02a10.c | 1025 +++++++++++++++++++++++++++++++++++++++++++
> > 4 files changed, 1040 insertions(+)
> > create mode 100644 drivers/media/i2c/ov02a10.c
> >
>
> [snip]
>
> > +static int ov02a10_probe(struct i2c_client *client)
> > +{
> > + struct device *dev = &client->dev;
> > + struct ov02a10 *ov02a10;
> > + unsigned int rotation;
> > + unsigned int clock_lane_tx_speed;
> > + unsigned int i;
> > + int ret;
> > +
> > + ov02a10 = devm_kzalloc(dev, sizeof(*ov02a10), GFP_KERNEL);
> > + if (!ov02a10)
> > + return -ENOMEM;
> > +
> > + ret = ov02a10_check_hwcfg(dev, ov02a10);
> > + if (ret) {
> > + dev_err(dev, "failed to check HW configuration: %d", ret);
> > + return ret;
> > + }
> > +
> > + v4l2_i2c_subdev_init(&ov02a10->subdev, client, &ov02a10_subdev_ops);
> > + ov02a10->mipi_clock_tx_speed = OV02A10_MIPI_TX_SPEED_DEFAULT;
> > + ov02a10->fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
> > +
> > + /* Optional indication of physical rotation of sensor */
> > + ret = fwnode_property_read_u32(dev_fwnode(dev), "rotation", &rotation);
> > + if (!ret && rotation == 180) {
> > + ov02a10->upside_down = true;
> > + ov02a10->fmt.code = MEDIA_BUS_FMT_SRGGB10_1X10;
> > + }
> > +
> > + /* Optional indication of mipi TX speed */
> > + ret = fwnode_property_read_u32(dev_fwnode(dev), "ovti,mipi-tx-speed",
> > + &clock_lane_tx_speed);
> > +
> > + if (!ret)
> > + ov02a10->mipi_clock_tx_speed = clock_lane_tx_speed;
> > +
> > + /* Get system clock (eclk) */
> > + ov02a10->eclk = devm_clk_get(dev, "eclk");
> > + if (IS_ERR(ov02a10->eclk)) {
> > + ret = PTR_ERR(ov02a10->eclk);
> > + dev_err(dev, "failed to get eclk %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
> > + &ov02a10->eclk_freq);
> > + if (ret) {
> > + dev_err(dev, "failed to get eclk frequency\n");
> > + return ret;
> > + }
> > +
> > + ret = clk_set_rate(ov02a10->eclk, ov02a10->eclk_freq);
> > + if (ret) {
> > + dev_err(dev, "failed to set eclk frequency (24MHz)\n");
> > + return ret;
> > + }
> > +
> > + if (clk_get_rate(ov02a10->eclk) != OV02A10_ECLK_FREQ) {
> > + dev_warn(dev, "wrong eclk frequency %d Hz, expected: %d Hz\n",
> > + ov02a10->eclk_freq, OV02A10_ECLK_FREQ);
> > + return -EINVAL;
> > + }
> > +
> > + ov02a10->pd_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_HIGH);
> > + if (IS_ERR(ov02a10->pd_gpio)) {
> > + ret = PTR_ERR(ov02a10->pd_gpio);
> > + dev_err(dev, "failed to get powerdown-gpios %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ov02a10->n_rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> > + if (IS_ERR(ov02a10->n_rst_gpio)) {
> > + ret = PTR_ERR(ov02a10->n_rst_gpio);
> > + dev_err(dev, "failed to get reset-gpios %d\n", ret);
> > + return ret;
> > + }
> > +
> > + for (i = 0; i < ARRAY_SIZE(ov02a10_supply_names); i++)
> > + ov02a10->supplies[i].supply = ov02a10_supply_names[i];
> > +
> > + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ov02a10_supply_names),
> > + ov02a10->supplies);
> > + if (ret) {
> > + dev_err(dev, "failed to get regulators\n");
> > + return ret;
> > + }
> > +
> > + mutex_init(&ov02a10->mutex);
> > + ov02a10->cur_mode = &supported_modes[0];
> > + ret = ov02a10_initialize_controls(ov02a10);
> > + if (ret) {
> > + dev_err(dev, "failed to initialize controls\n");
> > + goto err_destroy_mutex;
> > + }
> > +
> > + ov02a10->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> > + ov02a10->subdev.entity.ops = &ov02a10_subdev_entity_ops;
> > + ov02a10->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> > + ov02a10->pad.flags = MEDIA_PAD_FL_SOURCE;
> > + ret = media_entity_pads_init(&ov02a10->subdev.entity, 1, &ov02a10->pad);
> > + if (ret < 0) {
> > + dev_err(dev, "failed to init entity pads: %d", ret);
> > + goto err_free_handler;
> > + }
> > +
> > + pm_runtime_enable(dev);
> > + if (!pm_runtime_enabled(dev)) {
> > + ret = ov02a10_power_on(dev);
> > + if (ret < 0) {
> > + dev_err(dev, "failed to power on: %d\n", ret);
> > + goto err_free_handler;
> > + }
> > + }
> > +
> > + ret = v4l2_async_register_subdev(&ov02a10->subdev);
> > + if (ret) {
> > + dev_err(dev, "failed to register V4L2 subdev: %d", ret);
> > + if (!pm_runtime_enabled(dev))
> > + ov02a10_power_off(dev);
This should be moved to error handling section below.
> > + goto err_clean_entity;
> > + }
>
> Tomasz, Sakari, is this ok?
> or coding like this:
>
> ret = v4l2_async_register_subdev(&ov02a10->subdev);
> if (!pm_runtime_enabled(dev))
> ov02a10_power_off(dev);
> if (ret) {
> dev_err(dev, "failed to register V4L2 subdev: %d", ret);
> goto err_clean_entity;
> }
>
> What's your opinions about the change?
This turns power off if runtime PM is disabled. I'd keep it as-is, as it'd
require re-implementing what runtime PM is used for now --- and that's not
a sensor driver's job.
>
> > +
> > + return 0;
> > +
> > +err_clean_entity:
> > + media_entity_cleanup(&ov02a10->subdev.entity);
> > +err_free_handler:
> > + v4l2_ctrl_handler_free(ov02a10->subdev.ctrl_handler);
> > +err_destroy_mutex:
> > + mutex_destroy(&ov02a10->mutex);
> > +
> > + return ret;
> > +}
> > +
> > +static int ov02a10_remove(struct i2c_client *client)
> > +{
> > + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > + struct ov02a10 *ov02a10 = to_ov02a10(sd);
> > +
> > + v4l2_async_unregister_subdev(sd);
> > + media_entity_cleanup(&sd->entity);
> > + v4l2_ctrl_handler_free(sd->ctrl_handler);
> > + pm_runtime_disable(&client->dev);
> > + if (!pm_runtime_status_suspended(&client->dev))
> > + ov02a10_power_off(&client->dev);
> > + pm_runtime_set_suspended(&client->dev);
> > + mutex_destroy(&ov02a10->mutex);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id ov02a10_of_match[] = {
> > + { .compatible = "ovti,ov02a10" },
> > + {}
> > +};
> > +MODULE_DEVICE_TABLE(of, ov02a10_of_match);
> > +
> > +static struct i2c_driver ov02a10_i2c_driver = {
> > + .driver = {
> > + .name = "ov02a10",
> > + .pm = &ov02a10_pm_ops,
> > + .of_match_table = ov02a10_of_match,
> > + },
> > + .probe_new = &ov02a10_probe,
> > + .remove = &ov02a10_remove,
> > +};
> > +
> > +module_i2c_driver(ov02a10_i2c_driver);
> > +
> > +MODULE_AUTHOR("Dongchun Zhu <dongchun.zhu@mediatek.com>");
> > +MODULE_DESCRIPTION("OmniVision OV02A10 sensor driver");
> > +MODULE_LICENSE("GPL v2");
> > +
>
--
Sakari Ailus
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 0/5 v2] KASan for ARM
From: Linus Walleij @ 2020-06-04 9:24 UTC (permalink / raw)
To: Florian Fainelli, Rob Herring
Cc: Abbott Liu, Andrey Ryabinin, Russell King, Linux ARM,
Ard Biesheuvel
In-Reply-To: <CACRpkdbEhnOfvHEQZ1GbdKuTchfBn1TozeD02NBFJ_YF6WwH=g@mail.gmail.com>
On Wed, Jun 3, 2020 at 10:45 AM Linus Walleij <linus.walleij@linaro.org> wrote:
> On Mon, Jun 1, 2020 at 6:37 PM Florian Fainelli <f.fainelli@gmail.com> wrote:
>
> > This branch got me a bit further,
>
> Thanks, at least we get improvements. :)
>
> > but still failed to fully initialize
> > (see attached kasan.log), on another platform with a slightly different
> > memory map, I ended up getting a different error (kasan2.log).
>
> I have this error too on a Qualcomm board, it is what I report
> in the cover letter, that if I load the kernel into 0x40200000
> this happens but when I load it into 0x50000000 it does not
> happen.
So this is what happens to me, even after I try to de-instrument
the DT parsing code (maybe I do it all wrong...)
This is done with that patch:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/commit/?h=kasan-apq8060-test&id=1cd83357f3c35b037400f6ec2547eeff074c578c
If I boot from physical memory at 0x40200000
fastboot --base 40200000 --cmdline "console=ttyMSM0,115200,n8" boot zImage
kasan: populating shadow for b7040000, b75c0000
kasan: populating shadow for b8000000, bb000000
kasan: populating shadow for b6e00000, b7000000
kasan: Kernel address sanitizer initialized
8<--- cut here ---
Unable to handle kernel paging request at virtual address c30050b0
pgd = (ptrval)
[c30050b0] *pgd=00000000c
Internal error: Oops: 5 [#1] PREEMPT SMP ARM
Modules linked in:c
CPU: 0 PID: 0 Comm: swapper Not tainted 5.7.0-00011-g1cd83357f3c3 #34
Hardware name: Generic DT based system
PC is at fdt_check_header+0x0/0x168
LR is at __unflatten_device_tree+0x6c/0x338
pc : [<c08e6968>] lr : [<c0d698a8>] psr: 60000093
sp : c1e03db8 ip : cffffee0 fp : fffff000
r10: 00000000 r9 : c2646000 r8 : 00000000
r7 : c30050b0 r6 : c192e9e4 r5 : c19492e8 r4 : c21d7448
r3 : 00000000 r2 : c2646000 r1 : 00000000 r0 : c30050b0
(...)
[<c08e6968>] (fdt_check_header) from [<c192e9e4>]
(early_init_dt_alloc_memory_arch+0x0/0x64)
[<c192e9e4>] (early_init_dt_alloc_memory_arch) from [<c1930264>]
(unflatten_device_tree+0x34/0x44)
[<c1930264>] (unflatten_device_tree) from [<c1905794>] (setup_arch+0xac4/0xde8)
[<c1905794>] (setup_arch) from [<c1900b98>] (start_kernel+0xd8/0x634)
[<c1900b98>] (start_kernel) from [<00000000>] (0x0)
Code: e3a00020 e12fff1e e3a0001c e12fff1e (e5901000)
random: get_random_bytes called from print_oops_end_marker+0x38/0x50
with crng_init=0
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Attempted to kill the idle task!
---[ end Kernel panic - not syncing: Attempted to kill the idle task! ]---
But if I instead boot from 0x50000000 I just get this lesser error and
the platform actually comes up:
fastboot --base 50000000 --cmdline "console=ttyMSM0,115200,n8" boot zImage
[ 0.000000] kasan: populating shadow for b7000000, b9000000
[ 0.000000] kasan: populating shadow for b6e00000, b7000000
[ 0.000000] kasan: Kernel address sanitizer initialized
[ 0.000000] ==================================================================
[ 0.000000] BUG: KASAN: stack-out-of-bounds in
memblock_alloc_try_nid+0x9c/0xac
[ 0.000000] Write of size 61920 at addr cdbd6e20 by task swapper/0
[ 0.000000]
[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted
5.7.0-00011-g1cd83357f3c3 #34
[ 0.000000] Hardware name: Generic DT based system
[ 0.000000] [<c0317844>] (unwind_backtrace) from [<c0310544>]
(show_stack+0x10/0x14)
[ 0.000000] [<c0310544>] (show_stack) from [<c08e6374>]
(dump_stack+0x80/0x98)
[ 0.000000] [<c08e6374>] (dump_stack) from [<c050eed0>]
(print_address_description.constprop.3+0x50/0x478)
[ 0.000000] [<c050eed0>] (print_address_description.constprop.3)
from [<c050f508>] (__kasan_report+0xf0/0x12c)
[ 0.000000] [<c050f508>] (__kasan_report) from [<c050e95c>]
(kasan_report+0x34/0x3c)
[ 0.000000] [<c050e95c>] (kasan_report) from [<c050fed0>]
(check_memory_region+0x14c/0x1b0)
[ 0.000000] [<c050fed0>] (check_memory_region) from [<c050e100>]
(memset+0x20/0x3c)
[ 0.000000] [<c050e100>] (memset) from [<c1918898>]
(memblock_alloc_try_nid+0x9c/0xac)
[ 0.000000] [<c1918898>] (memblock_alloc_try_nid) from [<c192ea14>]
(early_init_dt_alloc_memory_arch+0x30/0x64)
[ 0.000000] [<c192ea14>] (early_init_dt_alloc_memory_arch) from
[<c0d698f0>] (__unflatten_device_tree+0xb4/0x338)
[ 0.000000] [<c0d698f0>] (__unflatten_device_tree) from
[<c1930264>] (unflatten_device_tree+0x34/0x44)
[ 0.000000] [<c1930264>] (unflatten_device_tree) from [<c1905794>]
(setup_arch+0xac4/0xde8)
[ 0.000000] [<c1905794>] (setup_arch) from [<c1900b98>]
(start_kernel+0xd8/0x634)
[ 0.000000] [<c1900b98>] (start_kernel) from [<00000000>] (0x0)
[ 0.000000]
[ 0.000000] The buggy address belongs to the page:
[ 0.000000] page:cffafac0 refcount:1 mapcount:0 mapping:00000000 index:0x0
[ 0.000000] flags: 0x0()
[ 0.000000] raw: 00000000 cffafac4 cffafac4 00000000 00000000
00000000 ffffffff 00000001
[ 0.000000] page dumped because: kasan: bad access detected
[ 0.000000]
[ 0.000000] Memory state around the buggy address:
[ 0.000000] cdbe3d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 0.000000] cdbe3d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 0.000000] >cdbe3e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 0.000000] ^
[ 0.000000] cdbe3e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 0.000000] cdbe3f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 0.000000] ==================================================================
There is something really funky going on with how devicetree is unflattened
in this platform I think, I just need to figure it out.
I do not think it is a KASan bug per se, more of a DT parser issue, like it is
doing stuff that need to be properly de-instrumented.
Any hints welcome!
Yours,
Linus Walleij
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC] dt-bindings: mailbox: add doorbell support to ARM MHU
From: Sudeep Holla @ 2020-06-04 9:20 UTC (permalink / raw)
To: Jassi Brar
Cc: Rob Herring, Arnd Bergmann, Devicetree List, Viresh Kumar,
Linux Kernel Mailing List, Bjorn Andersson, Frank Rowand,
linux-arm-kernel
In-Reply-To: <CABb+yY0cW1GZHVmwEr19JRdJTmsAxw9uq83QV_aq-tdPJO5_Fg@mail.gmail.com>
On Wed, Jun 03, 2020 at 01:32:42PM -0500, Jassi Brar wrote:
> On Wed, Jun 3, 2020 at 1:04 PM Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Fri, May 29, 2020 at 09:37:58AM +0530, Viresh Kumar wrote:
> > > On 28-05-20, 13:20, Rob Herring wrote:
> > > > Whether Linux
> > > > requires serializing mailbox accesses is a separate issue. On that side,
> > > > it seems silly to not allow driving the h/w in the most efficient way
> > > > possible.
> > >
> > > That's exactly what we are trying to say. The hardware allows us to
> > > write all 32 bits in parallel, without any hardware issues, why
> > > shouldn't we do that ? The delay (which Sudeep will find out, he is
> > > facing issues with hardware access because of lockdown right now)
> >
> > OK, I was able to access the setup today. I couldn't reach a point
> > where I can do measurements as the system just became unusable with
> > one physical channel instead of 2 virtual channels as in my patches.
> >
> > My test was simple. Switch to schedutil and read sensors periodically
> > via sysfs.
> >
> > arm-scmi firmware:scmi: message for 1 is not expected!
> >
> This sounds like you are not serialising requests on a shared channel.
> Can you please also share the patch?
OK, I did try with a small patch initially and then realised we must hit
issue with mainline as is. Tried and the behaviour is exact same. All
I did is removed my patches and use bit[0] as the signal. It doesn't
matter as writes to the register are now serialised. Oh, the above
message comes when OS times out in advance while firmware continues to
process the old request and respond.
The trace I sent gives much better view of what's going on.
--
Regards,
Sudeep
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH RESEND v9 18/18] media: platform: Add jpeg enc feature
From: Xia Jiang @ 2020-06-04 9:05 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
Matthias Brugger, Rick Chang
Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604090553.10861-1-xia.jiang@mediatek.com>
Add mtk jpeg encode v4l2 driver based on jpeg decode, because that jpeg
decode and encode have great similarities with function operation.
Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: add member variable(struct v4l2_rect) in out_q structure for storing
the active crop information.
move the renaming exsting functions/defines/variables to a separate patch.
---
drivers/media/platform/mtk-jpeg/Makefile | 5 +-
.../media/platform/mtk-jpeg/mtk_jpeg_core.c | 845 +++++++++++++++---
.../media/platform/mtk-jpeg/mtk_jpeg_core.h | 44 +-
.../media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c | 193 ++++
.../media/platform/mtk-jpeg/mtk_jpeg_enc_hw.h | 123 +++
5 files changed, 1084 insertions(+), 126 deletions(-)
create mode 100644 drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
create mode 100644 drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.h
diff --git a/drivers/media/platform/mtk-jpeg/Makefile b/drivers/media/platform/mtk-jpeg/Makefile
index 48516dcf96e6..76c33aad0f3f 100644
--- a/drivers/media/platform/mtk-jpeg/Makefile
+++ b/drivers/media/platform/mtk-jpeg/Makefile
@@ -1,3 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-mtk_jpeg-objs := mtk_jpeg_core.o mtk_jpeg_dec_hw.o mtk_jpeg_dec_parse.o
+mtk_jpeg-objs := mtk_jpeg_core.o \
+ mtk_jpeg_dec_hw.o \
+ mtk_jpeg_dec_parse.o \
+ mtk_jpeg_enc_hw.o
obj-$(CONFIG_VIDEO_MEDIATEK_JPEG) += mtk_jpeg.o
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index 29b8b82c606c..d7ef69920530 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -3,6 +3,7 @@
* Copyright (c) 2016 MediaTek Inc.
* Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
* Rick Chang <rick.chang@mediatek.com>
+ * Xia Jiang <xia.jiang@mediatek.com>
*/
#include <linux/clk.h>
@@ -23,10 +24,59 @@
#include <media/videobuf2-dma-contig.h>
#include <soc/mediatek/smi.h>
+#include "mtk_jpeg_enc_hw.h"
#include "mtk_jpeg_dec_hw.h"
#include "mtk_jpeg_core.h"
#include "mtk_jpeg_dec_parse.h"
+static struct mtk_jpeg_fmt mtk_jpeg_enc_formats[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .colplanes = 1,
+ .flags = MTK_JPEG_FMT_FLAG_ENC_CAPTURE,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12M,
+ .hw_format = JPEG_ENC_YUV_FORMAT_NV12,
+ .h_sample = {4, 4},
+ .v_sample = {4, 2},
+ .colplanes = 2,
+ .h_align = 4,
+ .v_align = 4,
+ .flags = MTK_JPEG_FMT_FLAG_ENC_OUTPUT,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV21M,
+ .hw_format = JEPG_ENC_YUV_FORMAT_NV21,
+ .h_sample = {4, 4},
+ .v_sample = {4, 2},
+ .colplanes = 2,
+ .h_align = 4,
+ .v_align = 4,
+ .flags = MTK_JPEG_FMT_FLAG_ENC_OUTPUT,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .hw_format = JPEG_ENC_YUV_FORMAT_YUYV,
+ .h_sample = {8},
+ .v_sample = {4},
+ .colplanes = 1,
+ .h_align = 5,
+ .v_align = 3,
+ .flags = MTK_JPEG_FMT_FLAG_ENC_OUTPUT,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .hw_format = JPEG_ENC_YUV_FORMAT_YVYU,
+ .h_sample = {8},
+ .v_sample = {4},
+ .colplanes = 1,
+ .h_align = 5,
+ .v_align = 3,
+ .flags = MTK_JPEG_FMT_FLAG_ENC_OUTPUT,
+ },
+};
+
static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
{
.fourcc = V4L2_PIX_FMT_JPEG,
@@ -53,6 +103,7 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
},
};
+#define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats)
#define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
struct mtk_jpeg_src_buf {
@@ -64,6 +115,11 @@ struct mtk_jpeg_src_buf {
static int debug;
module_param(debug, int, 0644);
+static inline struct mtk_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl)
+{
+ return container_of(ctrl->handler, struct mtk_jpeg_ctx, ctrl_hdl);
+}
+
static inline struct mtk_jpeg_ctx *mtk_jpeg_fh_to_ctx(struct v4l2_fh *fh)
{
return container_of(fh, struct mtk_jpeg_ctx, fh);
@@ -75,6 +131,19 @@ static inline struct mtk_jpeg_src_buf *mtk_jpeg_vb2_to_srcbuf(
return container_of(to_vb2_v4l2_buffer(vb), struct mtk_jpeg_src_buf, b);
}
+static int mtk_jpeg_enc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct mtk_jpeg_dev *jpeg = video_drvdata(file);
+
+ strscpy(cap->driver, MTK_JPEG_NAME, sizeof(cap->driver));
+ strscpy(cap->card, MTK_JPEG_NAME " encoder", sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+ dev_name(jpeg->dev));
+
+ return 0;
+}
+
static int mtk_jpeg_dec_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -88,6 +157,54 @@ static int mtk_jpeg_dec_querycap(struct file *file, void *priv,
return 0;
}
+static int vidioc_jpeg_enc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct mtk_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
+
+ switch (ctrl->id) {
+ case V4L2_CID_JPEG_RESTART_INTERVAL:
+ ctx->restart_interval = ctrl->val;
+ break;
+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+ ctx->enc_quality = ctrl->val;
+ break;
+ case V4L2_CID_JPEG_ACTIVE_MARKER:
+ ctx->enable_exif = ctrl->val & V4L2_JPEG_ACTIVE_MARKER_APP1 ?
+ true : false;
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops mtk_jpeg_enc_ctrl_ops = {
+ .s_ctrl = vidioc_jpeg_enc_s_ctrl,
+};
+
+static int mtk_jpeg_enc_ctrls_setup(struct mtk_jpeg_ctx *ctx)
+{
+ const struct v4l2_ctrl_ops *ops = &mtk_jpeg_enc_ctrl_ops;
+ struct v4l2_ctrl_handler *handler = &ctx->ctrl_hdl;
+
+ v4l2_ctrl_handler_init(handler, 3);
+
+ v4l2_ctrl_new_std(handler, ops, V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100,
+ 1, 0);
+ v4l2_ctrl_new_std(handler, ops, V4L2_CID_JPEG_COMPRESSION_QUALITY, 48,
+ 100, 1, 90);
+ v4l2_ctrl_new_std(handler, ops, V4L2_CID_JPEG_ACTIVE_MARKER, 0,
+ V4L2_JPEG_ACTIVE_MARKER_APP1, 0, 0);
+
+ if (handler->error) {
+ v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+ return handler->error;
+ }
+
+ v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+
+ return 0;
+}
+
static int mtk_jpeg_enum_fmt(struct mtk_jpeg_fmt *mtk_jpeg_formats, int n,
struct v4l2_fmtdesc *f, u32 type)
{
@@ -109,6 +226,14 @@ static int mtk_jpeg_enum_fmt(struct mtk_jpeg_fmt *mtk_jpeg_formats, int n,
return 0;
}
+static int mtk_jpeg_enc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ return mtk_jpeg_enum_fmt(mtk_jpeg_enc_formats,
+ MTK_JPEG_ENC_NUM_FORMATS, f,
+ MTK_JPEG_FMT_FLAG_ENC_CAPTURE);
+}
+
static int mtk_jpeg_dec_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
@@ -117,6 +242,14 @@ static int mtk_jpeg_dec_enum_fmt_vid_cap(struct file *file, void *priv,
MTK_JPEG_FMT_FLAG_DEC_CAPTURE);
}
+static int mtk_jpeg_enc_enum_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ return mtk_jpeg_enum_fmt(mtk_jpeg_enc_formats,
+ MTK_JPEG_ENC_NUM_FORMATS, f,
+ MTK_JPEG_FMT_FLAG_ENC_OUTPUT);
+}
+
static int mtk_jpeg_dec_enum_fmt_vid_out(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
@@ -132,93 +265,66 @@ mtk_jpeg_get_q_data(struct mtk_jpeg_ctx *ctx, enum v4l2_buf_type type)
return &ctx->cap_q;
}
-static struct mtk_jpeg_fmt *mtk_jpeg_find_format(struct mtk_jpeg_ctx *ctx,
- u32 pixelformat,
+static struct mtk_jpeg_fmt *mtk_jpeg_find_format(u32 pixelformat,
unsigned int fmt_type)
{
- unsigned int k, fmt_flag;
+ unsigned int k;
+ struct mtk_jpeg_fmt *fmt;
- fmt_flag = (fmt_type == MTK_JPEG_FMT_TYPE_OUTPUT) ?
- MTK_JPEG_FMT_FLAG_DEC_OUTPUT :
- MTK_JPEG_FMT_FLAG_DEC_CAPTURE;
+ for (k = 0; k < MTK_JPEG_ENC_NUM_FORMATS; k++) {
+ fmt = &mtk_jpeg_enc_formats[k];
+
+ if (fmt->fourcc == pixelformat && fmt->flags & fmt_type)
+ return fmt;
+ }
for (k = 0; k < MTK_JPEG_DEC_NUM_FORMATS; k++) {
- struct mtk_jpeg_fmt *fmt = &mtk_jpeg_dec_formats[k];
+ fmt = &mtk_jpeg_dec_formats[k];
- if (fmt->fourcc == pixelformat && fmt->flags & fmt_flag)
+ if (fmt->fourcc == pixelformat && fmt->flags & fmt_type)
return fmt;
}
return NULL;
}
-static void mtk_jpeg_adjust_fmt_mplane(struct mtk_jpeg_ctx *ctx,
- struct v4l2_format *f)
-{
- struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
- struct mtk_jpeg_q_data *q_data;
- int i;
-
- q_data = mtk_jpeg_get_q_data(ctx, f->type);
-
- pix_mp->width = q_data->w;
- pix_mp->height = q_data->h;
- pix_mp->pixelformat = q_data->fmt->fourcc;
- pix_mp->num_planes = q_data->fmt->colplanes;
-
- for (i = 0; i < pix_mp->num_planes; i++) {
- pix_mp->plane_fmt[i].bytesperline = q_data->bytesperline[i];
- pix_mp->plane_fmt[i].sizeimage = q_data->sizeimage[i];
- }
-}
-
-static int mtk_jpeg_try_fmt_mplane(struct v4l2_format *f,
- struct mtk_jpeg_fmt *fmt,
- struct mtk_jpeg_ctx *ctx, int q_type)
+static int vidioc_try_fmt(struct v4l2_format *f, struct mtk_jpeg_fmt *fmt)
{
struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
int i;
pix_mp->field = V4L2_FIELD_NONE;
-
- if (ctx->state != MTK_JPEG_INIT) {
- mtk_jpeg_adjust_fmt_mplane(ctx, f);
- return 0;
- }
-
pix_mp->num_planes = fmt->colplanes;
pix_mp->pixelformat = fmt->fourcc;
- if (q_type == MTK_JPEG_FMT_TYPE_OUTPUT) {
- struct v4l2_plane_pix_format *pfmt = &pix_mp->plane_fmt[0];
-
+ if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
pix_mp->height = clamp(pix_mp->height, MTK_JPEG_MIN_HEIGHT,
MTK_JPEG_MAX_HEIGHT);
pix_mp->width = clamp(pix_mp->width, MTK_JPEG_MIN_WIDTH,
MTK_JPEG_MAX_WIDTH);
-
- pfmt->bytesperline = 0;
- /* Source size must be aligned to 128 */
- pfmt->sizeimage = round_up(pfmt->sizeimage, 128);
- if (pfmt->sizeimage == 0)
- pfmt->sizeimage = MTK_JPEG_DEFAULT_SIZEIMAGE;
- return 0;
+ pix_mp->plane_fmt[0].bytesperline = 0;
+ pix_mp->plane_fmt[0].sizeimage =
+ round_up(pix_mp->plane_fmt[0].sizeimage, 128);
+ if (pix_mp->plane_fmt[0].sizeimage == 0)
+ pix_mp->plane_fmt[0].sizeimage =
+ MTK_JPEG_DEFAULT_SIZEIMAGE;
+ } else {
+ pix_mp->height = clamp(round_up(pix_mp->height, fmt->v_align),
+ MTK_JPEG_MIN_HEIGHT,
+ MTK_JPEG_MAX_HEIGHT);
+ pix_mp->width = clamp(round_up(pix_mp->width, fmt->h_align),
+ MTK_JPEG_MIN_WIDTH, MTK_JPEG_MAX_WIDTH);
+ for (i = 0; i < pix_mp->num_planes; i++) {
+ struct v4l2_plane_pix_format *pfmt =
+ &pix_mp->plane_fmt[i];
+ u32 stride = pix_mp->width * fmt->h_sample[i] / 4;
+ u32 h = pix_mp->height * fmt->v_sample[i] / 4;
+
+ pfmt->bytesperline = stride;
+ pfmt->sizeimage = stride * h;
+ }
}
- /* type is MTK_JPEG_FMT_TYPE_CAPTURE */
- pix_mp->height = clamp(round_up(pix_mp->height, fmt->v_align),
- MTK_JPEG_MIN_HEIGHT, MTK_JPEG_MAX_HEIGHT);
- pix_mp->width = clamp(round_up(pix_mp->width, fmt->h_align),
- MTK_JPEG_MIN_WIDTH, MTK_JPEG_MAX_WIDTH);
-
- for (i = 0; i < fmt->colplanes; i++) {
- struct v4l2_plane_pix_format *pfmt = &pix_mp->plane_fmt[i];
- u32 stride = pix_mp->width * fmt->h_sample[i] / 4;
- u32 h = pix_mp->height * fmt->v_sample[i] / 4;
-
- pfmt->bytesperline = stride;
- pfmt->sizeimage = stride * h;
- }
return 0;
}
@@ -271,14 +377,35 @@ static int mtk_jpeg_g_fmt_vid_mplane(struct file *file, void *priv,
return 0;
}
+static int mtk_jpeg_enc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
+ struct mtk_jpeg_fmt *fmt;
+
+ fmt = mtk_jpeg_find_format(f->fmt.pix_mp.pixelformat,
+ MTK_JPEG_FMT_FLAG_ENC_CAPTURE);
+ if (!fmt)
+ fmt = ctx->cap_q.fmt;
+
+ v4l2_dbg(2, debug, &ctx->jpeg->v4l2_dev, "(%d) try_fmt:%c%c%c%c\n",
+ f->type,
+ (fmt->fourcc & 0xff),
+ (fmt->fourcc >> 8 & 0xff),
+ (fmt->fourcc >> 16 & 0xff),
+ (fmt->fourcc >> 24 & 0xff));
+
+ return vidioc_try_fmt(f, fmt);
+}
+
static int mtk_jpeg_dec_try_fmt_vid_cap_mplane(struct file *file, void *priv,
struct v4l2_format *f)
{
struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
struct mtk_jpeg_fmt *fmt;
- fmt = mtk_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat,
- MTK_JPEG_FMT_TYPE_CAPTURE);
+ fmt = mtk_jpeg_find_format(f->fmt.pix_mp.pixelformat,
+ MTK_JPEG_FMT_FLAG_DEC_CAPTURE);
if (!fmt)
fmt = ctx->cap_q.fmt;
@@ -289,7 +416,33 @@ static int mtk_jpeg_dec_try_fmt_vid_cap_mplane(struct file *file, void *priv,
(fmt->fourcc >> 16 & 0xff),
(fmt->fourcc >> 24 & 0xff));
- return mtk_jpeg_try_fmt_mplane(f, fmt, ctx, MTK_JPEG_FMT_TYPE_CAPTURE);
+ if (ctx->state != MTK_JPEG_INIT) {
+ mtk_jpeg_g_fmt_vid_mplane(file, priv, f);
+ return 0;
+ }
+
+ return vidioc_try_fmt(f, fmt);
+}
+
+static int mtk_jpeg_enc_try_fmt_vid_out_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
+ struct mtk_jpeg_fmt *fmt;
+
+ fmt = mtk_jpeg_find_format(f->fmt.pix_mp.pixelformat,
+ MTK_JPEG_FMT_FLAG_ENC_OUTPUT);
+ if (!fmt)
+ fmt = ctx->out_q.fmt;
+
+ v4l2_dbg(2, debug, &ctx->jpeg->v4l2_dev, "(%d) try_fmt:%c%c%c%c\n",
+ f->type,
+ (fmt->fourcc & 0xff),
+ (fmt->fourcc >> 8 & 0xff),
+ (fmt->fourcc >> 16 & 0xff),
+ (fmt->fourcc >> 24 & 0xff));
+
+ return vidioc_try_fmt(f, fmt);
}
static int mtk_jpeg_dec_try_fmt_vid_out_mplane(struct file *file, void *priv,
@@ -298,8 +451,8 @@ static int mtk_jpeg_dec_try_fmt_vid_out_mplane(struct file *file, void *priv,
struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
struct mtk_jpeg_fmt *fmt;
- fmt = mtk_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat,
- MTK_JPEG_FMT_TYPE_OUTPUT);
+ fmt = mtk_jpeg_find_format(f->fmt.pix_mp.pixelformat,
+ MTK_JPEG_FMT_FLAG_DEC_OUTPUT);
if (!fmt)
fmt = ctx->out_q.fmt;
@@ -310,17 +463,21 @@ static int mtk_jpeg_dec_try_fmt_vid_out_mplane(struct file *file, void *priv,
(fmt->fourcc >> 16 & 0xff),
(fmt->fourcc >> 24 & 0xff));
- return mtk_jpeg_try_fmt_mplane(f, fmt, ctx, MTK_JPEG_FMT_TYPE_OUTPUT);
+ if (ctx->state != MTK_JPEG_INIT) {
+ mtk_jpeg_g_fmt_vid_mplane(file, priv, f);
+ return 0;
+ }
+
+ return vidioc_try_fmt(f, fmt);
}
static int mtk_jpeg_s_fmt_mplane(struct mtk_jpeg_ctx *ctx,
- struct v4l2_format *f)
+ struct v4l2_format *f, unsigned int fmt_type)
{
struct vb2_queue *vq;
struct mtk_jpeg_q_data *q_data = NULL;
struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
struct mtk_jpeg_dev *jpeg = ctx->jpeg;
- unsigned int f_type;
int i;
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
@@ -334,12 +491,11 @@ static int mtk_jpeg_s_fmt_mplane(struct mtk_jpeg_ctx *ctx,
return -EBUSY;
}
- f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
- MTK_JPEG_FMT_TYPE_OUTPUT : MTK_JPEG_FMT_TYPE_CAPTURE;
-
- q_data->fmt = mtk_jpeg_find_format(ctx, pix_mp->pixelformat, f_type);
+ q_data->fmt = mtk_jpeg_find_format(pix_mp->pixelformat, fmt_type);
q_data->w = pix_mp->width;
q_data->h = pix_mp->height;
+ q_data->crop_rect.width = pix_mp->width;
+ q_data->crop_rect.height = pix_mp->height;
ctx->colorspace = pix_mp->colorspace;
ctx->ycbcr_enc = pix_mp->ycbcr_enc;
ctx->xfer_func = pix_mp->xfer_func;
@@ -365,6 +521,19 @@ static int mtk_jpeg_s_fmt_mplane(struct mtk_jpeg_ctx *ctx,
return 0;
}
+static int mtk_jpeg_enc_s_fmt_vid_out_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ int ret;
+
+ ret = mtk_jpeg_enc_try_fmt_vid_out_mplane(file, priv, f);
+ if (ret)
+ return ret;
+
+ return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f,
+ MTK_JPEG_FMT_FLAG_ENC_OUTPUT);
+}
+
static int mtk_jpeg_dec_s_fmt_vid_out_mplane(struct file *file, void *priv,
struct v4l2_format *f)
{
@@ -374,7 +543,21 @@ static int mtk_jpeg_dec_s_fmt_vid_out_mplane(struct file *file, void *priv,
if (ret)
return ret;
- return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f);
+ return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f,
+ MTK_JPEG_FMT_FLAG_DEC_OUTPUT);
+}
+
+static int mtk_jpeg_enc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ int ret;
+
+ ret = mtk_jpeg_enc_try_fmt_vid_cap_mplane(file, priv, f);
+ if (ret)
+ return ret;
+
+ return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f,
+ MTK_JPEG_FMT_FLAG_ENC_CAPTURE);
}
static int mtk_jpeg_dec_s_fmt_vid_cap_mplane(struct file *file, void *priv,
@@ -386,7 +569,8 @@ static int mtk_jpeg_dec_s_fmt_vid_cap_mplane(struct file *file, void *priv,
if (ret)
return ret;
- return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f);
+ return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f,
+ MTK_JPEG_FMT_FLAG_DEC_CAPTURE);
}
static void mtk_jpeg_queue_src_chg_event(struct mtk_jpeg_ctx *ctx)
@@ -411,6 +595,29 @@ static int mtk_jpeg_subscribe_event(struct v4l2_fh *fh,
return v4l2_ctrl_subscribe_event(fh, sub);
}
+static int mtk_jpeg_enc_g_selection(struct file *file, void *priv,
+ struct v4l2_selection *s)
+{
+ struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
+
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ s->r.width = ctx->out_q.w;
+ s->r.height = ctx->out_q.h;
+ s->r.left = 0;
+ s->r.top = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int mtk_jpeg_dec_g_selection(struct file *file, void *priv,
struct v4l2_selection *s)
{
@@ -440,6 +647,29 @@ static int mtk_jpeg_dec_g_selection(struct file *file, void *priv,
return 0;
}
+static int mtk_jpeg_enc_s_selection(struct file *file, void *priv,
+ struct v4l2_selection *s)
+{
+ struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
+
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP:
+ s->r.left = 0;
+ s->r.top = 0;
+ s->r.width = min(s->r.width, ctx->out_q.w);
+ s->r.height = min(s->r.height, ctx->out_q.h);
+ ctx->out_q.crop_rect = s->r;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int mtk_jpeg_dec_s_selection(struct file *file, void *priv,
struct v4l2_selection *s)
{
@@ -484,6 +714,33 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
}
+static const struct v4l2_ioctl_ops mtk_jpeg_enc_ioctl_ops = {
+ .vidioc_querycap = mtk_jpeg_enc_querycap,
+ .vidioc_enum_fmt_vid_cap = mtk_jpeg_enc_enum_fmt_vid_cap,
+ .vidioc_enum_fmt_vid_out = mtk_jpeg_enc_enum_fmt_vid_out,
+ .vidioc_try_fmt_vid_cap_mplane = mtk_jpeg_enc_try_fmt_vid_cap_mplane,
+ .vidioc_try_fmt_vid_out_mplane = mtk_jpeg_enc_try_fmt_vid_out_mplane,
+ .vidioc_g_fmt_vid_cap_mplane = mtk_jpeg_g_fmt_vid_mplane,
+ .vidioc_g_fmt_vid_out_mplane = mtk_jpeg_g_fmt_vid_mplane,
+ .vidioc_s_fmt_vid_cap_mplane = mtk_jpeg_enc_s_fmt_vid_cap_mplane,
+ .vidioc_s_fmt_vid_out_mplane = mtk_jpeg_enc_s_fmt_vid_out_mplane,
+ .vidioc_qbuf = mtk_jpeg_qbuf,
+ .vidioc_subscribe_event = mtk_jpeg_subscribe_event,
+ .vidioc_g_selection = mtk_jpeg_enc_g_selection,
+ .vidioc_s_selection = mtk_jpeg_enc_s_selection,
+
+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
static const struct v4l2_ioctl_ops mtk_jpeg_dec_ioctl_ops = {
.vidioc_querycap = mtk_jpeg_dec_querycap,
.vidioc_enum_fmt_vid_cap = mtk_jpeg_dec_enum_fmt_vid_cap,
@@ -575,8 +832,9 @@ static bool mtk_jpeg_check_resolution_change(struct mtk_jpeg_ctx *ctx,
}
q_data = &ctx->cap_q;
- if (q_data->fmt != mtk_jpeg_find_format(ctx, param->dst_fourcc,
- MTK_JPEG_FMT_TYPE_CAPTURE)) {
+ if (q_data->fmt !=
+ mtk_jpeg_find_format(param->dst_fourcc,
+ MTK_JPEG_FMT_FLAG_DEC_CAPTURE)) {
v4l2_dbg(1, debug, &jpeg->v4l2_dev, "format change\n");
return true;
}
@@ -597,9 +855,8 @@ static void mtk_jpeg_set_queue_data(struct mtk_jpeg_ctx *ctx,
q_data = &ctx->cap_q;
q_data->w = param->dec_w;
q_data->h = param->dec_h;
- q_data->fmt = mtk_jpeg_find_format(ctx,
- param->dst_fourcc,
- MTK_JPEG_FMT_TYPE_CAPTURE);
+ q_data->fmt = mtk_jpeg_find_format(param->dst_fourcc,
+ MTK_JPEG_FMT_FLAG_DEC_CAPTURE);
for (i = 0; i < q_data->fmt->colplanes; i++) {
q_data->bytesperline[i] = param->mem_stride[i];
@@ -616,6 +873,17 @@ static void mtk_jpeg_set_queue_data(struct mtk_jpeg_ctx *ctx,
param->dec_w, param->dec_h);
}
+static void mtk_jpeg_enc_buf_queue(struct vb2_buffer *vb)
+{
+ struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+
+ v4l2_dbg(2, debug, &jpeg->v4l2_dev, "(%d) buf_q id=%d, vb=%p\n",
+ vb->vb2_queue->type, vb->index, vb);
+
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, to_vb2_v4l2_buffer(vb));
+}
+
static void mtk_jpeg_dec_buf_queue(struct vb2_buffer *vb)
{
struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
@@ -664,6 +932,15 @@ static struct vb2_v4l2_buffer *mtk_jpeg_buf_remove(struct mtk_jpeg_ctx *ctx,
return v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
}
+static void mtk_jpeg_enc_stop_streaming(struct vb2_queue *q)
+{
+ struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+ struct vb2_v4l2_buffer *vb;
+
+ while ((vb = mtk_jpeg_buf_remove(ctx, q->type)))
+ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
+}
+
static void mtk_jpeg_dec_stop_streaming(struct vb2_queue *q)
{
struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(q);
@@ -699,6 +976,15 @@ static const struct vb2_ops mtk_jpeg_dec_qops = {
.stop_streaming = mtk_jpeg_dec_stop_streaming,
};
+static const struct vb2_ops mtk_jpeg_enc_qops = {
+ .queue_setup = mtk_jpeg_queue_setup,
+ .buf_prepare = mtk_jpeg_buf_prepare,
+ .buf_queue = mtk_jpeg_enc_buf_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .stop_streaming = mtk_jpeg_enc_stop_streaming,
+};
+
static void mtk_jpeg_set_dec_src(struct mtk_jpeg_ctx *ctx,
struct vb2_buffer *src_buf,
struct mtk_jpeg_bs *bs)
@@ -736,6 +1022,85 @@ static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx,
return 0;
}
+static void mtk_jpeg_set_enc_dst(struct mtk_jpeg_ctx *ctx, void __iomem *base,
+ struct vb2_buffer *dst_buf,
+ struct mtk_jpeg_enc_bs *bs)
+{
+ bs->dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+ bs->dma_addr_offset = ctx->enable_exif ? MTK_JPEG_MAX_EXIF_SIZE : 0;
+ bs->dma_addr_offsetmask = bs->dma_addr & JPEG_ENC_DST_ADDR_OFFSET_MASK;
+ bs->size = vb2_plane_size(dst_buf, 0);
+
+ mtk_jpeg_enc_set_dst_addr(base, bs->dma_addr, bs->size,
+ bs->dma_addr_offset,
+ bs->dma_addr_offsetmask);
+}
+
+static void mtk_jpeg_set_enc_src(struct mtk_jpeg_ctx *ctx, void __iomem *base,
+ struct vb2_buffer *src_buf)
+{
+ int i;
+ dma_addr_t dma_addr;
+
+ mtk_jpeg_enc_set_img_size(base, ctx->out_q.crop_rect.width,
+ ctx->out_q.crop_rect.height);
+ mtk_jpeg_enc_set_blk_num(base, ctx->out_q.fmt->fourcc,
+ ctx->out_q.crop_rect.width,
+ ctx->out_q.crop_rect.height);
+ mtk_jpeg_enc_set_stride(base, ctx->out_q.fmt->fourcc, ctx->out_q.w,
+ ctx->out_q.h, ctx->out_q.bytesperline[0]);
+
+ for (i = 0; i < src_buf->num_planes; i++) {
+ dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, i) +
+ src_buf->planes[i].data_offset;
+ mtk_jpeg_enc_set_src_addr(base, dma_addr, i);
+ }
+}
+
+static void mtk_jpeg_enc_device_run(void *priv)
+{
+ struct mtk_jpeg_ctx *ctx = priv;
+ struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+ unsigned long flags;
+ struct mtk_jpeg_src_buf *jpeg_src_buf;
+ struct mtk_jpeg_enc_bs enc_bs;
+ int ret;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
+
+ ret = pm_runtime_get_sync(jpeg->dev);
+ if (ret < 0)
+ goto enc_end;
+
+ spin_lock_irqsave(&jpeg->hw_lock, flags);
+
+ /*
+ * Resetting the hardware every frame is to ensure that all the
+ * registers are cleared. This is a hardware requirement.
+ */
+ mtk_jpeg_enc_reset(jpeg->reg_base);
+
+ mtk_jpeg_set_enc_dst(ctx, jpeg->reg_base, &dst_buf->vb2_buf, &enc_bs);
+ mtk_jpeg_set_enc_src(ctx, jpeg->reg_base, &src_buf->vb2_buf);
+ mtk_jpeg_enc_set_config(jpeg->reg_base, ctx->out_q.fmt->hw_format,
+ ctx->enable_exif, ctx->enc_quality,
+ ctx->restart_interval);
+ mtk_jpeg_enc_start(jpeg->reg_base);
+ spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+ return;
+
+enc_end:
+ v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_buf_done(src_buf, buf_state);
+ v4l2_m2m_buf_done(dst_buf, buf_state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+}
+
static void mtk_jpeg_dec_device_run(void *priv)
{
struct mtk_jpeg_ctx *ctx = priv;
@@ -785,6 +1150,11 @@ static void mtk_jpeg_dec_device_run(void *priv)
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
}
+static int mtk_jpeg_enc_job_ready(void *priv)
+{
+ return 1;
+}
+
static int mtk_jpeg_dec_job_ready(void *priv)
{
struct mtk_jpeg_ctx *ctx = priv;
@@ -792,6 +1162,11 @@ static int mtk_jpeg_dec_job_ready(void *priv)
return (ctx->state == MTK_JPEG_RUNNING) ? 1 : 0;
}
+static const struct v4l2_m2m_ops mtk_jpeg_enc_m2m_ops = {
+ .device_run = mtk_jpeg_enc_device_run,
+ .job_ready = mtk_jpeg_enc_job_ready,
+};
+
static const struct v4l2_m2m_ops mtk_jpeg_dec_m2m_ops = {
.device_run = mtk_jpeg_dec_device_run,
.job_ready = mtk_jpeg_dec_job_ready,
@@ -830,24 +1205,109 @@ static int mtk_jpeg_dec_queue_init(void *priv, struct vb2_queue *src_vq,
return ret;
}
-static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
+static int mtk_jpeg_enc_queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq)
{
+ struct mtk_jpeg_ctx *ctx = priv;
int ret;
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ src_vq->io_modes = VB2_DMABUF | VB2_MMAP;
+ src_vq->drv_priv = ctx;
+ src_vq->buf_struct_size = sizeof(struct mtk_jpeg_src_buf);
+ src_vq->ops = &mtk_jpeg_enc_qops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->lock = &ctx->jpeg->lock;
+ src_vq->dev = ctx->jpeg->dev;
+ ret = vb2_queue_init(src_vq);
+ if (ret)
+ return ret;
+
+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ dst_vq->io_modes = VB2_DMABUF | VB2_MMAP;
+ dst_vq->drv_priv = ctx;
+ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ dst_vq->ops = &mtk_jpeg_enc_qops;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->lock = &ctx->jpeg->lock;
+ dst_vq->dev = ctx->jpeg->dev;
+ ret = vb2_queue_init(dst_vq);
+
+ return ret;
+}
+
+static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
+{
+ int ret, i;
+
ret = mtk_smi_larb_get(jpeg->larb);
if (ret)
dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret);
- clk_prepare_enable(jpeg->clk_jdec_smi);
- clk_prepare_enable(jpeg->clk_jdec);
+
+ for (i = 0; i < jpeg->variant->num_clocks; i++) {
+ ret = clk_prepare_enable(jpeg->clocks[i]);
+ if (ret) {
+ while (--i >= 0)
+ clk_disable_unprepare(jpeg->clocks[i]);
+ }
+ }
}
static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
{
- clk_disable_unprepare(jpeg->clk_jdec);
- clk_disable_unprepare(jpeg->clk_jdec_smi);
+ int i;
+
+ for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
+ clk_disable_unprepare(jpeg->clocks[i]);
mtk_smi_larb_put(jpeg->larb);
}
+static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv)
+{
+ struct mtk_jpeg_dev *jpeg = priv;
+ struct mtk_jpeg_ctx *ctx;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ struct mtk_jpeg_src_buf *jpeg_src_buf;
+ enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+ u32 enc_irq_ret;
+ u32 enc_ret, result_size;
+
+ ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+ if (!ctx) {
+ v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
+ return IRQ_HANDLED;
+ }
+
+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
+
+ enc_ret = mtk_jpeg_enc_get_and_clear_int_status(jpeg->reg_base);
+ enc_irq_ret = mtk_jpeg_enc_enum_result(jpeg->reg_base, enc_ret);
+
+ if (enc_irq_ret >= MTK_JPEG_ENC_RESULT_STALL)
+ mtk_jpeg_enc_reset(jpeg->reg_base);
+
+ if (enc_irq_ret != MTK_JPEG_ENC_RESULT_DONE) {
+ dev_err(jpeg->dev, "encode failed\n");
+ goto enc_end;
+ }
+
+ result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size);
+
+ buf_state = VB2_BUF_STATE_DONE;
+
+enc_end:
+ v4l2_m2m_buf_done(src_buf, buf_state);
+ v4l2_m2m_buf_done(dst_buf, buf_state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+ pm_runtime_put(ctx->jpeg->dev);
+ return IRQ_HANDLED;
+}
+
static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
{
struct mtk_jpeg_dev *jpeg = priv;
@@ -893,36 +1353,130 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
return IRQ_HANDLED;
}
+static void mtk_jpeg_set_enc_default_params(struct mtk_jpeg_ctx *ctx)
+{
+ struct mtk_jpeg_q_data *q = &ctx->out_q;
+ struct v4l2_pix_format_mplane *pix_mp;
+
+ pix_mp = kmalloc(sizeof(*pix_mp), GFP_KERNEL);
+
+ ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
+ ctx->colorspace = V4L2_COLORSPACE_JPEG,
+ ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+ ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+ pix_mp->width = MTK_JPEG_MIN_WIDTH;
+ pix_mp->height = MTK_JPEG_MIN_HEIGHT;
+
+ q->fmt = mtk_jpeg_find_format(V4L2_PIX_FMT_YUYV,
+ MTK_JPEG_FMT_FLAG_ENC_OUTPUT);
+ vidioc_try_fmt(container_of(pix_mp, struct v4l2_format,
+ fmt.pix_mp), q->fmt);
+ q->w = pix_mp->width;
+ q->h = pix_mp->height;
+ q->crop_rect.width = pix_mp->width;
+ q->crop_rect.height = pix_mp->height;
+ q->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+ q->bytesperline[0] = pix_mp->plane_fmt[0].bytesperline;
+
+ q = &ctx->cap_q;
+ q->fmt = mtk_jpeg_find_format(V4L2_PIX_FMT_JPEG,
+ MTK_JPEG_FMT_FLAG_ENC_CAPTURE);
+ pix_mp->width = MTK_JPEG_MIN_WIDTH;
+ pix_mp->height = MTK_JPEG_MIN_HEIGHT;
+ vidioc_try_fmt(container_of(pix_mp, struct v4l2_format,
+ fmt.pix_mp), q->fmt);
+ q->w = pix_mp->width;
+ q->h = pix_mp->height;
+ q->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+ q->bytesperline[0] = pix_mp->plane_fmt[0].bytesperline;
+}
+
static void mtk_jpeg_set_dec_default_params(struct mtk_jpeg_ctx *ctx)
{
struct mtk_jpeg_q_data *q = &ctx->out_q;
+ struct v4l2_pix_format_mplane *pix_mp;
int i;
+ pix_mp = kmalloc(sizeof(*pix_mp), GFP_KERNEL);
+
+ ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
ctx->colorspace = V4L2_COLORSPACE_JPEG,
ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
-
- q->fmt = mtk_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
- MTK_JPEG_FMT_TYPE_OUTPUT);
- q->w = MTK_JPEG_MIN_WIDTH;
- q->h = MTK_JPEG_MIN_HEIGHT;
- q->bytesperline[0] = 0;
- q->sizeimage[0] = MTK_JPEG_DEFAULT_SIZEIMAGE;
+ pix_mp->width = MTK_JPEG_MIN_WIDTH;
+ pix_mp->height = MTK_JPEG_MIN_HEIGHT;
+
+ q->fmt = mtk_jpeg_find_format(V4L2_PIX_FMT_JPEG,
+ MTK_JPEG_FMT_FLAG_DEC_OUTPUT);
+ vidioc_try_fmt(container_of(pix_mp, struct v4l2_format,
+ fmt.pix_mp), q->fmt);
+ q->w = pix_mp->width;
+ q->h = pix_mp->height;
+ q->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+ q->bytesperline[0] = pix_mp->plane_fmt[0].bytesperline;
q = &ctx->cap_q;
- q->fmt = mtk_jpeg_find_format(ctx, V4L2_PIX_FMT_YUV420M,
- MTK_JPEG_FMT_TYPE_CAPTURE);
- q->w = MTK_JPEG_MIN_WIDTH;
- q->h = MTK_JPEG_MIN_HEIGHT;
-
+ q->fmt = mtk_jpeg_find_format(V4L2_PIX_FMT_YUV420M,
+ MTK_JPEG_FMT_FLAG_DEC_CAPTURE);
+ pix_mp->width = MTK_JPEG_MIN_WIDTH;
+ pix_mp->height = MTK_JPEG_MIN_HEIGHT;
+ vidioc_try_fmt(container_of(pix_mp, struct v4l2_format,
+ fmt.pix_mp), q->fmt);
+ q->w = pix_mp->width;
+ q->h = pix_mp->height;
for (i = 0; i < q->fmt->colplanes; i++) {
- u32 stride = q->w * q->fmt->h_sample[i] / 4;
- u32 h = q->h * q->fmt->v_sample[i] / 4;
+ q->sizeimage[i] = pix_mp->plane_fmt[i].sizeimage;
+ q->bytesperline[i] = pix_mp->plane_fmt[i].bytesperline;
+ }
+}
- q->bytesperline[i] = stride;
- q->sizeimage[i] = stride * h;
+static int mtk_jpeg_enc_open(struct file *file)
+{
+ struct mtk_jpeg_dev *jpeg = video_drvdata(file);
+ struct video_device *vfd = video_devdata(file);
+ struct mtk_jpeg_ctx *ctx;
+ int ret = 0;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ if (mutex_lock_interruptible(&jpeg->lock)) {
+ ret = -ERESTARTSYS;
+ goto free;
+ }
+
+ v4l2_fh_init(&ctx->fh, vfd);
+ file->private_data = &ctx->fh;
+ v4l2_fh_add(&ctx->fh);
+
+ ctx->jpeg = jpeg;
+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx,
+ mtk_jpeg_enc_queue_init);
+ if (IS_ERR(ctx->fh.m2m_ctx)) {
+ ret = PTR_ERR(ctx->fh.m2m_ctx);
+ goto error;
}
+
+ ret = mtk_jpeg_enc_ctrls_setup(ctx);
+ if (ret) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to setup jpeg enc controls\n");
+ goto error;
+ }
+ mtk_jpeg_set_enc_default_params(ctx);
+
+ mutex_unlock(&jpeg->lock);
+ return 0;
+
+error:
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ mutex_unlock(&jpeg->lock);
+free:
+ kfree(ctx);
+ return ret;
}
static int mtk_jpeg_dec_open(struct file *file)
@@ -953,6 +1507,12 @@ static int mtk_jpeg_dec_open(struct file *file)
goto error;
}
+ v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 0);
+ ret = v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+ if (ret) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to setup jpeg dec controls\n");
+ goto error;
+ }
mtk_jpeg_set_dec_default_params(ctx);
mutex_unlock(&jpeg->lock);
return 0;
@@ -973,6 +1533,7 @@ static int mtk_jpeg_release(struct file *file)
mutex_lock(&jpeg->lock);
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+ v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
kfree(ctx);
@@ -980,6 +1541,15 @@ static int mtk_jpeg_release(struct file *file)
return 0;
}
+static const struct v4l2_file_operations mtk_jpeg_enc_fops = {
+ .owner = THIS_MODULE,
+ .open = mtk_jpeg_enc_open,
+ .release = mtk_jpeg_release,
+ .poll = v4l2_m2m_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = v4l2_m2m_fop_mmap,
+};
+
static const struct v4l2_file_operations mtk_jpeg_dec_fops = {
.owner = THIS_MODULE,
.open = mtk_jpeg_dec_open,
@@ -993,6 +1563,7 @@ static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
{
struct device_node *node;
struct platform_device *pdev;
+ int i;
node = of_parse_phandle(jpeg->dev->of_node, "mediatek,larb", 0);
if (!node)
@@ -1006,12 +1577,17 @@ static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
jpeg->larb = &pdev->dev;
- jpeg->clk_jdec = devm_clk_get(jpeg->dev, "jpgdec");
- if (IS_ERR(jpeg->clk_jdec))
- return PTR_ERR(jpeg->clk_jdec);
+ for (i = 0; i < jpeg->variant->num_clocks; i++) {
+ jpeg->clocks[i] = devm_clk_get(jpeg->dev,
+ jpeg->variant->clk_names[i]);
+ if (IS_ERR(jpeg->clocks[i])) {
+ dev_err(&pdev->dev, "failed to get clock: %s\n",
+ jpeg->variant->clk_names[i]);
+ return PTR_ERR(jpeg->clocks[i]);
+ }
+ }
- jpeg->clk_jdec_smi = devm_clk_get(jpeg->dev, "jpgdec-smi");
- return PTR_ERR_OR_ZERO(jpeg->clk_jdec_smi);
+ return 0;
}
static int mtk_jpeg_probe(struct platform_device *pdev)
@@ -1028,6 +1604,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
mutex_init(&jpeg->lock);
spin_lock_init(&jpeg->hw_lock);
jpeg->dev = &pdev->dev;
+ jpeg->variant = of_device_get_match_data(jpeg->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
jpeg->reg_base = devm_ioremap_resource(&pdev->dev, res);
@@ -1042,8 +1619,12 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
return jpeg_irq;
}
- ret = devm_request_irq(&pdev->dev, jpeg_irq, mtk_jpeg_dec_irq, 0,
- pdev->name, jpeg);
+ if (jpeg->variant->is_encoder)
+ ret = devm_request_irq(&pdev->dev, jpeg_irq, mtk_jpeg_enc_irq,
+ 0, pdev->name, jpeg);
+ else
+ ret = devm_request_irq(&pdev->dev, jpeg_irq, mtk_jpeg_dec_irq,
+ 0, pdev->name, jpeg);
if (ret) {
dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
jpeg_irq, ret);
@@ -1063,7 +1644,10 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
goto err_dev_register;
}
- jpeg->m2m_dev = v4l2_m2m_init(&mtk_jpeg_dec_m2m_ops);
+ if (jpeg->variant->is_encoder)
+ jpeg->m2m_dev = v4l2_m2m_init(&mtk_jpeg_enc_m2m_ops);
+ else
+ jpeg->m2m_dev = v4l2_m2m_init(&mtk_jpeg_dec_m2m_ops);
if (IS_ERR(jpeg->m2m_dev)) {
v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
ret = PTR_ERR(jpeg->m2m_dev);
@@ -1076,9 +1660,15 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
goto err_vfd_jpeg_alloc;
}
snprintf(jpeg->vdev->name, sizeof(jpeg->vdev->name),
- "%s-dec", MTK_JPEG_NAME);
- jpeg->vdev->fops = &mtk_jpeg_dec_fops;
- jpeg->vdev->ioctl_ops = &mtk_jpeg_dec_ioctl_ops;
+ "%s-%s", MTK_JPEG_NAME,
+ jpeg->variant->is_encoder ? "enc" : "dec");
+ if (jpeg->variant->is_encoder) {
+ jpeg->vdev->fops = &mtk_jpeg_enc_fops;
+ jpeg->vdev->ioctl_ops = &mtk_jpeg_enc_ioctl_ops;
+ } else {
+ jpeg->vdev->fops = &mtk_jpeg_dec_fops;
+ jpeg->vdev->ioctl_ops = &mtk_jpeg_dec_ioctl_ops;
+ }
jpeg->vdev->minor = -1;
jpeg->vdev->release = video_device_release;
jpeg->vdev->lock = &jpeg->lock;
@@ -1095,8 +1685,9 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
video_set_drvdata(jpeg->vdev, jpeg);
v4l2_info(&jpeg->v4l2_dev,
- "decoder device registered as /dev/video%d (%d,%d)\n",
- jpeg->vdev->num, VIDEO_MAJOR, jpeg->vdev->minor);
+ "jpeg %s device registered as /dev/video%d (%d,%d)\n",
+ jpeg->variant->is_encoder ? "enc" : "dec", jpeg->vdev->num,
+ VIDEO_MAJOR, jpeg->vdev->minor);
platform_set_drvdata(pdev, jpeg);
@@ -1187,14 +1778,36 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = {
SET_RUNTIME_PM_OPS(mtk_jpeg_pm_suspend, mtk_jpeg_pm_resume, NULL)
};
+static struct mtk_jpeg_variant mt8173_jpeg_drvdata = {
+ .is_encoder = false,
+ .clk_names = {"jpgdec-smi", "jpgdec"},
+ .num_clocks = 2,
+};
+
+static struct mtk_jpeg_variant mt2701_jpeg_drvdata = {
+ .is_encoder = false,
+ .clk_names = {"jpgdec-smi", "jpgdec"},
+ .num_clocks = 2,
+};
+
+static struct mtk_jpeg_variant mtk_jpeg_drvdata = {
+ .is_encoder = true,
+ .clk_names = {"jpgenc"},
+ .num_clocks = 1,
+};
+
static const struct of_device_id mtk_jpeg_match[] = {
{
.compatible = "mediatek,mt8173-jpgdec",
- .data = NULL,
+ .data = &mt8173_jpeg_drvdata,
},
{
.compatible = "mediatek,mt2701-jpgdec",
- .data = NULL,
+ .data = &mt2701_jpeg_drvdata,
+ },
+ {
+ .compatible = "mediatek,mtk-jpgenc",
+ .data = &mtk_jpeg_drvdata,
},
{},
};
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 0b59e48495d5..9ec2c3350a16 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -3,6 +3,7 @@
* Copyright (c) 2016 MediaTek Inc.
* Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
* Rick Chang <rick.chang@mediatek.com>
+ * Xia Jiang <xia.jiang@mediatek.com>
*/
#ifndef _MTK_JPEG_CORE_H
@@ -16,19 +17,21 @@
#define MTK_JPEG_NAME "mtk-jpeg"
#define MTK_JPEG_COMP_MAX 3
+#define MTK_JPEG_MAX_CLOCKS 2
+
#define MTK_JPEG_FMT_FLAG_DEC_OUTPUT BIT(0)
#define MTK_JPEG_FMT_FLAG_DEC_CAPTURE BIT(1)
-
-#define MTK_JPEG_FMT_TYPE_OUTPUT 1
-#define MTK_JPEG_FMT_TYPE_CAPTURE 2
+#define MTK_JPEG_FMT_FLAG_ENC_OUTPUT BIT(2)
+#define MTK_JPEG_FMT_FLAG_ENC_CAPTURE BIT(3)
#define MTK_JPEG_MIN_WIDTH 32U
#define MTK_JPEG_MIN_HEIGHT 32U
-#define MTK_JPEG_MAX_WIDTH 8192U
-#define MTK_JPEG_MAX_HEIGHT 8192U
+#define MTK_JPEG_MAX_WIDTH 65535U
+#define MTK_JPEG_MAX_HEIGHT 65535U
#define MTK_JPEG_DEFAULT_SIZEIMAGE (1 * 1024 * 1024)
+#define MTK_JPEG_MAX_EXIF_SIZE (64 * 1024)
/**
* enum mtk_jpeg_ctx_state - states of the context state machine
@@ -42,6 +45,18 @@ enum mtk_jpeg_ctx_state {
MTK_JPEG_SOURCE_CHANGE,
};
+/**
+ * mtk_jpeg_variant - mtk jpeg driver variant
+ * @is_encoder: driver mode is jpeg encoder
+ * @clk_names: clock names
+ * @num_clocks: numbers of clock
+ */
+struct mtk_jpeg_variant {
+ bool is_encoder;
+ const char *clk_names[MTK_JPEG_MAX_CLOCKS];
+ int num_clocks;
+};
+
/**
* struct mt_jpeg - JPEG IP abstraction
* @lock: the mutex protecting this structure
@@ -53,9 +68,9 @@ enum mtk_jpeg_ctx_state {
* @alloc_ctx: videobuf2 memory allocator's context
* @vdev: video device node for jpeg mem2mem mode
* @reg_base: JPEG registers mapping
- * @clk_jdec: JPEG hw working clock
- * @clk_jdec_smi: JPEG SMI bus clock
* @larb: SMI device
+ * @clocks: JPEG IP clock(s)
+ * @variant: driver variant to be used
*/
struct mtk_jpeg_dev {
struct mutex lock;
@@ -67,14 +82,15 @@ struct mtk_jpeg_dev {
void *alloc_ctx;
struct video_device *vdev;
void __iomem *reg_base;
- struct clk *clk_jdec;
- struct clk *clk_jdec_smi;
struct device *larb;
+ struct clk *clocks[MTK_JPEG_MAX_CLOCKS];
+ const struct mtk_jpeg_variant *variant;
};
/**
* struct jpeg_fmt - driver's internal color format data
* @fourcc: the fourcc code, 0 if not applicable
+ * @hw_format: hardware format value
* @h_sample: horizontal sample count of plane in 4 * 4 pixel image
* @v_sample: vertical sample count of plane in 4 * 4 pixel image
* @colplanes: number of color planes (1 for packed formats)
@@ -84,6 +100,7 @@ struct mtk_jpeg_dev {
*/
struct mtk_jpeg_fmt {
u32 fourcc;
+ u32 hw_format;
int h_sample[VIDEO_MAX_PLANES];
int v_sample[VIDEO_MAX_PLANES];
int colplanes;
@@ -107,6 +124,7 @@ struct mtk_jpeg_q_data {
u32 h;
u32 bytesperline[VIDEO_MAX_PLANES];
u32 sizeimage[VIDEO_MAX_PLANES];
+ struct v4l2_rect crop_rect;
};
/**
@@ -116,6 +134,10 @@ struct mtk_jpeg_q_data {
* @cap_q: destination (capture) queue queue information
* @fh: V4L2 file handle
* @state: state of the context
+ * @enable_exif: enable exif mode of jpeg encoder
+ * @enc_quality: jpeg encoder quality
+ * @restart_interval: jpeg encoder restart interval
+ * @ctrl_hdl: controls handler
* @colorspace: enum v4l2_colorspace; supplemental to pixelformat
* @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
* @quantization: enum v4l2_quantization, colorspace quantization
@@ -127,6 +149,10 @@ struct mtk_jpeg_ctx {
struct mtk_jpeg_q_data cap_q;
struct v4l2_fh fh;
enum mtk_jpeg_ctx_state state;
+ bool enable_exif;
+ u8 enc_quality;
+ u8 restart_interval;
+ struct v4l2_ctrl_handler ctrl_hdl;
enum v4l2_colorspace colorspace;
enum v4l2_ycbcr_encoding ycbcr_enc;
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
new file mode 100644
index 000000000000..7fc1de920a75
--- /dev/null
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Author: Xia Jiang <xia.jiang@mediatek.com>
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <media/videobuf2-core.h>
+
+#include "mtk_jpeg_enc_hw.h"
+
+static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
+ {.quality_param = 34, .hardware_value = JPEG_ENC_QUALITY_Q34},
+ {.quality_param = 39, .hardware_value = JPEG_ENC_QUALITY_Q39},
+ {.quality_param = 48, .hardware_value = JPEG_ENC_QUALITY_Q48},
+ {.quality_param = 60, .hardware_value = JPEG_ENC_QUALITY_Q60},
+ {.quality_param = 64, .hardware_value = JPEG_ENC_QUALITY_Q64},
+ {.quality_param = 68, .hardware_value = JPEG_ENC_QUALITY_Q68},
+ {.quality_param = 74, .hardware_value = JPEG_ENC_QUALITY_Q74},
+ {.quality_param = 80, .hardware_value = JPEG_ENC_QUALITY_Q80},
+ {.quality_param = 82, .hardware_value = JPEG_ENC_QUALITY_Q82},
+ {.quality_param = 84, .hardware_value = JPEG_ENC_QUALITY_Q84},
+ {.quality_param = 87, .hardware_value = JPEG_ENC_QUALITY_Q87},
+ {.quality_param = 90, .hardware_value = JPEG_ENC_QUALITY_Q90},
+ {.quality_param = 92, .hardware_value = JPEG_ENC_QUALITY_Q92},
+ {.quality_param = 95, .hardware_value = JPEG_ENC_QUALITY_Q95},
+ {.quality_param = 97, .hardware_value = JPEG_ENC_QUALITY_Q97},
+};
+
+void mtk_jpeg_enc_reset(void __iomem *base)
+{
+ writel(0x00, base + JPEG_ENC_RSTB);
+ writel(JPEG_ENC_RESET_BIT, base + JPEG_ENC_RSTB);
+ writel(0x00, base + JPEG_ENC_CODEC_SEL);
+}
+
+u32 mtk_jpeg_enc_get_and_clear_int_status(void __iomem *base)
+{
+ u32 ret;
+
+ ret = readl(base + JPEG_ENC_INT_STS) &
+ JPEG_ENC_INT_STATUS_MASK_ALLIRQ;
+ if (ret)
+ writel(0, base + JPEG_ENC_INT_STS);
+
+ return ret;
+}
+
+u32 mtk_jpeg_enc_get_file_size(void __iomem *base)
+{
+ return readl(base + JPEG_ENC_DMA_ADDR0) -
+ readl(base + JPEG_ENC_DST_ADDR0);
+}
+
+u32 mtk_jpeg_enc_enum_result(void __iomem *base, u32 irq_status)
+{
+ if (irq_status & JPEG_ENC_INT_STATUS_DONE)
+ return MTK_JPEG_ENC_RESULT_DONE;
+ else if (irq_status & JPEG_ENC_INT_STATUS_STALL)
+ return MTK_JPEG_ENC_RESULT_STALL;
+ else
+ return MTK_JPEG_ENC_RESULT_VCODEC_IRQ;
+}
+
+void mtk_jpeg_enc_set_img_size(void __iomem *base, u32 width, u32 height)
+{
+ u32 value;
+
+ value = width << 16 | height;
+ writel(value, base + JPEG_ENC_IMG_SIZE);
+}
+
+void mtk_jpeg_enc_set_blk_num(void __iomem *base, u32 enc_format, u32 width,
+ u32 height)
+{
+ u32 blk_num;
+ u32 is_420;
+ u32 padding_width;
+ u32 padding_height;
+ u32 luma_blocks;
+ u32 chroma_blocks;
+
+ is_420 = (enc_format == V4L2_PIX_FMT_NV12M ||
+ enc_format == V4L2_PIX_FMT_NV21M) ? 1 : 0;
+ padding_width = round_up(width, 16);
+ padding_height = round_up(height, is_420 ? 16 : 8);
+
+ luma_blocks = padding_width / 8 * padding_height / 8;
+ if (is_420)
+ chroma_blocks = luma_blocks / 4;
+ else
+ chroma_blocks = luma_blocks / 2;
+
+ blk_num = luma_blocks + 2 * chroma_blocks - 1;
+
+ writel(blk_num, base + JPEG_ENC_BLK_NUM);
+}
+
+void mtk_jpeg_enc_set_stride(void __iomem *base, u32 enc_format, u32 width,
+ u32 height, u32 bytesperline)
+{
+ u32 img_stride;
+ u32 mem_stride;
+
+ if (enc_format == V4L2_PIX_FMT_NV12M ||
+ enc_format == V4L2_PIX_FMT_NV21M) {
+ img_stride = round_up(width, 16);
+ mem_stride = bytesperline;
+ } else {
+ img_stride = round_up(width * 2, 32);
+ mem_stride = img_stride;
+ }
+
+ writel(img_stride, base + JPEG_ENC_IMG_STRIDE);
+ writel(mem_stride, base + JPEG_ENC_STRIDE);
+}
+
+void mtk_jpeg_enc_set_src_addr(void __iomem *base, u32 src_addr,
+ u32 plane_index)
+{
+ if (!plane_index)
+ writel(src_addr, base + JPEG_ENC_SRC_LUMA_ADDR);
+ else
+ writel(src_addr, base + JPEG_ENC_SRC_CHROMA_ADDR);
+}
+
+void mtk_jpeg_enc_set_dst_addr(void __iomem *base, u32 dst_addr,
+ u32 stall_size, u32 init_offset,
+ u32 offset_mask)
+{
+ writel(init_offset & ~0xf, base + JPEG_ENC_OFFSET_ADDR);
+ writel(offset_mask & 0xf, base + JPEG_ENC_BYTE_OFFSET_MASK);
+ writel(dst_addr & ~0xf, base + JPEG_ENC_DST_ADDR0);
+ writel((dst_addr + stall_size) & ~0xf, base + JPEG_ENC_STALL_ADDR0);
+}
+
+static void mtk_jpeg_enc_set_quality(void __iomem *base, u32 quality)
+{
+ u32 value;
+ u32 i, enc_quality;
+
+ enc_quality = mtk_jpeg_enc_quality[0].hardware_value;
+ for (i = 0; i < ARRAY_SIZE(mtk_jpeg_enc_quality); i++) {
+ if (quality <= mtk_jpeg_enc_quality[i].quality_param) {
+ enc_quality = mtk_jpeg_enc_quality[i].hardware_value;
+ break;
+ }
+ }
+
+ value = readl(base + JPEG_ENC_QUALITY);
+ value = (value & JPEG_ENC_QUALITY_MASK) | enc_quality;
+ writel(value, base + JPEG_ENC_QUALITY);
+}
+
+static void mtk_jpeg_enc_set_ctrl(void __iomem *base, u32 enc_format,
+ bool exif_en, u32 restart_interval)
+{
+ u32 value;
+
+ value = readl(base + JPEG_ENC_CTRL);
+ value &= ~JPEG_ENC_CTRL_YUV_FORMAT_MASK;
+ value |= (enc_format & 3) << 3;
+ if (exif_en)
+ value |= JPEG_ENC_CTRL_FILE_FORMAT_BIT;
+ else
+ value &= ~JPEG_ENC_CTRL_FILE_FORMAT_BIT;
+ if (restart_interval)
+ value |= JPEG_ENC_CTRL_RESTART_EN_BIT;
+ else
+ value &= ~JPEG_ENC_CTRL_RESTART_EN_BIT;
+ writel(value, base + JPEG_ENC_CTRL);
+}
+
+void mtk_jpeg_enc_set_config(void __iomem *base, u32 enc_format, bool exif_en,
+ u32 quality, u32 restart_interval)
+{
+ mtk_jpeg_enc_set_quality(base, quality);
+
+ mtk_jpeg_enc_set_ctrl(base, enc_format, exif_en, restart_interval);
+
+ writel(restart_interval, base + JPEG_ENC_RST_MCU_NUM);
+}
+
+void mtk_jpeg_enc_start(void __iomem *base)
+{
+ u32 value;
+
+ value = readl(base + JPEG_ENC_CTRL);
+ value |= JPEG_ENC_CTRL_INT_EN_BIT | JPEG_ENC_CTRL_ENABLE_BIT;
+ writel(value, base + JPEG_ENC_CTRL);
+}
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.h
new file mode 100644
index 000000000000..73faf49b667c
--- /dev/null
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Author: Xia Jiang <xia.jiang@mediatek.com>
+ *
+ */
+
+#ifndef _MTK_JPEG_ENC_HW_H
+#define _MTK_JPEG_ENC_HW_H
+
+#include <media/videobuf2-core.h>
+
+#include "mtk_jpeg_core.h"
+
+#define JPEG_ENC_INT_STATUS_DONE BIT(0)
+#define JPEG_ENC_INT_STATUS_STALL BIT(1)
+#define JPEG_ENC_INT_STATUS_VCODEC_IRQ BIT(4)
+#define JPEG_ENC_INT_STATUS_MASK_ALLIRQ 0x13
+
+#define JPEG_ENC_DST_ADDR_OFFSET_MASK GENMASK(3, 0)
+#define JPEG_ENC_QUALITY_MASK GENMASK(31, 16)
+
+#define JPEG_ENC_CTRL_YUV_FORMAT_MASK 0x18
+#define JPEG_ENC_CTRL_RESTART_EN_BIT BIT(10)
+#define JPEG_ENC_CTRL_FILE_FORMAT_BIT BIT(5)
+#define JPEG_ENC_CTRL_INT_EN_BIT BIT(2)
+#define JPEG_ENC_CTRL_ENABLE_BIT BIT(0)
+#define JPEG_ENC_RESET_BIT BIT(0)
+
+#define JPEG_ENC_YUV_FORMAT_YUYV 0
+#define JPEG_ENC_YUV_FORMAT_YVYU 1
+#define JPEG_ENC_YUV_FORMAT_NV12 2
+#define JEPG_ENC_YUV_FORMAT_NV21 3
+
+#define JPEG_ENC_QUALITY_Q60 0x0
+#define JPEG_ENC_QUALITY_Q80 0x1
+#define JPEG_ENC_QUALITY_Q90 0x2
+#define JPEG_ENC_QUALITY_Q95 0x3
+#define JPEG_ENC_QUALITY_Q39 0x4
+#define JPEG_ENC_QUALITY_Q68 0x5
+#define JPEG_ENC_QUALITY_Q84 0x6
+#define JPEG_ENC_QUALITY_Q92 0x7
+#define JPEG_ENC_QUALITY_Q48 0x8
+#define JPEG_ENC_QUALITY_Q74 0xa
+#define JPEG_ENC_QUALITY_Q87 0xb
+#define JPEG_ENC_QUALITY_Q34 0xc
+#define JPEG_ENC_QUALITY_Q64 0xe
+#define JPEG_ENC_QUALITY_Q82 0xf
+#define JPEG_ENC_QUALITY_Q97 0x10
+
+#define JPEG_ENC_RSTB 0x100
+#define JPEG_ENC_CTRL 0x104
+#define JPEG_ENC_QUALITY 0x108
+#define JPEG_ENC_BLK_NUM 0x10C
+#define JPEG_ENC_BLK_CNT 0x110
+#define JPEG_ENC_INT_STS 0x11c
+#define JPEG_ENC_DST_ADDR0 0x120
+#define JPEG_ENC_DMA_ADDR0 0x124
+#define JPEG_ENC_STALL_ADDR0 0x128
+#define JPEG_ENC_OFFSET_ADDR 0x138
+#define JPEG_ENC_RST_MCU_NUM 0x150
+#define JPEG_ENC_IMG_SIZE 0x154
+#define JPEG_ENC_DEBUG_INFO0 0x160
+#define JPEG_ENC_DEBUG_INFO1 0x164
+#define JPEG_ENC_TOTAL_CYCLE 0x168
+#define JPEG_ENC_BYTE_OFFSET_MASK 0x16c
+#define JPEG_ENC_SRC_LUMA_ADDR 0x170
+#define JPEG_ENC_SRC_CHROMA_ADDR 0x174
+#define JPEG_ENC_STRIDE 0x178
+#define JPEG_ENC_IMG_STRIDE 0x17c
+#define JPEG_ENC_DCM_CTRL 0x300
+#define JPEG_ENC_CODEC_SEL 0x314
+#define JPEG_ENC_ULTRA_THRES 0x318
+
+enum {
+ MTK_JPEG_ENC_RESULT_DONE,
+ MTK_JPEG_ENC_RESULT_STALL,
+ MTK_JPEG_ENC_RESULT_VCODEC_IRQ
+};
+
+/**
+ * struct mtk_jpeg_enc_qlt - JPEG encoder quality data
+ * @quality_param: quality value
+ * @hardware_value: hardware value of quality
+ */
+struct mtk_jpeg_enc_qlt {
+ u8 quality_param;
+ u8 hardware_value;
+};
+
+/**
+ * struct mt_jpeg_enc_bs - JPEG encoder bitstream buffer
+ * @dma_addr: JPEG encoder destination address
+ * @size: JPEG encoder bistream size
+ * @dma_addr_offset: JPEG encoder offset address
+ * @dma_addr_offsetmask: JPEG encoder destination address offset mask
+ */
+struct mtk_jpeg_enc_bs {
+ dma_addr_t dma_addr;
+ size_t size;
+ u32 dma_addr_offset;
+ u32 dma_addr_offsetmask;
+};
+
+void mtk_jpeg_enc_reset(void __iomem *base);
+u32 mtk_jpeg_enc_get_and_clear_int_status(void __iomem *base);
+u32 mtk_jpeg_enc_get_file_size(void __iomem *base);
+u32 mtk_jpeg_enc_enum_result(void __iomem *base, u32 irq_status);
+void mtk_jpeg_enc_set_img_size(void __iomem *base, u32 width, u32 height);
+void mtk_jpeg_enc_set_blk_num(void __iomem *base, u32 enc_format, u32 width,
+ u32 height);
+void mtk_jpeg_enc_set_stride(void __iomem *base, u32 enc_format, u32 width,
+ u32 height, u32 bytesperline);
+void mtk_jpeg_enc_set_src_addr(void __iomem *base, u32 src_addr,
+ u32 plane_index);
+void mtk_jpeg_enc_set_dst_addr(void __iomem *base, u32 dst_addr,
+ u32 stall_size, u32 init_offset,
+ u32 offset_mask);
+void mtk_jpeg_enc_set_config(void __iomem *base, u32 enc_format, bool exif_en,
+ u32 quality, u32 restart_interval);
+void mtk_jpeg_enc_start(void __iomem *enc_reg_base);
+
+#endif /* _MTK_JPEG_ENC_HW_H */
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH RESEND v9 17/18] media: platform: Rename existing functions/defines/variables
From: Xia Jiang @ 2020-06-04 9:05 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
Matthias Brugger, Rick Chang
Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604090553.10861-1-xia.jiang@mediatek.com>
Rename existing funcitons/defines/variables with a _dec prefix and
without dec_ prefix to prepare for the addition of the jpeg encoder
feature.
Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: new patch
---
.../media/platform/mtk-jpeg/mtk_jpeg_core.c | 200 +++++++++---------
.../media/platform/mtk-jpeg/mtk_jpeg_core.h | 8 +-
.../media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h | 7 +-
3 files changed, 109 insertions(+), 106 deletions(-)
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index e0e522a502e1..29b8b82c606c 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -27,7 +27,7 @@
#include "mtk_jpeg_core.h"
#include "mtk_jpeg_dec_parse.h"
-static struct mtk_jpeg_fmt mtk_jpeg_formats[] = {
+static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
{
.fourcc = V4L2_PIX_FMT_JPEG,
.colplanes = 1,
@@ -53,7 +53,7 @@ static struct mtk_jpeg_fmt mtk_jpeg_formats[] = {
},
};
-#define MTK_JPEG_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_formats)
+#define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
struct mtk_jpeg_src_buf {
struct vb2_v4l2_buffer b;
@@ -75,12 +75,12 @@ static inline struct mtk_jpeg_src_buf *mtk_jpeg_vb2_to_srcbuf(
return container_of(to_vb2_v4l2_buffer(vb), struct mtk_jpeg_src_buf, b);
}
-static int mtk_jpeg_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
+static int mtk_jpeg_dec_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
{
struct mtk_jpeg_dev *jpeg = video_drvdata(file);
- strscpy(cap->driver, MTK_JPEG_NAME " decoder", sizeof(cap->driver));
+ strscpy(cap->driver, MTK_JPEG_NAME, sizeof(cap->driver));
strscpy(cap->card, MTK_JPEG_NAME " decoder", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
dev_name(jpeg->dev));
@@ -109,22 +109,23 @@ static int mtk_jpeg_enum_fmt(struct mtk_jpeg_fmt *mtk_jpeg_formats, int n,
return 0;
}
-static int mtk_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
+static int mtk_jpeg_dec_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
{
- return mtk_jpeg_enum_fmt(mtk_jpeg_formats, MTK_JPEG_NUM_FORMATS, f,
+ return mtk_jpeg_enum_fmt(mtk_jpeg_dec_formats,
+ MTK_JPEG_DEC_NUM_FORMATS, f,
MTK_JPEG_FMT_FLAG_DEC_CAPTURE);
}
-static int mtk_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
+static int mtk_jpeg_dec_enum_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
{
- return mtk_jpeg_enum_fmt(mtk_jpeg_formats, MTK_JPEG_NUM_FORMATS, f,
- MTK_JPEG_FMT_FLAG_DEC_OUTPUT);
+ return mtk_jpeg_enum_fmt(mtk_jpeg_dec_formats, MTK_JPEG_DEC_NUM_FORMATS,
+ f, MTK_JPEG_FMT_FLAG_DEC_OUTPUT);
}
-static struct mtk_jpeg_q_data *mtk_jpeg_get_q_data(struct mtk_jpeg_ctx *ctx,
- enum v4l2_buf_type type)
+static struct mtk_jpeg_q_data *
+mtk_jpeg_get_q_data(struct mtk_jpeg_ctx *ctx, enum v4l2_buf_type type)
{
if (V4L2_TYPE_IS_OUTPUT(type))
return &ctx->out_q;
@@ -141,8 +142,8 @@ static struct mtk_jpeg_fmt *mtk_jpeg_find_format(struct mtk_jpeg_ctx *ctx,
MTK_JPEG_FMT_FLAG_DEC_OUTPUT :
MTK_JPEG_FMT_FLAG_DEC_CAPTURE;
- for (k = 0; k < MTK_JPEG_NUM_FORMATS; k++) {
- struct mtk_jpeg_fmt *fmt = &mtk_jpeg_formats[k];
+ for (k = 0; k < MTK_JPEG_DEC_NUM_FORMATS; k++) {
+ struct mtk_jpeg_fmt *fmt = &mtk_jpeg_dec_formats[k];
if (fmt->fourcc == pixelformat && fmt->flags & fmt_flag)
return fmt;
@@ -270,8 +271,8 @@ static int mtk_jpeg_g_fmt_vid_mplane(struct file *file, void *priv,
return 0;
}
-static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
+static int mtk_jpeg_dec_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
struct mtk_jpeg_fmt *fmt;
@@ -291,8 +292,8 @@ static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv,
return mtk_jpeg_try_fmt_mplane(f, fmt, ctx, MTK_JPEG_FMT_TYPE_CAPTURE);
}
-static int mtk_jpeg_try_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
+static int mtk_jpeg_dec_try_fmt_vid_out_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
struct mtk_jpeg_fmt *fmt;
@@ -364,24 +365,24 @@ static int mtk_jpeg_s_fmt_mplane(struct mtk_jpeg_ctx *ctx,
return 0;
}
-static int mtk_jpeg_s_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
+static int mtk_jpeg_dec_s_fmt_vid_out_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
{
int ret;
- ret = mtk_jpeg_try_fmt_vid_out_mplane(file, priv, f);
+ ret = mtk_jpeg_dec_try_fmt_vid_out_mplane(file, priv, f);
if (ret)
return ret;
return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f);
}
-static int mtk_jpeg_s_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
+static int mtk_jpeg_dec_s_fmt_vid_cap_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
{
int ret;
- ret = mtk_jpeg_try_fmt_vid_cap_mplane(file, priv, f);
+ ret = mtk_jpeg_dec_try_fmt_vid_cap_mplane(file, priv, f);
if (ret)
return ret;
@@ -410,8 +411,8 @@ static int mtk_jpeg_subscribe_event(struct v4l2_fh *fh,
return v4l2_ctrl_subscribe_event(fh, sub);
}
-static int mtk_jpeg_g_selection(struct file *file, void *priv,
- struct v4l2_selection *s)
+static int mtk_jpeg_dec_g_selection(struct file *file, void *priv,
+ struct v4l2_selection *s)
{
struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
@@ -439,8 +440,8 @@ static int mtk_jpeg_g_selection(struct file *file, void *priv,
return 0;
}
-static int mtk_jpeg_s_selection(struct file *file, void *priv,
- struct v4l2_selection *s)
+static int mtk_jpeg_dec_s_selection(struct file *file, void *priv,
+ struct v4l2_selection *s)
{
struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
@@ -483,20 +484,20 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
}
-static const struct v4l2_ioctl_ops mtk_jpeg_ioctl_ops = {
- .vidioc_querycap = mtk_jpeg_querycap,
- .vidioc_enum_fmt_vid_cap = mtk_jpeg_enum_fmt_vid_cap,
- .vidioc_enum_fmt_vid_out = mtk_jpeg_enum_fmt_vid_out,
- .vidioc_try_fmt_vid_cap_mplane = mtk_jpeg_try_fmt_vid_cap_mplane,
- .vidioc_try_fmt_vid_out_mplane = mtk_jpeg_try_fmt_vid_out_mplane,
+static const struct v4l2_ioctl_ops mtk_jpeg_dec_ioctl_ops = {
+ .vidioc_querycap = mtk_jpeg_dec_querycap,
+ .vidioc_enum_fmt_vid_cap = mtk_jpeg_dec_enum_fmt_vid_cap,
+ .vidioc_enum_fmt_vid_out = mtk_jpeg_dec_enum_fmt_vid_out,
+ .vidioc_try_fmt_vid_cap_mplane = mtk_jpeg_dec_try_fmt_vid_cap_mplane,
+ .vidioc_try_fmt_vid_out_mplane = mtk_jpeg_dec_try_fmt_vid_out_mplane,
.vidioc_g_fmt_vid_cap_mplane = mtk_jpeg_g_fmt_vid_mplane,
.vidioc_g_fmt_vid_out_mplane = mtk_jpeg_g_fmt_vid_mplane,
- .vidioc_s_fmt_vid_cap_mplane = mtk_jpeg_s_fmt_vid_cap_mplane,
- .vidioc_s_fmt_vid_out_mplane = mtk_jpeg_s_fmt_vid_out_mplane,
+ .vidioc_s_fmt_vid_cap_mplane = mtk_jpeg_dec_s_fmt_vid_cap_mplane,
+ .vidioc_s_fmt_vid_out_mplane = mtk_jpeg_dec_s_fmt_vid_out_mplane,
.vidioc_qbuf = mtk_jpeg_qbuf,
.vidioc_subscribe_event = mtk_jpeg_subscribe_event,
- .vidioc_g_selection = mtk_jpeg_g_selection,
- .vidioc_s_selection = mtk_jpeg_s_selection,
+ .vidioc_g_selection = mtk_jpeg_dec_g_selection,
+ .vidioc_s_selection = mtk_jpeg_dec_s_selection,
.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
@@ -615,7 +616,7 @@ static void mtk_jpeg_set_queue_data(struct mtk_jpeg_ctx *ctx,
param->dec_w, param->dec_h);
}
-static void mtk_jpeg_buf_queue(struct vb2_buffer *vb)
+static void mtk_jpeg_dec_buf_queue(struct vb2_buffer *vb)
{
struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct mtk_jpeg_dec_param *param;
@@ -663,7 +664,7 @@ static struct vb2_v4l2_buffer *mtk_jpeg_buf_remove(struct mtk_jpeg_ctx *ctx,
return v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
}
-static void mtk_jpeg_stop_streaming(struct vb2_queue *q)
+static void mtk_jpeg_dec_stop_streaming(struct vb2_queue *q)
{
struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(q);
struct vb2_v4l2_buffer *vb;
@@ -689,13 +690,13 @@ static void mtk_jpeg_stop_streaming(struct vb2_queue *q)
v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
}
-static const struct vb2_ops mtk_jpeg_qops = {
+static const struct vb2_ops mtk_jpeg_dec_qops = {
.queue_setup = mtk_jpeg_queue_setup,
.buf_prepare = mtk_jpeg_buf_prepare,
- .buf_queue = mtk_jpeg_buf_queue,
+ .buf_queue = mtk_jpeg_dec_buf_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
- .stop_streaming = mtk_jpeg_stop_streaming,
+ .stop_streaming = mtk_jpeg_dec_stop_streaming,
};
static void mtk_jpeg_set_dec_src(struct mtk_jpeg_ctx *ctx,
@@ -735,7 +736,7 @@ static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx,
return 0;
}
-static void mtk_jpeg_device_run(void *priv)
+static void mtk_jpeg_dec_device_run(void *priv)
{
struct mtk_jpeg_ctx *ctx = priv;
struct mtk_jpeg_dev *jpeg = ctx->jpeg;
@@ -763,15 +764,16 @@ static void mtk_jpeg_device_run(void *priv)
goto dec_end;
mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs);
- if (mtk_jpeg_set_dec_dst(ctx, &jpeg_src_buf->dec_param, &dst_buf->vb2_buf, &fb))
+ if (mtk_jpeg_set_dec_dst(ctx, &jpeg_src_buf->dec_param,
+ &dst_buf->vb2_buf, &fb))
goto dec_end;
spin_lock_irqsave(&jpeg->hw_lock, flags);
- mtk_jpeg_dec_reset(jpeg->dec_reg_base);
- mtk_jpeg_dec_set_config(jpeg->dec_reg_base,
+ mtk_jpeg_dec_reset(jpeg->reg_base);
+ mtk_jpeg_dec_set_config(jpeg->reg_base,
&jpeg_src_buf->dec_param, &bs, &fb);
- mtk_jpeg_dec_start(jpeg->dec_reg_base);
+ mtk_jpeg_dec_start(jpeg->reg_base);
spin_unlock_irqrestore(&jpeg->hw_lock, flags);
return;
@@ -783,20 +785,20 @@ static void mtk_jpeg_device_run(void *priv)
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
}
-static int mtk_jpeg_job_ready(void *priv)
+static int mtk_jpeg_dec_job_ready(void *priv)
{
struct mtk_jpeg_ctx *ctx = priv;
return (ctx->state == MTK_JPEG_RUNNING) ? 1 : 0;
}
-static const struct v4l2_m2m_ops mtk_jpeg_m2m_ops = {
- .device_run = mtk_jpeg_device_run,
- .job_ready = mtk_jpeg_job_ready,
+static const struct v4l2_m2m_ops mtk_jpeg_dec_m2m_ops = {
+ .device_run = mtk_jpeg_dec_device_run,
+ .job_ready = mtk_jpeg_dec_job_ready,
};
-static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
- struct vb2_queue *dst_vq)
+static int mtk_jpeg_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq)
{
struct mtk_jpeg_ctx *ctx = priv;
int ret;
@@ -805,7 +807,7 @@ static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->io_modes = VB2_DMABUF | VB2_MMAP;
src_vq->drv_priv = ctx;
src_vq->buf_struct_size = sizeof(struct mtk_jpeg_src_buf);
- src_vq->ops = &mtk_jpeg_qops;
+ src_vq->ops = &mtk_jpeg_dec_qops;
src_vq->mem_ops = &vb2_dma_contig_memops;
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
src_vq->lock = &ctx->jpeg->lock;
@@ -818,7 +820,7 @@ static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->io_modes = VB2_DMABUF | VB2_MMAP;
dst_vq->drv_priv = ctx;
dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- dst_vq->ops = &mtk_jpeg_qops;
+ dst_vq->ops = &mtk_jpeg_dec_qops;
dst_vq->mem_ops = &vb2_dma_contig_memops;
dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
dst_vq->lock = &ctx->jpeg->lock;
@@ -857,7 +859,7 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
u32 dec_ret;
int i;
- dec_ret = mtk_jpeg_dec_get_int_status(jpeg->dec_reg_base);
+ dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base);
dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret);
ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
if (!ctx) {
@@ -870,7 +872,7 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW)
- mtk_jpeg_dec_reset(jpeg->dec_reg_base);
+ mtk_jpeg_dec_reset(jpeg->reg_base);
if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) {
dev_err(jpeg->dev, "decode failed\n");
@@ -891,7 +893,7 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
return IRQ_HANDLED;
}
-static void mtk_jpeg_set_default_params(struct mtk_jpeg_ctx *ctx)
+static void mtk_jpeg_set_dec_default_params(struct mtk_jpeg_ctx *ctx)
{
struct mtk_jpeg_q_data *q = &ctx->out_q;
int i;
@@ -923,7 +925,7 @@ static void mtk_jpeg_set_default_params(struct mtk_jpeg_ctx *ctx)
}
}
-static int mtk_jpeg_open(struct file *file)
+static int mtk_jpeg_dec_open(struct file *file)
{
struct mtk_jpeg_dev *jpeg = video_drvdata(file);
struct video_device *vfd = video_devdata(file);
@@ -945,13 +947,13 @@ static int mtk_jpeg_open(struct file *file)
ctx->jpeg = jpeg;
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx,
- mtk_jpeg_queue_init);
+ mtk_jpeg_dec_queue_init);
if (IS_ERR(ctx->fh.m2m_ctx)) {
ret = PTR_ERR(ctx->fh.m2m_ctx);
goto error;
}
- mtk_jpeg_set_default_params(ctx);
+ mtk_jpeg_set_dec_default_params(ctx);
mutex_unlock(&jpeg->lock);
return 0;
@@ -978,9 +980,9 @@ static int mtk_jpeg_release(struct file *file)
return 0;
}
-static const struct v4l2_file_operations mtk_jpeg_fops = {
+static const struct v4l2_file_operations mtk_jpeg_dec_fops = {
.owner = THIS_MODULE,
- .open = mtk_jpeg_open,
+ .open = mtk_jpeg_dec_open,
.release = mtk_jpeg_release,
.poll = v4l2_m2m_fop_poll,
.unlocked_ioctl = video_ioctl2,
@@ -1016,7 +1018,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
{
struct mtk_jpeg_dev *jpeg;
struct resource *res;
- int dec_irq;
+ int jpeg_irq;
int ret;
jpeg = devm_kzalloc(&pdev->dev, sizeof(*jpeg), GFP_KERNEL);
@@ -1028,23 +1030,23 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
jpeg->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- jpeg->dec_reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(jpeg->dec_reg_base)) {
- ret = PTR_ERR(jpeg->dec_reg_base);
+ jpeg->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(jpeg->reg_base)) {
+ ret = PTR_ERR(jpeg->reg_base);
return ret;
}
- dec_irq = platform_get_irq(pdev, 0);
- if (dec_irq < 0) {
- dev_err(&pdev->dev, "Failed to get dec_irq %d.\n", dec_irq);
- return dec_irq;
+ jpeg_irq = platform_get_irq(pdev, 0);
+ if (jpeg_irq < 0) {
+ dev_err(&pdev->dev, "Failed to get jpeg_irq %d.\n", jpeg_irq);
+ return jpeg_irq;
}
- ret = devm_request_irq(&pdev->dev, dec_irq, mtk_jpeg_dec_irq, 0,
+ ret = devm_request_irq(&pdev->dev, jpeg_irq, mtk_jpeg_dec_irq, 0,
pdev->name, jpeg);
if (ret) {
- dev_err(&pdev->dev, "Failed to request dec_irq %d (%d)\n",
- dec_irq, ret);
+ dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
+ jpeg_irq, ret);
goto err_req_irq;
}
@@ -1061,40 +1063,40 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
goto err_dev_register;
}
- jpeg->m2m_dev = v4l2_m2m_init(&mtk_jpeg_m2m_ops);
+ jpeg->m2m_dev = v4l2_m2m_init(&mtk_jpeg_dec_m2m_ops);
if (IS_ERR(jpeg->m2m_dev)) {
v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
ret = PTR_ERR(jpeg->m2m_dev);
goto err_m2m_init;
}
- jpeg->dec_vdev = video_device_alloc();
- if (!jpeg->dec_vdev) {
+ jpeg->vdev = video_device_alloc();
+ if (!jpeg->vdev) {
ret = -ENOMEM;
- goto err_dec_vdev_alloc;
+ goto err_vfd_jpeg_alloc;
}
- snprintf(jpeg->dec_vdev->name, sizeof(jpeg->dec_vdev->name),
+ snprintf(jpeg->vdev->name, sizeof(jpeg->vdev->name),
"%s-dec", MTK_JPEG_NAME);
- jpeg->dec_vdev->fops = &mtk_jpeg_fops;
- jpeg->dec_vdev->ioctl_ops = &mtk_jpeg_ioctl_ops;
- jpeg->dec_vdev->minor = -1;
- jpeg->dec_vdev->release = video_device_release;
- jpeg->dec_vdev->lock = &jpeg->lock;
- jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
- jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
- jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
+ jpeg->vdev->fops = &mtk_jpeg_dec_fops;
+ jpeg->vdev->ioctl_ops = &mtk_jpeg_dec_ioctl_ops;
+ jpeg->vdev->minor = -1;
+ jpeg->vdev->release = video_device_release;
+ jpeg->vdev->lock = &jpeg->lock;
+ jpeg->vdev->v4l2_dev = &jpeg->v4l2_dev;
+ jpeg->vdev->vfl_dir = VFL_DIR_M2M;
+ jpeg->vdev->device_caps = V4L2_CAP_STREAMING |
V4L2_CAP_VIDEO_M2M_MPLANE;
- ret = video_register_device(jpeg->dec_vdev, VFL_TYPE_VIDEO, -1);
+ ret = video_register_device(jpeg->vdev, VFL_TYPE_VIDEO, -1);
if (ret) {
v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
- goto err_dec_vdev_register;
+ goto err_vfd_jpeg_register;
}
- video_set_drvdata(jpeg->dec_vdev, jpeg);
+ video_set_drvdata(jpeg->vdev, jpeg);
v4l2_info(&jpeg->v4l2_dev,
"decoder device registered as /dev/video%d (%d,%d)\n",
- jpeg->dec_vdev->num, VIDEO_MAJOR, jpeg->dec_vdev->minor);
+ jpeg->vdev->num, VIDEO_MAJOR, jpeg->vdev->minor);
platform_set_drvdata(pdev, jpeg);
@@ -1102,10 +1104,10 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
return 0;
-err_dec_vdev_register:
- video_device_release(jpeg->dec_vdev);
+err_vfd_jpeg_register:
+ video_device_release(jpeg->vdev);
-err_dec_vdev_alloc:
+err_vfd_jpeg_alloc:
v4l2_m2m_release(jpeg->m2m_dev);
err_m2m_init:
@@ -1125,8 +1127,8 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
struct mtk_jpeg_dev *jpeg = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
- video_unregister_device(jpeg->dec_vdev);
- video_device_release(jpeg->dec_vdev);
+ video_unregister_device(jpeg->vdev);
+ video_device_release(jpeg->vdev);
v4l2_m2m_release(jpeg->m2m_dev);
v4l2_device_unregister(&jpeg->v4l2_dev);
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 5fcdf6950782..0b59e48495d5 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -51,8 +51,8 @@ enum mtk_jpeg_ctx_state {
* @v4l2_dev: v4l2 device for mem2mem mode
* @m2m_dev: v4l2 mem2mem device data
* @alloc_ctx: videobuf2 memory allocator's context
- * @dec_vdev: video device node for decoder mem2mem mode
- * @dec_reg_base: JPEG registers mapping
+ * @vdev: video device node for jpeg mem2mem mode
+ * @reg_base: JPEG registers mapping
* @clk_jdec: JPEG hw working clock
* @clk_jdec_smi: JPEG SMI bus clock
* @larb: SMI device
@@ -65,8 +65,8 @@ struct mtk_jpeg_dev {
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
void *alloc_ctx;
- struct video_device *dec_vdev;
- void __iomem *dec_reg_base;
+ struct video_device *vdev;
+ void __iomem *reg_base;
struct clk *clk_jdec;
struct clk *clk_jdec_smi;
struct device *larb;
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h
index 1cc37dbfc8e7..ce263db5f30a 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h
@@ -3,10 +3,11 @@
* Copyright (c) 2016 MediaTek Inc.
* Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
* Rick Chang <rick.chang@mediatek.com>
+ * Xia Jiang <xia.jiang@mediatek.com>
*/
-#ifndef _MTK_JPEG_HW_H
-#define _MTK_JPEG_HW_H
+#ifndef _MTK_JPEG_DEC_HW_H
+#define _MTK_JPEG_DEC_HW_H
#include <media/videobuf2-core.h>
@@ -75,4 +76,4 @@ void mtk_jpeg_dec_set_config(void __iomem *base,
void mtk_jpeg_dec_reset(void __iomem *dec_reg_base);
void mtk_jpeg_dec_start(void __iomem *dec_reg_base);
-#endif /* _MTK_JPEG_HW_H */
+#endif /* _MTK_JPEG_DEC_HW_H */
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH RESEND v9 10/18] media: platform: Stylistic changes for improving code quality
From: Xia Jiang @ 2020-06-04 9:05 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
Matthias Brugger, Rick Chang
Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604090553.10861-1-xia.jiang@mediatek.com>
Change register offset hex numerals from uppercase to lowercase.
Change data type of max/min width/height from integer to unsigned
integer.
Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: move changing data type of max/min width/height to this patch
---
.../media/platform/mtk-jpeg/mtk_jpeg_core.h | 8 ++++----
drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h | 18 +++++++++---------
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 999bd1427809..28e9b30ad5c3 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -21,10 +21,10 @@
#define MTK_JPEG_FMT_TYPE_OUTPUT 1
#define MTK_JPEG_FMT_TYPE_CAPTURE 2
-#define MTK_JPEG_MIN_WIDTH 32
-#define MTK_JPEG_MIN_HEIGHT 32
-#define MTK_JPEG_MAX_WIDTH 8192
-#define MTK_JPEG_MAX_HEIGHT 8192
+#define MTK_JPEG_MIN_WIDTH 32U
+#define MTK_JPEG_MIN_HEIGHT 32U
+#define MTK_JPEG_MAX_WIDTH 8192U
+#define MTK_JPEG_MAX_HEIGHT 8192U
#define MTK_JPEG_DEFAULT_SIZEIMAGE (1 * 1024 * 1024)
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h
index 94db04e9cdb6..2945da842dfa 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h
@@ -20,29 +20,29 @@
#define BIT_INQST_MASK_ALLIRQ 0x37
#define JPGDEC_REG_RESET 0x0090
-#define JPGDEC_REG_BRZ_FACTOR 0x00F8
-#define JPGDEC_REG_DU_NUM 0x00FC
+#define JPGDEC_REG_BRZ_FACTOR 0x00f8
+#define JPGDEC_REG_DU_NUM 0x00fc
#define JPGDEC_REG_DEST_ADDR0_Y 0x0140
#define JPGDEC_REG_DEST_ADDR0_U 0x0144
#define JPGDEC_REG_DEST_ADDR0_V 0x0148
-#define JPGDEC_REG_DEST_ADDR1_Y 0x014C
+#define JPGDEC_REG_DEST_ADDR1_Y 0x014c
#define JPGDEC_REG_DEST_ADDR1_U 0x0150
#define JPGDEC_REG_DEST_ADDR1_V 0x0154
#define JPGDEC_REG_STRIDE_Y 0x0158
-#define JPGDEC_REG_STRIDE_UV 0x015C
+#define JPGDEC_REG_STRIDE_UV 0x015c
#define JPGDEC_REG_IMG_STRIDE_Y 0x0160
#define JPGDEC_REG_IMG_STRIDE_UV 0x0164
-#define JPGDEC_REG_WDMA_CTRL 0x016C
+#define JPGDEC_REG_WDMA_CTRL 0x016c
#define JPGDEC_REG_PAUSE_MCU_NUM 0x0170
-#define JPGDEC_REG_OPERATION_MODE 0x017C
+#define JPGDEC_REG_OPERATION_MODE 0x017c
#define JPGDEC_REG_FILE_ADDR 0x0200
-#define JPGDEC_REG_COMP_ID 0x020C
+#define JPGDEC_REG_COMP_ID 0x020c
#define JPGDEC_REG_TOTAL_MCU_NUM 0x0210
#define JPGDEC_REG_COMP0_DATA_UNIT_NUM 0x0224
-#define JPGDEC_REG_DU_CTRL 0x023C
+#define JPGDEC_REG_DU_CTRL 0x023c
#define JPGDEC_REG_TRIG 0x0240
#define JPGDEC_REG_FILE_BRP 0x0248
-#define JPGDEC_REG_FILE_TOTAL_SIZE 0x024C
+#define JPGDEC_REG_FILE_TOTAL_SIZE 0x024c
#define JPGDEC_REG_QT_ID 0x0270
#define JPGDEC_REG_INTERRUPT_STATUS 0x0274
#define JPGDEC_REG_STATUS 0x0278
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH RESEND v9 13/18] media: platform: Delete redundant code and add annotation for an enum
From: Xia Jiang @ 2020-06-04 9:05 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
Matthias Brugger, Rick Chang
Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604090553.10861-1-xia.jiang@mediatek.com>
Delete unused member variables annotation.
Delete unused variable definition.
Delete redundant log print, because V4L2 debug logs already print it.
Add annotation for enum mtk_jpeg_ctx_state.
Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: add annotation for enum mtk_jpeg_ctx_state
---
drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 15 ++-------------
drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h | 8 ++++++--
2 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index c9c0357b2d6c..6c82134d6b3d 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -176,14 +176,13 @@ static int mtk_jpeg_try_fmt_mplane(struct v4l2_format *f,
struct mtk_jpeg_ctx *ctx, int q_type)
{
struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
- struct mtk_jpeg_dev *jpeg = ctx->jpeg;
int i;
pix_mp->field = V4L2_FIELD_NONE;
if (ctx->state != MTK_JPEG_INIT) {
mtk_jpeg_adjust_fmt_mplane(ctx, f);
- goto end;
+ return 0;
}
pix_mp->num_planes = fmt->colplanes;
@@ -202,7 +201,7 @@ static int mtk_jpeg_try_fmt_mplane(struct v4l2_format *f,
pfmt->sizeimage = round_up(pfmt->sizeimage, 128);
if (pfmt->sizeimage == 0)
pfmt->sizeimage = MTK_JPEG_DEFAULT_SIZEIMAGE;
- goto end;
+ return 0;
}
/* type is MTK_JPEG_FMT_TYPE_CAPTURE */
@@ -219,16 +218,6 @@ static int mtk_jpeg_try_fmt_mplane(struct v4l2_format *f,
pfmt->bytesperline = stride;
pfmt->sizeimage = stride * h;
}
-end:
- v4l2_dbg(2, debug, &jpeg->v4l2_dev, "wxh:%ux%u\n",
- pix_mp->width, pix_mp->height);
- for (i = 0; i < pix_mp->num_planes; i++) {
- v4l2_dbg(2, debug, &jpeg->v4l2_dev,
- "plane[%d] bpl=%u, size=%u\n",
- i,
- pix_mp->plane_fmt[i].bytesperline,
- pix_mp->plane_fmt[i].sizeimage);
- }
return 0;
}
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 64a731261214..5fcdf6950782 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -30,6 +30,12 @@
#define MTK_JPEG_DEFAULT_SIZEIMAGE (1 * 1024 * 1024)
+/**
+ * enum mtk_jpeg_ctx_state - states of the context state machine
+ * @MTK_JPEG_INIT: current state is initialized
+ * @MTK_JPEG_RUNNING: current state is running
+ * @MTK_JPEG_SOURCE_CHANGE: current state is source resolution change
+ */
enum mtk_jpeg_ctx_state {
MTK_JPEG_INIT = 0,
MTK_JPEG_RUNNING,
@@ -109,9 +115,7 @@ struct mtk_jpeg_q_data {
* @out_q: source (output) queue information
* @cap_q: destination (capture) queue queue information
* @fh: V4L2 file handle
- * @dec_param parameters for HW decoding
* @state: state of the context
- * @header_valid: set if header has been parsed and valid
* @colorspace: enum v4l2_colorspace; supplemental to pixelformat
* @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
* @quantization: enum v4l2_quantization, colorspace quantization
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox