* PROBLEM: DWC3 USB 3.0 not working on Odroid-XU4 with Exynos 5422
From: Vivek Gautam @ 2016-10-04 6:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANAwSgQMsK8YPxR==UXtR49kiJzYhkzvSCNwn8mDJfj-3wpa2w@mail.gmail.com>
Hi Michael,
On Tue, Aug 30, 2016 at 10:32 AM, Anand Moon <linux.amoon@gmail.com> wrote:
> Hi All
>
> Adding Vivek Gautam.
Sorry for missing out this conversation. I am no longer part of Samsung.
>
> On 29 August 2016 at 16:35, Michael Niew?hner <linux@mniewoehner.de> wrote:
>> Hi Mathias,
>> On Mo, 2016-08-29 at 13:59 +0300, Mathias Nyman wrote:
>>> On 29.08.2016 10:28, Felipe Balbi wrote:
>>> >
>>> >
>>> > Hi,
>>> >
>>> > Michael Niew?hner <linux@mniewoehner.de> writes:
>>> > >
>>> > > [1.] One line summary of the problem:
>>> > > DWC3 USB 3.0 not working on Odroid-XU4 with Exynos 5422
>>> > >
>>> > > [2.] Full description of the problem/report:
>>> > > No usb 3.0 devices are being detected when attached while USB 2.0
>>> > > devices work on the same port.
>>> > > USB 3.0 works after applying patches [9.1] and [9.2], but seems
>>> > > to be
>>> > > buggy. The usb hub is redetected every time an usb device is
>>> > > attached.
[snip]
>>> >
>>> > >
>>> > > [9.] Other notes, patches, fixes, workarounds:
>>> > > [9.1] https://lkml.org/lkml/2014/4/28/234
>>> > > [9.2] https://lkml.org/lkml/2015/2/2/259
These patches are required to get USB super-speed working on Exynos5420/5800.
But they did not make to upstream. There was resistance on adding new
phy_calibrate()
callback.
Without these patches the Exynos5420/5800 will enumerate all
super-speed capable devices
as high-speed devices.
Last time we checked with exynos542x smdk boards and peach-* boards,
we could get the
Super - speed devices working. I have not tested odroid anytime so
don't have much idea about the
its intricacies.
I guess Anand was able to use these patches to get his kernel working in past.
When you have a downstream on-board usb hub, ideally it should be able
to detect the devices
and not reset everytime you connect a new device (like you mentioned earlier).
There can be two possible reasons why the hub keeps getting reset ever
after applying the above
mentioned patches:
1) the clock rates are not proper.
2) the regulator load setting is not enough to drive the hub.
Anand, can you please point Michael to an older kernel with which you
could test usb on odroid successfully ?
You can compare the clocks with an older version and see if there'a
any difference.
Any possibility of any other framework (such as, bus-freq) trimming
down the clock - rates ?
[snip]
>
> There are two dwc3 ports in the SoC : one for Gbit Ethernet another
> one for on-board GL3521 USB 3.0 hub controller.
>
> 3.10.x kernel
> odroid at odroid:~$ lsusb -t
> /: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
> |__ Port 1: Dev 2, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M
> /: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
> /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
> |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
> /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
> |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
> /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
> /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=s5p-ehci/3p, 480M
>
> 4.x kernel
> odroid at odroid:~$ lsusb -t
> /: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
> /: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
> |__ Port 1: Dev 2, If 0, Class=Vendor Specific Class, Driver=r8152, 480M
> /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
> |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
> |__ Port 1: Dev 3, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
> |__ Port 2: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
> /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
> |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
> /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
> /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p, 480M
[snip]
Michael, please paste the output of lsusb -t and/or lsusb -v as well.
Best regards
Vivek
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [RFC] arm64: Enforce observed order for spinlock and data
From: Peter Zijlstra @ 2016-10-04 6:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b86926dc0203384522e0e6ce18bbb132@codeaurora.org>
On Mon, Oct 03, 2016 at 03:20:57PM -0400, bdegraaf at codeaurora.org wrote:
> Thinking about this, as the reader/writer code has no known "abuse"
> case, I'll remove it from the patchset, then provide a v2 patchset
> with a detailed explanation for the lockref problem using the commits
> you provided as an example, as well as performance consideration.
Please, fix lockref in those patches. Touching the spinlock because
lockref does something dubious really is the wrong thing.
^ permalink raw reply
* [PATCH v2] ARM64: dts: meson-gxbb-odroidc2: Enable USB Nodes
From: Brian Kim @ 2016-10-04 7:06 UTC (permalink / raw)
To: linux-arm-kernel
Enable both gxbb USB controller and add a 5V regulator for the OTG port
VBUS
Signed-off-by: Brian Kim <brian.kim@hardkernel.com>
---
This patch was written on Kevin Hilman's repository[1] and branch[2]:
[1] https://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic.git
[2] v4.8/integ
Chnages since v1:
- rename the usb_pwr node to usb_otg_pwr
- rename the regulator-name "USB_PWR" to "USB_OTG_PWR"
.../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 29 ++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 8d89edc..bfacaf7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -64,6 +64,18 @@
reg = <0x0 0x0 0x0 0x80000000>;
};
+ usb_otg_pwr: regulator-usb-pwrs {
+ compatible = "regulator-fixed";
+
+ regulator-name = "USB_OTG_PWR";
+
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
leds {
compatible = "gpio-leds";
blue {
@@ -149,6 +161,23 @@
pinctrl-names = "default";
};
+&usb0_phy {
+ status = "okay";
+ phy-supply = <&usb_otg_pwr>;
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
/* SD */
&sd_emmc_b {
status = "okay";
--
2.7.4
^ permalink raw reply related
* [PATCH 3/3] Revert "ACPI,PCI,IRQ: remove SCI penalize function"
From: Thomas Gleixner @ 2016-10-04 7:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475343976-20744-3-git-send-email-okaya@codeaurora.org>
On Sat, 1 Oct 2016, Sinan Kaya wrote:
> This reverts commit 9e5ed6d1fb87 ("ACPI,PCI,IRQ: remove SCI penalize
> function"). SCI penalty API was replaced by the runtime penalty calculation
> based on the value of acpi_gbl_FADT.sci_interrupt.
This does more than only reverting said commit ....
> acpi_gbl_FADT.sci_interrupt type does not get updated at the right time
> for some platforms and results in incorrect penalty assignment for PCI
> IRQs as irq_get_trigger_type returns the wrong type.
And the obvious question is: Why does irq_get_trigger_type() return the
wrong type?
What's the root cause of this problem? Your changelog does not tell
anything.
Thanks,
tglx
^ permalink raw reply
* [PATCHv4 2/3] tty/serial: at91: fix hardware handshake with GPIOs
From: Uwe Kleine-König @ 2016-10-04 7:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACQ1gAgE+BvteH9y62PcRx_tA9_e2X11RCJ12PC98FK+5z98QQ@mail.gmail.com>
On Fri, Sep 30, 2016 at 01:04:28PM +0200, Richard Genoud wrote:
> 2016-09-30 11:12 GMT+02:00 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> > Hello Richard,
> >
> > On Fri, Sep 30, 2016 at 10:58:00AM +0200, Richard Genoud wrote:
> >> Commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when
> >> hardware handshake is enabled") broke the hardware handshake when GPIOs
> >> were used.
> >>
> >> Hardware handshake with GPIOs used to work before this commit because
> >> the CRTSCTS flag (termios->c_cflag) was set, but not the
> >> ATMEL_US_USMODE_HWHS flag (controller register) ; so hardware handshake
> >> enabled, but not handled by the controller.
> >
> > What does the HWHS flag control? What if only RTS is a gpio and CTS is
> > not? Or the other way round?
> First, HWHS flag is used only in SAMA5D2. (if I correctly understood
> Atmel HW guys,
> all other platforms (sam9, sam9x5, sama5d3...) have this flag, but it
> is unusable,
> because they don't have Fifos nor PDC).
> So, on SAMA5D2, the HWHS flag tells the controller to drive the RTS
> pin according to
> the number of char present in the rx fifo (cf Figure 44-29 ?44.7.3.15 p.1438 of
> http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf).
> The controller will also start/stop the transmission on CTS changes.
> But, as I haven't got this hard, I couldn't test it. (but Cyrille did I guess).
> With this flag set, It's mandatory to have CTS and RTS not handled via
> GPIO, because if
> they were, the controller couldn't, well, control them.
Assuming the respective pin doesn't reach the hardware both are no
problem though. And it would keep the driver simpler to just ignore
this. There would be no need for patch 1 and also this patch could be
dropped. So I guess there is really something to fix, otherwise you
wouldn't start patching the driver. But I don't understand the issue, so
I'd like to have a better picture.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCHv4 1/3] serial: mctrl_gpio: implement mctrl_gpio_use_rtscts
From: Uwe Kleine-König @ 2016-10-04 7:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160930085801.21497-2-richard.genoud@gmail.com>
Hello Greg,
On Fri, Sep 30, 2016 at 10:57:59AM +0200, Richard Genoud wrote:
> This function returns true if CTS and RTS are used as GPIOs.
> Some drivers (like atmel_serial) needs to know if the flow control is
> handled by the controller or by GPIOs.
just for the record: I don't like this patch because I think it's highly
at91 specific and could so well live in that driver. Moreover I'm not
conviced yet that it's really the correct thing to do even for this
driver. So please don't apply, at least until we're done with the
discussion of patch 2.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v2 0/6] Support PWM polarity control
From: Lukasz Majewski @ 2016-10-04 7:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-1-bhuvanchandra.dv@toradex.com>
Dear Bhuvanchandra,
Thank you for your effort to send those patches to ML.
> Changes since v2:
>
> - Picked the stalled patchset[1] from Lothar Wassmann which adds the
> basic support for polarity control on imx-pwm driver and adds
> backward compatibility support for devices which does not have
> polarity control feature.
>
> Changes since Lothars v6:
>
> - Squash Lukasz patch[2].
>
> [1] http://thread.gmane.org/gmane.linux.pwm/1621
> [2] https://www.spinics.net/lists/arm-kernel/msg530818.html
>
> Bhuvanchandra DV (3):
> arm: dts: imx7: Update #pwm-cells for PWM polarity control
> arm: dts: imx7-colibri: Use pwm polarity control
> arm: dts: imx7-colibri: Use enable-gpios for BL_ON
>
> Lothar Wassmann (3):
> pwm: print error messages with pr_err() instead of pr_debug()
> pwm: core: make the PWM_POLARITY flag in DTB optional
> pwm: imx: support output polarity inversion
For some reason this patchset works differently than the one developed
by Lothar.
The difference is with the brightness level control.
My brightness definition in DTS:
pwms = <&pwm2 0 5000000 PWM_POLARITY_INVERTED>;
brightness-levels = < 0 1 2 3 4 5 6 7 8 9
.. ............
250 251 252 253 254 255>;
default-brightness-level = <50>;
enable-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
When I go to the backlight sysfs entry:
cd /sys/devices/soc0/backlight/backlight/backlight
It seems like the brightness level control is inverted - i.e.
'echo 20 > brightness" makes picture on the screen very bright, and
'echo 200 > brightness' makes the picture diminish.
With my "internal" patches the situation is opposite (and I've checked it with
my HW connections).
Could you check on your setup if similar situation takes place? I mean
if the brightness control works as expected?
Thanks in advance,
?ukasz Majewski
>
> Documentation/devicetree/bindings/pwm/imx-pwm.txt | 6 +--
> arch/arm/boot/dts/imx7-colibri.dtsi | 12 +++++-
> arch/arm/boot/dts/imx7s.dtsi | 8 ++--
> drivers/pwm/core.c | 31 ++++++++------
> drivers/pwm/pwm-imx.c | 51
> +++++++++++++++++++++-- 5 files changed, 83 insertions(+), 25
> deletions(-)
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161004/797a9606/attachment-0001.sig>
^ permalink raw reply
* [PATCH 1/3] pinctrl: sunxi: Add support for fetching pinconf settings from hardware
From: Maxime Ripard @ 2016-10-04 8:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161004015112.20833-2-wens@csie.org>
On Tue, Oct 04, 2016 at 09:51:10AM +0800, Chen-Yu Tsai wrote:
> The sunxi pinctrl driver only caches whatever pinconf setting was last
> set on a given pingroup. This is not particularly helpful, nor is it
> correct.
>
> Fix this by actually reading the hardware registers and returning
> the correct results or error codes. Also filter out unsupported
> pinconf settings. Since this driver has a peculiar setup of 1 pin
> per group, we can support both pin and pingroup pinconf setting
> read back with the same code. The sunxi_pconf_reg helper and code
> structure is inspired by pinctrl-msm.
>
> With this done we can also claim to support generic pinconf, by
> setting .is_generic = true in pinconf_ops.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 85 +++++++++++++++++++++++++++++++++--
> 1 file changed, 82 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index 54455af566ec..609843c9a65c 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -10,6 +10,7 @@
> * warranty of any kind, whether express or implied.
> */
>
> +#include <dt-bindings/pinctrl/sun4i-a10.h>
> #include <linux/io.h>
> #include <linux/clk.h>
> #include <linux/gpio/driver.h>
> @@ -269,15 +270,91 @@ static const struct pinctrl_ops sunxi_pctrl_ops = {
> .get_group_pins = sunxi_pctrl_get_group_pins,
> };
>
> +static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param,
> + u32 *offset, u32 *shift, u32 *mask)
> +{
> + switch (param) {
> + case PIN_CONFIG_DRIVE_STRENGTH:
> + *offset = sunxi_dlevel_reg(pin);
> + *shift = sunxi_dlevel_offset(pin);
> + *mask = DLEVEL_PINS_MASK;
> + break;
> +
> + case PIN_CONFIG_BIAS_PULL_UP:
> + case PIN_CONFIG_BIAS_PULL_DOWN:
> + case PIN_CONFIG_BIAS_DISABLE:
> + *offset = sunxi_pull_reg(pin);
> + *shift = sunxi_pull_offset(pin);
> + *mask = PULL_PINS_MASK;
> + break;
> +
> + default:
> + return -ENOTSUPP;
> + }
> +
> + return 0;
> +}
> +
> +static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
> + unsigned long *config)
> +{
> + struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
> + enum pin_config_param param = pinconf_to_config_param(*config);
> + u32 offset, shift, mask, val;
> + u16 arg;
> + int ret;
> +
> + pin -= pctl->desc->pin_base;
> +
> + ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
> + if (ret < 0)
> + return ret;
> +
> + val = (readl(pctl->membase + offset) >> shift) & mask;
> +
> + switch (pinconf_to_config_param(*config)) {
> + case PIN_CONFIG_DRIVE_STRENGTH:
> + arg = (val + 1) * 10;
> + break;
> +
> + case PIN_CONFIG_BIAS_PULL_UP:
> + if (val != SUN4I_PINCTRL_PULL_UP)
> + return -EINVAL;
> + arg = 1; /* hardware is weak pull-up */
> + break;
> +
> + case PIN_CONFIG_BIAS_PULL_DOWN:
> + if (val != SUN4I_PINCTRL_PULL_DOWN)
> + return -EINVAL;
> + arg = 1; /* hardware is weak pull-down */
> + break;
> +
> + case PIN_CONFIG_BIAS_DISABLE:
> + if (val != SUN4I_PINCTRL_NO_PULL)
> + return -EINVAL;
> + arg = 0;
> + break;
> +
> + default:
> + /* sunxi_pconf_reg should catch anything unsupported */
> + WARN_ON(1);
> + return -ENOTSUPP;
This should be EINVAL. The operation is supported, but one of the
argument is not valid.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161004/a71ffd23/attachment.sig>
^ permalink raw reply
* [PATCH 3/3] pinctrl: sunxi: Make sunxi_pconf_group_set use sunxi_pconf_reg helper
From: Maxime Ripard @ 2016-10-04 8:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161004015112.20833-4-wens@csie.org>
On Tue, Oct 04, 2016 at 09:51:12AM +0800, Chen-Yu Tsai wrote:
> The sunxi_pconf_reg helper introduced in the last patch gives us the
> chance to rework sunxi_pconf_group_set to have it match the structure
> of sunxi_pconf_(group_)get and make it easier to understand.
>
> For each config to set, it:
>
> 1. checks if the parameter is supported.
> 2. checks if the argument is within limits.
> 3. converts argument to the register value.
> 4. writes to the register with spinlock held.
>
> As a result the function now blocks unsupported config parameters,
> instead of silently ignoring them.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 65 +++++++++++++++++++----------------
> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 -
> 2 files changed, 35 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index 236272a2339d..1f02c4cd55c7 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -364,23 +364,27 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
> {
> struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
> struct sunxi_pinctrl_group *g = &pctl->groups[group];
> - unsigned long flags;
> unsigned pin = g->pin - pctl->desc->pin_base;
> - u32 val, mask;
> - u16 strength;
> - u8 dlevel;
> int i;
>
> - spin_lock_irqsave(&pctl->lock, flags);
> -
> for (i = 0; i < num_configs; i++) {
> - switch (pinconf_to_config_param(configs[i])) {
> + enum pin_config_param param;
> + unsigned long flags;
> + u32 offset, shift, mask, val;
> + u16 arg;
> + int ret;
> +
> + param = pinconf_to_config_param(configs[i]);
> + arg = pinconf_to_config_argument(configs[i]);
> +
> + ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
> + if (ret < 0)
> + return ret;
> +
> + switch (param) {
> case PIN_CONFIG_DRIVE_STRENGTH:
> - strength = pinconf_to_config_argument(configs[i]);
> - if (strength > 40) {
> - spin_unlock_irqrestore(&pctl->lock, flags);
> + if (arg < 10 || arg > 40)
This is a nitpick, but I'd really like to store the value in a
separate variable, to have a distinction between the value that was
given us as an argument, and what we're going to write.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161004/bed27c82/attachment.sig>
^ permalink raw reply
* [PATCH v2 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Peter Ujfalusi @ 2016-10-04 8:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-3-mugunthanvnm@ti.com>
On 10/03/16 16:03, Mugunthan V N wrote:
> +static int tiadc_request_dma(struct platform_device *pdev,
> + struct tiadc_device *adc_dev)
> +{
> + struct tiadc_dma *dma = &adc_dev->dma;
> + dma_cap_mask_t mask;
> +
> + /* Default slave configuration parameters */
> + dma->conf.direction = DMA_DEV_TO_MEM;
> + dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> + dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
> +
> + dma_cap_zero(mask);
> + dma_cap_set(DMA_CYCLIC, mask);
> +
> + /* Get a channel for RX */
> + dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
> + if (!dma->chan)
> + return -ENODEV;
dma_request_chan() ERR_PTR in case of failure, never NULL. You should reuse
the returned error code to support deferred probing.
> +
> + /* RX buffer */
> + dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
> + &dma->addr, GFP_KERNEL);
> + if (!dma->buf)
> + goto err;
> +
> + return 0;
> +err:
> + dma_release_channel(dma->chan);
> +
> + return -ENOMEM;
> +}
> +
> static int tiadc_parse_dt(struct platform_device *pdev,
> struct tiadc_device *adc_dev)
> {
> @@ -512,8 +639,14 @@ static int tiadc_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, indio_dev);
>
> + err = tiadc_request_dma(pdev, adc_dev);
> + if (err && err != -ENODEV)
> + goto err_dma;
You should handle the deferred probing for DMA channel.
> +
> return 0;
>
> +err_dma:
> + iio_device_unregister(indio_dev);
> err_buffer_unregister:
> tiadc_iio_buffered_hardware_remove(indio_dev);
> err_free_channels:
> @@ -525,8 +658,14 @@ static int tiadc_remove(struct platform_device *pdev)
> {
> struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + struct tiadc_dma *dma = &adc_dev->dma;
> u32 step_en;
>
> + if (dma->chan) {
> + dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
> + dma->buf, dma->addr);
> + dma_release_channel(dma->chan);
> + }
> iio_device_unregister(indio_dev);
> tiadc_iio_buffered_hardware_remove(indio_dev);
> tiadc_channels_remove(indio_dev);
> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index e45a208..b9a53e0 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -23,6 +23,8 @@
> #define REG_IRQENABLE 0x02C
> #define REG_IRQCLR 0x030
> #define REG_IRQWAKEUP 0x034
> +#define REG_DMAENABLE_SET 0x038
> +#define REG_DMAENABLE_CLEAR 0x03c
> #define REG_CTRL 0x040
> #define REG_ADCFSM 0x044
> #define REG_CLKDIV 0x04C
> @@ -36,6 +38,7 @@
> #define REG_FIFO0THR 0xE8
> #define REG_FIFO1CNT 0xF0
> #define REG_FIFO1THR 0xF4
> +#define REG_DMA1REQ 0xF8
> #define REG_FIFO0 0x100
> #define REG_FIFO1 0x200
>
> @@ -126,6 +129,10 @@
> #define FIFOREAD_DATA_MASK (0xfff << 0)
> #define FIFOREAD_CHNLID_MASK (0xf << 16)
>
> +/* DMA ENABLE/CLEAR Register */
> +#define DMA_FIFO0 BIT(0)
> +#define DMA_FIFO1 BIT(1)
> +
> /* Sequencer Status */
> #define SEQ_STATUS BIT(5)
> #define CHARGE_STEP 0x11
>
--
P?ter
^ permalink raw reply
* [PATCH 6/6] ARM: da850: adjust memory settings for tilcdc
From: Bartosz Golaszewski @ 2016-10-04 9:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <91db8934-bfd6-8fc4-74e3-4844ef3bd3e7@ti.com>
2016-09-30 21:19 GMT+02:00 Peter Ujfalusi <peter.ujfalusi@ti.com>:
> On 09/30/2016 06:06 PM, Bartosz Golaszewski wrote:
>>
>> Just ran a quick test with speaker-test -c2 -twav. Besides the fact
>> that the left and right channels are inverted (I'm looking into that),
>> I didn't notice any problems. Even at 1024x768 resolution, playing
>> audio at the same time seems to work fine.
>
Hi Peter
> That's good to hear, but I think the priorities should be set:
> LCDC and EDMA30TC1 to highest priority
> EDMA30TC0 to priority 2
>
> The 0TC0 is used by MMC and if you want to play a video you might need the
> servicing TC to be higher priority then other masters.
>
> If audio playback would trigger sync losts in lcdc then we might need to move
> 0TC1 to priority 1.
>
Did you mean "set EDMA31TC0 to priority 2"? EDMA30TC0 is already at
the highest priority. Or did you mean that we need to lower the
EDMA30TC0 priority? In that case: is 2 the correct value? EDMA31TC0 is
used by mmc1 and its priority is 4. Shouldn't we set both to be the
same?
> I agree that LCDC priority needs to be higher, but I do wonder why the default
> (5) is not working and if it is not working why it is 5...
>
> My guess is that the change in the PBBPR register is the one actually helping
> here.
>
While it seems that lowering the EDMA30TC0 priority is indeed
unnecessary, if I don't set the LCDC master to priority 0, I still get
FIFO underflows even with the change in PBBPR.
Thanks,
Bartosz
^ permalink raw reply
* [PATCH] bus: qcom-ebi2: depend on HAS_IOMEM
From: Arnd Bergmann @ 2016-10-04 9:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e3b1a575-7f97-ed6c-e2c0-16ae193b1b49@codeaurora.org>
On Monday, October 3, 2016 12:04:00 PM CEST Stephen Boyd wrote:
> On 10/02/2016 02:53 PM, Linus Walleij wrote:
> > After being asked to not depend on ARCH_QCOM* or similar,
> > unsurprisingly compilation fails on UM as it has no I/O
> > memory:
>
> We could have depends on ARCH_QCOM || COMPILE_TEST and then life is
> good. The HAS_IOMEM would of course stick around for compile testing.
Agreed, that would be nice also since most x86 don't want to
see the Kconfig option unless they set COMPILE_TEST.
Note that COMPILE_TEST now depends on !UML, so we don't have
to worry about that any more.
Arnd
^ permalink raw reply
* Applied "spi: omap2-mcspi: Fix modifying platform resource data" to the spi tree
From: Mark Brown @ 2016-10-04 9:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405683053-14104-1-git-send-email-LW@KARO-electronics.de>
The patch
spi: omap2-mcspi: Fix modifying platform resource data
has been applied to the spi tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 0142d2ee7e9f107248ebf69bd66037c536d3f6cc Mon Sep 17 00:00:00 2001
From: Vikram N <vicky773@gmail.com>
Date: Fri, 30 Sep 2016 19:53:11 +0530
Subject: [PATCH] spi: omap2-mcspi: Fix modifying platform resource data
currently during probe the resource data gets modified and device
physical address remains valid only during first load. If the module is
unloaded and loaded again, the ioremp will be done on a incorrect address
as the resource was modified during previous module load.
This patch fixes this issue.
Signed-off-by: Vikram N <vicky773@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/spi/spi-omap2-mcspi.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index d5157b2222ce..3567e1dfd30d 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1391,15 +1391,13 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
goto free_master;
}
- r->start += regs_offset;
- r->end += regs_offset;
- mcspi->phys = r->start;
-
mcspi->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(mcspi->base)) {
status = PTR_ERR(mcspi->base);
goto free_master;
}
+ mcspi->phys = r->start + regs_offset;
+ mcspi->base += regs_offset;
mcspi->dev = &pdev->dev;
--
2.9.3
^ permalink raw reply related
* [PATCH 00/14] ASoc: sunxi: Add Allwinner A33 codec driver
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
Hi everyone,
This patchset add the audio codec for Allwinner A33 (sun8i) SoC.
It adds different drivers:
- sun8i-codec-analog (patch 4): This driver implements the analog part
of the audio codec. The analog part is handled in PRCM registers so this
driver must be added as prcm's subnode (patch 5).
- sun8i-codec (patch 6): This driver implements the digital part of the
A33 codec.
- sun8i (patch 7): This driver implements a sound card for A33.
It links the DAI and the audio codec. The analog codec driver is handled
as an "aux_device".
The DAI for this codec is the same than for A20: "sun4i-i2s".
The digital codec code is coming from Allwinner's BSP (after some
cleanup and DAPM conversion) [1]
The analog codec driver is coming from Chen-Yu Tsai's driver [2]
with some modifications (such as read/write regmap functions).
Currently, all the drivers handle only the playback feature.
The other ones (such as capture) and all other interfaces except
headphone are not supported.
These drivers are functional except for one issue. When playing a sound
for the first time, a short delay can be noticed. On a second play
(right after), the sound is played correctly. If we wait a short time
(~5 sec), the delay is back.
There is the same behavior for left/right channel. On the first
time, a left sound is played on the left channel but in the second
time, the sound will be played on wrong channel.
These issues will be fixed in a second time. Is someone have suggestions
about it?
Examples of amixer commands:
amixer set 'Headphone' 75%
amixer set 'Headphone' on
amixer set 'DAC' on
amixer set 'Right DAC Mixer RSlot 0' on
amixer set 'Left DAC Mixer LSlot 0' on
amixer set 'DAC Reversed Right' on
amixer set 'DAC Reversed Left' on
It was tested on Parrot and Sinlinx board where device tree's modifications
are added (patch 11 to 14).
Thank you in advance,
Best regards,
[1]: https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/sound/soc/sunxi/audiocodec/sun8iw5_sndcodec.c
[2]: https://github.com/wens/linux/tree/a31-audio
Myl?ne Josserand (14):
dma: sun6i-dma: Add burst case of 4
clk: ccu-sun8i-a33: Add CLK_SET_RATE_PARENT to ac-dig
ASoC: sun4i-i2s: Add apb reset
ASoC: Add sun8i analog codec driver
mfd: sun6i-prcm: Add sun8i analog codec as subnode
ASoC: Add sun8i digital audio codec
ASoC: Add sun8i audio card
dt-bindings: sound: Add sun8i analog codec documentation
dt-bindings: sound: Add sun8i codec documentation
dt-bindings: sound: Add sun8i audio card documentation
ARM: dts: sun8i: Add analog codec on prcm node
ARM: dts: sun8i: Add audio codec, dai and card for A33
ARM: dts: sun8i: parrot: Enable audio nodes
ARM: dts: sun8i: sinlinx: Enable audio nodes
.../devicetree/bindings/sound/sun8i-audio.txt | 17 +
.../bindings/sound/sun8i-codec-analog.txt | 20 +
.../devicetree/bindings/sound/sun8i-codec.txt | 24 +
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 7 +
arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts | 8 +
arch/arm/boot/dts/sun8i-a33.dtsi | 33 ++
arch/arm/boot/dts/sun8i-r16-parrot.dts | 8 +
drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 2 +-
drivers/dma/sun6i-dma.c | 2 +
drivers/mfd/sun6i-prcm.c | 16 +
sound/soc/sunxi/Kconfig | 30 ++
sound/soc/sunxi/Makefile | 3 +
sound/soc/sunxi/sun4i-i2s.c | 16 +-
sound/soc/sunxi/sun8i-codec-analog.c | 305 +++++++++++++
sound/soc/sunxi/sun8i-codec.c | 492 +++++++++++++++++++++
sound/soc/sunxi/sun8i.c | 101 +++++
16 files changed, 1082 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-audio.txt
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-codec.txt
create mode 100644 sound/soc/sunxi/sun8i-codec-analog.c
create mode 100644 sound/soc/sunxi/sun8i-codec.c
create mode 100644 sound/soc/sunxi/sun8i.c
--
2.9.3
^ permalink raw reply
* [PATCH 01/14] dma: sun6i-dma: Add burst case of 4
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the case of a burst of 4 which is handled by the SoC.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
drivers/dma/sun6i-dma.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 8346199..0485204 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -240,6 +240,8 @@ static inline s8 convert_burst(u32 maxburst)
switch (maxburst) {
case 1:
return 0;
+ case 4:
+ return 1;
case 8:
return 2;
default:
--
2.9.3
^ permalink raw reply related
* [PATCH 02/14] clk: ccu-sun8i-a33: Add CLK_SET_RATE_PARENT to ac-dig
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the flag CLK_SET_RATE_PARENT to 'ac-dig' clock.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
index 96b40ca..37c4d8d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
@@ -440,7 +440,7 @@ static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio",
- 0x140, BIT(31), 0);
+ 0x140, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(ac_dig_4x_clk, "ac-dig-4x", "pll-audio-4x",
0x140, BIT(30), 0);
static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
--
2.9.3
^ permalink raw reply related
* [PATCH 03/14] ASoC: sun4i-i2s: Add apb reset
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add APB deassert function for sun4i-i2s driver.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
sound/soc/sunxi/sun4i-i2s.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 687a8f8..f3f7026 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
@@ -589,6 +590,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
{
struct sun4i_i2s *i2s;
struct resource *res;
+ struct reset_control *reset_apb;
void __iomem *regs;
int irq, ret;
@@ -626,7 +628,19 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Can't get our mod clock\n");
return PTR_ERR(i2s->mod_clk);
}
-
+
+ reset_apb = devm_reset_control_get(&pdev->dev, "apb_reset");
+ if (IS_ERR(reset_apb)) {
+ dev_err(&pdev->dev, "Can't get apb reset\n");
+ return PTR_ERR(i2s->mod_clk);
+ }
+
+ ret = reset_control_deassert(reset_apb);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Can't deassert apb reset (%d)\n", ret);
+ return ret;
+ }
+
i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG;
i2s->playback_dma_data.maxburst = 4;
--
2.9.3
^ permalink raw reply related
* [PATCH 04/14] ASoC: Add sun8i analog codec driver
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the analog part of the sun8i (A33) codec driver. This driver
implements all the analog part of the codec using PRCM registers.
The read/write regmap functions must be handled in a custom way as
the PRCM register behaves as "mailbox" register.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
sound/soc/sunxi/Kconfig | 7 +
sound/soc/sunxi/Makefile | 1 +
sound/soc/sunxi/sun8i-codec-analog.c | 304 +++++++++++++++++++++++++++++++++++
3 files changed, 312 insertions(+)
create mode 100644 sound/soc/sunxi/sun8i-codec-analog.c
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig
index dd23682..7aee95a 100644
--- a/sound/soc/sunxi/Kconfig
+++ b/sound/soc/sunxi/Kconfig
@@ -26,4 +26,11 @@ config SND_SUN4I_SPDIF
help
Say Y or M to add support for the S/PDIF audio block in the Allwinner
A10 and affiliated SoCs.
+
+config SND_SUN8I_CODEC_ANALOG
+ tristate "Allwinner SUN8I analog codec"
+ select REGMAP_MMIO
+ help
+ Say Y or M if you want to add sun8i analog audiocodec support
+
endmenu
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile
index 604c7b84..241c0df 100644
--- a/sound/soc/sunxi/Makefile
+++ b/sound/soc/sunxi/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o
obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o
obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
+obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o
diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c
new file mode 100644
index 0000000..be3d540
--- /dev/null
+++ b/sound/soc/sunxi/sun8i-codec-analog.c
@@ -0,0 +1,304 @@
+/*
+ * This driver supports the analog controls for the internal codec
+ * found in Allwinner's A31s, A33 and A23 SoCs.
+ *
+ * Copyright 2016 Chen-Yu Tsai <wens@csie.org>
+ * Copyright 2016 Myl?ne Josserand <mylene.josserand@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+/* Codec analog control register offsets and bit fields */
+#define SUN8I_ADDA_HP_VOLC 0x00
+#define SUN8I_ADDA_HP_VOLC_PA_CLK_GATE 7
+#define SUN8I_ADDA_HP_VOLC_HP_VOL 0
+#define SUN8I_ADDA_LOMIXSC 0x01
+#define SUN8I_ADDA_LOMIXSC_MIC1 6
+#define SUN8I_ADDA_LOMIXSC_MIC2 5
+#define SUN8I_ADDA_LOMIXSC_PHONE 4
+#define SUN8I_ADDA_LOMIXSC_PHONEN 3
+#define SUN8I_ADDA_LOMIXSC_LINEINL 2
+#define SUN8I_ADDA_LOMIXSC_DACL 1
+#define SUN8I_ADDA_LOMIXSC_DACR 0
+#define SUN8I_ADDA_ROMIXSC 0x02
+#define SUN8I_ADDA_ROMIXSC_MIC1 6
+#define SUN8I_ADDA_ROMIXSC_MIC2 5
+#define SUN8I_ADDA_ROMIXSC_PHONE 4
+#define SUN8I_ADDA_ROMIXSC_PHONEP 3
+#define SUN8I_ADDA_ROMIXSC_LINEINR 2
+#define SUN8I_ADDA_ROMIXSC_DACR 1
+#define SUN8I_ADDA_ROMIXSC_DACL 0
+#define SUN8I_ADDA_DAC_PA_SRC 0x03
+#define SUN8I_ADDA_DAC_PA_SRC_DACAREN 7
+#define SUN8I_ADDA_DAC_PA_SRC_DACALEN 6
+#define SUN8I_ADDA_DAC_PA_SRC_RMIXEN 5
+#define SUN8I_ADDA_DAC_PA_SRC_LMIXEN 4
+#define SUN8I_ADDA_DAC_PA_SRC_RHPPAMUTE 3
+#define SUN8I_ADDA_DAC_PA_SRC_LHPPAMUTE 2
+#define SUN8I_ADDA_DAC_PA_SRC_RHPIS 1
+#define SUN8I_ADDA_DAC_PA_SRC_LHPIS 0
+#define SUN8I_ADDA_PHONEIN_GCTRL 0x04
+#define SUN8I_ADDA_PHONEIN_GCTRL_PHONEPG 4
+#define SUN8I_ADDA_PHONEIN_GCTRL_PHONENG 0
+#define SUN8I_ADDA_LINEIN_GCTRL 0x05
+#define SUN8I_ADDA_LINEIN_GCTRL_LINEING 4
+#define SUN8I_ADDA_LINEIN_GCTRL_PHONEG 0
+#define SUN8I_ADDA_MICIN_GCTRL 0x06
+#define SUN8I_ADDA_MICIN_GCTRL_MIC1G 4
+#define SUN8I_ADDA_MICIN_GCTRL_MIC2G 0
+#define SUN8I_ADDA_PAEN_HP_CTRL 0x07
+#define SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN 7
+#define SUN8I_ADDA_PAEN_HP_CTRL_HPCOM_FC 5
+#define SUN8I_ADDA_PAEN_HP_CTRL_COMPTEN 4
+#define SUN8I_ADDA_PAEN_HP_CTRL_PA_ANTI_POP_CTRL 2
+#define SUN8I_ADDA_PAEN_HP_CTRL_LTRNMUTE 1
+#define SUN8I_ADDA_PAEN_HP_CTRL_RTLNMUTE 0
+#define SUN8I_ADDA_PHONEOUT_CTRL 0x08
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTG 5
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTEN 4
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTS3 3
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTS2 2
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTS1 1
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTS0 0
+#define SUN8I_ADDA_PHONE_GAIN_CTRL 0x09
+#define SUN8I_ADDA_PHONE_GAIN_CTRL_PHONEPREG 0
+#define SUN8I_ADDA_MIC2G_CTRL 0x0a
+#define SUN8I_ADDA_MIC2G_CTRL_MIC2AMPEN 7
+#define SUN8I_ADDA_MIC2G_CTRL_MIC2BOOST 4
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL 0x0b
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIASEN 7
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MMICBIASEN 6
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIAS_MODE 5
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN 3
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1BOOST 0
+#define SUN8I_ADDA_PA_ANTI_POP_CTRL 0x0e
+#define SUN8I_ADDA_ADC_AP_EN 0x0f
+
+/* Analog control register access bits */
+#define ADDA_PR 0x0 /* PRCM base + 0x1c0 */
+#define ADDA_PR_RESET BIT(28)
+#define ADDA_PR_WRITE BIT(24)
+#define ADDA_PR_ADDR_SHIFT 16
+#define ADDA_PR_ADDR_MASK GENMASK(4, 0)
+#define ADDA_PR_DATA_IN_SHIFT 8
+#define ADDA_PR_DATA_IN_MASK GENMASK(7, 0)
+#define ADDA_PR_DATA_OUT_SHIFT 0
+#define ADDA_PR_DATA_OUT_MASK GENMASK(7, 0)
+
+/* regmap access bits */
+static int adda_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ void __iomem *base = context;
+ u32 tmp;
+
+ tmp = readl(base);
+
+ /* De-assert reset */
+ writel(tmp | ADDA_PR_RESET, base);
+
+ tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT);
+ tmp |= reg << ADDA_PR_ADDR_SHIFT;
+ writel(tmp, base);
+
+ *val = readl(base) & ADDA_PR_DATA_OUT_MASK;
+
+ return 0;
+}
+
+static int adda_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ void __iomem *base = context;
+ u32 tmp;
+
+ tmp = readl(base);
+ /* De-assert reset */
+ writel(tmp | ADDA_PR_RESET, base);
+
+ /* Write the address */
+ tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT);
+ tmp |= reg << ADDA_PR_ADDR_SHIFT;
+ writel(tmp, base);
+
+ /* Write the value */
+ tmp &= ~(ADDA_PR_DATA_IN_MASK << ADDA_PR_DATA_IN_SHIFT);
+ tmp |= val << ADDA_PR_DATA_IN_SHIFT;
+ writel(tmp, base);
+
+ /* Indicate that the previous value must be written */
+ writel(readl(base) | ADDA_PR_WRITE, base);
+
+ /* Reset the write bit */
+ writel(readl(base) & ~(ADDA_PR_WRITE), base);
+
+ return 0;
+}
+
+struct regmap_config adda_pr_regmap_cfg = {
+ .name = "adda-pr",
+ .reg_bits = 5,
+ .reg_stride = 1,
+ .val_bits = 8,
+ .reg_read = adda_reg_read,
+ .reg_write = adda_reg_write,
+ .fast_io = true,
+ .max_register = 24,
+};
+
+static DECLARE_TLV_DB_SCALE(sun8i_codec_headphone_volume_scale, -6300, 100, 1);
+
+static const struct snd_kcontrol_new sun8i_analog_widgets[] = {
+ SOC_SINGLE_TLV("Headphone Volume", SUN8I_ADDA_HP_VOLC,
+ SUN8I_ADDA_HP_VOLC_HP_VOL, 0x3F, 0,
+ sun8i_codec_headphone_volume_scale),
+
+ /* Playback Switch */
+ SOC_DOUBLE("DAC Playback Switch", SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_DACALEN, SUN8I_ADDA_DAC_PA_SRC_DACAREN,
+ 1, 0),
+
+ SOC_DOUBLE("Headphone Playback Switch", SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_LHPPAMUTE,
+ SUN8I_ADDA_DAC_PA_SRC_RHPPAMUTE, 1, 0),
+};
+
+/* headphone controls */
+static const char * const sun8i_codec_hp_src_enum_text[] = {
+ "DAC", "Mixer",
+};
+
+static SOC_ENUM_DOUBLE_DECL(sun8i_codec_hp_src_enum,
+ SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_LHPIS,
+ SUN8I_ADDA_DAC_PA_SRC_RHPIS,
+ sun8i_codec_hp_src_enum_text);
+
+static const struct snd_kcontrol_new sun8i_codec_hp_src[] = {
+ SOC_DAPM_ENUM("Headphone Source Playback Route",
+ sun8i_codec_hp_src_enum),
+};
+
+static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DAC Left Playback Switch",
+ SUN8I_ADDA_LOMIXSC,
+ SUN8I_ADDA_LOMIXSC_DACL, 1, 0),
+ SOC_DAPM_SINGLE("DAC Right Playback Switch",
+ SUN8I_ADDA_ROMIXSC,
+ SUN8I_ADDA_ROMIXSC_DACR, 1, 0),
+ SOC_DAPM_SINGLE("DAC Reversed Left Playback Switch",
+ SUN8I_ADDA_LOMIXSC,
+ SUN8I_ADDA_LOMIXSC_DACR, 1, 0),
+ SOC_DAPM_SINGLE("DAC Reversed Right Playback Switch",
+ SUN8I_ADDA_ROMIXSC,
+ SUN8I_ADDA_ROMIXSC_DACL, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget sun8i_codec_analog_dapm_widgets[] = {
+ /* Mixers */
+ SOC_MIXER_ARRAY("Left Mixer", SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0,
+ sun8i_codec_mixer_controls),
+ SOC_MIXER_ARRAY("Right Mixer", SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_RMIXEN, 0,
+ sun8i_codec_mixer_controls),
+
+ /* Headphone output path */
+ SND_SOC_DAPM_MUX("Headphone Source Playback Route",
+ SND_SOC_NOPM, 0, 0, sun8i_codec_hp_src),
+ SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN8I_ADDA_PAEN_HP_CTRL,
+ SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN, 0, NULL, 0),
+
+ /* Headphone outputs */
+ SND_SOC_DAPM_OUTPUT("HP"),
+
+};
+
+static const struct snd_soc_dapm_route sun8i_codec_analog_dapm_routes[] = {
+ /* Left Mixer Routes */
+ { "Left Mixer", "DAC Playback Switch", "Left DAC" },
+ { "Left Mixer", "DAC Reversed Left Playback Switch", "Right DAC" },
+
+ /* Right Mixer Routes */
+ { "Right Mixer", "DAC Playback Switch", "Right DAC" },
+ { "Right Mixer", "DAC Reversed Right Playback Switch", "Left DAC" },
+
+ /* Headphone Routes */
+ { "Headphone Source Playback Route", "DAC", "Left DAC" },
+ { "Headphone Source Playback Route", "DAC", "Right DAC" },
+ { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
+ { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
+ { "Headphone Amp", NULL, "Headphone Source Playback Route" },
+ { "HP", NULL, "Headphone Amp" },
+};
+
+static const struct snd_soc_component_driver sun8i_codec_analog_cmpnt_drv = {
+ .name = "sun8i-codec-analog",
+ .controls = sun8i_analog_widgets,
+ .num_controls = ARRAY_SIZE(sun8i_analog_widgets),
+ .dapm_widgets = sun8i_codec_analog_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_analog_dapm_widgets),
+ .dapm_routes = sun8i_codec_analog_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(sun8i_codec_analog_dapm_routes),
+};
+
+static const struct of_device_id sun8i_codec_analog_of_match[] = {
+ { .compatible = "allwinner,sun8i-codec-analog", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_codec_analog_of_match);
+
+static int sun8i_codec_analog_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct regmap *regmap;
+ void __iomem *base;
+
+ /* Get PRCM resources and registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base)) {
+ dev_err(&pdev->dev, "Failed to map PRCM registers\n");
+ return PTR_ERR(base);
+ }
+
+ regmap = devm_regmap_init(&pdev->dev, NULL, base, &adda_pr_regmap_cfg);
+ if (IS_ERR(regmap)) {
+ dev_err(&pdev->dev, "Regmap initialisation failed\n");
+ return PTR_ERR(regmap);
+ }
+
+ return devm_snd_soc_register_component(&pdev->dev,
+ &sun8i_codec_analog_cmpnt_drv,
+ NULL, 0);
+}
+
+static struct platform_driver sun8i_codec_analog_driver = {
+ .driver = {
+ .name = "sun8i-codec-analog",
+ .of_match_table = sun8i_codec_analog_of_match,
+ },
+ .probe = sun8i_codec_analog_probe,
+};
+module_platform_driver(sun8i_codec_analog_driver);
+
+MODULE_DESCRIPTION("Allwinner A31s/A33/A23 codec analog controls driver");
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_AUTHOR("Myl?ne Josserand <mylene.josserand@free-electrons.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sun8i-codec-analog");
--
2.9.3
^ permalink raw reply related
* [PATCH 05/14] mfd: sun6i-prcm: Add sun8i analog codec as subnode
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
The sun8i audio codec is using PRCM registers to configure all the
analog part of the audio codec. It is added as a subnode of the PRCM
with his resource (offset of 0x1c0).
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
drivers/mfd/sun6i-prcm.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c
index 011fcc5..e0c6bf5 100644
--- a/drivers/mfd/sun6i-prcm.c
+++ b/drivers/mfd/sun6i-prcm.c
@@ -12,6 +12,8 @@
#include <linux/init.h>
#include <linux/of.h>
+#define SUN6I_AUDIO_CODEC_ANALOG 0x1c0
+
struct prcm_data {
int nsubdevs;
const struct mfd_cell *subdevs;
@@ -57,6 +59,14 @@ static const struct resource sun6i_a31_apb0_rstc_res[] = {
},
};
+static const struct resource sun8i_adda_res[] = {
+ {
+ .start = SUN6I_AUDIO_CODEC_ANALOG,
+ .end = 0x1c3,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
{
.name = "sun6i-a31-ar100-clk",
@@ -109,6 +119,12 @@ static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
.num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
.resources = sun6i_a31_apb0_rstc_res,
},
+ {
+ .name = "sun8i-codec-analog",
+ .of_compatible = "allwinner,sun8i-codec-analog",
+ .num_resources = ARRAY_SIZE(sun8i_adda_res),
+ .resources = sun8i_adda_res,
+ },
};
static const struct prcm_data sun6i_a31_prcm_data = {
--
2.9.3
^ permalink raw reply related
* [PATCH 06/14] ASoC: Add sun8i digital audio codec
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the digital sun8i audio codec which handles the base register
(without DAI).
The driver handles only the basic playback of the A33 codec, from
the DAC to the headphones. All other features (microphone, capture,
etc) will be added later.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
sound/soc/sunxi/Kconfig | 9 +
sound/soc/sunxi/Makefile | 1 +
sound/soc/sunxi/sun8i-codec.c | 492 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 502 insertions(+)
create mode 100644 sound/soc/sunxi/sun8i-codec.c
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig
index 7aee95a..9e287b0 100644
--- a/sound/soc/sunxi/Kconfig
+++ b/sound/soc/sunxi/Kconfig
@@ -27,6 +27,15 @@ config SND_SUN4I_SPDIF
Say Y or M to add support for the S/PDIF audio block in the Allwinner
A10 and affiliated SoCs.
+config SND_SUN8I_CODEC
+ tristate "Allwinner SUN8I audio codec"
+ select REGMAP_MMIO
+ help
+ This option enables the digital part of the internal audio codec for
+ Allwinner sun8i SoC.
+
+ Say Y or M if you want to add sun8i digital audio codec support.
+
config SND_SUN8I_CODEC_ANALOG
tristate "Allwinner SUN8I analog codec"
select REGMAP_MMIO
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile
index 241c0df..1da63d3 100644
--- a/sound/soc/sunxi/Makefile
+++ b/sound/soc/sunxi/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o
obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o
obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
+obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o
obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
new file mode 100644
index 0000000..e157f89
--- /dev/null
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -0,0 +1,492 @@
+/*
+ * This driver supports the digital controls for the internal codec
+ * found in Allwinner's A33 and A23 SoCs.
+ *
+ * (C) Copyright 2010-2016
+ * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
+ * huangxin <huangxin@Reuuimllatech.com>
+ * Myl?ne Josserand <mylene.josserand@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+/* CODEC_OFFSET represents the offset of the codec registers
+ * and not all the DAI registers
+ */
+#define CODEC_OFFSET 0x200
+#define CODEC_BASSADDRESS 0x01c22c00
+#define SUN8I_SYSCLK_CTL (0x20c - CODEC_OFFSET)
+#define SUN8I_SYSCLK_CTL_AIF1CLK_ENA (11)
+#define SUN8I_SYSCLK_CTL_SYSCLK_ENA (3)
+#define SUN8I_SYSCLK_CTL_SYSCLK_SRC (0)
+#define SUN8I_MOD_CLK_ENA (0x210 - CODEC_OFFSET)
+#define SUN8I_MOD_CLK_ENA_AIF1 (15)
+#define SUN8I_MOD_CLK_ENA_DAC (2)
+#define SUN8I_MOD_RST_CTL (0x214 - CODEC_OFFSET)
+#define SUN8I_MOD_RST_CTL_AIF1 (15)
+#define SUN8I_MOD_RST_CTL_DAC (2)
+#define SUN8I_SYS_SR_CTRL (0x218 - CODEC_OFFSET)
+#define SUN8I_SYS_SR_CTRL_AIF1_FS (12)
+#define SUN8I_SYS_SR_CTRL_AIF2_FS (8)
+#define SUN8I_AIF1CLK_CTRL (0x240 - CODEC_OFFSET)
+#define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD (15)
+#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV (14)
+#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV (13)
+#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV (9)
+#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV (6)
+#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ (4)
+#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT (2)
+#define SUN8I_AIF1_DACDAT_CTRL (0x248 - CODEC_OFFSET)
+#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA (15)
+#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA (14)
+#define SUN8I_DAC_DIG_CTRL (0x320 - CODEC_OFFSET)
+#define SUN8I_DAC_DIG_CTRL_ENDA (15)
+#define SUN8I_DAC_MXR_SRC (0x330 - CODEC_OFFSET)
+#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L (15)
+#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L (14)
+#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL (13)
+#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL (12)
+#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R (11)
+#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R (10)
+#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR (9)
+#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR (8)
+
+struct sun8i_codec {
+ struct device *dev;
+ struct regmap *regmap;
+ struct clk *clk_module;
+ struct clk *clk_apb;
+};
+
+static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
+{
+ unsigned int rate = params_rate(params);
+
+ switch (rate) {
+ case 8000:
+ case 7350:
+ return 0x0;
+ case 11025:
+ return 0x1;
+ case 12000:
+ return 0x2;
+ case 16000:
+ return 0x3;
+ case 22050:
+ return 0x4;
+ case 24000:
+ return 0x5;
+ case 32000:
+ return 0x6;
+ case 44100:
+ return 0x7;
+ case 48000:
+ return 0x8;
+ case 96000:
+ return 0x9;
+ case 192000:
+ return 0xa;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct sun8i_codec *scodec = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned long value;
+
+ /* clock masters */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS: /* DAI Slave */
+ value = 0x0; /* Codec Master */
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM: /* DAI Master */
+ value = 0x1; /* Codec Slave */
+ break;
+ default:
+ return -EINVAL;
+ }
+ regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+ BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD),
+ value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD);
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF: /* Normal */
+ value = 0x0;
+ break;
+ case SND_SOC_DAIFMT_IB_IF: /* Inversion */
+ value = 0x1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+ BIT(SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV),
+ value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV);
+ regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+ BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV),
+ value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV);
+
+ /* DAI format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ value = 0x0;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ value = 0x1;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ value = 0x2;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ value = 0x3;
+ break;
+ default:
+ return -EINVAL;
+ }
+ regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+ BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT),
+ value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
+
+ return 0;
+}
+
+static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int rs_value = 0;
+ u32 bclk_lrck_div = 0, sample_resolution;
+ int sample_rate = 0;
+ struct sun8i_codec *scodec = snd_soc_codec_get_drvdata(dai->codec);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ sample_resolution = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ sample_resolution = 24;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /*calculate word select bit*/
+ switch (sample_resolution) {
+ case 8:
+ rs_value = 0x0;
+ break;
+ case 16:
+ rs_value = 0x1;
+ break;
+ case 20:
+ rs_value = 0x2;
+ break;
+ case 24:
+ rs_value = 0x3;
+ break;
+ default:
+ break;
+ }
+ regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+ 0x3 << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ,
+ rs_value << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ);
+
+ /* calculate bclk_lrck_div Ratio */
+ bclk_lrck_div = sample_resolution * 2;
+ switch (bclk_lrck_div) {
+ case 16:
+ bclk_lrck_div = 0;
+ break;
+ case 32:
+ bclk_lrck_div = 1;
+ break;
+ case 64:
+ bclk_lrck_div = 2;
+ break;
+ case 128:
+ bclk_lrck_div = 3;
+ break;
+ case 256:
+ bclk_lrck_div = 4;
+ break;
+ default:
+ break;
+ }
+ regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+ 0x7 << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV,
+ bclk_lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
+
+ sample_rate = sun8i_codec_get_hw_rate(params);
+ if (sample_rate < 0)
+ return sample_rate;
+
+ regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
+ 0xf << SUN8I_SYS_SR_CTRL_AIF1_FS,
+ sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
+ regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
+ 0xf << SUN8I_SYS_SR_CTRL_AIF2_FS,
+ sample_rate << SUN8I_SYS_SR_CTRL_AIF2_FS);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new sun8i_output_left_mixer_controls[] = {
+ SOC_DAPM_SINGLE("LSlot 0", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L, 1, 0),
+ SOC_DAPM_SINGLE("LSlot 1", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L, 1, 0),
+ SOC_DAPM_SINGLE("DACL", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL, 1, 0),
+ SOC_DAPM_SINGLE("ADCL", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL, 1, 0),
+};
+
+static const struct snd_kcontrol_new sun8i_output_right_mixer_controls[] = {
+ SOC_DAPM_SINGLE("RSlot 0", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
+ SOC_DAPM_SINGLE("RSlot 1", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0),
+ SOC_DAPM_SINGLE("DACR", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),
+ SOC_DAPM_SINGLE("ADCR", SUN8I_DAC_MXR_SRC,
+ SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
+ /* Digital parts of the DACs */
+ SND_SOC_DAPM_SUPPLY("DAC", SUN8I_DAC_DIG_CTRL, SUN8I_DAC_DIG_CTRL_ENDA,
+ 0, NULL, 0),
+
+ /* Analog DAC */
+ SND_SOC_DAPM_DAC("Left DAC", "Playback", SUN8I_AIF1_DACDAT_CTRL,
+ SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0),
+ SND_SOC_DAPM_DAC("Right DAC", "Playback", SUN8I_AIF1_DACDAT_CTRL,
+ SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
+
+ /* DAC Mixers */
+ SND_SOC_DAPM_MIXER("Left DAC Mixer", SND_SOC_NOPM, 0, 0,
+ sun8i_output_left_mixer_controls,
+ ARRAY_SIZE(sun8i_output_left_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right DAC Mixer", SND_SOC_NOPM, 0, 0,
+ sun8i_output_right_mixer_controls,
+ ARRAY_SIZE(sun8i_output_right_mixer_controls)),
+
+ /* Clocks */
+ SND_SOC_DAPM_SUPPLY("MODCLK AFI1", SUN8I_MOD_CLK_ENA,
+ SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MODCLK DAC", SUN8I_MOD_CLK_ENA,
+ SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF1", SUN8I_SYSCLK_CTL,
+ SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SYSCLK", SUN8I_SYSCLK_CTL,
+ SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("AIF1 PLL", SUN8I_SYSCLK_CTL, 0x9, 0, NULL, 0),
+ /* Inversion as 0=AIF1, 1=AIF2 */
+ SND_SOC_DAPM_SUPPLY("SYSCLK AIF1", SUN8I_SYSCLK_CTL,
+ SUN8I_SYSCLK_CTL_SYSCLK_SRC, 1, NULL, 0),
+
+ /* Module reset */
+ SND_SOC_DAPM_SUPPLY("RST AIF1", SUN8I_MOD_RST_CTL,
+ SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("RST DAC", SUN8I_MOD_RST_CTL,
+ SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
+
+ /* Headphone outputs */
+ SND_SOC_DAPM_OUTPUT("HPOUTL"),
+ SND_SOC_DAPM_OUTPUT("HPOUTR"),
+
+};
+
+static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
+ /* Clock Routes */
+ { "AIF1", NULL, "SYSCLK AIF1" },
+ { "AIF1 PLL", NULL, "AIF1" },
+ { "RST AIF1", NULL, "AIF1 PLL" },
+ { "MODCLK AFI1", NULL, "RST AIF1" },
+ { "DAC", NULL, "MODCLK AFI1" },
+
+ { "RST DAC", NULL, "SYSCLK" },
+ { "MODCLK DAC", NULL, "RST DAC" },
+ { "DAC", NULL, "MODCLK DAC" },
+
+ /* DAC Routes */
+ { "Left DAC", NULL, "DAC" },
+ { "Right DAC", NULL, "DAC" },
+
+ /* DAC Mixer Routes */
+ { "Left DAC Mixer", "LSlot 0", "Left DAC"},
+ { "Right DAC Mixer", "RSlot 0", "Right DAC"},
+
+ /* End of route : HP out */
+ { "HPOUTL", NULL, "Left DAC Mixer" },
+ { "HPOUTR", NULL, "Right DAC Mixer" },
+};
+
+static struct snd_soc_dai_ops sun8i_codec_dai_ops = {
+ .hw_params = sun8i_codec_hw_params,
+ .set_fmt = sun8i_set_fmt,
+};
+
+static struct snd_soc_dai_driver sun8i_codec_dai = {
+ .name = "sun8i",
+ /* playback capabilities */
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000 |
+ SNDRV_PCM_RATE_KNOT,
+ .formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S18_3LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ /* pcm operations */
+ .ops = &sun8i_codec_dai_ops,
+};
+EXPORT_SYMBOL(sun8i_codec_dai);
+
+static int sun8i_soc_probe(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+/* power down chip */
+static int sun8i_soc_remove(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static struct snd_soc_codec_driver sun8i_soc_codec = {
+ .probe = sun8i_soc_probe,
+ .remove = sun8i_soc_remove,
+ .component_driver = {
+ .dapm_widgets = sun8i_codec_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets),
+ .dapm_routes = sun8i_codec_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes),
+ },
+};
+
+static const struct regmap_config sun8i_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN8I_DAC_MXR_SRC,
+};
+
+static int sun8i_codec_probe(struct platform_device *pdev)
+{
+ struct resource *res_base;
+ struct sun8i_codec *scodec;
+ void __iomem *base;
+
+ scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
+ if (!scodec)
+ return -ENOMEM;
+
+ scodec->dev = &pdev->dev;
+
+ /* Get the clocks from the DT */
+ scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
+ if (IS_ERR(scodec->clk_module)) {
+ dev_err(&pdev->dev, "Failed to get the module clock\n");
+ return PTR_ERR(scodec->clk_module);
+ }
+ if (clk_prepare_enable(scodec->clk_module))
+ pr_err("err:open failed;\n");
+
+ scodec->clk_apb = devm_clk_get(&pdev->dev, "apb");
+ if (IS_ERR(scodec->clk_apb)) {
+ dev_err(&pdev->dev, "Failed to get the apb clock\n");
+ return PTR_ERR(scodec->clk_apb);
+ }
+ if (clk_prepare_enable(scodec->clk_apb))
+ pr_err("err:open failed;\n");
+
+ /* Get base resources, registers and regmap */
+ res_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audio");
+ base = devm_ioremap_resource(&pdev->dev, res_base);
+ if (IS_ERR(base)) {
+ dev_err(&pdev->dev, "Failed to map the registers\n");
+ return PTR_ERR(base);
+ }
+
+ scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &sun8i_codec_regmap_config);
+ if (IS_ERR(scodec->regmap)) {
+ dev_err(&pdev->dev, "Failed to create our regmap\n");
+ return PTR_ERR(scodec->regmap);
+ }
+
+ /* Set the codec data as driver data */
+ dev_set_drvdata(&pdev->dev, scodec);
+
+ snd_soc_register_codec(&pdev->dev, &sun8i_soc_codec, &sun8i_codec_dai,
+ 1);
+
+ return 0;
+}
+
+static int sun8i_codec_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct sun8i_codec *scodec = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_codec(&pdev->dev);
+ clk_disable_unprepare(scodec->clk_module);
+ clk_disable_unprepare(scodec->clk_apb);
+
+ return 0;
+}
+
+static const struct of_device_id sun8i_codec_of_match[] = {
+ { .compatible = "allwinner,sun8i-a33-codec" },
+ { .compatible = "allwinner,sun8i-a23-codec" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);
+
+static struct platform_driver sun8i_codec_driver = {
+ .driver = {
+ .name = "sun8i-codec",
+ .owner = THIS_MODULE,
+ .of_match_table = sun8i_codec_of_match,
+ },
+ .probe = sun8i_codec_probe,
+ .remove = sun8i_codec_remove,
+};
+module_platform_driver(sun8i_codec_driver);
+
+MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
+MODULE_AUTHOR("huanxin<huanxin@reuuimllatech.com>");
+MODULE_AUTHOR("Myl?ne Josserand <mylene.josserand@free-electrons.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sun8i-codec");
--
2.9.3
^ permalink raw reply related
* [PATCH 07/14] ASoC: Add sun8i audio card
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the audio card for sun8i SoC. This card links the codec driver
(digital part) with the DAI driver. The analog codec driver is
added as an aux_device.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
sound/soc/sunxi/Kconfig | 14 +++++++
sound/soc/sunxi/Makefile | 1 +
sound/soc/sunxi/sun8i.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+)
create mode 100644 sound/soc/sunxi/sun8i.c
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig
index 9e287b0..7b97395 100644
--- a/sound/soc/sunxi/Kconfig
+++ b/sound/soc/sunxi/Kconfig
@@ -27,6 +27,20 @@ config SND_SUN4I_SPDIF
Say Y or M to add support for the S/PDIF audio block in the Allwinner
A10 and affiliated SoCs.
+config SND_SUN8I
+ tristate "Allwinner SUN6I/SUN8I audio card support"
+ select SND_SUN8I_CODEC
+ select SND_SUN4I_I2S
+ select SND_SUN8I_CODEC_ANALOG
+ select REGMAP_MMIO
+ help
+ This option enables the audio card for Allwinner A33 (sun8i) SoC.
+ It enables the DAI driver (SND_SUN4I_I2S), the digital audio
+ codec driver (SND_SUN8I_CODEC) and the analog codec driver
+ (SND_SUN8I_CODEC_ANALOG).
+
+ Say Y or M if you want to add sun8i/6i card support
+
config SND_SUN8I_CODEC
tristate "Allwinner SUN8I audio codec"
select REGMAP_MMIO
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile
index 1da63d3..7f1bab9 100644
--- a/sound/soc/sunxi/Makefile
+++ b/sound/soc/sunxi/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o
obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o
obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
+obj-$(CONFIG_SND_SUN8I) += sun8i.o
obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o
obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o
diff --git a/sound/soc/sunxi/sun8i.c b/sound/soc/sunxi/sun8i.c
new file mode 100644
index 0000000..565cd88
--- /dev/null
+++ b/sound/soc/sunxi/sun8i.c
@@ -0,0 +1,101 @@
+/*
+ * ALSA SoC driver for Allwinner sun8i SoC
+ *
+ * Copyright (C) 2016 Myl?ne Josserand <mylene.josserand@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/firmware.h>
+#include <linux/module.h>
+
+#include <sound/soc.h>
+
+static struct snd_soc_aux_dev sun8i_audio_prcm_aux_devs[] = {
+ {
+ .name = "sun8i-codec-analog",
+ .codec_name = "sun8i-codec-analog.0",
+ },
+};
+
+static struct snd_soc_dai_link sun8i_dai_link = {
+ .name = "sun4i-i2s",
+ .stream_name = "Playback",
+ .codec_dai_name = "sun8i",
+ .dai_fmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_CBM_CFM,
+};
+
+static struct snd_soc_card sun8i_card = {
+ .name = "sun8i-card",
+ .owner = THIS_MODULE,
+ .dai_link = &sun8i_dai_link,
+ .num_links = 1,
+ .aux_dev = sun8i_audio_prcm_aux_devs,
+ .num_aux_devs = ARRAY_SIZE(sun8i_audio_prcm_aux_devs),
+};
+
+static int sun8i_probe(struct platform_device *pdev)
+{
+ struct snd_soc_dai_link *link = &sun8i_dai_link;
+ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ /* register the soc card */
+ sun8i_card.dev = &pdev->dev;
+
+ /* Retrieve the audio-codec from DT */
+ link->codec_of_node = of_parse_phandle(np, "allwinner,audio-codec", 0);
+ if (!link->codec_of_node) {
+ dev_err(&pdev->dev, "Missing audio codec\n");
+ return -EINVAL;
+ }
+
+ /* Retrieve DAI from DT */
+ link->cpu_of_node = of_parse_phandle(np, "allwinner,i2s-controller", 0);
+ if (!link->cpu_of_node) {
+ dev_err(&pdev->dev, "Missing I2S controller\n");
+ return -EINVAL;
+ }
+
+ link->platform_of_node = link->cpu_of_node;
+
+ /* Register the sound card */
+ ret = devm_snd_soc_register_card(&pdev->dev, &sun8i_card);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Soc register card failed %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static const struct of_device_id sun8i_of_match[] = {
+ { .compatible = "allwinner,sun8i-audio", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, sun8i_of_match);
+
+static struct platform_driver sun8i_card_driver = {
+ .probe = sun8i_probe,
+ .driver = {
+ .name = "sun8i-audio",
+ .of_match_table = sun8i_of_match,
+ },
+};
+
+module_platform_driver(sun8i_card_driver);
+
+MODULE_AUTHOR("Myl?ne Josserand <mylene.josserand@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner sun8i machine ASoC driver");
+MODULE_LICENSE("GPL v2");
--
2.9.3
^ permalink raw reply related
* [PATCH 08/14] dt-bindings: sound: Add sun8i analog codec documentation
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the documentation for dt-binding of the analog audiocodec
driver for SUN8I SoC.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
.../devicetree/bindings/sound/sun8i-codec-analog.txt | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
diff --git a/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
new file mode 100644
index 0000000..a03ec20
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
@@ -0,0 +1,20 @@
+* Allwinner A23/A33 Analog Codec
+
+This codec must be handled as a PRCM subnode.
+
+Required properties:
+- compatible: must be either "allwinner,sun8i-codec-analog"
+- interrupts: must contain the codec interrupt
+- clocks: a list of phandle + clock-specifer pairs, one for each entry
+ in clock-names.
+- clock-names: should contain followings:
+ - "apb": the parent APB clock for this controller
+ - "codec": the parent module clock
+
+Example, in your prcm subnode:
+codec_analog: codec_analog {
+ compatible = "allwinner,sun8i-codec-analog";
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+ clock-names = "apb", "codec";
+};
--
2.9.3
^ permalink raw reply related
* [PATCH 09/14] dt-bindings: sound: Add sun8i codec documentation
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the documentation for dt-binding of the digital audio codec driver
for sun8i SoC.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
.../devicetree/bindings/sound/sun8i-codec.txt | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-codec.txt
diff --git a/Documentation/devicetree/bindings/sound/sun8i-codec.txt b/Documentation/devicetree/bindings/sound/sun8i-codec.txt
new file mode 100644
index 0000000..1808869
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sun8i-codec.txt
@@ -0,0 +1,24 @@
+* Allwinner A23/A33 Codec
+
+Required properties:
+- compatible: must be either "allwinner,sun4i-a23-codec" or
+ "allwinner,sun7i-a33-codec"
+- reg: must contain the registers location and length
+- interrupts: must contain the codec interrupt
+- clocks: a list of phandle + clock-specifer pairs, one for each entry
+ in clock-names.
+- clock-names: should contain followings:
+ - "apb": the parent APB clock for this controller
+ - "codec": the parent module clock
+
+Example:
+codec: codec at 01c22e00 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-a33-codec";
+ reg = <0x01c22e00 0x400>; /* SUNXI_AUDIO_PBASE + 0x200 */
+ reg-names = "audio";
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+ clock-names = "apb", "codec";
+ status = "disabled";
+};
--
2.9.3
^ permalink raw reply related
* [PATCH 10/14] dt-bindings: sound: Add sun8i audio card documentation
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
Add the documentation for dt-binding of the audio card driver
for sun8i SoC.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
Documentation/devicetree/bindings/sound/sun8i-audio.txt | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-audio.txt
diff --git a/Documentation/devicetree/bindings/sound/sun8i-audio.txt b/Documentation/devicetree/bindings/sound/sun8i-audio.txt
new file mode 100644
index 0000000..2403983
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sun8i-audio.txt
@@ -0,0 +1,17 @@
+* Allwinner A23/A33 audio card
+
+This binding implements the A33 audio card.
+
+Required properties:
+- compatible: must be "allwinner,sun8i-audio"
+- allwinner,audio-codec: must have the phandle of the audio codec
+ ("sun8i-a33-codec", for example).
+- allwinner,i2s-controller: must have the phandle of the DAI
+ ("allwinner,sun4i-a10-i2s", for example)
+
+Example:
+sound {
+ compatible = "allwinner,sun8i-audio";
+ allwinner,audio-codec = <&codec>;
+ allwinner,i2s-controller = <&dai>;
+};
--
2.9.3
^ permalink raw reply related
* [PATCH 11/14] ARM: dts: sun8i: Add analog codec on prcm node
From: Mylène Josserand @ 2016-10-04 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1475569400.git.mylene.josserand@free-electrons.com>
The analog codec for sun8i used PRCM registers so it should be added
in the device tree as a subnode of the prcm entry.
Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
---
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
index 48fc24f..5197812 100644
--- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
@@ -549,6 +549,13 @@
compatible = "allwinner,sun6i-a31-clock-reset";
#reset-cells = <1>;
};
+
+ codec_analog: codec_analog {
+ compatible = "allwinner,sun8i-codec-analog";
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+ clock-names = "apb", "codec";
+ };
};
cpucfg at 01f01c00 {
--
2.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox