* [PATCH v7 3/8] PWM: add pwm-stm32 DT bindings
From: Benjamin Gaignard @ 2017-01-18 9:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170118092021.GE18989@ulmo.ba.sec>
2017-01-18 10:20 GMT+01:00 Thierry Reding <thierry.reding@gmail.com>:
> On Thu, Jan 05, 2017 at 10:25:39AM +0100, Benjamin Gaignard wrote:
>> Define bindings for pwm-stm32
>>
>> version 6:
>> - change st,breakinput parameter format to make it usuable on stm32f7 too.
>>
>> version 2:
>> - use parameters instead of compatible of handle the hardware configuration
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>> ---
>> .../devicetree/bindings/pwm/pwm-stm32.txt | 33 ++++++++++++++++++++++
>> 1 file changed, 33 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/pwm/pwm-stm32.txt
>>
>> diff --git a/Documentation/devicetree/bindings/pwm/pwm-stm32.txt b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
>> new file mode 100644
>> index 0000000..866f222
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
>> @@ -0,0 +1,33 @@
>> +STMicroelectronics STM32 Timers PWM bindings
>> +
>> +Must be a sub-node of an STM32 Timers device tree node.
>> +See ../mfd/stm32-timers.txt for details about the parent node.
>> +
>> +Required parameters:
>> +- compatible: Must be "st,stm32-pwm".
>> +- pinctrl-names: Set to "default".
>> +- pinctrl-0: List of phandles pointing to pin configuration nodes for PWM module.
>> + For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt
>> +
>> +Optional parameters:
>> +- st,breakinput: Arrays of three u32 <index level filter> to describe break input configurations.
>> + "index" indicates on which break input the configuration should be applied.
>
> It might be useful to specify what the valid values are for the break
> input index.
It could 0 and 1, I will add this information.
>
> Also, u32 is kind of a Linuxism, perhaps "Arrays of three cells"? Also,
> does this mean there can be multiple entries? Such as 6 cells for two
> configurations? What's the maximum number of such configurations?
>
> If it's possible to specify multiple configurations, maybe a slightly
> clearer wording would be: "One or more <index level filter> triplets to
> describe..."
>
You can have one configuration per index so I will rephrase it like that:
One or two <index level filter> to describe break input configurations.
"index" indicates on which break input (0 or 1 ) the configuration
should be applied.
>> + "level" gives the active level (0=low or 1=high) for this configuration.
>
> So how does this work exactly? "level" specifies the output level if the
> filter value is matched?
No it specify on which input level the break event is generated
>
>> + "filter" gives the filtering value to be applied.
>
> Is this a single value at which "level" will be applied? Or is it an
> upper/lower bound that can be used to restrict the output to "level" if
> the signal goes beyond/below a certain threshold?
Very very basically filter is more a debounce value set on the signal
to avoid glitches.
The goal of break input feature is to stop PWM generation in hardware
errors failure case.
For a more completed description you can read "using break input
function" (starting page 645) in this doc:
http://www.st.com/content/ccc/resource/technical/document/reference_manual/c5/cf/ef/52/c0/f1/4b/fa/DM00124865.pdf/files/DM00124865.pdf/jcr:content/translations/en.DM00124865.pdf
>
> Maybe an example would clarify this. Or perhaps a reference to a manual
> where a more in-depth description of this functionality can be found.
>
> Thierry
--
Benjamin Gaignard
Graphic Study Group
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [linux-sunxi] [PATCH 1/2] drivers: pinctrl: add driver for Allwinner H5 SoC
From: Andre Przywara @ 2017-01-18 9:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170116163124.c5gusyd3j3goivnf@lukather>
Hi,
On 16/01/17 16:31, Maxime Ripard wrote:
> On Mon, Jan 09, 2017 at 12:16:00AM +0000, Andr? Przywara wrote:
>> On 05/01/17 22:42, Maxime Ripard wrote:
>>> On Fri, Dec 30, 2016 at 01:55:44PM +0100, Linus Walleij wrote:
>>>> On Mon, Dec 26, 2016 at 3:33 PM, Andr? Przywara <andre.przywara@arm.com> wrote:
>>>>
>>>>> So while this patch technically looks correct, I was wondering if we
>>>>> should really explore the possibility of making the whole of sunxi
>>>>> pinctrl DT controlled.
>>>>> I brought this up a while ago, but people weren't overly enthusiastic
>>>>> about it, though their argument weren't really convincing to me[1].
>>>>>
>>>>> So:
>>>>> As this "driver" here is basically a table linking GPIO bit settings
>>>>> (the actual mux value) to names and every pin we care about needs to be
>>>>> enumerated in the DT anyway, why not just add something like:
>>>>> allwinner,pinmux = <4>;
>>>>> to each pin(group) in the DT and get rid of this "driver" file here
>>>>> entirely?
>>>>
>>>> I'm open to that if you can use pinctrl-single which is in the kernel
>>>> for this purpose only, and is used with both OMAPs and HiSilicon.
>>>
>>> I'm not open to that, and I'm getting tired of discussing it over and
>>> over again. Andre, if you want to be convinced again, please read the
>>> last discussion we had on this topic.
>>
>> As I said: It didn't convince me back then. And frankly we didn't really
>> discuss it back then, I just refrained from entering a discussion
>> against _two_ maintainers at this time, since my capacity on this kind
>> of email threads is really very limited - especially for something that
>> is a hobby to me.
>
> This is also (mostly) a hobby to me, which is exactly why I prefer to
> work on something actually useful, rather than just discussing this
> over and over again. Just like I don't want (myself, or anyone,
> really, since we're all in the same boat) to have to maintain two
> separate pinctrl drivers.
>
> We're having a documented, simple, pinctrl binding, using the generic
> bindings now (that almost everyone else is using now, or is very close
> to), and we can leverage as much documentation and code from that. Why
> would we want to create and maintain a new driver with a new binding,
> that will need to be documented again, learned by everyone, and will
> lead only to confusion across the people who just want to have their
> board supported?
I agree, and thus was proposing a _slightly changed_ pinctrl driver
which actually *reduces* the maintenance burden in the kernel.
In the moment we need to add _both_ a pinctrl .dtsi node _and_ a kernel
"driver" file, which is really boilerplate code plus a table.
Also we need to make sure that both these files match.
If a new SoC is really 99% similar to an existing one, atm we still need
explicit kernel support if only one pin is changed (see the H5).
So my idea was to basically add the mux value as a DT property, thus
making the kernel pinctrl-sun[x]i-a[yz].c files obsolete and greatly
_reduce_ the maintenance burden. Ideally there wouldn't be any pinctrl
code changes in the kernel for future SoCs anymore - at least if
Allwinner sticks with their current pace of releasing copy&pasted SoC
designs. Changes beyond that would require a driver change anyway, even
with the current model.
I gave Linus' proposal to use the pinctrl-single binding a quick look
and don't think it's a match for Allwinner SoC. So my idea was to
basically just add a new compatible and the muxsel property to the
existing driver and binding. It would basically look the same, apart
from one or two additions (to cover interrupts, for instance).
Any future SoCs could then just use that compatible and would describe
the SoC details in the DT, like it's meant to be and like we do already,
but extended by putting the mux value in there as well.
So the only kernel contribution would then be the DT, really, which
technically could be delivered on some device storage as well, but
that's a different discussion ...
> And imagine the kind of mess we would be in if everyone getting a bit
> involved in the support of one platform at one point wanted to trash
> one big part of its infrastructure and start all over again because he
> likes it better this way.
Like I said above, I didn't mean to trash the current pinctrl binding,
just make it a bit more generic and simplify future kernel support.
> I'm sorry, but this is also our jobs as maintainers to prevent all
> these kind of issues, and to maintain consistency. Switching to one
> binding to another breaks that consistency on many level,
Yet we did it for the clocks. The very same argumentation that you gave
above applies there as well (two different bindings, two sets of drivers
in the kernel, new learnings for people, etc.)
One difference would be that the new pinctrl binding wouldn't be
fundamentally different to the old one, up to the point where the old
driver could possibly use the very same DT nodes (but that would need to
be worked out).
Cheers,
Andre.
> both in
> pinctrl and in the platform support itself. So sorry, but that's not
> going to happen.
>
> Maxime
>
^ permalink raw reply
* [PATCH] arm: Use generic irq_migrate_all_off_this_cpu() for CPU hotplug
From: Alexander Sverdlin @ 2017-01-18 9:45 UTC (permalink / raw)
To: linux-arm-kernel
I have found that .irq_bus_lock/.irq_bus_sync_unlock of irqchip are not
honored during CPU hotplug migration and the reason for this is open-coded
IRQ affinity re-configuration in the existing ARM migrate_irqs()
implementation. Fortunately, this was already fixed for ARM64 in 217d453d
("arm64: fix a migrating irq bug when hotplug cpu").
So, just switch to the same generic code for ARM.
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Aaron Tomlin <atomlin@redhat.com>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: Andiii <andi.shyti@samsung.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: linux-arm-kernel at lists.infradead.org
---
arch/arm/Kconfig | 1 +
arch/arm/include/asm/irq.h | 1 -
arch/arm/kernel/irq.c | 61 ----------------------------------------------
arch/arm/kernel/smp.c | 2 +-
4 files changed, 2 insertions(+), 63 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 186c4c214e0a..43080f4bbe4d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1463,6 +1463,7 @@ config NR_CPUS
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs"
depends on SMP
+ select GENERIC_IRQ_MIGRATION
help
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index e53638c8ed8a..61e1d089ce1a 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -24,7 +24,6 @@
#ifndef __ASSEMBLY__
struct irqaction;
struct pt_regs;
-extern void migrate_irqs(void);
extern void asm_do_IRQ(unsigned int, struct pt_regs *);
void handle_IRQ(unsigned int, struct pt_regs *);
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ece04a457486..a7e047127c05 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -119,64 +119,3 @@ int __init arch_probe_nr_irqs(void)
return nr_irqs;
}
#endif
-
-#ifdef CONFIG_HOTPLUG_CPU
-static bool migrate_one_irq(struct irq_desc *desc)
-{
- struct irq_data *d = irq_desc_get_irq_data(desc);
- const struct cpumask *affinity = irq_data_get_affinity_mask(d);
- struct irq_chip *c;
- bool ret = false;
-
- /*
- * If this is a per-CPU interrupt, or the affinity does not
- * include this CPU, then we have nothing to do.
- */
- if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
- return false;
-
- if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
- affinity = cpu_online_mask;
- ret = true;
- }
-
- c = irq_data_get_irq_chip(d);
- if (!c->irq_set_affinity)
- pr_debug("IRQ%u: unable to set affinity\n", d->irq);
- else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
- cpumask_copy(irq_data_get_affinity_mask(d), affinity);
-
- return ret;
-}
-
-/*
- * The current CPU has been marked offline. Migrate IRQs off this CPU.
- * If the affinity settings do not allow other CPUs, force them onto any
- * available CPU.
- *
- * Note: we must iterate over all IRQs, whether they have an attached
- * action structure or not, as we need to get chained interrupts too.
- */
-void migrate_irqs(void)
-{
- unsigned int i;
- struct irq_desc *desc;
- unsigned long flags;
-
- local_irq_save(flags);
-
- for_each_irq_desc(i, desc) {
- bool affinity_broken;
-
- raw_spin_lock(&desc->lock);
- affinity_broken = migrate_one_irq(desc);
- raw_spin_unlock(&desc->lock);
-
- if (affinity_broken)
- pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n",
- i, smp_processor_id());
- }
-
- local_irq_restore(flags);
-}
-#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 7dd14e8395e6..d28a06fc7001 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -222,7 +222,7 @@ int __cpu_disable(void)
/*
* OK - migrate IRQs away from this CPU
*/
- migrate_irqs();
+ irq_migrate_all_off_this_cpu();
/*
* Flush user cache and TLB mappings, and then remove this CPU
--
2.11.0
^ permalink raw reply related
* [PATCH v2 1/2] ARM: davinci: Allocate extra interrupts
From: Sekhar Nori @ 2017-01-18 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484337612-11120-2-git-send-email-david@lechnology.com>
On Saturday 14 January 2017 01:30 AM, David Lechner wrote:
> This allocates extra interrupts for mach-davinci. These extra interrupts
> are need for things like IIO triggers.
I am not really familiar with IIO triggers. Can you give some more
detail on what fails without this patch?
Thanks,
Sekhar
^ permalink raw reply
* [PATCH] ARM: smp: Remove CPU: shutdown notice
From: Petr Mladek @ 2017-01-18 9:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <fd4a4f48-f19e-dcac-c286-8e03db89e99a@gmail.com>
On Tue 2017-01-17 15:39:45, Florian Fainelli wrote:
> On 01/17/2017 03:23 PM, Russell King - ARM Linux wrote:
> > On Tue, Jan 17, 2017 at 03:07:12PM -0800, Florian Fainelli wrote:
> >> This message is not particularly informative, and is not paired with an
> >> identical message when a CPU is brought online. Finally, it slows the
> >> CPU hotplug path down, thus allowing less CPU hotplug operations per
> >> second. Just remove it.
> >
> > CPU hotplug isn't a fast operation anyway - it's also fairly disruptive
> > in that it uses stop_machine() to halt activity everywhere while taking
> > the CPU offline.
>
> We have a test that consists in shutting down all CPUs as frequently as
> we can and do this for about 2 million iterations which takes roughly
> 24h, and this printk slows thing down by a reasonable amount. Here are
> some numbers on 500 hotplug operations:
>
> w/ printk:
> real 0m9.997s
> user 0m0.725s
> sys 0m3.030s
> #
>
> w/o printk:
> real 0m8.547s
> user 0m0.436s
> sys 0m1.838s
I am curious that a single printk() might make such a big difference.
One reason might be that the messages are pushed to a "slow" console.
Another reason might be that there are many other messages printed
on the system and there is a contention on logbuf_lock or other
console related locks.
There might be also the opposite problem. The messages are also read
by userspace tools that store them into /var/log/messages or systemd
logs. If these are the only messages printed to the log and if there
is no other activity on the system. Then the waken loggers might make
a difference, especially if all CPUs are getting disabled and only
one is available at some point.
Well, I am not sure what other operations are needed to do the
CPU hotplug operation.
I cannot judge how the message is useful and if the speed up
is worth removing it.
Best Regards,
Petr
^ permalink raw reply
* [PATCH] ARM: davinci: da850-evm: fix read access to SPI flash
From: Sekhar Nori @ 2017-01-18 9:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <m237gh2ozw.fsf@baylibre.com>
On Wednesday 18 January 2017 05:55 AM, Kevin Hilman wrote:
> Fabien Parent <fparent@baylibre.com> writes:
>
>> Read access to the SPI flash are broken on da850-evm, i.e. the data
>> read is not what is actually programmed on the flash.
>> According to the datasheet for the M25P64 part present on the da850-evm,
>> if the SPI frequency is higher than 20MHz then the READ command is not
>> usable anymore and only the FAST_READ command can be used to read data.
>>
>> This commit specifies in the DTS that we should use FAST_READ command
>> instead of the READ command.
>>
>> Signed-off-by: Fabien Parent <fparent@baylibre.com>
>
> Tested on da850-evm on top of v4.10-rc3. This gets the DT boot
> functionatliy in line with the legacy (board-file) boot.
>
> Tested-by: Kevin Hilman <khilman@baylibre.com>
Applied with Kevin's Tested-by and also marked for stable. Sending pull
request for v4.10-rc shortly.
Thanks,
Sekhar
^ permalink raw reply
* drm: rockchip: CONFIG_DRM_FBDEV_EMULATION will crash the HDMI down sometimes
From: Randy Li @ 2017-01-18 9:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <587DD4E3.5070202@rock-chips.com>
On 01/17/2017 04:25 PM, Mark yao wrote:
>
> static void vop_plane_atomic_update(struct drm_plane *plane,
> struct drm_plane_state *old_state)
> {
> if (WARN_ON(!vop->is_enabled))
> return;
>
> The issues seems vop is not enable. but commit planes is using
> DRM_PLANE_COMMIT_ACTIVE_ONLY...
>
> Hi Randy
>
> Can you add some print for this bug:
> 1, I think vop_crtc_enable function should be call before
> vop_plane_atomic_update, you can add some print to verified it.
Not hint
> 2, also add a trace on vop_crtc_disable.
Not hint
> 3, print the status of crtc->state->active and
> plane_crtc_active(plane->state) when bug happen.
hint
[ 11.481977] vop active 1, state 1
The full log is attached here
[ 10.887294] rockchip-drm display-subsystem: bound ff940000.vop (ops
vop_component_ops [rockchipdrm])
[ OK ] Started Initialize hardware monitoring sensors.
[ 10.898567] rockchip-drm display-subsystem: bound ff930000.vop (ops
vop_component_ops [rockchipdrm])
[ 10.912280] dwhdmi-rockchip ff980000.hdmi: Detected HDMI controller
0x20:0xa:0xa0:0xc1
[ 10.921423] rockchip-drm display-subsystem: bound ff980000.hdmi (ops
dw_hdmi_rockchip_ops [dw_hdmi_rockchip])
[ 10.931413] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[ 10.938090] [drm] No driver support for vblank timestamp query.
[ 11.002102] rockchip-drm display-subsystem: fb0: frame buffer device
[ 11.031833] [drm] Initialized rockchip 1.0.0 20140818 for
display-subsystem on minor 0
[ OK ] Started Login Service.
[ OK ] Created slice system-systemd\x2dbacklight.slice.
Starting Load/Save Screen Backlight...htness of
backlight:backlight...
[ 11.128697] rk_iommu ff940300.iommu: FORCE_RESET command timed out
[ 11.134928] rockchip-vop ff940000.vop: failed to attach dma mapping, -110
[ 11.141805] rockchip-vop ff940000.vop: [drm:vop_crtc_enable] *ERROR*
Failed to enable vop (-110)
[ OK ] Started Load/Save Screen Backlight Brightness of
backlight:backlight.
[ 11.181850] ------------[ cut here ]------------
[ 11.186568] WARNING: CPU: 3 PID: 167 at
/home/ayaka/workspace/rk3288/kernel/linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm$
vop.c:731 vop_plane_atomic_update+0x94/0x17a8 [rockchipdrm]
[ 11.203254] Modules linked in: rockchip_vop_reg dw_hdmi_rockchip
dw_hdmi rockchipdrm drm_kms_helper mali_kbase cfbfillrect sys$
opyarea rk_crypto gpio_ir_recv cfbimgblt panel_simple sysfillrect
rc_core sysimgblt nvmem_rockchip_efuse fb_sys_fops cfbcopyarea $
rm des_generic dwc2 pwm_rockchip phy_rockchip_usb udc_core fb pwm_bl
backlight
[ 11.233011] CPU: 3 PID: 167 Comm: kworker/3:2 Not tainted
4.10.0-rc3-next-20170111+ #149
[ 11.241105] Hardware name: Rockchip (Device Tree)
[ 11.245898] Workqueue: events output_poll_execute [drm_kms_helper]
[ 11.252129] [<c0112b98>] (unwind_backtrace) from [<c010dab8>]
(show_stack+0x20/0x24)
[ 11.259896] [<c010dab8>] (show_stack) from [<c044973c>]
(dump_stack+0x8c/0xa0)
[ 11.267137] [<c044973c>] (dump_stack) from [<c0125f88>]
(__warn+0xf8/0x110)
[ 11.274119] [<c0125f88>] (__warn) from [<c01260b8>]
(warn_slowpath_null+0x30/0x38)
[ 11.281724] [<c01260b8>] (warn_slowpath_null) from [<bf57330c>]
(vop_plane_atomic_update+0x94/0x17a8 [rockchipdrm])
[ 11.292283] [<bf57330c>] (vop_plane_atomic_update [rockchipdrm]) from
[<bf494590>] (drm_atomic_helper_commit_planes+0xd4/0x2b8
[drm_kms_helper])
[ 11.305337] [<bf494590>] (drm_atomic_helper_commit_planes
[drm_kms_helper]) from [<bf56fa88>] (rockchip_atomic_commit_tail+0x44
/0x68 [rockchipdrm])
[ 11.318643] [<bf56fa88>] (rockchip_atomic_commit_tail [rockchipdrm])
from [<bf498714>] (commit_tail+0x50/0xb8 [drm_kms_helper])
[ 11.330262] [<bf498714>] (commit_tail [drm_kms_helper]) from
[<bf498870>] (drm_atomic_helper_commit+0xd4/0x13c [drm_kms_helper]
)
[ 11.342071] [<bf498870>] (drm_atomic_helper_commit [drm_kms_helper])
from [<bf10b18c>] (drm_atomic_commit+0x5c/0x68 [drm])
[ 11.353363] [<bf10b18c>] (drm_atomic_commit [drm]) from [<bf49c0f8>]
(restore_fbdev_mode+0x160/0x300 [drm_kms_helper])
[ 11.364207] [<bf49c0f8>] (restore_fbdev_mode [drm_kms_helper]) from
[<bf49d71c>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x4
0/0x84 [drm_kms_helper])
[ 11.377916] [<bf49d71c>] (drm_fb_helper_restore_fbdev_mode_unlocked
[drm_kms_helper]) from [<bf49d7a0>] (drm_fb_helper_set_par+
0x40/0x70 [drm_kms_helper])
[ 11.391942] [<bf49d7a0>] (drm_fb_helper_set_par [drm_kms_helper])
from [<bf49d6d4>] (drm_fb_helper_hotplug_event+0xb4/0xbc [drm
_kms_helper])
[ 11.404652] [<bf49d6d4>] (drm_fb_helper_hotplug_event
[drm_kms_helper]) from [<bf56fad0>] (rockchip_drm_output_poll_changed+0x2
4/0x28 [rockchipdrm])
[ 11.418047] [<bf56fad0>] (rockchip_drm_output_poll_changed
[rockchipdrm]) from [<bf48db64>] (drm_kms_helper_hotplug_event+0x34$
0x38 [drm_kms_helper])
[ 11.431573] [<bf48db64>] (drm_kms_helper_hotplug_event
[drm_kms_helper]) from [<bf48dc7c>] (output_poll_execute+0xbc/0x1f4 [dr$
_kms_helper])
[ 11.444286] [<bf48dc7c>] (output_poll_execute [drm_kms_helper]) from
[<c0142364>] (process_one_work+0x1b0/0x4c0)
[ 11.454476] [<c0142364>] (process_one_work) from [<c014328c>]
(worker_thread+0x60/0x548)
[ 11.462581] [<c014328c>] (worker_thread) from [<c0148ec0>]
(kthread+0x128/0x158)
[ 11.469994] [<c0148ec0>] (kthread) from [<c0108e90>]
(ret_from_fork+0x14/0x24)
[ 11.477309] ---[ end trace 92447684af807ac2 ]---
[ 11.481977] vop active 1, state 1
[ 11.481985] ------------[ cut here ]------------
[ 11.482021] WARNING: CPU: 3 PID: 167 at
/home/ayaka/workspace/rk3288/kernel/linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm_
vop.c:1023 vop_crtc_atomic_flush+0x27c/0x2b8 [rockchipdrm]
[ 11.482030] Modules linked in: rockchip_vop_reg dw_hdmi_rockchip
dw_hdmi rockchipdrm drm_kms_helper mali_kbase cfbfillrect sysc
opyarea rk_crypto gpio_ir_recv cfbimgblt panel_simple sysfillrect
rc_core sysimgblt nvmem_rockchip_efuse fb_sys_fops cfbcopyarea d
rm des_generic dwc2 pwm_rockchip phy_rockchip_usb udc_core fb pwm_bl
backlight
[ 11.482119] CPU: 3 PID: 167 Comm: kworker/3:2 Tainted: G W
4.10.0-rc3-next-20170111+ #149
[ 11.482122] Hardware name: Rockchip (Device Tree)
[ 11.482200] Workqueue: events output_poll_execute [drm_kms_helper]
[ 11.482227] [<c0112b98>] (unwind_backtrace) from [<c010dab8>]
(show_stack+0x20/0x24)
[ 11.482242] [<c010dab8>] (show_stack) from [<c044973c>]
(dump_stack+0x8c/0xa0)
[ 11.482259] [<c044973c>] (dump_stack) from [<c0125f88>]
(__warn+0xf8/0x110)
[ 11.482275] [<c0125f88>] (__warn) from [<c01260b8>]
(warn_slowpath_null+0x30/0x38)
[ 11.482308] [<c01260b8>] (warn_slowpath_null) from [<bf5713e0>]
(vop_crtc_atomic_flush+0x27c/0x2b8 [rockchipdrm])
[ 11.482416] [<bf5713e0>] (vop_crtc_atomic_flush [rockchipdrm]) from
[<bf49468c>] (drm_atomic_helper_commit_planes+0x1d0/0x2b8 [
drm_kms_helper])
[ 11.482522] [<bf49468c>] (drm_atomic_helper_commit_planes
[drm_kms_helper]) from [<bf56fa88>] (rockchip_atomic_commit_tail+0x44
/0x68 [rockchipdrm])
[ 11.482623] [<bf56fa88>] (rockchip_atomic_commit_tail [rockchipdrm])
from [<bf498714>] (commit_tail+0x50/0xb8 [drm_kms_helper])
[ 11.482779] [<bf498714>] (commit_tail [drm_kms_helper]) from
[<bf498870>] (drm_atomic_helper_commit+0xd4/0x13c [drm_kms_helper]
)
[ 11.483024] [<bf498870>] (drm_atomic_helper_commit [drm_kms_helper])
from [<bf10b18c>] (drm_atomic_commit+0x5c/0x68 [drm])
[ 11.483270] [<bf10b18c>] (drm_atomic_commit [drm]) from [<bf49c0f8>]
(restore_fbdev_mode+0x160/0x300 [drm_kms_helper])
[ 11.483422] [<bf49c0f8>] (restore_fbdev_mode [drm_kms_helper]) from
[<bf49d71c>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x4
0/0x84 [drm_kms_helper])
[ 11.483569] [<bf49d71c>] (drm_fb_helper_restore_fbdev_mode_unlocked
[drm_kms_helper]) from [<bf49d7a0>] (drm_fb_helper_set_par+
0x40/0x70 [drm_kms_helper])
[ 11.483715] [<bf49d7a0>] (drm_fb_helper_set_par [drm_kms_helper])
from [<bf49d6d4>] (drm_fb_helper_hotplug_event+0xb4/0xbc [drm
_kms_helper])
[ 11.483821] [<bf49d6d4>] (drm_fb_helper_hotplug_event
[drm_kms_helper]) from [<bf56fad0>] (rockchip_drm_output_poll_changed+0x2
4/0x28 [rockchipdrm])
>
> Thanks.
> On 2017?01?17? 15:58, Randy Li wrote:
>> Hello:
>> I want to enable the video output at RK3288 Firefly board, but I
>> found if I enable CONFIG_DRM_FBDEV_EMULATION, the HDMI would crash
>> down sometimes but sometimes it works. After disable that opinion, I
>> never meet a problem. I have not verified it with eDP as I meet a big
>> problem in there.
>>[..]
>> [ 34.464856] ---[ end trace 95ed2c3f167607d5 ]---
>
>
--
Randy Li
^ permalink raw reply
* [PATCH 00/11] Add MFC v10.10 support
From: Smitha T Murthy @ 2017-01-18 10:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20170118100714epcas1p274e2e68d14a788417fbde2c26c91bcb9@epcas1p2.samsung.com>
This patch series adds MFC v10.10 support. MFC v10.10 is used in some
of Exynos7 variants.
This adds support for following:
* Add support for HEVC encoder and decoder
* Add support for VP9 decoder
* Update Documentation for control id definitions
* Update computation of min scratch buffer size requirement for V8 onwards
This patch series is created on top of krzk/for-next and following patch [1]
[1]: https://lkml.org/lkml/2017/1/18/136
Smitha T Murthy (11):
[media] s5p-mfc: Rename IS_MFCV8 macro
[media] s5p-mfc: Adding initial support for MFC v10.10
[media] s5p-mfc: Use min scratch buffer size
[media] s5p-mfc: Support MFCv10.10 buffer requirements
[media] s5p-mfc: Add support for HEVC decoder
[media] videodev2.h: Add v4l2 definition for HEVC
Documentation: v4l: Documentation for HEVC v4l2 definition
[media] s5p-mfc: Add VP9 decoder support
[media] s5p-mfc: Add support for HEVC encoder
[media] v4l2: Add v4l2 control IDs for HEVC encoder
Documention: v4l: Documentation for HEVC CIDs
.../devicetree/bindings/media/s5p-mfc.txt | 1 +
Documentation/media/uapi/v4l/extended-controls.rst | 190 ++++++
Documentation/media/uapi/v4l/pixfmt-013.rst | 5 +
drivers/media/platform/s5p-mfc/regs-mfc-v10.h | 84 +++
drivers/media/platform/s5p-mfc/regs-mfc-v8.h | 2 +
drivers/media/platform/s5p-mfc/s5p_mfc.c | 33 +
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 9 +
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 64 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 6 +-
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 62 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 623 +++++++++++++++++++-
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 14 +
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 420 ++++++++++++--
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 16 +
drivers/media/v4l2-core/v4l2-ctrls.c | 51 ++
include/uapi/linux/v4l2-controls.h | 109 ++++
include/uapi/linux/videodev2.h | 1 +
17 files changed, 1613 insertions(+), 77 deletions(-)
create mode 100644 drivers/media/platform/s5p-mfc/regs-mfc-v10.h
--
1.7.2.3
^ permalink raw reply
* [PATCH 01/11] [media] s5p-mfc: Rename IS_MFCV8 macro
From: Smitha T Murthy @ 2017-01-18 10:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
This patch renames macro IS_MFCV8 to IS_MFCV8_PLUS so that the MFCv8
code can be resued for MFCv10.10 support. Since the MFCv8 specific code
holds good for MFC v10.10 also.
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 2 +-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 2 +-
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 2 +-
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 18 +++++++++---------
4 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index ab23236..b45d18c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -722,7 +722,7 @@ struct mfc_control {
#define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0)
#define IS_MFCV6_PLUS(dev) (dev->variant->version >= 0x60 ? 1 : 0)
#define IS_MFCV7_PLUS(dev) (dev->variant->version >= 0x70 ? 1 : 0)
-#define IS_MFCV8(dev) (dev->variant->version >= 0x80 ? 1 : 0)
+#define IS_MFCV8_PLUS(dev) (dev->variant->version >= 0x80 ? 1 : 0)
#define MFC_V5_BIT BIT(0)
#define MFC_V6_BIT BIT(1)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index cc88871..484af6b 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -427,7 +427,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
s5p_mfc_clear_cmds(dev);
s5p_mfc_clean_dev_int_flags(dev);
/* 3. Send MFC wakeup command and wait for completion*/
- if (IS_MFCV8(dev))
+ if (IS_MFCV8_PLUS(dev))
ret = s5p_mfc_v8_wait_wakeup(dev);
else
ret = s5p_mfc_wait_wakeup(dev);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 367ef8e..0ec2928 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -1177,7 +1177,7 @@ void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
struct v4l2_format f;
f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
- if (IS_MFCV8(ctx->dev))
+ if (IS_MFCV8_PLUS(ctx->dev))
f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
else if (IS_MFCV6_PLUS(ctx->dev))
f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 57da798..0572521 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -74,7 +74,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->luma_size, ctx->chroma_size, ctx->mv_size);
mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
} else if (ctx->type == MFCINST_ENCODER) {
- if (IS_MFCV8(dev))
+ if (IS_MFCV8_PLUS(dev))
ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V8(mb_width, mb_height),
S5P_FIMV_TMV_BUFFER_ALIGN_V6);
@@ -89,7 +89,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
- if (IS_MFCV8(dev))
+ if (IS_MFCV8_PLUS(dev))
ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V8(
ctx->img_width, ctx->img_height,
mb_width, mb_height),
@@ -110,7 +110,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
switch (ctx->codec_mode) {
case S5P_MFC_CODEC_H264_DEC:
case S5P_MFC_CODEC_H264_MVC_DEC:
- if (IS_MFCV8(dev))
+ if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(
mb_width,
@@ -167,7 +167,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->bank1.size = ctx->scratch_buf_size;
break;
case S5P_MFC_CODEC_VP8_DEC:
- if (IS_MFCV8(dev))
+ if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(
mb_width,
@@ -182,7 +182,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->bank1.size = ctx->scratch_buf_size;
break;
case S5P_MFC_CODEC_H264_ENC:
- if (IS_MFCV8(dev))
+ if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(
mb_width,
@@ -215,7 +215,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->bank2.size = 0;
break;
case S5P_MFC_CODEC_VP8_ENC:
- if (IS_MFCV8(dev))
+ if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(
mb_width,
@@ -366,7 +366,7 @@ static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
- if (IS_MFCV8(ctx->dev)) {
+ if (IS_MFCV8_PLUS(ctx->dev)) {
/* MFCv8 needs additional 64 bytes for luma,chroma dpb*/
ctx->luma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8;
ctx->chroma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8;
@@ -454,7 +454,7 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
writel(buf_addr1, mfc_regs->d_scratch_buffer_addr);
writel(ctx->scratch_buf_size, mfc_regs->d_scratch_buffer_size);
- if (IS_MFCV8(dev)) {
+ if (IS_MFCV8_PLUS(dev)) {
writel(ctx->img_width,
mfc_regs->d_first_plane_dpb_stride_size);
writel(ctx->img_width,
@@ -2120,7 +2120,7 @@ static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7);
R(e_vp8_options, S5P_FIMV_E_VP8_OPTIONS_V7);
- if (!IS_MFCV8(dev))
+ if (!IS_MFCV8_PLUS(dev))
goto done;
/* Initialize registers used in MFC v8 only.
--
1.7.2.3
^ permalink raw reply related
* [PATCH 02/11] [media] s5p-mfc: Adding initial support for MFC v10.10
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Adding the support for MFC v10.10, with new register file and
necessary hw control, decoder, encoder and structural changes.
CC: Rob Herring <robh+dt@kernel.org>
CC: devicetree at vger.kernel.org
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
.../devicetree/bindings/media/s5p-mfc.txt | 1 +
drivers/media/platform/s5p-mfc/regs-mfc-v10.h | 36 ++++++++++++++++
drivers/media/platform/s5p-mfc/s5p_mfc.c | 30 +++++++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 4 +-
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 4 ++
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 44 +++++++++++---------
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 21 +++++----
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 9 +++-
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 2 +
9 files changed, 118 insertions(+), 33 deletions(-)
create mode 100644 drivers/media/platform/s5p-mfc/regs-mfc-v10.h
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt
index 2c90128..b70c613 100644
--- a/Documentation/devicetree/bindings/media/s5p-mfc.txt
+++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt
@@ -13,6 +13,7 @@ Required properties:
(c) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC
(d) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC
(e) "samsung,exynos5433-mfc" for MFC v8 present in Exynos5433 SoC
+ (f) "samsung,mfc-v10" for MFC v10 present in a variant of Exynos7 SoC
- reg : Physical base address of the IP registers and length of memory
mapped region.
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
new file mode 100644
index 0000000..bd671a5
--- /dev/null
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
@@ -0,0 +1,36 @@
+/*
+ * Register definition file for Samsung MFC V10.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _REGS_MFC_V10_H
+#define _REGS_MFC_V10_H
+
+#include <linux/sizes.h>
+#include "regs-mfc-v8.h"
+
+/* MFCv10 register definitions*/
+#define S5P_FIMV_MFC_CLOCK_OFF_V10 0x7120
+#define S5P_FIMV_MFC_STATE_V10 0x7124
+
+/* MFCv10 Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V10 (30 * SZ_1K) /* 30KB */
+#define MFC_H264_DEC_CTX_BUF_SIZE_V10 (2 * SZ_1M) /* 2MB */
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V10 (20 * SZ_1K) /* 20KB */
+#define MFC_H264_ENC_CTX_BUF_SIZE_V10 (100 * SZ_1K) /* 100KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V10 (15 * SZ_1K) /* 15KB */
+
+/* MFCv10 variant defines */
+#define MAX_FW_SIZE_V10 (SZ_1M) /* 1MB */
+#define MAX_CPB_SIZE_V10 (3 * SZ_1M) /* 3MB */
+#define MFC_VERSION_V10 0xA0
+#define MFC_NUM_PORTS_V10 1
+
+#endif /*_REGS_MFC_V10_H*/
+
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index bb0a588..a043cce 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1542,6 +1542,33 @@ static int s5p_mfc_resume(struct device *dev)
.num_clocks = 3,
};
+static struct s5p_mfc_buf_size_v6 mfc_buf_size_v10 = {
+ .dev_ctx = MFC_CTX_BUF_SIZE_V10,
+ .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V10,
+ .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V10,
+ .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V10,
+ .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V10,
+};
+
+static struct s5p_mfc_buf_size buf_size_v10 = {
+ .fw = MAX_FW_SIZE_V10,
+ .cpb = MAX_CPB_SIZE_V10,
+ .priv = &mfc_buf_size_v10,
+};
+
+static struct s5p_mfc_buf_align mfc_buf_align_v10 = {
+ .base = 0,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v10 = {
+ .version = MFC_VERSION_V10,
+ .version_bit = MFC_V10_BIT,
+ .port_num = MFC_NUM_PORTS_V10,
+ .buf_size = &buf_size_v10,
+ .buf_align = &mfc_buf_align_v10,
+ .fw_name[0] = "s5p-mfc-v10.fw",
+};
+
static const struct of_device_id exynos_mfc_match[] = {
{
.compatible = "samsung,mfc-v5",
@@ -1558,6 +1585,9 @@ static int s5p_mfc_resume(struct device *dev)
}, {
.compatible = "samsung,exynos5433-mfc",
.data = &mfc_drvdata_v8_5433,
+ }, {
+ .compatible = "samsung,mfc-v10",
+ .data = &mfc_drvdata_v10,
},
{},
};
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index b45d18c..1941c63 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -23,7 +23,7 @@
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-v4l2.h>
#include "regs-mfc.h"
-#include "regs-mfc-v8.h"
+#include "regs-mfc-v10.h"
#define S5P_MFC_NAME "s5p-mfc"
@@ -723,11 +723,13 @@ struct mfc_control {
#define IS_MFCV6_PLUS(dev) (dev->variant->version >= 0x60 ? 1 : 0)
#define IS_MFCV7_PLUS(dev) (dev->variant->version >= 0x70 ? 1 : 0)
#define IS_MFCV8_PLUS(dev) (dev->variant->version >= 0x80 ? 1 : 0)
+#define IS_MFCV10(dev) (dev->variant->version >= 0xA0 ? 1 : 0)
#define MFC_V5_BIT BIT(0)
#define MFC_V6_BIT BIT(1)
#define MFC_V7_BIT BIT(2)
#define MFC_V8_BIT BIT(3)
+#define MFC_V10_BIT BIT(5)
#endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 484af6b..0ded23c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -267,6 +267,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
}
else
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+
+ if (IS_MFCV10(dev))
+ mfc_write(dev, 0x0, S5P_FIMV_MFC_CLOCK_OFF_V10);
+
mfc_debug(2, "Will now wait for completion of firmware transfer\n");
if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
mfc_err("Failed to load firmware\n");
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 0ec2928..784b28e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -54,7 +54,8 @@
.codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
- .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT,
+ .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT |
+ MFC_V10_BIT,
},
{
.name = "4:2:0 2 Planes Y/CrCb",
@@ -62,7 +63,8 @@
.codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
- .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT,
+ .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT |
+ MFC_V10_BIT,
},
{
.name = "H264 Encoded Stream",
@@ -70,8 +72,8 @@
.codec_mode = S5P_MFC_CODEC_H264_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "H264/MVC Encoded Stream",
@@ -79,7 +81,8 @@
.codec_mode = S5P_MFC_CODEC_H264_MVC_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT,
+ .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT |
+ MFC_V10_BIT,
},
{
.name = "H263 Encoded Stream",
@@ -87,8 +90,8 @@
.codec_mode = S5P_MFC_CODEC_H263_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "MPEG1 Encoded Stream",
@@ -96,8 +99,8 @@
.codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "MPEG2 Encoded Stream",
@@ -105,8 +108,8 @@
.codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "MPEG4 Encoded Stream",
@@ -114,8 +117,8 @@
.codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "XviD Encoded Stream",
@@ -123,8 +126,8 @@
.codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "VC1 Encoded Stream",
@@ -132,8 +135,8 @@
.codec_mode = S5P_MFC_CODEC_VC1_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "VC1 RCV Encoded Stream",
@@ -141,8 +144,8 @@
.codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "VP8 Encoded Stream",
@@ -150,7 +153,8 @@
.codec_mode = S5P_MFC_CODEC_VP8_DEC,
.type = MFC_FMT_DEC,
.num_planes = 1,
- .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT,
+ .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT |
+ MFC_V10_BIT,
},
};
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index e39d9e0..9042378 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -57,8 +57,8 @@
.codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "4:2:0 2 Planes Y/CrCb",
@@ -66,7 +66,8 @@
.codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
- .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT,
+ .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT |
+ MFC_V10_BIT,
},
{
.name = "H264 Encoded Stream",
@@ -74,8 +75,8 @@
.codec_mode = S5P_MFC_CODEC_H264_ENC,
.type = MFC_FMT_ENC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "MPEG4 Encoded Stream",
@@ -83,8 +84,8 @@
.codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
.type = MFC_FMT_ENC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "H263 Encoded Stream",
@@ -92,8 +93,8 @@
.codec_mode = S5P_MFC_CODEC_H263_ENC,
.type = MFC_FMT_ENC,
.num_planes = 1,
- .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
- MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT |
+ MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
{
.name = "VP8 Encoded Stream",
@@ -101,7 +102,7 @@
.codec_mode = S5P_MFC_CODEC_VP8_ENC,
.type = MFC_FMT_ENC,
.num_planes = 1,
- .versions = MFC_V7_BIT | MFC_V8_BIT,
+ .versions = MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
};
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 0572521..63dce5a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -358,6 +358,7 @@ static int calc_plane(int width, int height)
static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
{
+ struct s5p_mfc_dev *dev = ctx->dev;
ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
@@ -374,8 +375,12 @@ static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
- ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
- ctx->img_height);
+ if (IS_MFCV10(dev))
+ ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V10(ctx->img_width,
+ ctx->img_height);
+ else
+ ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
+ ctx->img_height);
ctx->mv_size = ALIGN(ctx->mv_size, 16);
} else {
ctx->mv_size = 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
index 16a7b1d..fcc2368 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
@@ -24,6 +24,8 @@
#define MB_HEIGHT(y_size) DIV_ROUND_UP(y_size, 16)
#define S5P_MFC_DEC_MV_SIZE_V6(x, y) (MB_WIDTH(x) * \
(((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
+#define S5P_MFC_DEC_MV_SIZE_V10(x, y) (MB_WIDTH(x) * \
+ (((MB_HEIGHT(y)+1)/2)*2) * 64 + 512)
/* Definition */
#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
--
1.7.2.3
^ permalink raw reply related
* [PATCH 03/11] [media] s5p-mfc: Use min scratch buffer size
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
After MFC v8.0, mfc f/w lets the driver know how much scratch buffer
size is required for decoder. If mfc f/w has the functionality,
E_MIN_SCRATCH_BUFFER_SIZE, driver can know how much scratch buffer size
is required for encoder too.
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
drivers/media/platform/s5p-mfc/regs-mfc-v8.h | 2 +
drivers/media/platform/s5p-mfc/s5p_mfc.c | 2 +
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 7 ++
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 4 +
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 68 +++++++++++++++++------
6 files changed, 67 insertions(+), 17 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
index 4d1c375..2cd396b 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
@@ -17,6 +17,7 @@
/* Additional registers for v8 */
#define S5P_FIMV_D_MVC_NUM_VIEWS_V8 0xf104
+#define S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE_V8 0xf108
#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8 0xf144
#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8 0xf148
#define S5P_FIMV_D_MV_BUFFER_SIZE_V8 0xf150
@@ -84,6 +85,7 @@
#define S5P_FIMV_E_VBV_BUFFER_SIZE_V8 0xf78c
#define S5P_FIMV_E_VBV_INIT_DELAY_V8 0xf790
+#define S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE_V8 0xf894
#define S5P_FIMV_E_ASPECT_RATIO_V8 0xfb4c
#define S5P_FIMV_E_EXTENDED_SAR_V8 0xfb50
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index a043cce..b014038 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -520,6 +520,8 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
dev);
ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
dev);
+ ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
+ get_min_scratch_buf_size, dev);
if (ctx->img_width == 0 || ctx->img_height == 0)
ctx->state = MFCINST_ERROR;
else
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 1941c63..998e24b 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -724,6 +724,7 @@ struct mfc_control {
#define IS_MFCV7_PLUS(dev) (dev->variant->version >= 0x70 ? 1 : 0)
#define IS_MFCV8_PLUS(dev) (dev->variant->version >= 0x80 ? 1 : 0)
#define IS_MFCV10(dev) (dev->variant->version >= 0xA0 ? 1 : 0)
+#define FW_HAS_E_MIN_SCRATCH_BUF(dev) (IS_MFCV10(dev))
#define MFC_V5_BIT BIT(0)
#define MFC_V6_BIT BIT(1)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 9042378..ef15831 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -818,6 +818,13 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
get_enc_dpb_count, dev);
if (ctx->pb_count < enc_pb_count)
ctx->pb_count = enc_pb_count;
+ if (FW_HAS_E_MIN_SCRATCH_BUF(dev)) {
+ ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
+ get_e_min_scratch_buf_size, dev);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+ S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+ ctx->bank1.size += ctx->scratch_buf_size;
+ }
ctx->state = MFCINST_HEAD_PRODUCED;
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index b6ac417..6478f70 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -169,6 +169,7 @@ struct s5p_mfc_regs {
void __iomem *d_decoded_third_addr;/* only v7 */
void __iomem *d_used_dpb_flag_upper;/* v7 and v8 */
void __iomem *d_used_dpb_flag_lower;/* v7 and v8 */
+ void __iomem *d_min_scratch_buffer_size; /* v10 */
/* encoder registers */
void __iomem *e_frame_width;
@@ -268,6 +269,7 @@ struct s5p_mfc_regs {
void __iomem *e_vp8_hierarchical_qp_layer0;/* v7 and v8 */
void __iomem *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */
void __iomem *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */
+ void __iomem *e_min_scratch_buffer_size; /* v10 */
};
struct s5p_mfc_hw_ops {
@@ -311,6 +313,8 @@ struct s5p_mfc_hw_ops {
unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
+ int (*get_min_scratch_buf_size)(struct s5p_mfc_dev *dev);
+ int (*get_e_min_scratch_buf_size)(struct s5p_mfc_dev *dev);
};
void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 63dce5a..faceee6 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -110,7 +110,9 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
switch (ctx->codec_mode) {
case S5P_MFC_CODEC_H264_DEC:
case S5P_MFC_CODEC_H264_MVC_DEC:
- if (IS_MFCV8_PLUS(dev))
+ if (IS_MFCV10(dev))
+ mfc_debug(2, "Use min scratch buffer size\n");
+ else if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(
mb_width,
@@ -127,7 +129,9 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
(ctx->mv_count * ctx->mv_size);
break;
case S5P_MFC_CODEC_MPEG4_DEC:
- if (IS_MFCV7_PLUS(dev)) {
+ if (IS_MFCV10(dev))
+ mfc_debug(2, "Use min scratch buffer size\n");
+ else if (IS_MFCV7_PLUS(dev)) {
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(
mb_width,
@@ -145,10 +149,14 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
break;
case S5P_MFC_CODEC_VC1RCV_DEC:
case S5P_MFC_CODEC_VC1_DEC:
- ctx->scratch_buf_size =
- S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
- mb_width,
- mb_height);
+ if (IS_MFCV10(dev))
+ mfc_debug(2, "Use min scratch buffer size\n");
+ else
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
+ mb_width,
+ mb_height);
+
ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
ctx->bank1.size = ctx->scratch_buf_size;
@@ -158,16 +166,21 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->bank2.size = 0;
break;
case S5P_MFC_CODEC_H263_DEC:
- ctx->scratch_buf_size =
- S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
- mb_width,
- mb_height);
+ if (IS_MFCV10(dev))
+ mfc_debug(2, "Use min scratch buffer size\n");
+ else
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
+ mb_width,
+ mb_height);
ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
ctx->bank1.size = ctx->scratch_buf_size;
break;
case S5P_MFC_CODEC_VP8_DEC:
- if (IS_MFCV8_PLUS(dev))
+ if (IS_MFCV10(dev))
+ mfc_debug(2, "Use min scratch buffer size\n");
+ else if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(
mb_width,
@@ -182,7 +195,9 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->bank1.size = ctx->scratch_buf_size;
break;
case S5P_MFC_CODEC_H264_ENC:
- if (IS_MFCV8_PLUS(dev))
+ if (IS_MFCV10(dev)) {
+ mfc_debug(2, "Use min scratch buffer size\n");
+ } else if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(
mb_width,
@@ -202,10 +217,13 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
break;
case S5P_MFC_CODEC_MPEG4_ENC:
case S5P_MFC_CODEC_H263_ENC:
- ctx->scratch_buf_size =
- S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
- mb_width,
- mb_height);
+ if (IS_MFCV10(dev)) {
+ mfc_debug(2, "Use min scratch buffer size\n");
+ } else
+ ctx->scratch_buf_size =
+ S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
+ mb_width,
+ mb_height);
ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
ctx->bank1.size =
@@ -215,7 +233,9 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->bank2.size = 0;
break;
case S5P_MFC_CODEC_VP8_ENC:
- if (IS_MFCV8_PLUS(dev))
+ if (IS_MFCV10(dev)) {
+ mfc_debug(2, "Use min scratch buffer size\n");
+ } else if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(
mb_width,
@@ -1911,6 +1931,16 @@ static int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
return readl(dev->mfc_regs->d_min_num_mv);
}
+static int s5p_mfc_get_min_scratch_buf_size(struct s5p_mfc_dev *dev)
+{
+ return readl(dev->mfc_regs->d_min_scratch_buffer_size);
+}
+
+static int s5p_mfc_get_e_min_scratch_buf_size(struct s5p_mfc_dev *dev)
+{
+ return readl(dev->mfc_regs->e_min_scratch_buffer_size);
+}
+
static int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
{
return readl(dev->mfc_regs->ret_instance_id);
@@ -2169,6 +2199,7 @@ static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8);
R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V8);
R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V8);
+ R(d_min_scratch_buffer_size, S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE_V8);
/* encoder registers */
R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V8);
@@ -2184,6 +2215,7 @@ static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V8);
R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V8);
R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V8);
+ R(e_min_scratch_buffer_size, S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE_V8);
done:
return &mfc_regs;
@@ -2232,6 +2264,8 @@ static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
.get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6,
.get_crop_info_h = s5p_mfc_get_crop_info_h_v6,
.get_crop_info_v = s5p_mfc_get_crop_info_v_v6,
+ .get_min_scratch_buf_size = s5p_mfc_get_min_scratch_buf_size,
+ .get_e_min_scratch_buf_size = s5p_mfc_get_e_min_scratch_buf_size,
};
struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void)
--
1.7.2.3
^ permalink raw reply related
* [PATCH 04/11] [media] s5p-mfc: Support MFCv10.10 buffer requirements
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Aligning the luma_dpb_size, chroma_dpb_size, mv_size and me_buffer_size
for MFCv10.10.
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
drivers/media/platform/s5p-mfc/regs-mfc-v10.h | 13 +++
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 97 ++++++++++++++++++-----
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 2 +
3 files changed, 91 insertions(+), 21 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
index bd671a5..153ee68 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
@@ -32,5 +32,18 @@
#define MFC_VERSION_V10 0xA0
#define MFC_NUM_PORTS_V10 1
+/* Encoder buffer size for MFC v10.0 */
+#define ENC_V100_H264_ME_SIZE(x, y) \
+ (((x + 3) * (y + 3) * 8) \
+ + ((((x * y) + 63) / 64) * 32) \
+ + (((y * 64) + 1280) * (x + 7) / 8))
+#define ENC_V100_MPEG4_ME_SIZE(x, y) \
+ (((x + 3) * (y + 3) * 8) \
+ + ((((x * y) + 127) / 128) * 16) \
+ + (((y * 64) + 1280) * (x + 7) / 8))
+#define ENC_V100_VP8_ME_SIZE(x, y) \
+ (((x + 3) * (y + 3) * 8) \
+ + (((y * 64) + 1280) * (x + 7) / 8))
+
#endif /*_REGS_MFC_V10_H*/
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index faceee6..369210a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -64,6 +64,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
unsigned int mb_width, mb_height;
+ unsigned int lcu_width = 0, lcu_height = 0;
int ret;
mb_width = MB_WIDTH(ctx->img_width);
@@ -74,7 +75,9 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->luma_size, ctx->chroma_size, ctx->mv_size);
mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
} else if (ctx->type == MFCINST_ENCODER) {
- if (IS_MFCV8_PLUS(dev))
+ if (IS_MFCV10(dev)) {
+ ctx->tmv_buffer_size = 0;
+ } else if (IS_MFCV8_PLUS(dev))
ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V8(mb_width, mb_height),
S5P_FIMV_TMV_BUFFER_ALIGN_V6);
@@ -82,13 +85,36 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height),
S5P_FIMV_TMV_BUFFER_ALIGN_V6);
-
- ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
- S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
- S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
- ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
- S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
- S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
+ if (IS_MFCV10(dev)) {
+ lcu_width = enc_lcu_width(ctx->img_width);
+ lcu_height = enc_lcu_height(ctx->img_height);
+ if (ctx->codec_mode != S5P_FIMV_CODEC_HEVC_ENC) {
+ ctx->luma_dpb_size =
+ ALIGN((((mb_width * 16) + 63) / 64)
+ * 64 * (((mb_height * 16) + 31)
+ / 32) * 32 + 64, 64);
+ ctx->chroma_dpb_size =
+ ALIGN((((mb_width * 16) + 63) / 64)
+ * 64 * (mb_height * 8)
+ + 64, 64);
+ } else {
+ ctx->luma_dpb_size =
+ ALIGN((((lcu_width * 32) + 63) / 64)
+ * 64 * (((lcu_height * 32) + 31)
+ / 32) * 32 + 64, 64);
+ ctx->chroma_dpb_size =
+ ALIGN((((lcu_width * 32) + 63) / 64)
+ * 64 * (lcu_height * 16)
+ + 64, 64);
+ }
+ } else {
+ ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
+ S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
+ S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
+ ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
+ S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
+ S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
+ }
if (IS_MFCV8_PLUS(dev))
ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V8(
ctx->img_width, ctx->img_height,
@@ -197,6 +223,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_H264_ENC:
if (IS_MFCV10(dev)) {
mfc_debug(2, "Use min scratch buffer size\n");
+ ctx->me_buffer_size =
+ ALIGN(ENC_V100_H264_ME_SIZE(mb_width, mb_height), 16);
} else if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(
@@ -219,6 +247,9 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_H263_ENC:
if (IS_MFCV10(dev)) {
mfc_debug(2, "Use min scratch buffer size\n");
+ ctx->me_buffer_size =
+ ALIGN(ENC_V100_MPEG4_ME_SIZE(mb_width,
+ mb_height), 16);
} else
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
@@ -235,7 +266,10 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_VP8_ENC:
if (IS_MFCV10(dev)) {
mfc_debug(2, "Use min scratch buffer size\n");
- } else if (IS_MFCV8_PLUS(dev))
+ ctx->me_buffer_size =
+ ALIGN(ENC_V100_VP8_ME_SIZE(mb_width, mb_height),
+ 16);
+ } else if (IS_MFCV8_PLUS(dev))
ctx->scratch_buf_size =
S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(
mb_width,
@@ -395,13 +429,15 @@ static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
- if (IS_MFCV10(dev))
+ if (IS_MFCV10(dev)) {
ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V10(ctx->img_width,
ctx->img_height);
- else
+ ctx->mv_size = ALIGN(ctx->mv_size, 32);
+ } else {
ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
ctx->img_height);
- ctx->mv_size = ALIGN(ctx->mv_size, 16);
+ ctx->mv_size = ALIGN(ctx->mv_size, 16);
+ }
} else {
ctx->mv_size = 0;
}
@@ -607,15 +643,34 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
- for (i = 0; i < ctx->pb_count; i++) {
- writel(buf_addr1, mfc_regs->e_luma_dpb + (4 * i));
- buf_addr1 += ctx->luma_dpb_size;
- writel(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i));
- buf_addr1 += ctx->chroma_dpb_size;
- writel(buf_addr1, mfc_regs->e_me_buffer + (4 * i));
- buf_addr1 += ctx->me_buffer_size;
- buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
- ctx->me_buffer_size);
+ if (IS_MFCV10(dev)) {
+ /* start address of per buffer is aligned */
+ for (i = 0; i < ctx->pb_count; i++) {
+ writel(buf_addr1, mfc_regs->e_luma_dpb + (4 * i));
+ buf_addr1 += ctx->luma_dpb_size;
+ buf_size1 -= ctx->luma_dpb_size;
+ }
+ for (i = 0; i < ctx->pb_count; i++) {
+ writel(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i));
+ buf_addr1 += ctx->chroma_dpb_size;
+ buf_size1 -= ctx->chroma_dpb_size;
+ }
+ for (i = 0; i < ctx->pb_count; i++) {
+ writel(buf_addr1, mfc_regs->e_me_buffer + (4 * i));
+ buf_addr1 += ctx->me_buffer_size;
+ buf_size1 -= ctx->me_buffer_size;
+ }
+ } else {
+ for (i = 0; i < ctx->pb_count; i++) {
+ writel(buf_addr1, mfc_regs->e_luma_dpb + (4 * i));
+ buf_addr1 += ctx->luma_dpb_size;
+ writel(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i));
+ buf_addr1 += ctx->chroma_dpb_size;
+ writel(buf_addr1, mfc_regs->e_me_buffer + (4 * i));
+ buf_addr1 += ctx->me_buffer_size;
+ buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size
+ + ctx->me_buffer_size);
+ }
}
writel(buf_addr1, mfc_regs->e_scratch_buffer_addr);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
index fcc2368..2b5a9f4 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
@@ -26,6 +26,8 @@
(((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
#define S5P_MFC_DEC_MV_SIZE_V10(x, y) (MB_WIDTH(x) * \
(((MB_HEIGHT(y)+1)/2)*2) * 64 + 512)
+#define enc_lcu_width(x_size) ((x_size + 31) / 32)
+#define enc_lcu_height(y_size) ((y_size + 31) / 32)
/* Definition */
#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
--
1.7.2.3
^ permalink raw reply related
* [PATCH 05/11] [media] s5p-mfc: Add support for HEVC decoder
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Add support for codec definition and corresponding buffer
requirements for HEVC decoder.
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
drivers/media/platform/s5p-mfc/regs-mfc-v10.h | 3 +++
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 3 +++
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 8 ++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 18 ++++++++++++++++--
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 5 +++++
6 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
index 153ee68..a57009a 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
@@ -32,6 +32,9 @@
#define MFC_VERSION_V10 0xA0
#define MFC_NUM_PORTS_V10 1
+/* MFCv10 codec defines*/
+#define S5P_FIMV_CODEC_HEVC_DEC 17
+
/* Encoder buffer size for MFC v10.0 */
#define ENC_V100_H264_ME_SIZE(x, y) \
(((x + 3) * (y + 3) * 8) \
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
index b1b1491..76eca67 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
@@ -101,6 +101,9 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_VP8_DEC:
codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
break;
+ case S5P_MFC_CODEC_HEVC_DEC:
+ codec_type = S5P_FIMV_CODEC_HEVC_DEC;
+ break;
case S5P_MFC_CODEC_H264_ENC:
codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
break;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 998e24b..5c46060 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -79,6 +79,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
#define S5P_MFC_CODEC_H263_DEC 5
#define S5P_MFC_CODEC_VC1RCV_DEC 6
#define S5P_MFC_CODEC_VP8_DEC 7
+#define S5P_MFC_CODEC_HEVC_DEC 17
#define S5P_MFC_CODEC_H264_ENC 20
#define S5P_MFC_CODEC_H264_MVC_ENC 21
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 784b28e..9f459b3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -156,6 +156,14 @@
.versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT |
MFC_V10_BIT,
},
+ {
+ .name = "HEVC Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_HEVC,
+ .codec_mode = S5P_FIMV_CODEC_HEVC_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
+ .versions = MFC_V10_BIT,
+ },
};
#define NUM_FORMATS ARRAY_SIZE(formats)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 369210a..b6cb280 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -220,6 +220,13 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
ctx->bank1.size = ctx->scratch_buf_size;
break;
+ case S5P_MFC_CODEC_HEVC_DEC:
+ mfc_debug(2, "Use min scratch buffer size\n");
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+ ctx->bank1.size =
+ ctx->scratch_buf_size +
+ (ctx->mv_count * ctx->mv_size);
+ break;
case S5P_MFC_CODEC_H264_ENC:
if (IS_MFCV10(dev)) {
mfc_debug(2, "Use min scratch buffer size\n");
@@ -322,6 +329,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
switch (ctx->codec_mode) {
case S5P_MFC_CODEC_H264_DEC:
case S5P_MFC_CODEC_H264_MVC_DEC:
+ case S5P_MFC_CODEC_HEVC_DEC:
ctx->ctx.size = buf_size->h264_dec_ctx;
break;
case S5P_MFC_CODEC_MPEG4_DEC:
@@ -438,6 +446,10 @@ static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
ctx->img_height);
ctx->mv_size = ALIGN(ctx->mv_size, 16);
}
+ } else if (ctx->codec_mode == S5P_MFC_CODEC_HEVC_DEC) {
+ ctx->mv_size = s5p_mfc_dec_hevc_mv_size(ctx->img_width,
+ ctx->img_height);
+ ctx->mv_size = ALIGN(ctx->mv_size, 32);
} else {
ctx->mv_size = 0;
}
@@ -526,7 +538,8 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
buf_size1 -= ctx->scratch_buf_size;
if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
- ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){
+ ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC ||
+ ctx->codec_mode == S5P_FIMV_CODEC_HEVC_DEC) {
writel(ctx->mv_size, mfc_regs->d_mv_buffer_size);
writel(ctx->mv_count, mfc_regs->d_num_mv);
}
@@ -549,7 +562,8 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
mfc_regs->d_second_plane_dpb + i * 4);
}
if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
- ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+ ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC ||
+ ctx->codec_mode == S5P_MFC_CODEC_HEVC_DEC) {
for (i = 0; i < ctx->mv_count; i++) {
/* To test alignment */
align_gap = buf_addr1;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
index 2b5a9f4..2e404d8 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
@@ -29,6 +29,11 @@
#define enc_lcu_width(x_size) ((x_size + 31) / 32)
#define enc_lcu_height(y_size) ((y_size + 31) / 32)
+#define dec_lcu_width(x_size) ((x_size + 63) / 64)
+#define dec_lcu_height(y_size) ((y_size + 63) / 64)
+#define s5p_mfc_dec_hevc_mv_size(x, y) \
+ (dec_lcu_width(x) * dec_lcu_height(y) * 256 + 512)
+
/* Definition */
#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
#define ENC_MULTI_SLICE_BIT_MIN 2800
--
1.7.2.3
^ permalink raw reply related
* [PATCH 06/11] [media] videodev2.h: Add v4l2 definition for HEVC
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Add V4L2 definition for HEVC compressed format
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
include/uapi/linux/videodev2.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 46e8a2e3..620e941 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -630,6 +630,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
#define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0') /* VP9 */
+#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC */
/* Vendor-specific formats */
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
--
1.7.2.3
^ permalink raw reply related
* [PATCH 08/11] [media] s5p-mfc: Add VP9 decoder support
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Add support for codec definition and corresponding buffer
requirements for VP9 decoder.
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
drivers/media/platform/s5p-mfc/regs-mfc-v10.h | 6 +++++
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 3 ++
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 8 ++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 2 +
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 28 +++++++++++++++++++++++
6 files changed, 48 insertions(+), 0 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
index a57009a..81a0a96 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
@@ -18,6 +18,8 @@
/* MFCv10 register definitions*/
#define S5P_FIMV_MFC_CLOCK_OFF_V10 0x7120
#define S5P_FIMV_MFC_STATE_V10 0x7124
+#define S5P_FIMV_D_STATIC_BUFFER_ADDR_V10 0xF570
+#define S5P_FIMV_D_STATIC_BUFFER_SIZE_V10 0xF574
/* MFCv10 Context buffer sizes */
#define MFC_CTX_BUF_SIZE_V10 (30 * SZ_1K) /* 30KB */
@@ -34,6 +36,10 @@
/* MFCv10 codec defines*/
#define S5P_FIMV_CODEC_HEVC_DEC 17
+#define S5P_FIMV_CODEC_VP9_DEC 18
+
+/* Decoder buffer size for MFC v10 */
+#define DEC_VP9_STATIC_BUFFER_SIZE 20480
/* Encoder buffer size for MFC v10.0 */
#define ENC_V100_H264_ME_SIZE(x, y) \
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
index 76eca67..102b47e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
@@ -104,6 +104,9 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_HEVC_DEC:
codec_type = S5P_FIMV_CODEC_HEVC_DEC;
break;
+ case S5P_MFC_CODEC_VP9_DEC:
+ codec_type = S5P_FIMV_CODEC_VP9_DEC;
+ break;
case S5P_MFC_CODEC_H264_ENC:
codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
break;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 5c46060..e720ce6 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -80,6 +80,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
#define S5P_MFC_CODEC_VC1RCV_DEC 6
#define S5P_MFC_CODEC_VP8_DEC 7
#define S5P_MFC_CODEC_HEVC_DEC 17
+#define S5P_MFC_CODEC_VP9_DEC 18
#define S5P_MFC_CODEC_H264_ENC 20
#define S5P_MFC_CODEC_H264_MVC_ENC 21
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 9f459b3..93626ed 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -164,6 +164,14 @@
.num_planes = 1,
.versions = MFC_V10_BIT,
},
+ {
+ .name = "VP9 Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_VP9,
+ .codec_mode = S5P_FIMV_CODEC_VP9_DEC,
+ .type = MFC_FMT_DEC,
+ .num_planes = 1,
+ .versions = MFC_V10_BIT,
+ },
};
#define NUM_FORMATS ARRAY_SIZE(formats)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index 6478f70..565decf 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -170,6 +170,8 @@ struct s5p_mfc_regs {
void __iomem *d_used_dpb_flag_upper;/* v7 and v8 */
void __iomem *d_used_dpb_flag_lower;/* v7 and v8 */
void __iomem *d_min_scratch_buffer_size; /* v10 */
+ void __iomem *d_static_buffer_addr; /* v10 */
+ void __iomem *d_static_buffer_size; /* v10 */
/* encoder registers */
void __iomem *e_frame_width;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index b6cb280..da4202f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -227,6 +227,13 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->scratch_buf_size +
(ctx->mv_count * ctx->mv_size);
break;
+ case S5P_MFC_CODEC_VP9_DEC:
+ mfc_debug(2, "Use min scratch buffer size\n");
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+ ctx->bank1.size =
+ ctx->scratch_buf_size +
+ DEC_VP9_STATIC_BUFFER_SIZE;
+ break;
case S5P_MFC_CODEC_H264_ENC:
if (IS_MFCV10(dev)) {
mfc_debug(2, "Use min scratch buffer size\n");
@@ -338,6 +345,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_VC1_DEC:
case S5P_MFC_CODEC_MPEG2_DEC:
case S5P_MFC_CODEC_VP8_DEC:
+ case S5P_MFC_CODEC_VP9_DEC:
ctx->ctx.size = buf_size->other_dec_ctx;
break;
case S5P_MFC_CODEC_H264_ENC:
@@ -579,6 +587,14 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
}
}
+ if (ctx->codec_mode == S5P_FIMV_CODEC_VP9_DEC) {
+ writel(buf_addr1, mfc_regs->d_static_buffer_addr);
+ writel(DEC_VP9_STATIC_BUFFER_SIZE,
+ mfc_regs->d_static_buffer_size);
+ buf_addr1 += DEC_VP9_STATIC_BUFFER_SIZE;
+ buf_size1 -= DEC_VP9_STATIC_BUFFER_SIZE;
+ }
+
mfc_debug(2, "Buf1: %zu, buf_size1: %d (frames %d)\n",
buf_addr1, buf_size1, ctx->total_dpb_count);
if (buf_size1 < 0) {
@@ -2286,6 +2302,18 @@ static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V8);
R(e_min_scratch_buffer_size, S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE_V8);
+ if (!IS_MFCV10(dev))
+ goto done;
+
+ /* Initialize registers used in MFC v10 only.
+ * Also, over-write the registers which have
+ * a different offset for MFC v10.
+ */
+
+ /* decoder registers */
+ R(d_static_buffer_addr, S5P_FIMV_D_STATIC_BUFFER_ADDR_V10);
+ R(d_static_buffer_size, S5P_FIMV_D_STATIC_BUFFER_SIZE_V10);
+
done:
return &mfc_regs;
#undef S5P_MFC_REG_ADDR
--
1.7.2.3
^ permalink raw reply related
* [PATCH 09/11] [media] s5p-mfc: Add support for HEVC encoder
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Add HEVC encoder support and necessary registers, V4L2 CIDs,
and hevc encoder parameters
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
drivers/media/platform/s5p-mfc/regs-mfc-v10.h | 28 +-
drivers/media/platform/s5p-mfc/s5p_mfc.c | 1 +
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | 3 +
drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 55 ++-
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 595 +++++++++++++++++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 8 +
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 200 ++++++++
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | 7 +
8 files changed, 895 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
index 81a0a96..914ffec 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
@@ -20,13 +20,35 @@
#define S5P_FIMV_MFC_STATE_V10 0x7124
#define S5P_FIMV_D_STATIC_BUFFER_ADDR_V10 0xF570
#define S5P_FIMV_D_STATIC_BUFFER_SIZE_V10 0xF574
+#define S5P_FIMV_E_NUM_T_LAYER_V10 0xFBAC
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0_V10 0xFBB0
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1_V10 0xFBB4
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2_V10 0xFBB8
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER3_V10 0xFBBC
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER4_V10 0xFBC0
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER5_V10 0xFBC4
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6_V10 0xFBC8
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0_V10 0xFD18
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1_V10 0xFD1C
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2_V10 0xFD20
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3_V10 0xFD24
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4_V10 0xFD28
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5_V10 0xFD2C
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6_V10 0xFD30
+#define S5P_FIMV_E_HEVC_OPTIONS_V10 0xFDD4
+#define S5P_FIMV_E_HEVC_REFRESH_PERIOD_V10 0xFDD8
+#define S5P_FIMV_E_HEVC_CHROMA_QP_OFFSET_V10 0xFDDC
+#define S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2_V10 0xFDE0
+#define S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2_V10 0xFDE4
+#define S5P_FIMV_E_HEVC_NAL_CONTROL_V10 0xFDE8
/* MFCv10 Context buffer sizes */
#define MFC_CTX_BUF_SIZE_V10 (30 * SZ_1K) /* 30KB */
#define MFC_H264_DEC_CTX_BUF_SIZE_V10 (2 * SZ_1M) /* 2MB */
#define MFC_OTHER_DEC_CTX_BUF_SIZE_V10 (20 * SZ_1K) /* 20KB */
#define MFC_H264_ENC_CTX_BUF_SIZE_V10 (100 * SZ_1K) /* 100KB */
-#define MFC_OTHER_ENC_CTX_BUF_SIZE_V10 (15 * SZ_1K) /* 15KB */
+#define MFC_HEVC_ENC_CTX_BUF_SIZE_V10 (30 * SZ_1K) /* 30KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V10 (15 * SZ_1K) /* 15KB */
/* MFCv10 variant defines */
#define MAX_FW_SIZE_V10 (SZ_1M) /* 1MB */
@@ -37,6 +59,7 @@
/* MFCv10 codec defines*/
#define S5P_FIMV_CODEC_HEVC_DEC 17
#define S5P_FIMV_CODEC_VP9_DEC 18
+#define S5P_FIMV_CODEC_HEVC_ENC 26
/* Decoder buffer size for MFC v10 */
#define DEC_VP9_STATIC_BUFFER_SIZE 20480
@@ -53,6 +76,9 @@
#define ENC_V100_VP8_ME_SIZE(x, y) \
(((x + 3) * (y + 3) * 8) \
+ (((y * 64) + 1280) * (x + 7) / 8))
+#define ENC_V100_HEVC_ME_SIZE(x, y) \
+ (((x + 3) * (y + 3) * 32) \
+ + (((y * 128) + 1280) * (x + 3) / 4))
#endif /*_REGS_MFC_V10_H*/
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index b014038..b01c556 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1549,6 +1549,7 @@ static int s5p_mfc_resume(struct device *dev)
.h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V10,
.other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V10,
.h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V10,
+ .hevc_enc_ctx = MFC_HEVC_ENC_CTX_BUF_SIZE_V10,
.other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V10,
};
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
index 102b47e..7521fce 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
@@ -122,6 +122,9 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_VP8_ENC:
codec_type = S5P_FIMV_CODEC_VP8_ENC_V7;
break;
+ case S5P_MFC_CODEC_HEVC_ENC:
+ codec_type = S5P_FIMV_CODEC_HEVC_ENC;
+ break;
default:
codec_type = S5P_FIMV_CODEC_NONE_V6;
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index e720ce6..9eec446 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -68,7 +68,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
#define MFC_ENC_CAP_PLANE_COUNT 1
#define MFC_ENC_OUT_PLANE_COUNT 2
#define STUFF_BYTE 4
-#define MFC_MAX_CTRLS 77
+#define MFC_MAX_CTRLS 128
#define S5P_MFC_CODEC_NONE -1
#define S5P_MFC_CODEC_H264_DEC 0
@@ -87,6 +87,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
#define S5P_MFC_CODEC_MPEG4_ENC 22
#define S5P_MFC_CODEC_H263_ENC 23
#define S5P_MFC_CODEC_VP8_ENC 24
+#define S5P_MFC_CODEC_HEVC_ENC 26
#define S5P_MFC_R2H_CMD_EMPTY 0
#define S5P_MFC_R2H_CMD_SYS_INIT_RET 1
@@ -222,6 +223,7 @@ struct s5p_mfc_buf_size_v6 {
unsigned int h264_dec_ctx;
unsigned int other_dec_ctx;
unsigned int h264_enc_ctx;
+ unsigned int hevc_enc_ctx;
unsigned int other_enc_ctx;
};
@@ -440,6 +442,56 @@ struct s5p_mfc_vp8_enc_params {
u8 profile;
};
+struct s5p_mfc_hevc_enc_params {
+ u8 level;
+ u8 tier_flag;
+ /* HEVC Only */
+ u32 rc_framerate;
+ u8 rc_min_qp;
+ u8 rc_max_qp;
+ u8 rc_lcu_dark;
+ u8 rc_lcu_smooth;
+ u8 rc_lcu_static;
+ u8 rc_lcu_activity;
+ u8 rc_frame_qp;
+ u8 rc_p_frame_qp;
+ u8 rc_b_frame_qp;
+ u8 max_partition_depth;
+ u8 num_refs_for_p;
+ u8 refreshtype;
+ u16 refreshperiod;
+ s32 lf_beta_offset_div2;
+ s32 lf_tc_offset_div2;
+ u8 loopfilter_disable;
+ u8 loopfilter_across;
+ u8 nal_control_length_filed;
+ u8 nal_control_user_ref;
+ u8 nal_control_store_ref;
+ u8 const_intra_period_enable;
+ u8 lossless_cu_enable;
+ u8 wavefront_enable;
+ u8 enable_ltr;
+ u8 hier_qp_enable;
+ enum v4l2_mpeg_video_hevc_hier_coding_type hier_qp_type;
+ u8 hier_ref_type;
+ u8 num_hier_layer;
+ u8 hier_qp_layer[7];
+ u32 hier_bit_layer[7];
+ u8 sign_data_hiding;
+ u8 general_pb_enable;
+ u8 temporal_id_enable;
+ u8 strong_intra_smooth;
+ u8 intra_pu_split_disable;
+ u8 tmv_prediction_disable;
+ u8 max_num_merge_mv;
+ u8 eco_mode_enable;
+ u8 encoding_nostartcode_enable;
+ u8 size_of_length_field;
+ u8 user_ref;
+ u8 store_ref;
+ u8 prepend_sps_pps_to_idr;
+};
+
/**
* struct s5p_mfc_enc_params - general encoding parameters
*/
@@ -477,6 +529,7 @@ struct s5p_mfc_enc_params {
struct s5p_mfc_h264_enc_params h264;
struct s5p_mfc_mpeg4_enc_params mpeg4;
struct s5p_mfc_vp8_enc_params vp8;
+ struct s5p_mfc_hevc_enc_params hevc;
} codec;
};
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index ef15831..72da776 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -104,6 +104,14 @@
.num_planes = 1,
.versions = MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT,
},
+ {
+ .name = "HEVC Encoded Stream",
+ .fourcc = V4L2_PIX_FMT_HEVC,
+ .codec_mode = S5P_FIMV_CODEC_HEVC_ENC,
+ .type = MFC_FMT_ENC,
+ .num_planes = 1,
+ .versions = MFC_V10_BIT,
+ },
};
#define NUM_FORMATS ARRAY_SIZE(formats)
@@ -698,6 +706,447 @@
.default_value = 0,
},
{
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Frame QP value",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC P frame QP value",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC B frame QP value",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Minimum QP value",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Maximum QP value",
+ .minimum = 0,
+ .maximum = 51,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_DARK,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC dark region adaptive",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC smooth region adaptive",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_STATIC,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC static region adaptive",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC activity adaptive",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC Profile",
+ .minimum = 0,
+ .maximum = 0,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC level",
+ .minimum = 10,
+ .maximum = 62,
+ .step = 1,
+ .default_value = 10,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC tier_flag default is Main",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_RC_FRAME_RATE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Frame rate",
+ .minimum = 1,
+ .maximum = (1 << 16) - 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC Maximum coding unit depth",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Number of reference picture",
+ .minimum = 1,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Number of reference picture",
+ .minimum = 0,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC refresh type",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC lossless encoding select",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC Wavefront enable",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_DISABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC Filter disable",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_SLICE_BOUNDARY,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "across or not slice boundary",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LTR_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "long term reference enable",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "QP values for temporal layer",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Hierarchical Coding Type",
+ .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
+ .maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer",
+ .minimum = 0,
+ .maximum = 7,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer QP",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT0",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT1",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT2",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT3",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT4",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT5",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer BIT6",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hierarchical Coding Layer Change",
+ .minimum = INT_MIN,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SIGN_DATA_HIDING,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC Sign data hiding",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC General pb enable",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC Temporal id enable",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOTHING_FLAG,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC Strong intra smoothing flag",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC disable intra pu split",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_TMV_PREDICTION,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "HEVC disable tmv prediction",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "max number of candidate MVs",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "ENC without startcode enable",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC Number of reference picture",
+ .minimum = 0,
+ .maximum = (1 << 16) - 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC loop filter beta offset",
+ .minimum = -6,
+ .maximum = 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC loop filter tc offset",
+ .minimum = -6,
+ .maximum = 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HEVC size of length field",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_USER_REF,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "user long term reference frame",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_STORE_REF,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "store long term reference frame",
+ .minimum = 0,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Prepend SPS/PPS to every IDR",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ {
.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Minimum number of output bufs",
@@ -1642,6 +2091,152 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:
p->codec.vp8.profile = ctrl->val;
break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
+ p->codec.hevc.rc_frame_qp = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
+ p->codec.hevc.rc_p_frame_qp = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
+ p->codec.hevc.rc_b_frame_qp = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_RC_FRAME_RATE:
+ p->codec.hevc.rc_framerate = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+ p->codec.hevc.rc_min_qp = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+ p->codec.hevc.rc_max_qp = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
+ p->codec.hevc.level = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_DARK:
+ p->codec.hevc.rc_lcu_dark = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH:
+ p->codec.hevc.rc_lcu_smooth = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_STATIC:
+ p->codec.hevc.rc_lcu_static = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY:
+ p->codec.hevc.rc_lcu_activity = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG:
+ p->codec.hevc.tier_flag = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH:
+ p->codec.hevc.max_partition_depth = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES:
+ p->codec.hevc.num_refs_for_p = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE:
+ p->codec.hevc.refreshtype = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE:
+ p->codec.hevc.const_intra_period_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU_ENABLE:
+ p->codec.hevc.lossless_cu_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT_ENABLE:
+ p->codec.hevc.wavefront_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_DISABLE:
+ p->codec.hevc.loopfilter_disable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_SLICE_BOUNDARY:
+ p->codec.hevc.loopfilter_across = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LTR_ENABLE:
+ p->codec.hevc.enable_ltr = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE:
+ p->codec.hevc.hier_qp_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE:
+ p->codec.hevc.hier_qp_type =
+ (enum v4l2_mpeg_video_hevc_hier_coding_type)(ctrl->val);
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER:
+ p->codec.hevc.num_hier_layer = ctrl->val & 0x7;
+ p->codec.hevc.hier_ref_type = (ctrl->val >> 16) & 0x1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP:
+ p->codec.hevc.hier_qp_layer[(ctrl->val >> 16) & 0x7]
+ = ctrl->val & 0xFF;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0:
+ p->codec.hevc.hier_bit_layer[0] = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1:
+ p->codec.hevc.hier_bit_layer[1] = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2:
+ p->codec.hevc.hier_bit_layer[2] = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3:
+ p->codec.hevc.hier_bit_layer[3] = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4:
+ p->codec.hevc.hier_bit_layer[4] = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5:
+ p->codec.hevc.hier_bit_layer[5] = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6:
+ p->codec.hevc.hier_bit_layer[6] = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_SIGN_DATA_HIDING:
+ p->codec.hevc.sign_data_hiding = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB_ENABLE:
+ p->codec.hevc.general_pb_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID_ENABLE:
+ p->codec.hevc.temporal_id_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOTHING_FLAG:
+ p->codec.hevc.strong_intra_smooth = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT:
+ p->codec.hevc.intra_pu_split_disable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_TMV_PREDICTION:
+ p->codec.hevc.tmv_prediction_disable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
+ p->codec.hevc.max_num_merge_mv = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE:
+ p->codec.hevc.encoding_nostartcode_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD:
+ p->codec.hevc.refreshperiod = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
+ p->codec.hevc.lf_beta_offset_div2 = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
+ p->codec.hevc.lf_tc_offset_div2 = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
+ p->codec.hevc.size_of_length_field = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_USER_REF:
+ p->codec.hevc.user_ref = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_STORE_REF:
+ p->codec.hevc.store_ref = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR:
+ p->codec.hevc.prepend_sps_pps_to_idr = ctrl->val;
+ break;
default:
v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n",
ctrl->id, ctrl->val);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index 565decf..7751272 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -272,6 +272,14 @@ struct s5p_mfc_regs {
void __iomem *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */
void __iomem *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */
void __iomem *e_min_scratch_buffer_size; /* v10 */
+ void __iomem *e_num_t_layer; /* v10 */
+ void __iomem *e_hier_qp_layer0; /* v10 */
+ void __iomem *e_hier_bit_rate_layer0; /* v10 */
+ void __iomem *e_hevc_options; /* v10 */
+ void __iomem *e_hevc_refresh_period; /* v10 */
+ void __iomem *e_hevc_lf_beta_offset_div2; /* v10 */
+ void __iomem *e_hevc_lf_tc_offset_div2; /* v10 */
+ void __iomem *e_hevc_nal_control; /* v10 */
};
struct s5p_mfc_hw_ops {
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index da4202f..733c578 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -301,6 +301,17 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->chroma_dpb_size + ctx->me_buffer_size));
ctx->bank2.size = 0;
break;
+ case S5P_MFC_CODEC_HEVC_ENC:
+ mfc_debug(2, "Use min scratch buffer size\n");
+ ctx->me_buffer_size =
+ ALIGN(ENC_V100_HEVC_ME_SIZE(lcu_width, lcu_height), 16);
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+ ctx->bank1.size =
+ ctx->scratch_buf_size + ctx->tmv_buffer_size +
+ (ctx->pb_count * (ctx->luma_dpb_size +
+ ctx->chroma_dpb_size + ctx->me_buffer_size));
+ ctx->bank2.size = 0;
+ break;
default:
break;
}
@@ -351,6 +362,9 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
case S5P_MFC_CODEC_H264_ENC:
ctx->ctx.size = buf_size->h264_enc_ctx;
break;
+ case S5P_MFC_CODEC_HEVC_ENC:
+ ctx->ctx.size = buf_size->hevc_enc_ctx;
+ break;
case S5P_MFC_CODEC_MPEG4_ENC:
case S5P_MFC_CODEC_H263_ENC:
case S5P_MFC_CODEC_VP8_ENC:
@@ -1442,6 +1456,180 @@ static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
return 0;
}
+static int s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx)
+{
+ struct s5p_mfc_dev *dev = ctx->dev;
+ const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+ struct s5p_mfc_enc_params *p = &ctx->enc_params;
+ struct s5p_mfc_hevc_enc_params *p_hevc = &p->codec.hevc;
+ unsigned int reg = 0;
+ int i;
+
+ mfc_debug_enter();
+
+ s5p_mfc_set_enc_params(ctx);
+
+ /* pictype : number of B */
+ reg = readl(mfc_regs->e_gop_config);
+ /* num_b_frame - 0 ~ 2 */
+ reg &= ~(0x3 << 16);
+ reg |= (p->num_b_frame << 16);
+ writel(reg, mfc_regs->e_gop_config);
+
+ /* UHD encoding case */
+ if ((ctx->img_width == 3840) && (ctx->img_height == 2160)) {
+ p_hevc->level = 51;
+ p_hevc->tier_flag = 0;
+ /* this tier_flag can be changed */
+ }
+
+ /* tier_flag & level */
+ reg = 0;
+ /* level */
+ reg &= ~(0xFF << 8);
+ reg |= (p_hevc->level << 8);
+ /* tier_flag - 0 ~ 1 */
+ reg |= (p_hevc->tier_flag << 16);
+ writel(reg, mfc_regs->e_picture_profile);
+
+ /* max partition depth */
+ reg = 0;
+ reg |= (p_hevc->max_partition_depth & 0x1);
+ reg |= (p_hevc->num_refs_for_p-1) << 2;
+ reg |= (2 << 3); /* always set IDR encoding */
+ reg |= (p_hevc->const_intra_period_enable & 0x1) << 5;
+ reg |= (p_hevc->lossless_cu_enable & 0x1) << 6;
+ reg |= (p_hevc->wavefront_enable & 0x1) << 7;
+ reg |= (p_hevc->loopfilter_disable & 0x1) << 8;
+ reg |= (p_hevc->loopfilter_across & 0x1) << 9;
+ reg |= (p_hevc->enable_ltr & 0x1) << 10;
+ reg |= (p_hevc->hier_qp_enable & 0x1) << 11;
+ reg |= (p_hevc->sign_data_hiding & 0x1) << 12;
+ reg |= (p_hevc->general_pb_enable & 0x1) << 13;
+ reg |= (p_hevc->temporal_id_enable & 0x1) << 14;
+ reg |= (p_hevc->strong_intra_smooth & 0x1) << 15;
+ reg |= (p_hevc->intra_pu_split_disable & 0x1) << 16;
+ reg |= (p_hevc->tmv_prediction_disable & 0x1) << 17;
+ reg |= (p_hevc->max_num_merge_mv & 0x7) << 18;
+ reg |= (0 << 21); /* always eco mode disable */
+ reg |= (p_hevc->encoding_nostartcode_enable & 0x1) << 22;
+ reg |= (p_hevc->prepend_sps_pps_to_idr << 26);
+
+ writel(reg, mfc_regs->e_hevc_options);
+ /* refresh period */
+ if (p_hevc->refreshtype) {
+ reg = 0;
+ reg |= (p_hevc->refreshperiod & 0xFFFF);
+ writel(reg, mfc_regs->e_hevc_refresh_period);
+ }
+ /* loop filter setting */
+ if (!p_hevc->loopfilter_disable) {
+ reg = 0;
+ reg |= (p_hevc->lf_beta_offset_div2);
+ writel(reg, mfc_regs->e_hevc_lf_beta_offset_div2);
+ reg = 0;
+ reg |= (p_hevc->lf_tc_offset_div2);
+ writel(reg, mfc_regs->e_hevc_lf_tc_offset_div2);
+ }
+ /* long term reference */
+ if (p_hevc->enable_ltr) {
+ reg = 0;
+ reg |= (p_hevc->store_ref & 0x3);
+ reg &= ~(0x3 << 2);
+ reg |= (p_hevc->user_ref & 0x3) << 2;
+ writel(reg, mfc_regs->e_hevc_nal_control);
+ }
+ /* hier qp enable */
+ if (p_hevc->num_hier_layer) {
+ reg = 0;
+ reg |= (p_hevc->hier_qp_type & 0x1) << 0x3;
+ reg |= p_hevc->num_hier_layer & 0x7;
+ if (p_hevc->hier_ref_type) {
+ reg |= 0x1 << 7;
+ reg |= 0x3 << 4;
+ } else {
+ reg |= 0x7 << 4;
+ }
+ writel(reg, mfc_regs->e_num_t_layer);
+ /* QP value for each layer */
+ if (p_hevc->hier_qp_enable) {
+ for (i = 0; i < 7; i++)
+ writel(p_hevc->hier_qp_layer[i],
+ mfc_regs->e_hier_qp_layer0 + i * 4);
+ }
+ if (p->rc_frame) {
+ for (i = 0; i < 7; i++)
+ writel(p_hevc->hier_bit_layer[i],
+ mfc_regs->e_hier_bit_rate_layer0
+ + i * 4);
+ }
+ }
+
+ /* rate control config. */
+ reg = readl(mfc_regs->e_rc_config);
+ /* macroblock level rate control */
+ reg &= ~(0x1 << 8);
+ reg |= (p->rc_mb << 8);
+ writel(reg, mfc_regs->e_rc_config);
+ /* frame QP */
+ reg &= ~(0x3F);
+ reg |= p_hevc->rc_frame_qp;
+ writel(reg, mfc_regs->e_rc_config);
+
+ /* frame rate */
+ if (p->rc_frame) {
+ reg = 0;
+ reg &= ~(0xffff << 16);
+ reg |= ((p_hevc->rc_framerate * FRAME_DELTA_DEFAULT) << 16);
+ reg &= ~(0xffff);
+ reg |= FRAME_DELTA_DEFAULT;
+ writel(reg, mfc_regs->e_rc_frame_rate);
+ }
+
+ /* max & min value of QP */
+ reg = 0;
+ /* max QP */
+ reg &= ~(0x3F << 8);
+ reg |= (p_hevc->rc_max_qp << 8);
+ /* min QP */
+ reg &= ~(0x3F);
+ reg |= p_hevc->rc_min_qp;
+ writel(reg, mfc_regs->e_rc_qp_bound);
+
+ /* macroblock adaptive scaling features */
+ writel(0x0, mfc_regs->e_mb_rc_config);
+ if (p->rc_mb) {
+ reg = 0;
+ /* dark region */
+ reg &= ~(0x1 << 3);
+ reg |= (p_hevc->rc_lcu_dark << 3);
+ /* smooth region */
+ reg &= ~(0x1 << 2);
+ reg |= (p_hevc->rc_lcu_smooth << 2);
+ /* static region */
+ reg &= ~(0x1 << 1);
+ reg |= (p_hevc->rc_lcu_static << 1);
+ /* high activity region */
+ reg &= ~(0x1);
+ reg |= p_hevc->rc_lcu_activity;
+ writel(reg, mfc_regs->e_mb_rc_config);
+ }
+ writel(0x0, mfc_regs->e_fixed_picture_qp);
+ if (!p->rc_frame && !p->rc_mb) {
+ reg = 0;
+ reg &= ~(0x3f << 16);
+ reg |= (p_hevc->rc_b_frame_qp << 16);
+ reg &= ~(0x3f << 8);
+ reg |= (p_hevc->rc_p_frame_qp << 8);
+ reg &= ~(0x3f);
+ reg |= p_hevc->rc_frame_qp;
+ writel(reg, mfc_regs->e_fixed_picture_qp);
+ }
+ mfc_debug_leave();
+
+ return 0;
+}
+
/* Initialize decoding */
static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
{
@@ -1561,6 +1749,8 @@ static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
s5p_mfc_set_enc_params_h263(ctx);
else if (ctx->codec_mode == S5P_MFC_CODEC_VP8_ENC)
s5p_mfc_set_enc_params_vp8(ctx);
+ else if (ctx->codec_mode == S5P_FIMV_CODEC_HEVC_ENC)
+ s5p_mfc_set_enc_params_hevc(ctx);
else {
mfc_err("Unknown codec for encoding (%x).\n",
ctx->codec_mode);
@@ -2314,6 +2504,16 @@ static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
R(d_static_buffer_addr, S5P_FIMV_D_STATIC_BUFFER_ADDR_V10);
R(d_static_buffer_size, S5P_FIMV_D_STATIC_BUFFER_SIZE_V10);
+ /* encoder registers */
+ R(e_num_t_layer, S5P_FIMV_E_NUM_T_LAYER_V10);
+ R(e_hier_qp_layer0, S5P_FIMV_E_HIERARCHICAL_QP_LAYER0_V10);
+ R(e_hier_bit_rate_layer0, S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0_V10);
+ R(e_hevc_options, S5P_FIMV_E_HEVC_OPTIONS_V10);
+ R(e_hevc_refresh_period, S5P_FIMV_E_HEVC_REFRESH_PERIOD_V10);
+ R(e_hevc_lf_beta_offset_div2, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2_V10);
+ R(e_hevc_lf_tc_offset_div2, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2_V10);
+ R(e_hevc_nal_control, S5P_FIMV_E_HEVC_NAL_CONTROL_V10);
+
done:
return &mfc_regs;
#undef S5P_MFC_REG_ADDR
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
index 2e404d8..e971f3a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
@@ -48,7 +48,14 @@
#define ENC_MPEG4_VOP_TIME_RES_MAX ((1 << 16) - 1)
#define FRAME_DELTA_H264_H263 1
#define TIGHT_CBR_MAX 10
+#define ENC_HEVC_RC_FRAME_RATE_MAX ((1 << 16) - 1)
+#define ENC_HEVC_QP_INDEX_MIN -12
+#define ENC_HEVC_QP_INDEX_MAX 12
+#define ENC_HEVC_LOOP_FILTER_MIN -12
+#define ENC_HEVC_LOOP_FILTER_MAX 12
+#define ENC_HEVC_LEVEL_MAX 62
+#define FRAME_DELTA_DEFAULT 1
#define CPB_ALIGN 512
#define set_strm_size_max(cpb_max) ((cpb_max) - CPB_ALIGN)
--
1.7.2.3
^ permalink raw reply related
* [PATCH 10/11] [media] v4l2: Add v4l2 control IDs for HEVC encoder
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Add v4l2 controls for HEVC encoder
CC: Hans Verkuil <hans.verkuil@cisco.com>
CC: Wu-Cheng Li <wuchengli@chromium.org>
CC: Kieran Bingham <kieran@bingham.xyz>
CC: Vladimir Zapolskiy <vz@mleia.com>
CC: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
drivers/media/v4l2-core/v4l2-ctrls.c | 51 ++++++++++++++++
include/uapi/linux/v4l2-controls.h | 109 ++++++++++++++++++++++++++++++++++
2 files changed, 160 insertions(+), 0 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 47001e2..387439d 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -775,6 +775,57 @@ static bool is_new_manual(const struct v4l2_ctrl *master)
case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile";
+ /* HEVC controls */
+ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC Frame QP value";
+ case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: return "HEVC P frame QP value";
+ case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP: return "HEVC B frame QP value";
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP: return "HEVC Minimum QP value";
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP: return "HEVC Maximum QP value";
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_DARK: return "HEVC dark region adaptive";
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH: return "HEVC smooth region adaptive";
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_STATIC: return "HEVC static region adaptive";
+ case V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY: return "HEVC activity adaptive";
+ case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: return "HEVC Profile";
+ case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: return "HEVC level";
+ case V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG: return "HEVC tier_flag default is Main";
+ case V4L2_CID_MPEG_VIDEO_HEVC_RC_FRAME_RATE: return "HEVC Frame rate";
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH: return "HEVC Maximum coding unit depth";
+ case V4L2_CID_MPEG_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES: return "HEVC Number of reference picture";
+ case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE: return "HEVC refresh type";
+ case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE: return "HEVC constant intra prediction enabled";
+ case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU_ENABLE: return "HEVC lossless encoding select";
+ case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT_ENABLE: return "HEVC Wavefront enable";
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_DISABLE: return "HEVC Filter disable";
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_SLICE_BOUNDARY: return "across or not slice boundary";
+ case V4L2_CID_MPEG_VIDEO_HEVC_LTR_ENABLE: return "long term reference enable";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE: return "QP values for temporal layer";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE: return "Hierarchical Coding Type";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER:return "Hierarchical Coding Layer";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP:return "Hierarchical Coding Layer QP";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0:return "Hierarchical Coding Layer BIT0";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1:return "Hierarchical Coding Layer BIT1";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2:return "Hierarchical Coding Layer BIT2";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3:return "Hierarchical Coding Layer BIT3";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4:return "Hierarchical Coding Layer BIT4";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5:return "Hierarchical Coding Layer BIT5";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6:return "Hierarchical Coding Layer BIT6";
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:return "Hierarchical Coding Layer Change";
+ case V4L2_CID_MPEG_VIDEO_HEVC_SIGN_DATA_HIDING: return "HEVC Sign data hiding";
+ case V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB_ENABLE: return "HEVC General pb enable";
+ case V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID_ENABLE: return "HEVC Temporal id enable";
+ case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOTHING_FLAG: return "HEVC Strong intra smoothing flag";
+ case V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT: return "HEVC disable intra pu split";
+ case V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_TMV_PREDICTION: return "HEVC disable tmv prediction";
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1: return "max number of candidate MVs";
+ case V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE: return "ENC without startcode enable";
+ case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD: return "HEVC Number of reference picture";
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2: return "HEVC loop filter beta offset";
+ case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2: return "HEVC loop filter tc offset";
+ case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: return "HEVC size of length field";
+ case V4L2_CID_MPEG_VIDEO_HEVC_USER_REF: return "user long term reference frame";
+ case V4L2_CID_MPEG_VIDEO_HEVC_STORE_REF: return "store long term reference frame";
+ case V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS/PPS to every IDR";
+
/* CAMERA controls */
/* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_CAMERA_CLASS: return "Camera Controls";
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 0d2e1e0..a2a1c5d 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -579,6 +579,115 @@ enum v4l2_vp8_golden_frame_sel {
#define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (V4L2_CID_MPEG_BASE+510)
#define V4L2_CID_MPEG_VIDEO_VPX_PROFILE (V4L2_CID_MPEG_BASE+511)
+/* CIDs for HEVC encoding. Number gaps are for compatibility */
+
+#define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP \
+ (V4L2_CID_MPEG_BASE + 512)
+#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP \
+ (V4L2_CID_MPEG_BASE + 513)
+#define V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP \
+ (V4L2_CID_MPEG_BASE + 514)
+#define V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP \
+ (V4L2_CID_MPEG_BASE + 515)
+#define V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP \
+ (V4L2_CID_MPEG_BASE + 516)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE \
+ (V4L2_CID_MPEG_BASE + 517)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE \
+ (V4L2_CID_MPEG_BASE + 518)
+enum v4l2_mpeg_video_hevc_hier_coding_type {
+ V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B = 0,
+ V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER \
+ (V4L2_CID_MPEG_BASE + 519)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP \
+ (V4L2_CID_MPEG_BASE + 520)
+#define V4L2_CID_MPEG_VIDEO_HEVC_PROFILE \
+ (V4L2_CID_MPEG_BASE + 521)
+#define V4L2_CID_MPEG_VIDEO_HEVC_LEVEL \
+ (V4L2_CID_MPEG_BASE + 522)
+#define V4L2_CID_MPEG_VIDEO_HEVC_RC_FRAME_RATE \
+ (V4L2_CID_MPEG_BASE + 523)
+#define V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG \
+ (V4L2_CID_MPEG_BASE + 524)
+#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH \
+ (V4L2_CID_MPEG_BASE + 525)
+#define V4L2_CID_MPEG_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES \
+ (V4L2_CID_MPEG_BASE + 526)
+#define V4L2_CID_MPEG_VIDEO_HEVC_LF_DISABLE \
+ (V4L2_CID_MPEG_BASE + 527)
+#define V4L2_CID_MPEG_VIDEO_HEVC_LF_SLICE_BOUNDARY \
+ (V4L2_CID_MPEG_BASE + 528)
+#define V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2 \
+ (V4L2_CID_MPEG_BASE + 529)
+#define V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2 \
+ (V4L2_CID_MPEG_BASE + 530)
+#define V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE \
+ (V4L2_CID_MPEG_BASE + 531)
+#define V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD \
+ (V4L2_CID_MPEG_BASE + 532)
+#define V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU_ENABLE \
+ (V4L2_CID_MPEG_BASE + 533)
+#define V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE \
+ (V4L2_CID_MPEG_BASE + 534)
+#define V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT_ENABLE \
+ (V4L2_CID_MPEG_BASE + 535)
+#define V4L2_CID_MPEG_VIDEO_HEVC_LTR_ENABLE \
+ (V4L2_CID_MPEG_BASE + 536)
+#define V4L2_CID_MPEG_VIDEO_HEVC_USER_REF \
+ (V4L2_CID_MPEG_BASE + 537)
+#define V4L2_CID_MPEG_VIDEO_HEVC_STORE_REF \
+ (V4L2_CID_MPEG_BASE + 538)
+#define V4L2_CID_MPEG_VIDEO_HEVC_SIGN_DATA_HIDING \
+ (V4L2_CID_MPEG_BASE + 539)
+#define V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB_ENABLE \
+ (V4L2_CID_MPEG_BASE + 540)
+#define V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID_ENABLE \
+ (V4L2_CID_MPEG_BASE + 541)
+#define V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOTHING_FLAG \
+ (V4L2_CID_MPEG_BASE + 542)
+#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1 \
+ (V4L2_CID_MPEG_BASE + 543)
+#define V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_DARK \
+ (V4L2_CID_MPEG_BASE + 544)
+#define V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH \
+ (V4L2_CID_MPEG_BASE + 545)
+#define V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_STATIC \
+ (V4L2_CID_MPEG_BASE + 546)
+#define V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY \
+ (V4L2_CID_MPEG_BASE + 547)
+#define V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT \
+ (V4L2_CID_MPEG_BASE + 548)
+#define V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_TMV_PREDICTION \
+ (V4L2_CID_MPEG_BASE + 549)
+#define V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE \
+ (V4L2_CID_MPEG_BASE + 550)
+#define V4L2_CID_MPEG_VIDEO_HEVC_QP_INDEX_CR \
+ (V4L2_CID_MPEG_BASE + 551)
+#define V4L2_CID_MPEG_VIDEO_HEVC_QP_INDEX_CB \
+ (V4L2_CID_MPEG_BASE + 552)
+#define V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD \
+ (V4L2_CID_MPEG_BASE + 553)
+#define V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR \
+ (V4L2_CID_MPEG_BASE + 554)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH \
+ (V4L2_CID_MPEG_BASE + 555)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0 \
+ (V4L2_CID_MPEG_BASE + 556)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1 \
+ (V4L2_CID_MPEG_BASE + 557)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2 \
+ (V4L2_CID_MPEG_BASE + 558)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3 \
+ (V4L2_CID_MPEG_BASE + 559)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4 \
+ (V4L2_CID_MPEG_BASE + 560)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5 \
+ (V4L2_CID_MPEG_BASE + 561)
+#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6 \
+ (V4L2_CID_MPEG_BASE + 562)
+
/* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
#define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000)
#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0)
--
1.7.2.3
^ permalink raw reply related
* [PATCH 11/11] Documention: v4l: Documentation for HEVC CIDs
From: Smitha T Murthy @ 2017-01-18 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484733729-25371-1-git-send-email-smitha.t@samsung.com>
Added V4l2 controls for HEVC encoder
CC: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
---
Documentation/media/uapi/v4l/extended-controls.rst | 190 ++++++++++++++++++++
1 files changed, 190 insertions(+), 0 deletions(-)
diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
index abb1057..fe23919 100644
--- a/Documentation/media/uapi/v4l/extended-controls.rst
+++ b/Documentation/media/uapi/v4l/extended-controls.rst
@@ -1960,6 +1960,196 @@ enum v4l2_vp8_golden_frame_sel -
1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.
+HEVC Control Reference
+---------------------
+
+The HEVC controls include controls for encoding parameters of HEVC video
+codec.
+
+
+.. _hevc-control-id:
+
+HEVC Control IDs
+^^^^^^^^^^^^^^^
+
+``V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP``
+ Minimum quantization parameter for HEVC.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP``
+ Maximum quantization parameter for HEVC.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP``
+ Quantization parameter for an I frame for HEVC.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP``
+ Quantization parameter for a P frame for HEVC.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP``
+ Quantization parameter for a B frame for HEVC.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE``
+ Enable the QP values for temporal layer.
+
+.. _v4l2-mpeg-video-hevc-hier-coding-type:
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE``
+ (enum)
+
+enum v4l2_mpeg_video_hevc_hier_coding_type -
+ Selects the hierarchical coding type for encoding. Possible values are:
+
+.. raw:: latex
+
+ \begin{adjustbox}{width=\columnwidth}
+
+.. tabularcolumns:: |p{11.0cm}|p{10.0cm}|
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - ``V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B``
+ - Use the B frame for hierarchical coding.
+ * - ``V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P``
+ - Use the P frame for hierarchical coding.
+
+.. raw:: latex
+
+ \end{adjustbox}
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER``
+ Indicates the hierarchical coding layer.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP``
+ Indicates the hierarchical coding layer quantization parameter.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_PROFILE``
+ Select the desired profile for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_LEVEL``
+ Selects the desired level for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_RC_FRAME_RATE``
+ Selects the RC filter frame rate for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG``
+ By default selects HEVC tier_flag as Main.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH``
+ Selects HEVC Maximum coding unit depth.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES``
+ Selects number of P reference picture required for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_LF_DISABLE``
+ Disables HEVC filter.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_LF_SLICE_BOUNDARY``
+ Selects across or not slice boundary for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2``
+ Selects HEVC loop filter beta offset.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2``
+ Selects HEVC loop filter tc offset.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE``
+ Selects refresh type for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD``
+ Selects the refresh period for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU_ENABLE``
+ Selects HEVC lossless encoding.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE``
+ Enables constant intra prediction for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT_ENABLE``
+ Enables wavefront for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_LTR_ENABLE``
+ Enables long term reference for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_USER_REF``
+ Selects user long term reference frame.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_STORE_REF``
+ Stores long term reference frame.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_SIGN_DATA_HIDING``
+ Enable sign data hiding for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB_ENABLE``
+ Enable general picture buffers for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID_ENABLE``
+ Enable temporal ID for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOTHING_FLAG``
+ Enable HEVC Strong intra smoothing.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1``
+ Indicates max number of candidate motion vectors.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_DARK``
+ Indicates HEVC dark region adaptive.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH``
+ Indicates HEVC smooth region adaptive.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_STATIC``
+ Indicates HEVC static region adaptive.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY``
+ Indicates HEVC activity adaptive.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT``
+ Disables intra pu split for HEVC Encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_DISABLE_TMV_PREDICTION``
+ Disables tmv prediction for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE``
+ Enabling HEVC encoding without a startcode.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_QP_INDEX_CR``
+ Indicates the quantization parameter CR index.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_QP_INDEX_CB``
+ Indicates the quantization parameter CB index.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD``
+ Indicates size of length field for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR``
+ Indicates prepend SPS/PPS to every IDR.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH``
+ Indicates hierarchical coding layer change for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0``
+ Indicates hierarchical coding layer BIT0 for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1``
+ Indicates hierarchical coding layer BIT1 for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2``
+ Indicates hierarchical coding layer BIT2 for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3``
+ Indicates hierarchical coding layer BIT3 for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4``
+ Indicates hierarchical coding layer BIT4 for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5``
+ Indicates hierarchical coding layer BIT5 for HEVC encoder.
+
+``V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6``
+ Indicates hierarchical coding layer BIT6 for HEVC encoder.
+
+
.. _camera-controls:
Camera Control Reference
--
1.7.2.3
^ permalink raw reply related
* [PATCH] arm64: dts: hisilicon: add dtsi file for Hisilicon Hi3660 SOC
From: Wang Xiaoyin @ 2017-01-18 10:04 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds pinctrl dtsi file
Signed-off-by: Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>
---
arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 3 +-
.../arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi | 292 +++++++++++++++++++++
2 files changed, 293 insertions(+), 2 deletions(-)
create mode 100644 arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
index 9a1d36aa84ce..de21ebfa4bd8 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -8,8 +8,7 @@
/dts-v1/;
#include "hi3660.dtsi"
-/*#include "hi3660-ion.dtsi"*/
-/*#include "hikey960-pinctrl.dtsi"*/
+#include "hikey960-pinctrl.dtsi"
/ {
model = "HiKey960";
diff --git a/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi
new file mode 100644
index 000000000000..98a0b78289b6
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi
@@ -0,0 +1,292 @@
+/*
+ * pinctrl dts fils for Hislicon HiKey960 development board
+ *
+ */
+
+#include <dt-bindings/pinctrl/hisi.h>
+
+/ {
+ soc {
+ /* [IOMG_000, IOMG_123] */
+ range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+ pmx0: pinmux at e896c000 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0xe896c000 0x0 0x1f0>;
+ #pinctrl-cells = <1>;
+ #gpio-range-cells = <0x3>;
+ pinctrl-single,register-width = <0x20>;
+ pinctrl-single,function-mask = <0x7>;
+ /* pin base, nr pins & gpio function */
+ pinctrl-single,gpio-range = <
+ &range 0 7 0
+ &range 8 116 0>;
+
+ isp0_pmx_func: isp0_pmx_func {
+ pinctrl-single,pins = <
+ 0x058 MUX_M1 /* ISP_CLK0 */
+ 0x064 MUX_M1 /* ISP_SCL0 */
+ 0x068 MUX_M1 /* ISP_SDA0 */
+ >;
+ };
+
+ isp1_pmx_func: isp1_pmx_func {
+ pinctrl-single,pins = <
+ 0x05c MUX_M1 /* ISP_CLK1 */
+ 0x06c MUX_M1 /* ISP_SCL1 */
+ 0x070 MUX_M1 /* ISP_SDA1 */
+ >;
+ };
+
+ i2c3_pmx_func: i2c3_pmx_func {
+ pinctrl-single,pins = <
+ 0x02c MUX_M1 /* I2C3_SCL */
+ 0x030 MUX_M1 /* I2C3_SDA */
+ >;
+ };
+
+ i2c4_pmx_func: i2c4_pmx_func {
+ pinctrl-single,pins = <
+ 0x090 MUX_M1 /* I2C4_SCL */
+ 0x094 MUX_M1 /* I2C4_SDA */
+ >;
+ };
+
+ pcie_perstn_pmx_func: pcie_perstn_pmx_func {
+ pinctrl-single,pins = <
+ 0x15c MUX_M1 /* PCIE_PERST_N */
+ >;
+ };
+
+ usbhub5734_pmx_func: usbhub5734_pmx_func {
+ pinctrl-single,pins = <
+ 0x11c MUX_M0 /* GPIO_073 */
+ 0x120 MUX_M0 /* GPIO_074 */
+ >;
+ };
+
+ spi1_pmx_func: spi1_pmx_func {
+ pinctrl-single,pins = <
+ 0x034 MUX_M1 /* SPI1_CLK */
+ 0x038 MUX_M1 /* SPI1_DI */
+ 0x03c MUX_M1 /* SPI1_DO */
+ 0x040 MUX_M1 /* SPI1_CS_N */
+ >;
+ };
+
+ uart0_pmx_func: uart0_pmx_func {
+ pinctrl-single,pins = <
+ 0x0cc MUX_M2 /* UART0_RXD */
+ 0x0d0 MUX_M2 /* UART0_TXD */
+ 0x0d4 MUX_M2 /* UART0_RXD_M */
+ 0x0d8 MUX_M2 /* UART0_TXD_M */
+ >;
+ };
+
+ uart1_pmx_func: uart1_pmx_func {
+ pinctrl-single,pins = <
+ 0x0b0 MUX_M2 /* UART1_CTS_N */
+ 0x0b4 MUX_M2 /* UART1_RTS_N */
+ 0x0a8 MUX_M2 /* UART1_RXD */
+ 0x0ac MUX_M2 /* UART1_TXD */
+ >;
+ };
+
+ uart2_pmx_func: uart2_pmx_func {
+ pinctrl-single,pins = <
+ 0x0bc MUX_M2 /* UART2_CTS_N */
+ 0x0c0 MUX_M2 /* UART2_RTS_N */
+ 0x0c8 MUX_M2 /* UART2_RXD */
+ 0x0c4 MUX_M2 /* UART2_TXD */
+ >;
+ };
+
+ uart3_pmx_func: uart3_pmx_func {
+ pinctrl-single,pins = <
+ 0x0dc MUX_M1 /* UART3_CTS_N */
+ 0x0e0 MUX_M1 /* UART3_RTS_N */
+ 0x0e4 MUX_M1 /* UART3_RXD */
+ 0x0e8 MUX_M1 /* UART3_TXD */
+ >;
+ };
+
+ uart4_pmx_func: uart4_pmx_func {
+ pinctrl-single,pins = <
+ 0x0ec MUX_M1 /* UART4_CTS_N */
+ 0x0f0 MUX_M1 /* UART4_RTS_N */
+ 0x0f4 MUX_M1 /* UART4_RXD */
+ 0x0f8 MUX_M1 /* UART4_TXD */
+ >;
+ };
+
+ uart5_pmx_func: uart5_pmx_func {
+ pinctrl-single,pins = <
+ 0x0c4 MUX_M3 /* UART5_CTS_N */
+ 0x0c8 MUX_M3 /* UART5_RTS_N */
+ 0x0bc MUX_M3 /* UART5_RXD */
+ 0x0c0 MUX_M3 /* UART5_TXD */
+ >;
+ };
+
+ uart6_pmx_func: uart6_pmx_func {
+ pinctrl-single,pins = <
+ 0x0cc MUX_M1 /* UART6_CTS_N */
+ 0x0d0 MUX_M1 /* UART6_RTS_N */
+ 0x0d4 MUX_M1 /* UART6_RXD */
+ 0x0d8 MUX_M1 /* UART6_TXD */
+ >;
+ };
+ };
+
+ /* [IOMG_MMC0_000, IOMG_MMC0_005] */
+ pmx1: pinmux at ff37e000 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0xff37e000 0x0 0x18>;
+ #gpio-range-cells = <0x3>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <0x20>;
+ pinctrl-single,function-mask = <0x7>;
+ /* pin base, nr pins & gpio function */
+ pinctrl-single,gpio-range = <&range 0 6 0>;
+
+ sdcard_pmx_func: sdcard_pmx_func {
+ pinctrl-single,pins = <
+ 0x000 MUX_M1 /* SD_CLK */
+ 0x004 MUX_M1 /* SD_CMD */
+ 0x008 MUX_M1 /* SD_DATA0 */
+ 0x00c MUX_M1 /* SD_DATA1 */
+ 0x010 MUX_M1 /* SD_DATA2 */
+ 0x014 MUX_M1 /* SD_DATA3 */
+ >;
+ };
+ };
+
+ /* [IOMG_FIX_000, IOMG_FIX_011] */
+ pmx2: pinmux at ff3b6000 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0xff3b6000 0x0 0x30>;
+ #pinctrl-cells = <1>;
+ #gpio-range-cells = <0x3>;
+ pinctrl-single,register-width = <0x20>;
+ pinctrl-single,function-mask = <0x7>;
+ /* pin base, nr pins & gpio function */
+ pinctrl-single,gpio-range = <&range 0 12 0>;
+
+ spi3_pmx_func: spi3_pmx_func {
+ pinctrl-single,pins = <
+ 0x008 MUX_M1 /* SPI3_CLK */
+ 0x00c MUX_M1 /* SPI3_DI */
+ 0x010 MUX_M1 /* SPI3_DO */
+ 0x014 MUX_M1 /* SPI3_CS0_N */
+ >;
+ };
+ };
+
+ /* [IOMG_MMC1_000, IOMG_MMC1_005] */
+ pmx3: pinmux at ff3fd000 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0xff3fd000 0x0 0x18>;
+ #pinctrl-cells = <1>;
+ #gpio-range-cells = <0x3>;
+ pinctrl-single,register-width = <0x20>;
+ pinctrl-single,function-mask = <0x7>;
+ /* pin base, nr pins & gpio function */
+ pinctrl-single,gpio-range = <&range 0 6 0>;
+
+ sdio_pmx_func: sdio_pmx_func {
+ pinctrl-single,pins = <
+ 0x000 MUX_M1 /* SDIO_CLK */
+ 0x004 MUX_M1 /* SDIO_CMD */
+ 0x008 MUX_M1 /* SDIO_DATA0 */
+ 0x00c MUX_M1 /* SDIO_DATA1 */
+ 0x010 MUX_M1 /* SDIO_DATA2 */
+ 0x014 MUX_M1 /* SDIO_DATA3 */
+ >;
+ };
+ };
+
+ /* [IOMG_AO_000, IOMG_AO_041] */
+ pmx4: pinmux at fff11000 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0xfff11000 0x0 0xa8>;
+ #pinctrl-cells = <1>;
+ #gpio-range-cells = <0x3>;
+ pinctrl-single,register-width = <0x20>;
+ pinctrl-single,function-mask = <0x7>;
+ /* pin base in node, nr pins & gpio function */
+ pinctrl-single,gpio-range = <&range 0 42 0>;
+
+ i2s2_pmx_func: i2s2_pmx_func {
+ pinctrl-single,pins = <
+ 0x044 MUX_M1 /* I2S2_DI */
+ 0x048 MUX_M1 /* I2S2_DO */
+ 0x04c MUX_M1 /* I2S2_XCLK */
+ 0x050 MUX_M1 /* I2S2_XFS */
+ >;
+ };
+
+ slimbus_pmx_func: slimbus_pmx_func {
+ pinctrl-single,pins = <
+ 0x02c MUX_M1 /* SLIMBUS_CLK */
+ 0x030 MUX_M1 /* SLIMBUS_DATA */
+ >;
+ };
+
+ i2c0_pmx_func: i2c0_pmx_func {
+ pinctrl-single,pins = <
+ 0x014 MUX_M1 /* I2C0_SCL */
+ 0x018 MUX_M1 /* I2C0_SDA */
+ >;
+ };
+
+ i2c1_pmx_func: i2c1_pmx_func {
+ pinctrl-single,pins = <
+ 0x01c MUX_M1 /* I2C1_SCL */
+ 0x020 MUX_M1 /* I2C1_SDA */
+ >;
+ };
+
+ i2c2_pmx_func: i2c2_pmx_func {
+ pinctrl-single,pins = <
+ 0x024 MUX_M1 /* I2C2_SCL */
+ 0x028 MUX_M1 /* I2C2_SDA */
+ >;
+ };
+
+ i2c7_pmx_func: i2c7_pmx_func {
+ pinctrl-single,pins = <
+ 0x024 MUX_M3 /* I2C7_SCL */
+ 0x028 MUX_M3 /* I2C7_SDA */
+ >;
+ };
+
+ spi2_pmx_func: spi2_pmx_func {
+ pinctrl-single,pins = <
+ 0x08c MUX_M1 /* SPI2_CLK */
+ 0x090 MUX_M1 /* SPI2_DI */
+ 0x094 MUX_M1 /* SPI2_DO */
+ 0x098 MUX_M1 /* SPI2_CS0_N */
+ >;
+ };
+
+ spi4_pmx_func: spi4_pmx_func {
+ pinctrl-single,pins = <
+ 0x08c MUX_M4 /* SPI4_CLK */
+ 0x090 MUX_M4 /* SPI4_DI */
+ 0x094 MUX_M4 /* SPI4_DO */
+ 0x098 MUX_M4 /* SPI4_CS0_N */
+ >;
+ };
+
+ i2s0_pmx_func: i2s0_pmx_func {
+ pinctrl-single,pins = <
+ 0x034 MUX_M1 /* I2S0_DI */
+ 0x038 MUX_M1 /* I2S0_DO */
+ 0x03c MUX_M1 /* I2S0_XCLK */
+ 0x040 MUX_M1 /* I2S0_XFS */
+ >;
+ };
+ };
+ };
+};
--
2.11.0-rc2
^ permalink raw reply related
* [PATCH v7 4/8] PWM: add PWM driver for STM32 plaftorm
From: Thierry Reding @ 2017-01-18 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483608344-9012-5-git-send-email-benjamin.gaignard@st.com>
On Thu, Jan 05, 2017 at 10:25:40AM +0100, Benjamin Gaignard wrote:
> This driver adds support for PWM driver on STM32 platform.
> The SoC have multiple instances of the hardware IP and each
> of them could have small differences: number of channels,
> complementary output, auto reload register size...
>
> version 6:
> - change st,breakinput parameter to make it usuable for stm32f7 too.
>
> version 4:
> - detect at probe time hardware capabilities
> - fix comments done on v2 and v3
> - use PWM atomic ops
>
> version 2:
> - only keep one comptatible
> - use DT parameters to discover hardware block configuration
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
> drivers/pwm/Kconfig | 9 +
> drivers/pwm/Makefile | 1 +
> drivers/pwm/pwm-stm32.c | 434 ++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 444 insertions(+)
> create mode 100644 drivers/pwm/pwm-stm32.c
>
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index f92dd41..88035c0 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -397,6 +397,15 @@ config PWM_STI
> To compile this driver as a module, choose M here: the module
> will be called pwm-sti.
>
> +config PWM_STM32
> + tristate "STMicroelectronics STM32 PWM"
> + depends on (ARCH_STM32 && OF && MFD_STM32_TIMERS) || COMPILE_TEST
> + help
> + Generic PWM framework driver for STM32 SoCs.
> +
> + To compile this driver as a module, choose M here: the module
> + will be called pwm-stm32.
> +
> config PWM_STMPE
> bool "STMPE expander PWM export"
> depends on MFD_STMPE
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index a48bdb5..346a83b 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
> obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
> obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
> obj-$(CONFIG_PWM_STI) += pwm-sti.o
> +obj-$(CONFIG_PWM_STM32) += pwm-stm32.o
> obj-$(CONFIG_PWM_STMPE) += pwm-stmpe.o
> obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o
> obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
> diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
> new file mode 100644
> index 0000000..fcf0a78
> --- /dev/null
> +++ b/drivers/pwm/pwm-stm32.c
> @@ -0,0 +1,434 @@
> +/*
> + * Copyright (C) STMicroelectronics 2016
> + *
> + * Author: Gerald Baeza <gerald.baeza@st.com>
> + *
> + * License terms: GNU General Public License (GPL), version 2
> + *
> + * Inspired by timer-stm32.c from Maxime Coquelin
> + * pwm-atmel.c from Bo Shen
> + */
> +
> +#include <linux/mfd/stm32-timers.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/of.h>
Can you please sort these alphabetically?
> +
> +#define CCMR_CHANNEL_SHIFT 8
> +#define CCMR_CHANNEL_MASK 0xFF
> +#define MAX_BREAKINPUT 2
Okay, this answers my question regarding the st,breakinput property. I
still think it'd be good to have this in the binding documentation just
to avoid having to look at implementation to find out.
> +
> +struct stm32_pwm {
> + struct pwm_chip chip;
> + struct device *dev;
> + struct clk *clk;
> + struct regmap *regmap;
> + unsigned int caps;
This seems completely unused?
> + unsigned int npwm;
It's somewhat redundant to have this here, since the same information is
already contained in struct pwm_chip.npwm.
Since you use this primarily for detection, how about you make the
stm32_pwm_detect_channels() function return the value and store it in a
local variable in ->probe()? That might be useful also because you
need to check the return value of regmap_update_bits() which technically
could fail.
> + u32 max_arr;
> + bool have_complementary_output;
> +};
> +
> +struct stm32_breakinput {
> + u32 index;
> + u32 level;
> + u32 filter;
> +};
> +
> +static inline struct stm32_pwm *to_stm32_pwm_dev(struct pwm_chip *chip)
> +{
> + return container_of(chip, struct stm32_pwm, chip);
> +}
> +
> +static u32 active_channels(struct stm32_pwm *dev)
> +{
> + u32 ccer;
> +
> + regmap_read(dev->regmap, TIM_CCER, &ccer);
> +
> + return ccer & TIM_CCER_CCXE;
> +}
This looks like something that you could track in software, but this is
probably fine, too. Again, technically regmap_read() could fail, so you
might want to consider adding some code to handle it. In practice it
probably won't, so maybe you don't.
> +
> +static int write_ccrx(struct stm32_pwm *dev, struct pwm_device *pwm,
> + u32 value)
> +{
> + switch (pwm->hwpwm) {
> + case 0:
> + return regmap_write(dev->regmap, TIM_CCR1, value);
> + case 1:
> + return regmap_write(dev->regmap, TIM_CCR2, value);
> + case 2:
> + return regmap_write(dev->regmap, TIM_CCR3, value);
> + case 3:
> + return regmap_write(dev->regmap, TIM_CCR4, value);
> + }
> + return -EINVAL;
> +}
> +
> +static int stm32_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> + int duty_ns, int period_ns)
> +{
> + struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
> + unsigned long long prd, div, dty;
> + unsigned int prescaler = 0;
> + u32 ccmr, mask, shift;
> +
> + /* Period and prescaler values depends on clock rate */
> + div = (unsigned long long)clk_get_rate(priv->clk) * period_ns;
> +
> + do_div(div, NSEC_PER_SEC);
> + prd = div;
> +
> + while (div > priv->max_arr) {
> + prescaler++;
> + div = prd;
> + do_div(div, (prescaler + 1));
Nit: there's no need for the parentheses here.
> + }
> +
> + prd = div;
> +
> + if (prescaler > MAX_TIM_PSC) {
> + dev_err(chip->dev, "prescaler exceeds the maximum value\n");
> + return -EINVAL;
> + }
> +
> + /*
> + * All channels share the same prescaler and counter so when two
> + * channels are active at the same we can't change them
Nit: "at the same time"?
> + */
> + if (active_channels(priv) & ~(1 << pwm->hwpwm * 4)) {
> + u32 psc, arr;
> +
> + regmap_read(priv->regmap, TIM_PSC, &psc);
> + regmap_read(priv->regmap, TIM_ARR, &arr);
> +
> + if ((psc != prescaler) || (arr != prd - 1))
> + return -EBUSY;
> + }
> +
> + regmap_write(priv->regmap, TIM_PSC, prescaler);
> + regmap_write(priv->regmap, TIM_ARR, prd - 1);
> + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
> +
> + /* Calculate the duty cycles */
> + dty = prd * duty_ns;
> + do_div(dty, period_ns);
> +
> + write_ccrx(priv, pwm, dty);
> +
> + /* Configure output mode */
> + shift = (pwm->hwpwm & 0x1) * CCMR_CHANNEL_SHIFT;
> + ccmr = (TIM_CCMR_PE | TIM_CCMR_M1) << shift;
> + mask = CCMR_CHANNEL_MASK << shift;
> +
> + if (pwm->hwpwm < 2)
> + regmap_update_bits(priv->regmap, TIM_CCMR1, mask, ccmr);
> + else
> + regmap_update_bits(priv->regmap, TIM_CCMR2, mask, ccmr);
> +
> + regmap_update_bits(priv->regmap, TIM_BDTR,
> + TIM_BDTR_MOE | TIM_BDTR_AOE,
> + TIM_BDTR_MOE | TIM_BDTR_AOE);
> +
> + return 0;
> +}
> +
> +static int stm32_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
> + enum pwm_polarity polarity)
> +{
> + u32 mask;
> + struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
> +
> + mask = TIM_CCER_CC1P << (pwm->hwpwm * 4);
> + if (priv->have_complementary_output)
> + mask |= TIM_CCER_CC1NP << (pwm->hwpwm * 4);
> +
> + regmap_update_bits(priv->regmap, TIM_CCER, mask,
> + polarity == PWM_POLARITY_NORMAL ? 0 : mask);
> +
> + return 0;
> +}
> +
> +static int stm32_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> + u32 mask;
> + struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
> +
> + clk_enable(priv->clk);
This can fail, so its return value should be checked. Also, I don't see
a clk_prepare() anywhere. Is that something that maybe the MFD driver
should be doing? It currently isn't.
> +
> + /* Enable channel */
> + mask = TIM_CCER_CC1E << (pwm->hwpwm * 4);
> + if (priv->have_complementary_output)
> + mask |= TIM_CCER_CC1NE << (pwm->hwpwm * 4);
> +
> + regmap_update_bits(priv->regmap, TIM_CCER, mask, mask);
> +
> + /* Make sure that registers are updated */
> + regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
> +
> + /* Enable controller */
> + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
> +
> + return 0;
> +}
> +
> +static void stm32_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> + u32 mask;
> + struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
> +
> + /* Disable channel */
> + mask = TIM_CCER_CC1E << (pwm->hwpwm * 4);
> + if (priv->have_complementary_output)
> + mask |= TIM_CCER_CC1NE << (pwm->hwpwm * 4);
> +
> + regmap_update_bits(priv->regmap, TIM_CCER, mask, 0);
> +
> + /* When all channels are disabled, we can disable the controller */
> + if (!active_channels(priv))
> + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
> +
> + clk_disable(priv->clk);
> +}
> +
> +static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> + struct pwm_state *state)
> +{
> + struct pwm_state curstate;
> + bool enabled;
> + int ret;
> +
> + pwm_get_state(pwm, &curstate);
> + enabled = curstate.enabled;
There should be no need to do this in drivers. pwm_get_state() is for
PWM API users. Drivers can directly dereference pwm->state.
> +
> + if (enabled && !state->enabled) {
> + stm32_pwm_disable(chip, pwm);
> + return 0;
> + }
> +
> + if (state->polarity != curstate.polarity && enabled)
> + stm32_pwm_set_polarity(chip, pwm, state->polarity);
So that's kind of a violation of atomic API semantics. The above means
that if you have a PWM in the following state:
enabled: no
polarity: normal
and want to set this:
enabled: yes
polarity: inversed
then you will ignore the new polarity setting. What's the reason for
"&& enabled) in the conditional above?
> +
> + ret = stm32_pwm_config(chip, pwm, state->duty_cycle, state->period);
> + if (ret)
> + return ret;
> +
> + if (!enabled && state->enabled)
> + ret = stm32_pwm_enable(chip, pwm);
> +
> + return ret;
> +}
Would it be possible to merge stm32_pwm_disable(), stm32_pwm_enable(),
stm32_pwm_set_polarity() and stm32_pwm_config() into stm32_pwm_apply()?
Part of the reason for the atomic API was to make it easier to write
these drivers, but your implementation effectively copies what the
transitional helpers do.
It might not make a difference technically in your case, but I think
it'd make the implementation more compact and set a better example for
future reference.
> +
> +static const struct pwm_ops stm32pwm_ops = {
> + .owner = THIS_MODULE,
> + .apply = stm32_pwm_apply,
> +};
> +
> +static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
> + int level, int filter)
> +{
> + u32 bdtr = TIM_BDTR_BKE;
> +
> + if (level)
> + bdtr |= TIM_BDTR_BKP;
> +
> + bdtr |= (filter & TIM_BDTR_BKF_MASK) << TIM_BDTR_BKF_SHIFT;
> +
> + regmap_update_bits(priv->regmap,
> + TIM_BDTR, TIM_BDTR_BKE | TIM_BDTR_BKP | TIM_BDTR_BKF,
> + bdtr);
> +
> + regmap_read(priv->regmap, TIM_BDTR, &bdtr);
> +
> + return (bdtr & TIM_BDTR_BKE) ? 0 : -EINVAL;
> +}
> +
> +static int stm32_pwm_set_breakinput2(struct stm32_pwm *priv,
> + int level, int filter)
> +{
> + u32 bdtr = TIM_BDTR_BK2E;
> +
> + if (level)
> + bdtr |= TIM_BDTR_BK2P;
> +
> + bdtr |= (filter & TIM_BDTR_BKF_MASK) << TIM_BDTR_BK2F_SHIFT;
> +
> + regmap_update_bits(priv->regmap,
> + TIM_BDTR, TIM_BDTR_BK2E |
> + TIM_BDTR_BK2P |
> + TIM_BDTR_BK2F,
> + bdtr);
> +
> + regmap_read(priv->regmap, TIM_BDTR, &bdtr);
> +
> + return (bdtr & TIM_BDTR_BK2E) ? 0 : -EINVAL;
> +}
As far as I can tell the only difference here is the various bit
positions. Can you collapse the above two functions and add a new
parameter to unify some code?
> +
> +static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv,
> + struct device_node *np)
> +{
> + struct stm32_breakinput breakinput[MAX_BREAKINPUT];
> + int nb, ret, i, array_size;
> +
> + nb = of_property_count_elems_of_size(np, "st,breakinput",
> + sizeof(struct stm32_breakinput));
> +
> + /*
> + * Because "st,breakinput" parameter is optional do not make probe
> + * failed if it doesn't exist.
> + */
> + if (nb <= 0)
> + return 0;
> +
> + if (nb > MAX_BREAKINPUT)
> + return -EINVAL;
> +
> + array_size = nb * sizeof(struct stm32_breakinput) / sizeof(u32);
> + ret = of_property_read_u32_array(np, "st,breakinput",
> + &breakinput[0].index, array_size);
Maybe (u32 *)breakinput? That would make it more resilient against
changes in ordering of fields in the struct. Granted, that's not likely
to change, but I think it's a good idea in general to write code in a
way that's safe in a more general case. That way if somebody ever were
to copy from your code and then decide to reorder fields in their code
things wouldn't fall apart.
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < nb && !ret; i++) {
> + switch (breakinput[i].index) {
> + case 0:
> + {
> + ret = stm32_pwm_set_breakinput(priv,
> + breakinput[i].level,
> + breakinput[i].filter);
> + break;
> + }
Curly braces are unnecessary here.
> + case 1:
> + {
> + ret = stm32_pwm_set_breakinput2(priv,
> + breakinput[i].level,
> + breakinput[i].filter);
> +
> + break;
> + }
> + default:
> + {
> + ret = -EINVAL;
> + break;
> + }
> + }
> + }
> +
> + return ret;
> +}
> +
> +static void stm32_pwm_detect_complementary(struct stm32_pwm *priv)
> +{
> + u32 ccer;
> +
> + /*
> + * If complementary bit doesn't exist writing 1 will have no
> + * effect so we can detect it.
> + */
> + regmap_update_bits(priv->regmap,
> + TIM_CCER, TIM_CCER_CC1NE, TIM_CCER_CC1NE);
> + regmap_read(priv->regmap, TIM_CCER, &ccer);
> + regmap_update_bits(priv->regmap, TIM_CCER, TIM_CCER_CCXE, 0);
This is strange: why are we disabling outputs here? Shouldn't the last
line here undo the first instead?
> +
> + priv->have_complementary_output = (ccer != 0);
> +}
> +
> +static void stm32_pwm_detect_channels(struct stm32_pwm *priv)
> +{
> + u32 ccer;
> +
> + /*
> + * If channels enable bits don't exist writing 1 will have no
> + * effect so we can detect and count them.
> + */
> + regmap_update_bits(priv->regmap,
> + TIM_CCER, TIM_CCER_CCXE, TIM_CCER_CCXE);
> + regmap_read(priv->regmap, TIM_CCER, &ccer);
> + regmap_update_bits(priv->regmap, TIM_CCER, TIM_CCER_CCXE, 0);
Does this have the potential to glitch? I suspect that the clock may not
be on at this point and therefore no PWM outputs will be generated, but
is that guaranteed to always be the case?
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170118/305d63e0/attachment-0001.sig>
^ permalink raw reply
* [PATCH 1/1] ARM: dts: imx6dl: fix GPIO4 range
From: Sébastien Szymanski @ 2017-01-18 10:09 UTC (permalink / raw)
To: linux-arm-kernel
GPIO4_11 is on pin 152(MX6DL_PAD_KEY_ROW2) and not on pin
151(MX6DL_PAD_KEY_ROW1).
I found the error while booting a mainline kernel on APF6S SoM and
noticed the following message:
[ 2.609337] imx6dl-pinctrl 20e0000.iomuxc: pin MX6DL_PAD_KEY_ROW1
already requested by 20a8000.gpio:105; cannot claim for 20a8000.gpio:107
[ 2.621884] imx6dl-pinctrl 20e0000.iomuxc: pin-151 (20a8000.gpio:107)
status -22
[ 2.629303] spi_imx 2008000.ecspi: Can't get CS GPIO 107
With this patch, the message is gone and spi_imx driver probes correctly.
Fixes: bb728d662bed ("ARM: dts: add gpio-ranges property to iMX GPIO
controllers")
Signed-off-by: S?bastien Szymanski <sebastien.szymanski@armadeus.com>
---
arch/arm/boot/dts/imx6dl.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 1ade195..7aa120f 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -137,7 +137,7 @@
&gpio4 {
gpio-ranges = <&iomuxc 5 136 1>, <&iomuxc 6 145 1>, <&iomuxc 7 150 1>,
<&iomuxc 8 146 1>, <&iomuxc 9 151 1>, <&iomuxc 10 147 1>,
- <&iomuxc 11 151 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
+ <&iomuxc 11 152 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
<&iomuxc 14 149 1>, <&iomuxc 15 154 1>, <&iomuxc 16 39 7>,
<&iomuxc 23 56 1>, <&iomuxc 24 61 7>, <&iomuxc 31 46 1>;
};
--
2.7.3
^ permalink raw reply related
* [PATCH v7 4/8] PWM: add PWM driver for STM32 plaftorm
From: Thierry Reding @ 2017-01-18 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483608344-9012-5-git-send-email-benjamin.gaignard@st.com>
On Thu, Jan 05, 2017 at 10:25:40AM +0100, Benjamin Gaignard wrote:
[...]
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index f92dd41..88035c0 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -397,6 +397,15 @@ config PWM_STI
> To compile this driver as a module, choose M here: the module
> will be called pwm-sti.
>
> +config PWM_STM32
> + tristate "STMicroelectronics STM32 PWM"
> + depends on (ARCH_STM32 && OF && MFD_STM32_TIMERS) || COMPILE_TEST
One other thing: is the dependency on ARCH_STM32 and OF necessary here?
ARCH_STM32 and OF are both pulled in by MFD_STM32_TIMERS. The dependency
is probably fine for MFD_STM32_TIMERS, though even there && OF seems too
much, since it's already pulled in via ARCH_STM32 -> ARM_SINGLE_ARMV7M
-> USE_OF.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170118/f45a1318/attachment.sig>
^ permalink raw reply
* [PATCH 1/2] pinctrl: meson: fix uart_ao_b for GXBB and GXL/GXM
From: Linus Walleij @ 2017-01-18 10:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170115222029.8271-2-martin.blumenstingl@googlemail.com>
On Sun, Jan 15, 2017 at 11:20 PM, Martin Blumenstingl
<martin.blumenstingl@googlemail.com> wrote:
> The GXBB and GXL/GXM pinctrl drivers had a configuration which conflicts
> with uart_ao_a. According to the GXBB ("S905") datasheet the AO UART
> functions are:
> - GPIOAO_0: Func1 = UART_TX_AO_A (bit 12), Func2 = UART_TX_AO_B (bit 26)
> - GPIOAO_1: Func1 = UART_RX_AO_A (bit 11), Func2 = UART_RX_AO_B (bit 25)
> - GPIOAO_4: Func2 = UART_TX_AO_B (bit 24)
> - GPIOAO_5: Func2 = UART_RX_AO_B (bit 25)
>
> The existing definition for uart_AO_A already uses GPIOAO_0 and GPIOAO_1.
> The old definition of uart_AO_B however was broken, as it used GPIOAO_0
> for TX (which would be fine) and two pins (GPIOAO_1 and GPIOAO_5) for RX
> (which does not make any sense).
>
> This fixes the uart_AO_B configuration by moving it to GPIOAO_4 and
> GPIOAO_5 (it would be possible to use GPIOAO_0 and GPIOAO_1 in theory,
> but all existing hardware uses uart_AO_A there).
> The fix for GXBB and GXL/GXM is identical since it seems that these
> specific pins are identical on both SoC variants.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Patch applied for fixes.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 2/2] ARM64: dts: meson-gx: add the missing uart_AO_B
From: Linus Walleij @ 2017-01-18 10:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170115222029.8271-3-martin.blumenstingl@googlemail.com>
On Sun, Jan 15, 2017 at 11:20 PM, Martin Blumenstingl
<martin.blumenstingl@googlemail.com> wrote:
> This adds the missing node for the uart_AO_B port to the meson-gx.dtsi
> (as this is supported by GXBB, GXL and GXM) along with the required
> pinctrl pins. This is required as some boards are using it (the boards
> from the Khadas VIM series for example have it exposed on the pin
> headers).
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Please funnel this through the apropriate ARM SoC-feed tree.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] clk: rockchip: fix the incorrect pclk_edp div width for RK3399
From: Heiko Stübner @ 2017-01-18 10:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484713256-3005-1-git-send-email-zhengxing@rock-chips.com>
Am Mittwoch, 18. Januar 2017, 12:20:56 CET schrieb Xing Zheng:
> The range of the pclk_edp_div_con is [13:8] and 6 bits, not 5.
>
> Reported-by: Lin Huang <hl@rock-chips.com>
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
applied for 4.11 with Lin's test tag
Thanks
Heiko
^ permalink raw reply
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