Devicetree
 help / color / mirror / Atom feed
* Re: [PATCHv2 02/16] iommu/omap: omap_iommu_attach() should return ENODEV, not NULL
From: Laurent Pinchart @ 2014-02-26  2:05 UTC (permalink / raw)
  To: Suman Anna
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Tony Lindgren,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Florian Vaussard
In-Reply-To: <530D19E3.9030407-l0cyMroinI0@public.gmane.org>

Hi Suman,

On Tuesday 25 February 2014 16:32:03 Suman Anna wrote:
> On 02/25/2014 03:13 PM, Laurent Pinchart wrote:
> > On Thursday 13 February 2014 12:15:33 Suman Anna wrote:
> >> From: Florian Vaussard <florian.vaussard-p8DiymsW2f8@public.gmane.org>
> >> 
> >> omap_iommu_attach() returns NULL or ERR_PTR in case of error, but
> >> omap_iommu_attach_dev() only checks for IS_ERR. Thus a NULL return value
> >> (in case driver_find_device fails) will cause the kernel to panic when
> >> omap_iommu_attach_dev() dereferences the pointer.
> >> 
> >> In such case, omap_iommu_attach() should return ENODEV, not NULL.
> >> 
> >> Signed-off-by: Florian Vaussard <florian.vaussard-p8DiymsW2f8@public.gmane.org>
> >> Acked-by: Suman Anna <s-anna-l0cyMroinI0@public.gmane.org>
> >> ---
> >> 
> >>   drivers/iommu/omap-iommu.c | 4 ++--
> >>   1 file changed, 2 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
> >> index fff2ffd..6272c36 100644
> >> --- a/drivers/iommu/omap-iommu.c
> >> +++ b/drivers/iommu/omap-iommu.c
> >> @@ -863,7 +863,7 @@ static int device_match_by_alias(struct device *dev,
> >> void *data) **/
> >> 
> >>   static struct omap_iommu *omap_iommu_attach(const char *name, u32
> >>   *iopgd)
> >>   {
> >> -	int err = -ENOMEM;
> >> +	int err = -ENODEV;
> >>   	struct device *dev;
> >>   	struct omap_iommu *obj;
> >> 
> >> @@ -871,7 +871,7 @@ static struct omap_iommu *omap_iommu_attach(const
> >> char *name, u32 *iopgd)
> >>   				(void *)name,
> >>   				device_match_by_alias);
> >>   	if (!dev)
> >> -		return NULL;
> >> +		return ERR_PTR(err);
> > 
> > I would return ERR_PTR(-ENODEV) here, and remove the initialization at
> > declaration of err above.
> 
> The initialization at the beginning is also serving one another exit
> path (a check for try_module_get), where err is not being set. If the
> initialization is removed, then the err has to be set explicitly at the
> other place. Let me know if you still want this changed.

The return value of iommu_enable() is unconditionally stored in err before the 
try_module_get() call, so that code patch is buggy anyway and should be fixed. 
I would still remove the initialization at declaration and assign -ENODEV to 
err explicitly when try_module_get() fails before the goto err_module.

> >>   	obj = to_iommu(dev);

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCHv2 03/16] Documentation: dt: add OMAP iommu bindings
From: Laurent Pinchart @ 2014-02-26  2:13 UTC (permalink / raw)
  To: Suman Anna
  Cc: Joerg Roedel, Tony Lindgren, Florian Vaussard, iommu, devicetree,
	linux-omap, linux-arm-kernel
In-Reply-To: <530D210B.3070602@ti.com>

Hi Suman,

On Tuesday 25 February 2014 17:02:35 Suman Anna wrote:
> On 02/25/2014 03:26 PM, Laurent Pinchart wrote:
> > On Thursday 13 February 2014 12:15:34 Suman Anna wrote:
> >> From: Florian Vaussard <florian.vaussard@epfl.ch>
> >> 
> >> This patch adds the iommu bindings for all OMAP2+ SoCs. Apart from
> >> the standard bindings used by OMAP peripherals, this patch uses a
> >> 'dma-window' (already used by Tegra SMMU) and adds two OMAP custom
> >> bindings - 'ti,#tlb-entries' and 'ti,iommu-bus-err-back'.
> >> 
> >> Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
> >> [s-anna@ti.com: split bindings document, add dra7 and bus error back]
> >> Signed-off-by: Suman Anna <s-anna@ti.com>
> >> ---
> >> 
> >>   .../devicetree/bindings/iommu/ti,omap-iommu.txt    | 28
> >>   +++++++++++++++++++
> >>   1 file changed, 28 insertions(+)
> >>   create mode 100644
> >>   Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt
> >> 
> >> diff --git a/Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt
> >> b/Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt new file mode
> >> 100644
> >> index 0000000..116492d
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/iommu/ti,omap-iommu.txt
> >> @@ -0,0 +1,28 @@
> >> +OMAP2+ IOMMU
> >> +
> >> +Required properties:
> >> +- compatible : Should be one of,
> >> +		"ti,omap2-iommu" for OMAP2/OMAP3 IOMMU instances
> >> +		"ti,omap4-iommu" for OMAP4/OMAP5 IOMMU instances
> >> +		"ti,dra7-iommu" for DRA7xx IOMMU instances
> >> +- ti,hwmods  : Name of the hwmod associated with the IOMMU instance
> >> +- reg        : Address space for the configuration registers
> >> +- interrupts : Interrupt specifier for the IOMMU instance
> >> +- dma-window : IOVA start address and length
> > 
> > Isn't the dma window more of a system configuration property than a
> > hardware property ? How do you expect it to be set?
> 
> We are setting it based on the addressable range for the MMU.

A quick look at the ISP and IVA IOMMUs in the OMAP3 shows that both support 
the full 4GB VA space. Why do you need to restrict it ?

> We are reusing the existing defined property and it allows us to get rid of
> the IOVA start and end addresses defined in the pre-DT OMAP iommu platform
> data.
>
> >> +Optional properties:
> >> +- ti,#tlb-entries : Number of entries in the translation look-aside
> >> buffer. +                    Should be either 8 or 32 (default: 32)
> >> +- ti,iommu-bus-err-back : Indicates the IOMMU instance supports throwing
> >> +		          back a bus error response on MMU faults.
> > 
> > Do these features vary per IOMMU instance or per IOMMU model ? In the
> > latter case they could be inferred from the compatible string by the
> > driver without requiring them to be explicit in DT (whether you want to
> > do so is left to you though).
> 
> Well, these are fixed features given an IOMMU instance, like the OMAP3
> ISP is the only one that has 8 TLB entries, all the remaining ones have
> 32, and the IPU iommu instances are the only ones that support the bus
> error response back. I have no preference to any particular way, and
> sure the driver can infer these easily based on unique compatible
> strings per subsystem per SoC. I just happened to go with defining
> compatible strings per SoC, with the optional properties differentiating
> the fixed behavior between different IOMMU instances on that SoC. This
> is where I was looking for some inputs/guidance from the DT bindings
> maintainers on what is the preferred method.

I think you've made the right choice. I wasn't sure whether those parameters 
varied across IOMMU instances of compatible devices (from a compatible string 
point of view) or were constant. As they vary they should be expressed in DT.

> >> +Example:
> >> +	/* OMAP3 ISP MMU */
> >> +	mmu_isp: mmu@480bd400 {
> >> +		compatible = "ti,omap2-iommu";
> >> +		reg = <0x480bd400 0x80>;
> >> +		interrupts = <24>;
> >> +		ti,hwmods = "mmu_isp";
> >> +		ti,#tlb-entries = <8>;
> >> +		dma-window = <0 0xfffff000>;
> >> +	};

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* Re: [PATCH] ARM: tegra: add device tree for SHIELD
From: Alexandre Courbot @ 2014-02-26  4:52 UTC (permalink / raw)
  To: Arend van Spriel, Stephen Warren, Thierry Reding, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <530C67F4.7010208-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

On 02/25/2014 06:52 PM, Arend van Spriel wrote:
> On 02/25/2014 03:13 AM, Alexandre Courbot wrote:
>>>
>>>> +    /* Wifi */
>>>> +    sdhci@78000000 {
>>>> +        status = "okay";
>>>> +        bus-width = <4>;
>>>> +        broken-cd;
>>>> +        keep-power-in-suspend;
>>>> +        cap-sdio-irq;
>>>
>>> Is non-removable better than broken-cd, or are they entirely unrelated?
>>
>> They are unrelated actually. With non-removable the driver expects the
>> device to always be there since boot, and does not check for the card to
>> be removed/added after boot. broken-cd indicates there is no CD line and
>> the device should be polled regularly.
>>
>> For the Wifi chip, non-removable would be the correct setting
>> hardware-wise, but there is a trap: the chip has its reset line asserted
>> at boot-time, and you need to set GPIO 229 to de-assert it. Only after
>> that will the device be detected on the SDIO bus. Since it lacks a CD
>> line, it must be polled, hence the broken-cd property.
>>
>> This also raises another, redundant problem with DT bindings: AFAIK we
>> currently have no way to let the system know the device will only appear
>> after a given GPIO is set. It would also be nice to be able to give some
>> parameters to the Wifi driver through the DT (like the OOB interrupt).
>> Right now the Wifi chip is brought up by exporting the GPIO and writing
>> to it from user-space, and the OOB interrupt is not used.
>
> Hi Alexandre,
>
> I recently posted a proposal for brcmfmac DT binding [1]. I did receive
> some comments, but it would be great if you (and/or others involved) had
> a look at it as well and give me some feedback. DT work still needs to
> grow on me.

Hi Arend, (and thanks again for all the help with getting the chip to work!)

Great, I'm not subscribed to the devicetree list and so have missed this 
thread, but I'm glad to see it.

I don't think I have much to add to the comments you already received 
there. I'd need it to reference the 32K clock (which I currently 
force-enable manually), the OOB interrupt, and the reset pin as a GPIO 
(as for SHIELD the device needs to be put out of reset using an 
active-low GPIO before anything can happen). That last property could be 
optional as I suspect most designs won't use it.

Getting the device out of reset should be done before the bus probes the 
non-removable device, so I wonder how this would fit wrt. the DT 
power-on sequencing series by Olof. Something tells me this could rather 
be a property of the bus, but physically speaking the pin is connected 
to the wifi chip, so... Maybe we could get the platform driver to ask 
the bus to probe again after enabling power/getting the device out of reset?

^ permalink raw reply

* Re: [PATCH V5 2/4] DRIVERS: IRQCHIP: CROSSBAR: Add support for Crossbar IP
From: Sricharan R @ 2014-02-26  4:56 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, devicetree, linux-doc, linux-arm-kernel, linux-omap,
	linus.walleij, linux, tony, rnayak, marc.zyngier, grant.likely,
	mark.rutland, robherring2, galak, rob.herring, santosh.shilimkar,
	nm, bcousson, Kevin Hilman
In-Reply-To: <52F24683.9060200@ti.com>

Hi Tony,

On Wednesday 05 February 2014 07:41 PM, Sricharan R wrote:
> Tony,
> 
> On Wednesday 05 February 2014 06:41 PM, Sricharan R wrote:
>> On Tuesday 04 February 2014 09:44 PM, Thomas Gleixner wrote:
>>> On Mon, 3 Feb 2014, Sricharan R wrote:
>>>>> I already have your reviewed-by tag for the first patch in this series.
>>>>>
>>>>> Kevin was pointing out that irqchip maintainer tag is needed for this patch as well
>>>>> to be merged. We are planning to take this series through arm-soc tree.
>>>>>
>>>>> Can i please have your tag for this patch as well ?
>>>
>>> Acked-by-me
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>> Thanks Thomas.
>>
>> Kevin,
>>     I will re-send a branch based on rc1 for this.
>>
> 
> I have pushed a branch based on mainline,
>    git://github.com/Sricharanti/sricharan.git
>    branch: crossbar_3.14_rc1
> 
 Ping on this..

Regards,
 Sricharan

^ permalink raw reply

* Re: [PATCH] ARM: tegra: add device tree for SHIELD
From: Alexandre Courbot @ 2014-02-26  4:58 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <530D1B7A.9070209-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>

On 02/26/2014 07:38 AM, Stephen Warren wrote:
> On 02/24/2014 07:13 PM, Alexandre Courbot wrote:
>> On 02/25/2014 03:53 AM, Stephen Warren wrote:
>>> On 02/24/2014 03:26 AM, Alexandre Courbot wrote:
>>>> Add a device tree for NVIDIA SHIELD. The set of enabled features is
>>>> still minimal with no display option (although HDMI should be easy
>>>> to get to work) and USB requiring external power.
>
>>>> diff --git a/arch/arm/boot/dts/tegra114-roth.dts
>>>> b/arch/arm/boot/dts/tegra114-roth.dts
>>>
>>>> +    memory {
>>>> +        reg = <0x80000000 0x79600000>;
>>>
>>> It might be worth a comment here pointing out that the rest of RAM is
>>> reserved for some carveouts/..., or at least that these values are set
>>> this way in order to match what the bootloader usually passes to
>>> downstream kernels in the command-line?
>>
>> Yes, absolutely right. On a more general note I feel like DTs could gain
>> clarity if they had more comments (e.g. for pinmuxing which are a quite
>> heavy block otherwise), do you have any objection to this? (I guess not,
>> but so far the rule seems to be "no comment in DT" :P )
>
> I have no objection in particular. Specifically for pinmux, the values
> seem pretty obvious, so I'm not sure what extra the comment could
> convey, but I'll take a look at any proposed patch:-)

It would just make grouping of related pins according more visible than 
having to look at the "nvidia,function" property currently does - just a 
little added comfort.

>>>> +    /* Wifi */
>>>> +    sdhci@78000000 {
>>>> +        status = "okay";
>>>> +        bus-width = <4>;
>>>> +        broken-cd;
>>>> +        keep-power-in-suspend;
>>>> +        cap-sdio-irq;
>>>
>>> Is non-removable better than broken-cd, or are they entirely unrelated?
>>
>> They are unrelated actually. With non-removable the driver expects the
>> device to always be there since boot, and does not check for the card to
>> be removed/added after boot. broken-cd indicates there is no CD line and
>> the device should be polled regularly.
>
> It doesn't sound like that's what we want either; we should know exactly
> when the device is added/removed, based on when the relevant
> clocks/supplies/... are turned on/off.

Yes, I guess this will require a proper DT binding like what Arend proposed.

>> For the Wifi chip, non-removable would be the correct setting
>> hardware-wise, but there is a trap: the chip has its reset line asserted
>> at boot-time, and you need to set GPIO 229 to de-assert it. Only after
>> that will the device be detected on the SDIO bus. Since it lacks a CD
>> line, it must be polled, hence the broken-cd property.
>
> How does that GPIO get manipulated right now? I assume you must be
> manually configuring it via sysfs after boot or something? If so,
> perhaps it's best to just leave out the WiFi node until it works
> automatically.

The GPIO needs to be set from user-space, yes. But if we leave the Wifi 
node out, I'm concerned that wireless will not be usable at all, 
wouldn't it?

>> This also raises another, redundant problem with DT bindings: AFAIK we
>> currently have no way to let the system know the device will only appear
>> after a given GPIO is set. It would also be nice to be able to give some
>> parameters to the Wifi driver through the DT (like the OOB interrupt).
>> Right now the Wifi chip is brought up by exporting the GPIO and writing
>> to it from user-space, and the OOB interrupt is not used.
>
> There was a thread on this topic on LAKML recently. I didn't really
> follow it, so I don't know if there was a useful resolution. I think it
> was "mmc: add support for power-on sequencing through DT", although
> there may have been other related threads. It was possibly tangentially
> related to power-sequences-in-DT...
>
> ...
>> I'm not sure about cap-sdio-irq, it doesn't seem to make a difference
>> for SHIELD Wifi.
>
> I'd tend to leave it out then.

I will check whether it helps with the latency issues I have noticed and 
remove it if it doesn't.

Thanks,
Alex.

^ permalink raw reply

* Re: [PATCH] ARM: tegra: add device tree for SHIELD
From: Stephen Warren @ 2014-02-26  5:02 UTC (permalink / raw)
  To: Alexandre Courbot, Thierry Reding, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <530D748D.6010802-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

On 02/25/2014 09:58 PM, Alexandre Courbot wrote:
> On 02/26/2014 07:38 AM, Stephen Warren wrote:
>> On 02/24/2014 07:13 PM, Alexandre Courbot wrote:
>>> On 02/25/2014 03:53 AM, Stephen Warren wrote:
>>>> On 02/24/2014 03:26 AM, Alexandre Courbot wrote:
>>>>> Add a device tree for NVIDIA SHIELD. The set of enabled features is
>>>>> still minimal with no display option (although HDMI should be easy
>>>>> to get to work) and USB requiring external power.
...
>>> For the Wifi chip, non-removable would be the correct setting
>>> hardware-wise, but there is a trap: the chip has its reset line asserted
>>> at boot-time, and you need to set GPIO 229 to de-assert it. Only after
>>> that will the device be detected on the SDIO bus. Since it lacks a CD
>>> line, it must be polled, hence the broken-cd property.
>>
>> How does that GPIO get manipulated right now? I assume you must be
>> manually configuring it via sysfs after boot or something? If so,
>> perhaps it's best to just leave out the WiFi node until it works
>> automatically.
> 
> The GPIO needs to be set from user-space, yes. But if we leave the Wifi
> node out, I'm concerned that wireless will not be usable at all,
> wouldn't it?

True, but if we have no representation of the device in DT that works
without manually enabling clocks and/or GPIOs, it's not a
complete/accurate representation of the HW, so it doesn't make sense to
add it to DT. Yes, I admit that sucks.

^ permalink raw reply

* Re: [PATCH] ARM: tegra: add device tree for SHIELD
From: Alexandre Courbot @ 2014-02-26  5:12 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King
  Cc: devicetree@vger.kernel.org, linux-tegra@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <530D754A.60700@wwwdotorg.org>

On 02/26/2014 02:02 PM, Stephen Warren wrote:
> On 02/25/2014 09:58 PM, Alexandre Courbot wrote:
>> On 02/26/2014 07:38 AM, Stephen Warren wrote:
>>> On 02/24/2014 07:13 PM, Alexandre Courbot wrote:
>>>> On 02/25/2014 03:53 AM, Stephen Warren wrote:
>>>>> On 02/24/2014 03:26 AM, Alexandre Courbot wrote:
>>>>>> Add a device tree for NVIDIA SHIELD. The set of enabled features is
>>>>>> still minimal with no display option (although HDMI should be easy
>>>>>> to get to work) and USB requiring external power.
> ...
>>>> For the Wifi chip, non-removable would be the correct setting
>>>> hardware-wise, but there is a trap: the chip has its reset line asserted
>>>> at boot-time, and you need to set GPIO 229 to de-assert it. Only after
>>>> that will the device be detected on the SDIO bus. Since it lacks a CD
>>>> line, it must be polled, hence the broken-cd property.
>>>
>>> How does that GPIO get manipulated right now? I assume you must be
>>> manually configuring it via sysfs after boot or something? If so,
>>> perhaps it's best to just leave out the WiFi node until it works
>>> automatically.
>>
>> The GPIO needs to be set from user-space, yes. But if we leave the Wifi
>> node out, I'm concerned that wireless will not be usable at all,
>> wouldn't it?
>
> True, but if we have no representation of the device in DT that works
> without manually enabling clocks and/or GPIOs, it's not a
> complete/accurate representation of the HW, so it doesn't make sense to
> add it to DT. Yes, I admit that sucks.

Well, I can always enable it in my out-of-tree branch until we can push 
the complete binding in mainline, so I'm ok with taking it out of this 
patch for now.

^ permalink raw reply

* Re: [PATCHv1 0/2] Convert rx51-battery to IIO API and add DT support
From: Pali Rohár @ 2014-02-26  7:40 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	Jonathan Cameron, Marek Belisko, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, LKML,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Ivajlo Dimitrov
In-Reply-To: <1393375569-21751-1-git-send-email-sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>

Hi!

2014-02-26 1:46 GMT+01:00 Sebastian Reichel <sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>:
> Hi,
>
> This is PATCHv1 for converting rx51-battery to the IIO API
> and adding DT support. The patchset compiles and has been
> tested on my Nokia N900. It depends on another patchset
> converting twl4030-madc to the IIO API:
>
> https://lkml.org/lkml/2014/2/25/627
>
> -- Sebastian
>
> Sebastian Reichel (2):
>   rx51_battery: convert to iio consumer
>   Documentation: DT: Document rx51-battery binding
>
>  .../devicetree/bindings/power/rx51-battery.txt     | 25 ++++++++
>  drivers/power/rx51_battery.c                       | 68 ++++++++++++++--------
>  2 files changed, 70 insertions(+), 23 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/power/rx51-battery.txt
>
> --
> 1.8.5.3
>

Thanks for patch!

I would like to ask other kernel developers what do you think about
moving ADC channel numbers from rx51_battery.ko driver code to DT.
Driver rx51_battery.ko is platform specific for Nokia RX-51 (N900) so
it is usefull only for this one device.

Before this patch all driver data (look-up tables, adc channel
numbers, etc...) were in driver code. Now after this patch adc channel
numbers were moved to DT. What do you think? It is better to have all
data in one place (driver code) or some in DT and some in driver code?

For me it does not make sense to move these numbers to DT, because
driver is rx51 device specific and chaning it in DT does not make
sense. And I think it is better to have add driver data in one place
and not in two...

Sebastian already wrote me that this is normal to have numbers in DT
and other code in driver. But I think that driver which can be used
only in one device (so specified only in one DT file) does not need to
have configuration (via DT or board files).

Or do you think that driver specified only for one device needs to
have ADC numbers configuration via DT?

-- 
Pali Rohár
pali.rohar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

^ permalink raw reply

* Re: [RFCv3 5/7] mfd: twl4030-madc: Use twl_i2c_read/write_u16 for 16 bit registers
From: Lee Jones @ 2014-02-26  8:02 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Sebastian Reichel, Marek Belisko, Jonathan Cameron, Samuel Ortiz,
	Lars-Peter Clausen, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, linux-kernel, devicetree,
	linux-iio
In-Reply-To: <1393374270-20079-6-git-send-email-sre@debian.org>

> Simplify reading and writing of 16 bit TWL registers in the
> driver by using twl_i2c_read_u16 and twl_i2c_write_u16.
> 
> Signed-off-by: Sebastian Reichel <sre@debian.org>
> ---
>  drivers/mfd/twl4030-madc.c | 39 ++++++++-------------------------------
>  1 file changed, 8 insertions(+), 31 deletions(-)

Acked-by: Lee Jones <lee.jones@linaro.org>

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [RFCv3 4/7] mfd: twl-core: Add twl_i2c_read/write_u16
From: Lee Jones @ 2014-02-26  8:15 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Sebastian Reichel, Marek Belisko, Jonathan Cameron, Samuel Ortiz,
	Lars-Peter Clausen, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1393374270-20079-5-git-send-email-sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>

> Add a simple twl_i2c_read/write_u16 wrapper over
> the twl_i2c_read/write, which is similar to the
> twl_i2c_read/write_u8 wrapper.
> 
> Signed-off-by: Sebastian Reichel <sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>
> ---
>  include/linux/i2c/twl.h | 12 ++++++++++++
>  1 file changed, 12 insertions(+)

Acked-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFCv3 3/7] mfd: twl4030-madc: Cleanup driver
From: Lee Jones @ 2014-02-26  8:29 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Sebastian Reichel, Marek Belisko, Jonathan Cameron, Samuel Ortiz,
	Lars-Peter Clausen, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1393374270-20079-4-git-send-email-sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>

> Some style fixes in twl4030-madc driver.
> 
> Reported-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Sebastian Reichel <sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>
> ---
>  drivers/mfd/twl4030-madc.c       | 108 ++++++++++++++++++---------------------
>  include/linux/i2c/twl4030-madc.h |   2 +-
>  2 files changed, 51 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
> index 81484ee..c23025b 100644
> --- a/drivers/mfd/twl4030-madc.c
> +++ b/drivers/mfd/twl4030-madc.c

>  /*
> - * Return battery temperature
> + * Return battery temperature in degree Celsius

degrees

<snip>

> -	int count = 0, count_req = 0, i;
> -	u8 reg;
> +	int count = 0, i;

Ugly, please declare on separate lines.

>  	for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
> -		reg = reg_base + 2 * i;

Odd for this to be removed, as you calculate more than once now.

> -		buf[i] = twl4030_madc_channel_raw_read(madc, reg);
> +		buf[i] = twl4030_madc_channel_raw_read(madc, reg_base + 2 * i);

Better to bracket the math for clarity.

<snip>

> +			dev_err(madc->dev, "Unable to read register 0x%X\n",
> +				reg_base + 2 * i);

Here's the other calculation.

> +	regmask = (chan == 0) ? TWL4030_BCI_TYPEN : TWL4030_BCI_ITHEN;

regmask = chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN; 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH RESEND v10 0/7] mmc: omap_hsmmc: pbias dt and cleanup
From: Stefan Roese @ 2014-02-26  8:51 UTC (permalink / raw)
  To: Balaji T K, linux-omap, bcousson, devicetree, linux-mmc, chris,
	tony
  Cc: broonie
In-Reply-To: <1392821801-29673-1-git-send-email-balajitk@ti.com>

On 19.02.2014 15:56, Balaji T K wrote:
> Few cleanups to reduce code indent,
> Add pbias_regulator support and adapt omap_hsmmc to use pbias regulator
> to configure required voltage on mmc1 pad(SD card) i/o rails on OMAP SoCs.
>
> Balaji T K (7):
>    mmc: omap_hsmmc: use devm_regulator API
>    mmc: omap_hsmmc: handle vcc and vcc_aux independently
>    regulator: add pbias regulator support
>    mmc: omap_hsmmc: adapt hsmmc to use pbias regulator
>    ARM: dts: add pbias dt node
>    ARM: OMAP: enable SYSCON and REGULATOR_PBIAS in omap2plus_defconfig
>    mmc: omap_hsmmc: remove pbias workaround
>
>   .../bindings/regulator/pbias-regulator.txt         |   27 ++
>   arch/arm/boot/dts/dra7.dtsi                        |   17 ++
>   arch/arm/boot/dts/omap2430.dtsi                    |   17 ++
>   arch/arm/boot/dts/omap3.dtsi                       |   17 ++
>   arch/arm/boot/dts/omap4.dtsi                       |   17 ++
>   arch/arm/boot/dts/omap5.dtsi                       |   17 ++
>   arch/arm/configs/omap2plus_defconfig               |    2 +
>   drivers/mmc/host/omap_hsmmc.c                      |  111 +++++----
>   drivers/regulator/Kconfig                          |    9 +
>   drivers/regulator/Makefile                         |    1 +
>   drivers/regulator/pbias-regulator.c                |  255 ++++++++++++++++++++
>   11 files changed, 441 insertions(+), 49 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/regulator/pbias-regulator.txt
>   create mode 100644 drivers/regulator/pbias-regulator.c

This patch series (its v11 even though this mail has the subject v10) 
fixes problems I'm experiencing with MMC detection on some OMAP3 based 
boards. So:

Tested-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan


^ permalink raw reply

* Re: [PATCH 1/2] clk: ti: am335x: remove unecessary cpu0 clk node
From: Mike Turquette @ 2014-02-26  8:53 UTC (permalink / raw)
  To: Kodiak Furr
  Cc: Nishanth Menon, devicetree, Tony Lindgren, linux-kernel,
	Tero Kristo, bcousson, linux-omap, linux-arm-kernel
In-Reply-To: <BFF39FC5-A6EA-47D2-9345-6952157D57DD@aol.com>

Quoting Kodiak Furr (2014-02-25 16:51:34)
> Kodiak Furr liked your message with Boxer.

Dear Mr. Furr,

I don't know what Boxer is, but thanks for the like.

Regards,
Mike

> 
> 
> On February 25, 2014 at 2:24:11 AM CST, Mike Turquette <mturquette@linaro.org>
> wrote:
> 
>     Quoting Nishanth Menon (2014-01-29 10:19:16)
>     > cpu0 clock node has no functionality, since cpufreq-cpu0 is already
>     > capable of picking up the clock from dts.
>     >
>     > Signed-off-by: Nishanth Menon
> 
>     Taken into clk-next!
> 
>     Regards,
>     Mike
> 
>     > ---
>     > drivers/clk/ti/clk-33xx.c | 1 -
>     > 1 file changed, 1 deletion(-)
>     >
>     > diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c
>     > index 776ee45..028b337 100644
>     > --- a/drivers/clk/ti/clk-33xx.c
>     > +++ b/drivers/clk/ti/clk-33xx.c
>     > @@ -34,7 +34,6 @@ static struct ti_dt_clk am33xx_clks[] = {
>     > DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"),
>     > DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"),
>     > DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
>     > - DT_CLK("cpu0", NULL, "dpll_mpu_ck"),
>     > DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
>     > DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"),
>     > DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"),
>     > --
>     > 1.7.9.5
>     >
>     --
>     To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>     the body of a message to majordomo@vger.kernel.org
>     More majordomo info at http://vger.kernel.org/majordomo-info.html
>     Please read the FAQ at http://www.tux.org/lkml/
> 

^ permalink raw reply

* Re: devicetree repository separation/migration
From: Ian Campbell @ 2014-02-26  9:00 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Frank Rowand, Jason Cooper, Grant Likely, Rob Herring,
	pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	devicetree-spec-u79uwXL29TY76Z2rM5mHXA,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1393313764.9640.15.camel-ztPmHsLffjjnO4AKDKe2m+kiAK3p4hvP@public.gmane.org>

On Tue, 2014-02-25 at 07:36 +0000, Ian Campbell wrote:
> On Tue, 2014-02-25 at 08:26 +0100, Sascha Hauer wrote:
> > On Mon, Feb 24, 2014 at 03:59:17PM +0000, Ian Campbell wrote:
> > > On Fri, 2014-02-21 at 15:11 +0100, Sascha Hauer wrote:
> > > > Ians dts repository is a good start, but it contains a complete kernel
> > > > history and this is not very suitable as a submodule for other
> > > > projects. 
> > > 
> > > It only contains the full history for the files which it contains, not a
> > > complete kernel history. This is deliberate so that "git annotate" etc
> > > still works to tell you where a particular line came from.
> > 
> > I have cloned git://xenbits.xen.org/people/ianc/device-tree-rebasing.git.
> > .git is 843MB in size and after a 'git checkout v3.13' I see a vanilla v3.13
> > checked out. I may have done something wrong, but I don't see what it
> > could be.
> 
> There is a branch with the full Linux stuff in there too. It is needed
> in the tree doing the conversion but doesn't really need to be
> published. I pushed it in the early days without really thinking about
> the size impact. I'll remove that stuff from the published tree.

Done. The tree now has only a master branch and the vX.Y-dts tags (it is
still pushing the historical ones, they'll be there soon).

.git of a fresh clone is now 22M, which is more like it ;-)

I've moved the tree with all the conversion state aside into
device-tree-conversion.git. Most people won't need what is in there.

Ian.

--
To unsubscribe from this list: send the line "unsubscribe devicetree-spec" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH RFC 0/5] AM43xx-ePOS-EVM audio support with TLV320AIC31XX driver
From: Jyri Sarha @ 2014-02-26  9:14 UTC (permalink / raw)
  To: linux-omap, alsa-devel, devicetree, bcousson, broonie
  Cc: peter.ujfalusi, detheridge, Jyri Sarha

This patch set adds audio support for AM43xx-ePOS-EVM. I'll mail
the dts and defconfig changes once these have been merged.

Jyri Sarha (5):
  ASoC: tlv320aic31xx: Add basic codec driver implementation
  ASoC: tlv320aic31xx: Add codec driver to Makefile and Kconfig
  ASoC: tlv320aic31xx: Add DT binding document
  ASoC: davinci-evm: Add AM43xx-EPOS-EVM audio support
  ASoC: davinci: Add SND_AM43XX_SOC_EPOS_EVM build option

 .../bindings/sound/davinci-evm-audio.txt           |    9 +-
 .../devicetree/bindings/sound/tlv320aic31xx.txt    |   57 +
 sound/soc/codecs/Kconfig                           |    4 +
 sound/soc/codecs/Makefile                          |    2 +
 sound/soc/codecs/tlv320aic31xx.c                   | 1360 ++++++++++++++++++++
 sound/soc/codecs/tlv320aic31xx.h                   |  265 ++++
 sound/soc/davinci/Kconfig                          |   12 +
 sound/soc/davinci/Makefile                         |    1 +
 sound/soc/davinci/davinci-evm.c                    |   41 +
 9 files changed, 1748 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
 create mode 100644 sound/soc/codecs/tlv320aic31xx.c
 create mode 100644 sound/soc/codecs/tlv320aic31xx.h

-- 
1.7.9.5


^ permalink raw reply

* [PATCH RFC 1/5] ASoC: tlv320aic31xx: Add basic codec driver implementation
From: Jyri Sarha @ 2014-02-26  9:14 UTC (permalink / raw)
  To: linux-omap, alsa-devel, devicetree, bcousson, broonie
  Cc: peter.ujfalusi, detheridge, Jyri Sarha
In-Reply-To: <cover.1393405575.git.jsarha@ti.com>

This commit adds a bare bones driver support for TLV320AIC31XX family
audio codecs. The driver adds basic stereo playback trough headphone
and speaker outputs and mono capture trough microphone inputs.

The driver is currently missing support at least for mini DSP features
and jack detection. I have tested the driver only on TLV320AIC3111,
but based on the data sheets TLV320AIC3100, TLV320AIC3110, and
TLV320AIC3120 should work Ok too.

The base for the implementation was taken from:
git@gitorious.org:ti-codecs/ti-codecs.git ajitk/topics/k3.10.1-aic31xx
-branch at commit 77504eba0294764e9e63b4a0c696b44db187cd13.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 sound/soc/codecs/tlv320aic31xx.c | 1360 ++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/tlv320aic31xx.h |  265 ++++++++
 2 files changed, 1625 insertions(+)
 create mode 100644 sound/soc/codecs/tlv320aic31xx.c
 create mode 100644 sound/soc/codecs/tlv320aic31xx.h

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
new file mode 100644
index 0000000..1f83779
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -0,0 +1,1360 @@
+/*
+ * ALSA SoC TLV320AIC31XX codec driver
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Author: Jyri Sarha <jsarha@ti.com>
+ *
+ * Based on ground work by: Ajit Kulkarni <x0175765@ti.com>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * The TLV320AIC31xx series of audio codec is a low-power, highly integrated
+ * high performance codec which provides a stereo DAC, a mono ADC,
+ * and mono/stereo Class-D speaker driver.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "tlv320aic31xx.h"
+
+static const struct reg_default aic31xx_reg_defaults[] = {
+	{ AIC31XX_CLKMUX, 0x00 },
+	{ AIC31XX_PLLPR, 0x11 },
+	{ AIC31XX_PLLJ, 0x04 },
+	{ AIC31XX_PLLDMSB, 0x00 },
+	{ AIC31XX_PLLDLSB, 0x00 },
+	{ AIC31XX_NDAC, 0x01 },
+	{ AIC31XX_MDAC, 0x01 },
+	{ AIC31XX_DOSRMSB, 0x00 },
+	{ AIC31XX_DOSRLSB, 0x80 },
+	{ AIC31XX_NADC, 0x01 },
+	{ AIC31XX_MADC, 0x01 },
+	{ AIC31XX_AOSR, 0x80 },
+	{ AIC31XX_IFACE1, 0x00 },
+	{ AIC31XX_DATA_OFFSET, 0x00 },
+	{ AIC31XX_IFACE2, 0x00 },
+	{ AIC31XX_BCLKN, 0x01 },
+	{ AIC31XX_DACSETUP, 0x14 },
+	{ AIC31XX_DACMUTE, 0x0c },
+	{ AIC31XX_LDACVOL, 0x00 },
+	{ AIC31XX_RDACVOL, 0x00 },
+	{ AIC31XX_ADCSETUP, 0x00 },
+	{ AIC31XX_ADCFGA, 0x80 },
+	{ AIC31XX_ADCVOL, 0x00 },
+	{ AIC31XX_HPDRIVER, 0x04 },
+	{ AIC31XX_SPKAMP, 0x06 },
+	{ AIC31XX_DACMIXERROUTE, 0x00 },
+	{ AIC31XX_LANALOGHPL, 0x7f },
+	{ AIC31XX_RANALOGHPR, 0x7f },
+	{ AIC31XX_LANALOGSPL, 0x7f },
+	{ AIC31XX_RANALOGSPR, 0x7f },
+	{ AIC31XX_HPLGAIN, 0x02 },
+	{ AIC31XX_HPRGAIN, 0x02 },
+	{ AIC31XX_SPLGAIN, 0x00 },
+	{ AIC31XX_SPRGAIN, 0x00 },
+	{ AIC31XX_MICBIAS, 0x00 },
+	{ AIC31XX_MICPGA, 0x80 },
+	{ AIC31XX_MICPGAPI, 0x00 },
+	{ AIC31XX_MICPGAMI, 0x00 },
+};
+
+static bool aic31xx_precious(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AIC31XX_OFFLAG:
+	case AIC31XX_INTRDACFLAG:
+	case AIC31XX_INTRADCFLAG:
+		return true;
+	}
+	return false;
+}
+
+static bool aic31xx_real_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AIC31XX_OT_FLAG:
+	case AIC31XX_ADCFLAG:
+	case AIC31XX_DACFLAG1:
+	case AIC31XX_DACFLAG2:
+	case AIC31XX_INTRDACFLAG2:
+	case AIC31XX_INTRADCFLAG2:
+		return true;
+	}
+	return false;
+}
+
+static bool aic31xx_volatile(struct device *dev, unsigned int reg)
+{
+	if (aic31xx_precious(dev, reg) || aic31xx_real_volatile(dev, reg))
+		return true;
+
+	switch (reg) {
+	case AIC31XX_PAGECTL: /* regmap implementation requires this */
+	case AIC31XX_RESET: /* always clears after write */
+		return true;
+	}
+	return false;
+}
+
+static bool aic31xx_writeable(struct device *dev, unsigned int reg)
+{
+	if (aic31xx_precious(dev, reg) || aic31xx_real_volatile(dev, reg))
+		return false;
+
+	return true;
+}
+
+static const struct regmap_range_cfg aic31xx_ranges[] = {
+	{
+		.name = "codec-regmap",
+		.range_min = 0,
+		.range_max = 12 * 128,
+		.selector_reg = AIC31XX_PAGECTL,
+		.selector_mask = 0xff,
+		.selector_shift = 0,
+		.window_start = 0,
+		.window_len = 128,
+	},
+};
+
+struct regmap_config aic31xx_i2c_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.writeable_reg = aic31xx_writeable,
+	.volatile_reg = aic31xx_volatile,
+	.precious_reg = aic31xx_precious,
+	.reg_defaults = aic31xx_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(aic31xx_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+	.ranges = aic31xx_ranges,
+	.num_ranges = ARRAY_SIZE(aic31xx_ranges),
+	.max_register = 12 * 128,
+};
+
+#define AIC31XX_NUM_SUPPLIES	6
+static const char * const aic31xx_supply_names[] = {
+	"HPVDD",
+	"SPRVDD",
+	"SPLVDD",
+	"AVDD",
+	"IOVDD",
+	"DVDD",
+};
+
+struct aic31xx_disable_nb {
+	struct notifier_block nb;
+	struct aic31xx_priv *aic31xx;
+};
+
+struct aic31xx_priv {
+	struct snd_soc_codec *codec;
+	u8 i2c_regs_status;
+	struct device *dev;
+	struct regmap *regmap;
+	struct aic31xx_pdata pdata;
+	struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
+	struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
+	int power;
+	unsigned int sysclk;
+	int rate_div_line;
+	int codec_clk_on;
+};
+
+struct aic31xx_rate_divs {
+	u32 mclk;
+	u32 rate;
+	u8 p_val;
+	u8 pll_j;
+	u16 pll_d;
+	u16 dosr;
+	u8 ndac;
+	u8 mdac;
+	u8 aosr;
+	u8 nadc;
+	u8 madc;
+};
+
+/* ADC dividers can be disabled by cofiguring them to 0 */
+static const struct aic31xx_rate_divs aic31xx_divs[] = {
+	/* mclk      rate  pll: p  j	 d     dosr ndac mdac  aors nadc madc */
+	/* 8k rate */
+	{12000000,   8000,	1, 8, 1920,	128,  48,  2,	128,  48,  2},
+	{24000000,   8000,	2, 8, 1920,	128,  48,  2,	128,  48,  2},
+	{25000000,   8000,	2, 7, 8643,	128,  48,  2,	128,  48,  2},
+	/* 11.025k rate */
+	{12000000,  11025,	1, 7, 5264,	128,  32,  2,	128,  32,  2},
+	{24000000,  11025,	2, 7, 5264,	128,  32,  2,	128,  32,  2},
+	{25000000,  11025,	2, 7, 2253,	128,  32,  2,	128,  32,  2},
+	/* 16k rate */
+	{12000000,  16000,	1, 8, 1920,	128,  24,  2,	128,  24,  2},
+	{24000000,  16000,	2, 8, 1920,	128,  24,  2,	128,  24,  2},
+	{25000000,  16000,	2, 7, 8643,	128,  24,  2,	128,  24,  2},
+	/* 22.05k rate */
+	{12000000,  22050,	1, 7, 5264,	128,  16,  2,	128,  16,  2},
+	{24000000,  22050,	2, 7, 5264,	128,  16,  2,	128,  16,  2},
+	{25000000,  22050,	2, 7, 2253,	128,  16,  2,	128,  16,  2},
+	/* 32k rate */
+	{12000000,  32000,	1, 8, 1920,	128,  12,  2,	128,  12,  2},
+	{24000000,  32000,	2, 8, 1920,	128,  12,  2,	128,  12,  2},
+	{25000000,  32000,	2, 7, 8643,	128,  12,  2,	128,  12,  2},
+	/* 44.1k rate */
+	{12000000,  44100,	1, 7, 5264,	128,   8,  2,	128,   8,  2},
+	{24000000,  44100,	2, 7, 5264,	128,   8,  2,	128,   8,  2},
+	{25000000,  44100,	2, 7, 2253,	128,   8,  2,	128,   8,  2},
+	/* 48k rate */
+	{12000000,  48000,	1, 8, 1920,	128,   8,  2,	128,   8,  2},
+	{24000000,  48000,	2, 8, 1920,	128,   8,  2,	128,   8,  2},
+	{25000000,  48000,	2, 7, 8643,	128,   8,  2,	128,   8,  2},
+	/* 88.2k rate */
+	{12000000,  88200,	1, 7, 5264,	 64,   8,  2,	 64,   8,  2},
+	{24000000,  88200,	2, 7, 5264,	 64,   8,  2,	 64,   8,  2},
+	{25000000,  88200,	2, 7, 2253,	 64,   8,  2,	 64,   8,  2},
+	/* 96k rate */
+	{12000000,  96000,	1, 8, 1920,	 64,   8,  2,	 64,   8,  2},
+	{24000000,  96000,	2, 8, 1920,	 64,   8,  2,	 64,   8,  2},
+	{25000000,  96000,	2, 7, 8643,	 64,   8,  2,	 64,   8,  2},
+	/* 176.4k rate */
+	{12000000, 176400,	1, 7, 5264,	 32,   8,  2,	 32,   8,  2},
+	{24000000, 176400,	2, 7, 5264,	 32,   8,  2,	 32,   8,  2},
+	{25000000, 176400,	2, 7, 2253,	 32,   8,  2,	 32,   8,  2},
+	/* 192k rate */
+	{12000000, 192000,	1, 8, 1920,	 32,   8,  2,	 32,   8,  2},
+	{24000000, 192000,	2, 8, 1920,	 32,   8,  2,	 32,   8,  2},
+	{25000000, 192000,	2, 7, 8643,	 32,   8,  2,	 32,   8,  2},
+};
+
+static const char * const ldac_in_text[] = {
+	"off", "Left Data", "Right Data", "Mono"
+};
+
+static const char * const rdac_in_text[] = {
+	"off", "Right Data", "Left Data", "Mono"
+};
+
+static SOC_ENUM_SINGLE_DECL(ldac_in_enum, AIC31XX_DACSETUP, 4, ldac_in_text);
+
+static SOC_ENUM_SINGLE_DECL(rdac_in_enum, AIC31XX_DACSETUP, 2, rdac_in_text);
+
+static const char * const mic_select_text[] = {
+	"off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm"
+};
+
+static const
+SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text);
+static const
+SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text);
+static const
+SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text);
+
+static const
+SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
+static const
+SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text);
+
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0);
+static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0);
+static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, 0, 50, 0);
+static const DECLARE_TLV_DB_SCALE(hp_drv_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_SCALE(class_D_drv_tlv, 600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -6350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0);
+
+/*
+ * controls to be exported to the user space
+ */
+static const struct snd_kcontrol_new aic31xx_snd_controls[] = {
+	SOC_DOUBLE_R_SX_TLV("DAC Playback Volume", AIC31XX_LDACVOL,
+			    AIC31XX_RDACVOL, 0, 0x81, 0xaf, dac_vol_tlv),
+
+	SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1,
+		       adc_fgain_tlv),
+
+	SOC_SINGLE("ADC Capture Switch", AIC31XX_ADCFGA, 7, 1, 1),
+
+	/* ADC COARSE GAIN */
+	/* Writes to AIC31XX_ADCVOL should be masked with 0x7F, but there
+	   appears to be no side effect if writes are no masked. */
+	SOC_SINGLE_SX_TLV("ADC Capture Volume", AIC31XX_ADCVOL,
+			  0, 0x68, 0x40, adc_cgain_tlv),
+
+	SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0,
+		       119, 0, mic_pga_tlv),
+
+	SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN,
+		     AIC31XX_HPRGAIN, 2, 1, 0),
+	SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN,
+			 AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv),
+
+	SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL,
+			 AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv),
+};
+
+static const struct snd_kcontrol_new aic311x_snd_controls[] = {
+	SOC_DOUBLE_R("SP Driver Playback Switch", AIC31XX_SPLGAIN,
+		     AIC31XX_SPRGAIN, 2, 1, 0),
+	SOC_DOUBLE_R_TLV("SP Driver Playback Volume", AIC31XX_SPLGAIN,
+			 AIC31XX_SPRGAIN, 3, 3, 0, class_D_drv_tlv),
+
+	SOC_DOUBLE_R_TLV("SP Analog Playback Volume", AIC31XX_LANALOGSPL,
+			 AIC31XX_RANALOGSPR, 0, 0x7F, 1, sp_vol_tlv),
+};
+
+static const struct snd_kcontrol_new aic310x_snd_controls[] = {
+	SOC_SINGLE("SP Driver Playback Switch", AIC31XX_SPLGAIN,
+		   2, 1, 0),
+	SOC_SINGLE_TLV("SP Driver Playback Volume", AIC31XX_SPLGAIN,
+		       3, 3, 0, class_D_drv_tlv),
+
+	SOC_SINGLE_TLV("SP Analog Playback Volume", AIC31XX_LANALOGSPL,
+		       0, 0x7F, 1, sp_vol_tlv),
+};
+
+static const struct snd_kcontrol_new ldac_in_control =
+	SOC_DAPM_ENUM("DAC Left Input", ldac_in_enum);
+
+static const struct snd_kcontrol_new rdac_in_control =
+	SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum);
+
+int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg,
+		      unsigned int mask, unsigned int wbits, int sleep,
+		      int count)
+{
+	unsigned int bits;
+	int counter = count;
+	int ret = regmap_read(aic31xx->regmap, reg, &bits);
+	while ((bits & mask) != wbits && counter && !ret) {
+		usleep_range(sleep, sleep * 2);
+		ret = regmap_read(aic31xx->regmap, reg, &bits);
+		counter--;
+	}
+	if ((bits & mask) != wbits) {
+		dev_err(aic31xx->dev,
+			"%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n",
+			__func__, reg, bits, wbits, ret, mask,
+			(count - counter) * sleep);
+		ret = -1;
+	}
+	return ret;
+}
+
+static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
+				    struct snd_kcontrol *kcontrol, int event)
+{
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec);
+	unsigned int reg = AIC31XX_DACFLAG1;
+	unsigned int mask;
+
+	dev_dbg(w->codec->dev, "%s -> %s (event: %d)\n", w->name,
+		event == SND_SOC_DAPM_POST_PMU ? "on" :
+		event == SND_SOC_DAPM_POST_PMD ? "off" :
+		"(unsupported event)", event);
+
+	if (!strcmp(w->name, "DAC Left")) {
+		mask = AIC31XX_LDACPWRSTATUS_MASK;
+	} else if (!strcmp(w->name, "DAC Right")) {
+		mask = AIC31XX_RDACPWRSTATUS_MASK;
+	} else if (!strcmp(w->name, "HPL Driver")) {
+		mask = AIC31XX_HPLDRVPWRSTATUS_MASK;
+	} else if (!strcmp(w->name, "HPR Driver")) {
+		mask = AIC31XX_HPRDRVPWRSTATUS_MASK;
+	} else if (!strcmp(w->name, "SPL ClassD") ||
+		   !strcmp(w->name, "SPK ClassD")) {
+		mask = AIC31XX_SPLDRVPWRSTATUS_MASK;
+	} else if (!strcmp(w->name, "SPR ClassD")) {
+		mask = AIC31XX_SPRDRVPWRSTATUS_MASK;
+	} else if (!strcmp(w->name, "ADC")) {
+		mask = AIC31XX_ADCPWRSTATUS_MASK;
+		reg = AIC31XX_ADCFLAG;
+	} else {
+		dev_err(w->codec->dev, "Unknown widget '%s' calling %s/n",
+			w->name, __func__);
+		return -1;
+	}
+
+	if (event == SND_SOC_DAPM_POST_PMU)
+		return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100);
+	else if (event == SND_SOC_DAPM_POST_PMD)
+		return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100);
+
+	dev_dbg(w->codec->dev, "Unhandled dapm widget event %d from %s\n",
+		event, w->name);
+	return 0;
+}
+
+static const struct snd_kcontrol_new left_output_switches[] = {
+	SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0),
+	SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0),
+	SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_output_switches[] = {
+	SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0),
+	SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new p_term_mic1lp =
+	SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum);
+
+static const struct snd_kcontrol_new p_term_mic1rp =
+	SOC_DAPM_ENUM("MIC1RP P-Terminal", mic1rp_p_enum);
+
+static const struct snd_kcontrol_new p_term_mic1lm =
+	SOC_DAPM_ENUM("MIC1LM P-Terminal", mic1lm_p_enum);
+
+static const struct snd_kcontrol_new m_term_mic1lm =
+	SOC_DAPM_ENUM("MIC1LM M-Terminal", mic1lm_m_enum);
+
+static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch =
+	SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGHPL, 7, 1, 0);
+
+static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch =
+	SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGHPR, 7, 1, 0);
+
+static const struct snd_kcontrol_new aic31xx_dapm_spl_switch =
+	SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGSPL, 7, 1, 0);
+
+static const struct snd_kcontrol_new aic31xx_dapm_spr_switch =
+	SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGSPR, 7, 1, 0);
+
+static int aic31xx_clk_pm_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	u8 mask = AIC31XX_PM_MASK;
+	u8 on = AIC31XX_PM_MASK;
+	u8 off = 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		dev_dbg(codec->dev, "codec clock -> on (rate %d)\n",
+			aic31xx_divs[aic31xx->rate_div_line].rate);
+		snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, on);
+		mdelay(10);
+		snd_soc_update_bits(codec, AIC31XX_NDAC, mask, on);
+		snd_soc_update_bits(codec, AIC31XX_MDAC, mask, on);
+		if (aic31xx_divs[aic31xx->rate_div_line].nadc)
+			snd_soc_update_bits(codec, AIC31XX_NADC, mask, on);
+		if (aic31xx_divs[aic31xx->rate_div_line].madc)
+			snd_soc_update_bits(codec, AIC31XX_MADC, mask, on);
+		snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, on);
+		aic31xx->codec_clk_on = 1;
+	} else if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		dev_dbg(codec->dev, "codec clock -> off\n");
+		snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, off);
+		snd_soc_update_bits(codec, AIC31XX_MADC, mask, off);
+		snd_soc_update_bits(codec, AIC31XX_NADC, mask, off);
+		snd_soc_update_bits(codec, AIC31XX_MDAC, mask, off);
+		snd_soc_update_bits(codec, AIC31XX_NDAC, mask, off);
+		snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, off);
+		aic31xx->codec_clk_on = 0;
+	}
+	return 0;
+}
+
+static int mic_bias_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* change mic bias voltage to user defined */
+		if (aic31xx->pdata.micbias_vg != AIC31XX_MICBIAS_OFF) {
+			snd_soc_update_bits(codec, AIC31XX_MICBIAS,
+					    AIC31XX_MICBIAS_MASK,
+					    aic31xx->pdata.micbias_vg <<
+					    AIC31XX_MICBIAS_SHIFT);
+			dev_dbg(codec->dev, "%s: turned on\n", __func__);
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (aic31xx->pdata.micbias_vg != AIC31XX_MICBIAS_OFF) {
+			snd_soc_update_bits(codec, AIC31XX_MICBIAS,
+					    AIC31XX_MICBIAS_MASK, 0);
+			dev_dbg(codec->dev, "%s: turned off\n", __func__);
+		}
+		break;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MUX("DAC Left Input",
+			 SND_SOC_NOPM, 0, 0, &ldac_in_control),
+	SND_SOC_DAPM_MUX("DAC Right Input",
+			 SND_SOC_NOPM, 0, 0, &rdac_in_control),
+	/* DACs */
+	SND_SOC_DAPM_DAC_E("DAC Left", "DAC Left Input",
+			   AIC31XX_DACSETUP, 7, 0, aic31xx_dapm_power_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("DAC Right", "DAC Right Input",
+			   AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Output Mixers */
+	SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0,
+			   left_output_switches,
+			   ARRAY_SIZE(left_output_switches)),
+	SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0,
+			   right_output_switches,
+			   ARRAY_SIZE(right_output_switches)),
+
+	SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0,
+			    &aic31xx_dapm_hpl_switch),
+	SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0,
+			    &aic31xx_dapm_hpr_switch),
+
+	/* Output drivers */
+	SND_SOC_DAPM_OUT_DRV_E("HPL Driver", AIC31XX_HPDRIVER, 7, 0,
+			       NULL, 0, aic31xx_dapm_power_event,
+			       SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_OUT_DRV_E("HPR Driver", AIC31XX_HPDRIVER, 6, 0,
+			       NULL, 0, aic31xx_dapm_power_event,
+			       SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+
+	/* ADC */
+	SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0,
+			   aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_POST_PMD),
+
+	/* Input Selection to MIC_PGA */
+	SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0,
+			 &p_term_mic1lp),
+	SND_SOC_DAPM_MUX("MIC1RP P-Terminal", SND_SOC_NOPM, 0, 0,
+			 &p_term_mic1rp),
+	SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0,
+			 &p_term_mic1lm),
+
+	SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0,
+			 &m_term_mic1lm),
+	/* Enabling & Disabling MIC Gain Ctl */
+	SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA,
+			 7, 1, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("CODEC_CLK_IN", SND_SOC_NOPM, 0, 0,
+			    aic31xx_clk_pm_event,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Mic Bias */
+	SND_SOC_DAPM_SUPPLY("Mic Bias", SND_SOC_NOPM, 0, 0, mic_bias_event,
+			    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	/* Outputs */
+	SND_SOC_DAPM_OUTPUT("HPL"),
+	SND_SOC_DAPM_OUTPUT("HPR"),
+
+	/* Inputs */
+	SND_SOC_DAPM_INPUT("MIC1LP"),
+	SND_SOC_DAPM_INPUT("MIC1RP"),
+	SND_SOC_DAPM_INPUT("MIC1LM"),
+};
+
+static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = {
+	/* AIC3111 and AIC3110 have stereo class-D amplifier */
+	SND_SOC_DAPM_OUT_DRV_E("SPL ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0,
+			       aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+			       SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_OUT_DRV_E("SPR ClassD", AIC31XX_SPKAMP, 6, 0, NULL, 0,
+			       aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+			       SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SWITCH("SP Left", SND_SOC_NOPM, 0, 0,
+			    &aic31xx_dapm_spl_switch),
+	SND_SOC_DAPM_SWITCH("SP Right", SND_SOC_NOPM, 0, 0,
+			    &aic31xx_dapm_spr_switch),
+	SND_SOC_DAPM_OUTPUT("SPL"),
+	SND_SOC_DAPM_OUTPUT("SPR"),
+};
+
+/* AIC3100 and AIC3120 have only mono class-D amplifier */
+static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = {
+	SND_SOC_DAPM_OUT_DRV_E("SPK ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0,
+			       aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
+			       SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SWITCH("Speaker", SND_SOC_NOPM, 0, 0,
+			    &aic31xx_dapm_spl_switch),
+	SND_SOC_DAPM_OUTPUT("SPK"),
+};
+
+static const struct snd_soc_dapm_route
+aic31xx_audio_map[] = {
+	/* Clocks for ADC */
+	{"ADC", NULL, "CODEC_CLK_IN"},
+
+	/* DAC Input Routing */
+	{"DAC Left Input", "Left Data", "DAC IN"},
+	{"DAC Left Input", "Right Data", "DAC IN"},
+	{"DAC Left Input", "Mono", "DAC IN"},
+	{"DAC Right Input", "Left Data", "DAC IN"},
+	{"DAC Right Input", "Right Data", "DAC IN"},
+	{"DAC Right Input", "Mono", "DAC IN"},
+	{"DAC Left", NULL, "DAC Left Input"},
+	{"DAC Right", NULL, "DAC Right Input"},
+
+	/* Mic input */
+	{"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"},
+	{"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"},
+	{"MIC1LP P-Terminal", "FFR 40 Ohm", "MIC1LP"},
+	{"MIC1RP P-Terminal", "FFR 10 Ohm", "MIC1RP"},
+	{"MIC1RP P-Terminal", "FFR 20 Ohm", "MIC1RP"},
+	{"MIC1RP P-Terminal", "FFR 40 Ohm", "MIC1RP"},
+	{"MIC1LM P-Terminal", "FFR 10 Ohm", "MIC1LM"},
+	{"MIC1LM P-Terminal", "FFR 20 Ohm", "MIC1LM"},
+	{"MIC1LM P-Terminal", "FFR 40 Ohm", "MIC1LM"},
+
+	{"MIC1LM M-Terminal", "FFR 10 Ohm", "MIC1LM"},
+	{"MIC1LM M-Terminal", "FFR 20 Ohm", "MIC1LM"},
+	{"MIC1LM M-Terminal", "FFR 40 Ohm", "MIC1LM"},
+
+	{"MIC_GAIN_CTL", NULL, "MIC1LP P-Terminal"},
+	{"MIC_GAIN_CTL", NULL, "MIC1RP P-Terminal"},
+	{"MIC_GAIN_CTL", NULL, "MIC1LM P-Terminal"},
+	{"MIC_GAIN_CTL", NULL, "MIC1LM M-Terminal"},
+
+	{"ADC", NULL, "MIC_GAIN_CTL"},
+	{"MIC_GAIN_CTL", NULL, "Mic Bias"},
+
+	/* Clocks for DAC */
+	{"DAC Left", NULL, "CODEC_CLK_IN" },
+	{"DAC Right", NULL, "CODEC_CLK_IN"},
+
+	/* Left Output */
+	{"Output Left", "From Left DAC", "DAC Left"},
+	{"Output Left", "From MIC1LP", "MIC1LP"},
+	{"Output Left", "From MIC1RP", "MIC1RP"},
+
+	/* Right Output */
+	{"Output Right", "From Right DAC", "DAC Right"},
+	{"Output Right", "From MIC1RP", "MIC1RP"},
+
+	/* HPL path */
+	{"HP Left", "Switch", "Output Left"},
+	{"HPL Driver", NULL, "HP Left"},
+	{"HPL", NULL, "HPL Driver"},
+
+	/* HPR path */
+	{"HP Right", "Switch", "Output Right"},
+	{"HPR Driver", NULL, "HP Right"},
+	{"HPR", NULL, "HPR Driver"},
+};
+
+static const struct snd_soc_dapm_route
+aic311x_audio_map[] = {
+	/* SP L path */
+	{"SP Left", "Switch", "Output Left"},
+	{"SPL ClassD", NULL, "SP Left"},
+	{"SPL", NULL, "SPL ClassD"},
+
+	/* SP R path */
+	{"SP Right", "Switch", "Output Right"},
+	{"SPR ClassD", NULL, "SP Right"},
+	{"SPR", NULL, "SPR ClassD"},
+};
+
+static const struct snd_soc_dapm_route
+aic310x_audio_map[] = {
+	/* SP L path */
+	{"Speaker", "Switch", "Output Left"},
+	{"SPK ClassD", NULL, "Speaker"},
+	{"SPK", NULL, "SPK ClassD"},
+};
+
+static int aic31xx_add_controls(struct snd_soc_codec *codec)
+{
+	int err = 0;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+
+	if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) {
+		err = snd_soc_add_codec_controls(
+			codec, aic311x_snd_controls,
+			ARRAY_SIZE(aic311x_snd_controls));
+		if (err < 0)
+			dev_dbg(codec->dev, "Invalid control\n");
+
+	} else {
+		err = snd_soc_add_codec_controls(
+			codec, aic310x_snd_controls,
+			ARRAY_SIZE(aic310x_snd_controls));
+		if (err < 0)
+			dev_dbg(codec->dev, "Invalid Control\n");
+	}
+	return 0;
+}
+
+static int aic31xx_add_widgets(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	int ret = 0;
+
+	if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) {
+		ret = snd_soc_dapm_new_controls(
+			dapm, aic311x_dapm_widgets,
+			ARRAY_SIZE(aic311x_dapm_widgets));
+		if (ret)
+			dev_err(codec->dev,
+				"Adding %d dapm widgets failed: %d\n",
+				ARRAY_SIZE(aic311x_dapm_widgets), ret);
+		ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map,
+					      ARRAY_SIZE(aic311x_audio_map));
+		if (ret)
+			dev_err(codec->dev,
+				"Adding %d DAPM routes failed: %d\n",
+				ARRAY_SIZE(aic311x_audio_map), ret);
+	} else {
+		ret = snd_soc_dapm_new_controls(
+			dapm, aic310x_dapm_widgets,
+			ARRAY_SIZE(aic310x_dapm_widgets));
+		if (ret)
+			dev_err(codec->dev,
+				"Adding %d dapm widgets failed: %d\n",
+				ARRAY_SIZE(aic310x_dapm_widgets), ret);
+		ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map,
+					      ARRAY_SIZE(aic310x_audio_map));
+		if (ret)
+			dev_err(codec->dev,
+				"Adding %d DAPM routes failed: %d\n",
+				ARRAY_SIZE(aic310x_audio_map), ret);
+	}
+
+	return 0;
+}
+
+static int aic31xx_setup_pll(struct snd_soc_codec *codec,
+			     struct snd_pcm_hw_params *params)
+{
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	int bclk_n = 0;
+	int i;
+
+	/* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */
+	snd_soc_update_bits(codec, AIC31XX_CLKMUX,
+			    AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL);
+	snd_soc_update_bits(codec, AIC31XX_IFACE2,
+			    AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK);
+
+	for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) {
+		if (aic31xx_divs[i].rate == params_rate(params) &&
+		    aic31xx_divs[i].mclk == aic31xx->sysclk)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(aic31xx_divs)) {
+		dev_err(codec->dev, "%s: Sampling rate %u not supported\n",
+			__func__, params_rate(params));
+		return -EINVAL;
+	}
+
+	if (aic31xx->codec_clk_on) {
+		int old = aic31xx->rate_div_line;
+		if (aic31xx_divs[i].pll_j != aic31xx_divs[old].pll_j ||
+		    aic31xx_divs[i].pll_d != aic31xx_divs[old].pll_d ||
+		    aic31xx_divs[i].p_val != aic31xx_divs[old].p_val) {
+			dev_err(codec->dev,
+				"%s: Can't reconfigure PLL while it is on.\n",
+				__func__);
+			return -EBUSY;
+		}
+	} else {
+		/* PLL configuration */
+		snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK,
+				    (aic31xx_divs[i].p_val << 4) | 0x01);
+		snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j);
+
+		snd_soc_write(codec, AIC31XX_PLLDMSB,
+			      aic31xx_divs[i].pll_d >> 8);
+		snd_soc_write(codec, AIC31XX_PLLDLSB,
+			      aic31xx_divs[i].pll_d & 0xff);
+	}
+
+	/* DAC dividers configuration */
+	snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK,
+			    aic31xx_divs[i].ndac);
+	snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK,
+			    aic31xx_divs[i].mdac);
+
+	snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8);
+	snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff);
+
+	/* ADC dividers configuration. Write reset value 1 if not used. */
+	snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK,
+			    aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1);
+	snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK,
+			    aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1);
+
+	snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr);
+
+	/* Bit clock divider configuration. */
+	bclk_n = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac)
+		/ snd_soc_params_to_frame_size(params);
+	if (bclk_n == 0) {
+		dev_err(codec->dev, "%s: Not enough BLCK bandwidth\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, AIC31XX_BCLKN,
+			    AIC31XX_PLL_MASK, bclk_n);
+
+	aic31xx->rate_div_line = i;
+
+	dev_dbg(codec->dev,
+		"pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n",
+		aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d,
+		aic31xx_divs[i].p_val, aic31xx_divs[i].dosr,
+		aic31xx_divs[i].ndac, aic31xx_divs[i].mdac,
+		aic31xx_divs[i].aosr, aic31xx_divs[i].nadc,
+		aic31xx_divs[i].madc, bclk_n);
+
+	return 0;
+}
+
+static int aic31xx_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *tmp)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	u8 data = 0;
+
+	dev_dbg(codec->dev, "## %s: format %d rate %d\n",
+		__func__, params_format(params), params_rate(params));
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		data = (AIC31XX_WORD_LEN_20BITS <<
+			AIC31XX_IFACE1_DATALEN_SHIFT);
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		data = (AIC31XX_WORD_LEN_24BITS <<
+			AIC31XX_IFACE1_DATALEN_SHIFT);
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		data = (AIC31XX_WORD_LEN_32BITS <<
+			AIC31XX_IFACE1_DATALEN_SHIFT);
+		break;
+	default:
+		dev_err(codec->dev, "%s: Unsupported format %d\n",
+			__func__, params_format(params));
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, AIC31XX_IFACE1,
+			    AIC31XX_IFACE1_DATALEN_MASK,
+			    data);
+
+	return aic31xx_setup_pll(codec, params);
+}
+
+static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+
+	if (mute) {
+		snd_soc_update_bits(codec, AIC31XX_DACMUTE,
+				    AIC31XX_DACMUTE_MASK,
+				    AIC31XX_DACMUTE_MASK);
+	} else {
+		snd_soc_update_bits(codec, AIC31XX_DACMUTE,
+				    AIC31XX_DACMUTE_MASK, 0x0);
+	}
+
+	return 0;
+}
+
+static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			       unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	u8 iface_reg1 = 0;
+	u8 iface_reg3 = 0;
+	u8 dsp_a_val = 0;
+
+	dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt);
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+	case SND_SOC_DAIFMT_CBS_CFS:
+		dev_err(codec->dev, "Unsupported DAI master/slave interface\n");
+		return -EINVAL;
+	default:
+		dev_alert(codec->dev, "Invalid DAI master/slave interface\n");
+		return -EINVAL;
+	}
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		dsp_a_val = 0x1;
+	case SND_SOC_DAIFMT_DSP_B:
+		/* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			iface_reg3 |= AIC31XX_BCLKINV_MASK;
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			break;
+		default:
+			return -EINVAL;
+		}
+		iface_reg1 |= (AIC31XX_DSP_MODE <<
+			       AIC31XX_IFACE1_DATATYPE_SHIFT);
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE <<
+			       AIC31XX_IFACE1_DATATYPE_SHIFT);
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE <<
+			       AIC31XX_IFACE1_DATATYPE_SHIFT);
+		break;
+	default:
+		dev_err(codec->dev, "Invalid DAI interface format\n");
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, AIC31XX_IFACE1,
+			    AIC31XX_IFACE1_DATATYPE_MASK |
+			    AIC31XX_IFACE1_MASTER_MASK,
+			    iface_reg1);
+	snd_soc_update_bits(codec, AIC31XX_DATA_OFFSET,
+			    AIC31XX_DATA_OFFSET_MASK,
+			    dsp_a_val);
+	snd_soc_update_bits(codec, AIC31XX_IFACE2,
+			    AIC31XX_BCLKINV_MASK,
+			    iface_reg3);
+
+	return 0;
+}
+
+static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+				  int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	int i;
+
+	dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n",
+		__func__, clk_id, freq, dir);
+
+	for (i = 0; aic31xx_divs[i].mclk != freq; i++)
+		if (i == ARRAY_SIZE(aic31xx_divs)) {
+			dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n",
+				__func__, freq);
+			return -EINVAL;
+		}
+
+	/* set clock on MCLK, BCLK, or GPIO1 as PLL input */
+	snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK,
+			    clk_id << AIC31XX_PLL_CLKIN_SHIFT);
+
+	aic31xx->sysclk = freq;
+	return 0;
+}
+
+static int aic31xx_regulator_event(struct notifier_block *nb,
+				   unsigned long event, void *data)
+{
+	struct aic31xx_disable_nb *disable_nb =
+		container_of(nb, struct aic31xx_disable_nb, nb);
+	struct aic31xx_priv *aic31xx = disable_nb->aic31xx;
+
+	if (event & REGULATOR_EVENT_DISABLE) {
+		/*
+		 * Put codec to reset and as at least one
+		 * of the supplies was disabled
+		 */
+		dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__);
+		if (gpio_is_valid(aic31xx->pdata.gpio_reset))
+			gpio_set_value(aic31xx->pdata.gpio_reset, 0);
+		regcache_mark_dirty(aic31xx->regmap);
+	}
+
+	return 0;
+}
+
+static int aic31xx_set_power(struct snd_soc_codec *codec, int power)
+{
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__,
+		aic31xx->power, power);
+	if (aic31xx->power == power)
+		return 0;
+
+	if (power) {
+		ret = regulator_bulk_enable(ARRAY_SIZE(aic31xx->supplies),
+					    aic31xx->supplies);
+		if (ret)
+			return ret;
+		aic31xx->power = 1;
+
+		if (gpio_is_valid(aic31xx->pdata.gpio_reset)) {
+			gpio_set_value(aic31xx->pdata.gpio_reset, 1);
+			udelay(100);
+		}
+		snd_soc_write(codec, AIC31XX_RESET, 0x01);
+		udelay(100);
+		regcache_cache_only(aic31xx->regmap, false);
+		ret = regcache_sync(aic31xx->regmap);
+		if (ret != 0) {
+			dev_err(codec->dev,
+				"Failed to restore cache: %d\n", ret);
+			regcache_cache_only(aic31xx->regmap, true);
+			regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies),
+					       aic31xx->supplies);
+			return ret;
+		}
+	} else {
+		/*
+		 * Do soft reset to this codec instance in order to clear
+		 * possible VDD leakage currents in case the supply regulators
+		 * remain on
+		 */
+
+		snd_soc_write(codec, AIC31XX_RESET, 0x01);
+		regcache_cache_only(aic31xx->regmap, true);
+
+		if (gpio_is_valid(aic31xx->pdata.gpio_reset))
+			gpio_set_value(aic31xx->pdata.gpio_reset, 0);
+		aic31xx->power = 0;
+		ret = regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies),
+					     aic31xx->supplies);
+		regcache_mark_dirty(aic31xx->regmap);
+	}
+
+	return ret;
+}
+
+static int aic31xx_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__,
+		codec->dapm.bias_level, level);
+
+	switch (level) {
+	/* full On */
+	case SND_SOC_BIAS_ON:
+		/* All power is driven by DAPM system*/
+		break;
+	/* partial On */
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	/* Off, with power */
+	case SND_SOC_BIAS_STANDBY:
+		aic31xx_set_power(codec, 1);
+		break;
+	/* Off, without power */
+	case SND_SOC_BIAS_OFF:
+		aic31xx_set_power(codec, 0);
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+
+static int aic31xx_suspend(struct snd_soc_codec *codec)
+{
+	aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int aic31xx_resume(struct snd_soc_codec *codec)
+{
+	aic31xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+
+static int aic31xx_codec_probe(struct snd_soc_codec *codec)
+{
+	int ret = 0;
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	int i;
+
+	dev_dbg(aic31xx->dev, "## %s\n", __func__);
+
+	aic31xx = snd_soc_codec_get_drvdata(codec);
+	codec->control_data = aic31xx->regmap;
+
+	aic31xx->codec = codec;
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+
+	if (ret != 0) {
+		dev_err(codec->dev, "snd_soc_codec_set_cache_io failed %d\n",
+			ret);
+		return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
+		aic31xx->disable_nb[i].nb.notifier_call =
+			aic31xx_regulator_event;
+		aic31xx->disable_nb[i].aic31xx = aic31xx;
+		ret = regulator_register_notifier(aic31xx->supplies[i].consumer,
+						  &aic31xx->disable_nb[i].nb);
+		if (ret) {
+			dev_err(codec->dev,
+				"Failed to request regulator notifier: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	regcache_cache_only(aic31xx->regmap, true);
+	regcache_mark_dirty(aic31xx->regmap);
+
+	aic31xx_add_controls(codec);
+	aic31xx_add_widgets(codec);
+
+	return ret;
+}
+
+static int aic31xx_codec_remove(struct snd_soc_codec *codec)
+{
+	struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
+	int i;
+	/* power down chip */
+	aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
+		regulator_unregister_notifier(aic31xx->supplies[i].consumer,
+					      &aic31xx->disable_nb[i].nb);
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_driver_aic31xx = {
+	.probe			= aic31xx_codec_probe,
+	.remove			= aic31xx_codec_remove,
+	.suspend		= aic31xx_suspend,
+	.resume			= aic31xx_resume,
+	.set_bias_level		= aic31xx_set_bias_level,
+	.controls		= aic31xx_snd_controls,
+	.num_controls		= ARRAY_SIZE(aic31xx_snd_controls),
+	.dapm_widgets		= aic31xx_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(aic31xx_dapm_widgets),
+	.dapm_routes		= aic31xx_audio_map,
+	.num_dapm_routes	= ARRAY_SIZE(aic31xx_audio_map),
+};
+
+static struct snd_soc_dai_ops aic31xx_dai_ops = {
+	.hw_params	= aic31xx_hw_params,
+	.set_sysclk	= aic31xx_set_dai_sysclk,
+	.set_fmt	= aic31xx_set_dai_fmt,
+	.digital_mute	= aic31xx_dac_mute,
+};
+
+static struct snd_soc_dai_driver aic31xx_dai_driver[] = {
+	{
+		.name = "tlv320aic31xx-hifi",
+		.playback = {
+			.stream_name	 = "Playback",
+			.channels_min	 = 1,
+			.channels_max	 = 2,
+			.rates		 = AIC31XX_RATES,
+			.formats	 = AIC31XX_FORMATS,
+		},
+		.capture = {
+			.stream_name	 = "Capture",
+			.channels_min	 = 1,
+			.channels_max	 = 2,
+			.rates		 = AIC31XX_RATES,
+			.formats	 = AIC31XX_FORMATS,
+		},
+		.ops = &aic31xx_dai_ops,
+	}
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id tlv320aic31xx_of_match[] = {
+	{ .compatible = "ti,tlv320aic310x" },
+	{ .compatible = "ti,tlv320aic311x" },
+	{ .compatible = "ti,tlv320aic3100" },
+	{ .compatible = "ti,tlv320aic3110" },
+	{ .compatible = "ti,tlv320aic3120" },
+	{ .compatible = "ti,tlv320aic3111" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match);
+
+static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
+{
+	struct device_node *np = aic31xx->dev->of_node;
+	unsigned int value = 0;
+	int ret;
+
+	of_property_read_u32(np, "ai31xx-micbias-vg", &value);
+	switch (value) {
+	case 1:
+		aic31xx->pdata.micbias_vg = AIC31XX_MICBIAS_2_0V;
+		break;
+	case 2:
+		aic31xx->pdata.micbias_vg = AIC31XX_MICBIAS_2_5V;
+		break;
+	case 3:
+		aic31xx->pdata.micbias_vg = AIC31XX_MICBIAS_AVDDV;
+		break;
+	default:
+		dev_err(aic31xx->dev,
+			"Bad ai31xx-micbias-vg value %d DT\n",
+			value);
+		/* fallthrough */
+	case 0:
+		aic31xx->pdata.micbias_vg = AIC31XX_MICBIAS_OFF;
+	}
+
+	ret = of_get_named_gpio(np, "gpio-reset", 0);
+	if (ret > 0)
+		aic31xx->pdata.gpio_reset = ret;
+}
+#else /* CONFIG_OF */
+static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx)
+{
+}
+#endif /* CONFIG_OF */
+
+void aic31xx_device_init(struct aic31xx_priv *aic31xx)
+{
+	int ret, i;
+
+	dev_set_drvdata(aic31xx->dev, aic31xx);
+
+	if (dev_get_platdata(aic31xx->dev))
+		memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev),
+		       sizeof(aic31xx->pdata));
+	else if (aic31xx->dev->of_node)
+		aic31xx_pdata_from_of(aic31xx);
+
+	if (aic31xx->pdata.gpio_reset) {
+		ret = devm_gpio_request_one(aic31xx->dev,
+					    aic31xx->pdata.gpio_reset,
+					    GPIOF_OUT_INIT_HIGH,
+					    "aic31xx-reset-pin");
+		if (ret < 0) {
+			dev_err(aic31xx->dev, "not able to acquire gpio\n");
+			return;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
+		aic31xx->supplies[i].supply = aic31xx_supply_names[i];
+
+	ret = devm_regulator_bulk_get(aic31xx->dev,
+				      ARRAY_SIZE(aic31xx->supplies),
+				      aic31xx->supplies);
+	if (ret != 0)
+		dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret);
+
+}
+
+static int aic31xx_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
+{
+	struct aic31xx_priv *aic31xx;
+	int ret;
+	const struct regmap_config *regmap_config;
+
+	dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__,
+		id->name, (int) id->driver_data);
+
+	regmap_config = &aic31xx_i2c_regmap;
+
+	aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL);
+	if (aic31xx == NULL)
+		return -ENOMEM;
+
+	aic31xx->regmap = devm_regmap_init_i2c(i2c, regmap_config);
+
+	if (IS_ERR(aic31xx->regmap)) {
+		ret = PTR_ERR(aic31xx->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+	aic31xx->dev = &i2c->dev;
+
+	aic31xx->pdata.codec_type = id->driver_data;
+
+	aic31xx_device_init(aic31xx);
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx,
+				     aic31xx_dai_driver,
+				     ARRAY_SIZE(aic31xx_dai_driver));
+
+	return ret;
+}
+
+static int aic31xx_i2c_remove(struct i2c_client *i2c)
+{
+	struct aic31xx_priv *aic31xx = dev_get_drvdata(&i2c->dev);
+
+	kfree(aic31xx);
+	return 0;
+}
+
+static const struct i2c_device_id aic31xx_i2c_id[] = {
+	{ "tlv320aic310x", AIC3100 },
+	{ "tlv320aic311x", AIC3110 },
+	{ "tlv320aic3100", AIC3100 },
+	{ "tlv320aic3110", AIC3110 },
+	{ "tlv320aic3120", AIC3120 },
+	{ "tlv320aic3111", AIC3111 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id);
+
+static struct i2c_driver aic31xx_i2c_driver = {
+	.driver = {
+		.name	= "tlv320aic31xx-codec",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(tlv320aic31xx_of_match),
+	},
+	.probe		= aic31xx_i2c_probe,
+	.remove		= (aic31xx_i2c_remove),
+	.id_table	= aic31xx_i2c_id,
+};
+
+module_i2c_driver(aic31xx_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC3111 codec driver");
+MODULE_AUTHOR("Jyri Sarha");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h
new file mode 100644
index 0000000..28d1326
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic31xx.h
@@ -0,0 +1,265 @@
+/*
+ * ALSA SoC TLV320AIC31XX codec driver
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#ifndef _TLV320AIC31XX_H
+#define _TLV320AIC31XX_H
+
+#define AIC31XX_RATES	SNDRV_PCM_RATE_8000_192000
+
+#define AIC31XX_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+			 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+
+#define AIC31XX_STEREO_CLASS_D_BIT	0x1
+#define AIC31XX_MINIDSP_BIT		0x2
+
+enum aic31xx_type {
+	AIC3100	= 0,
+	AIC3110 = AIC31XX_STEREO_CLASS_D_BIT,
+	AIC3120 = AIC31XX_MINIDSP_BIT,
+	AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT),
+};
+
+enum aic31xx_micbias_voltage {
+	AIC31XX_MICBIAS_OFF = 0,
+	AIC31XX_MICBIAS_2_0V = 1,
+	AIC31XX_MICBIAS_2_5V = 2,
+	AIC31XX_MICBIAS_AVDDV = 3,
+};
+
+struct aic31xx_pdata {
+	enum aic31xx_type codec_type;
+	unsigned int gpio_reset;
+	enum aic31xx_micbias_voltage micbias_vg;
+};
+
+/* Page Control Register */
+#define AIC31XX_PAGECTL				0x00
+
+/* Page 0 Registers */
+/* Software reset register */
+#define AIC31XX_RESET				0x01
+/* OT FLAG register */
+#define AIC31XX_OT_FLAG				0x03
+/* Clock clock Gen muxing, Multiplexers*/
+#define AIC31XX_CLKMUX				0x04
+/* PLL P and R-VAL register */
+#define AIC31XX_PLLPR				0x05
+/* PLL J-VAL register */
+#define AIC31XX_PLLJ				0x06
+/* PLL D-VAL MSB register */
+#define AIC31XX_PLLDMSB				0x07
+/* PLL D-VAL LSB register */
+#define AIC31XX_PLLDLSB				0x08
+/* DAC NDAC_VAL register*/
+#define AIC31XX_NDAC				0x0B
+/* DAC MDAC_VAL register */
+#define AIC31XX_MDAC				0x0C
+/* DAC OSR setting register 1, MSB value */
+#define AIC31XX_DOSRMSB				0x0D
+/* DAC OSR setting register 2, LSB value */
+#define AIC31XX_DOSRLSB				0x0E
+#define AIC31XX_MINI_DSP_INPOL			0x10
+/* Clock setting register 8, PLL */
+#define AIC31XX_NADC				0x12
+/* Clock setting register 9, PLL */
+#define AIC31XX_MADC				0x13
+/* ADC Oversampling (AOSR) Register */
+#define AIC31XX_AOSR				0x14
+/* Clock setting register 9, Multiplexers */
+#define AIC31XX_CLKOUTMUX			0x19
+/* Clock setting register 10, CLOCKOUT M divider value */
+#define AIC31XX_CLKOUTMVAL			0x1A
+/* Audio Interface Setting Register 1 */
+#define AIC31XX_IFACE1				0x1B
+/* Audio Data Slot Offset Programming */
+#define AIC31XX_DATA_OFFSET			0x1C
+/* Audio Interface Setting Register 2 */
+#define AIC31XX_IFACE2				0x1D
+/* Clock setting register 11, BCLK N Divider */
+#define AIC31XX_BCLKN				0x1E
+/* Audio Interface Setting Register 3, Secondary Audio Interface */
+#define AIC31XX_IFACESEC1			0x1F
+/* Audio Interface Setting Register 4 */
+#define AIC31XX_IFACESEC2			0x20
+/* Audio Interface Setting Register 5 */
+#define AIC31XX_IFACESEC3			0x21
+/* I2C Bus Condition */
+#define AIC31XX_I2C				0x22
+/* ADC FLAG */
+#define AIC31XX_ADCFLAG				0x24
+/* DAC Flag Registers */
+#define AIC31XX_DACFLAG1			0x25
+#define AIC31XX_DACFLAG2			0x26
+/* Sticky Interrupt flag (overflow) */
+#define AIC31XX_OFFLAG				0x27
+/* Sticy DAC Interrupt flags */
+#define AIC31XX_INTRDACFLAG			0x2C
+/* Sticy ADC Interrupt flags */
+#define AIC31XX_INTRADCFLAG			0x2D
+/* DAC Interrupt flags 2 */
+#define AIC31XX_INTRDACFLAG2			0x2E
+/* ADC Interrupt flags 2 */
+#define AIC31XX_INTRADCFLAG2			0x2F
+/* INT1 interrupt control */
+#define AIC31XX_INT1CTRL			0x30
+/* INT2 interrupt control */
+#define AIC31XX_INT2CTRL			0x31
+/* GPIO1 control */
+#define AIC31XX_GPIO1				0x33
+
+#define AIC31XX_DACPRB				0x3C
+/* ADC Instruction Set Register */
+#define AIC31XX_ADCPRB				0x3D
+/* DAC channel setup register */
+#define AIC31XX_DACSETUP			0x3F
+/* DAC Mute and volume control register */
+#define AIC31XX_DACMUTE				0x40
+/* Left DAC channel digital volume control */
+#define AIC31XX_LDACVOL				0x41
+/* Right DAC channel digital volume control */
+#define AIC31XX_RDACVOL				0x42
+/* Headset detection */
+#define AIC31XX_HSDETECT			0x43
+/* ADC Digital Mic */
+#define AIC31XX_ADCSETUP			0x51
+/* ADC Digital Volume Control Fine Adjust */
+#define AIC31XX_ADCFGA				0x52
+/* ADC Digital Volume Control Coarse Adjust */
+#define AIC31XX_ADCVOL				0x53
+
+
+/* Page 1 Registers */
+/* Headphone drivers */
+#define AIC31XX_HPDRIVER			0x9F
+/* Class-D Speakear Amplifier */
+#define AIC31XX_SPKAMP				0xA0
+/* HP Output Drivers POP Removal Settings */
+#define AIC31XX_HPPOP				0xA1
+/* Output Driver PGA Ramp-Down Period Control */
+#define AIC31XX_SPPGARAMP			0xA2
+/* DAC_L and DAC_R Output Mixer Routing */
+#define AIC31XX_DACMIXERROUTE			0xA3
+/* Left Analog Vol to HPL */
+#define AIC31XX_LANALOGHPL			0xA4
+/* Right Analog Vol to HPR */
+#define AIC31XX_RANALOGHPR			0xA5
+/* Left Analog Vol to SPL */
+#define AIC31XX_LANALOGSPL			0xA6
+/* Right Analog Vol to SPR */
+#define AIC31XX_RANALOGSPR			0xA7
+/* HPL Driver */
+#define AIC31XX_HPLGAIN				0xA8
+/* HPR Driver */
+#define AIC31XX_HPRGAIN				0xA9
+/* SPL Driver */
+#define AIC31XX_SPLGAIN				0xAA
+/* SPR Driver */
+#define AIC31XX_SPRGAIN				0xAB
+/* HP Driver Control */
+#define AIC31XX_HPCONTROL			0xAC
+/* MIC Bias Control */
+#define AIC31XX_MICBIAS				0xAE
+/* MIC PGA*/
+#define AIC31XX_MICPGA				0xAF
+/* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */
+#define AIC31XX_MICPGAPI			0xB0
+/* ADC Input Selection for M-Terminal */
+#define AIC31XX_MICPGAMI			0xB1
+/* Input CM Settings */
+#define AIC31XX_MICPGACM			0xB2
+
+/* Bits, masks and shifts */
+
+/* AIC31XX_CLKMUX */
+#define AIC31XX_PLL_CLKIN_MASK			0x0c
+#define AIC31XX_PLL_CLKIN_SHIFT			2
+#define AIC31XX_PLL_CLKIN_MCLK			0
+#define AIC31XX_CODEC_CLKIN_MASK		0x03
+#define AIC31XX_CODEC_CLKIN_SHIFT		0
+#define AIC31XX_CODEC_CLKIN_PLL			3
+#define AIC31XX_CODEC_CLKIN_BCLK		1
+
+/* AIC31XX_PLLPR, AIC31XX_NDAC, AIC31XX_MDAC, AIC31XX_NADC, AIC31XX_MADC,
+   AIC31XX_BCLKN */
+#define AIC31XX_PLL_MASK		0x7f
+#define AIC31XX_PM_MASK			0x80
+
+/* AIC31XX_IFACE1 */
+#define AIC31XX_WORD_LEN_16BITS		0x00
+#define AIC31XX_WORD_LEN_20BITS		0x01
+#define AIC31XX_WORD_LEN_24BITS		0x02
+#define AIC31XX_WORD_LEN_32BITS		0x03
+#define AIC31XX_IFACE1_DATALEN_MASK	0x30
+#define AIC31XX_IFACE1_DATALEN_SHIFT	(4)
+#define AIC31XX_IFACE1_DATATYPE_MASK	0xC0
+#define AIC31XX_IFACE1_DATATYPE_SHIFT	(6)
+#define AIC31XX_I2S_MODE		0x00
+#define AIC31XX_DSP_MODE		0x01
+#define AIC31XX_RIGHT_JUSTIFIED_MODE	0x02
+#define AIC31XX_LEFT_JUSTIFIED_MODE	0x03
+#define AIC31XX_IFACE1_MASTER_MASK	0x0C
+#define AIC31XX_BCLK_MASTER		0x08
+#define AIC31XX_WCLK_MASTER		0x04
+
+/* AIC31XX_DATA_OFFSET */
+#define AIC31XX_DATA_OFFSET_MASK	0xFF
+
+/* AIC31XX_IFACE2 */
+#define AIC31XX_BCLKINV_MASK		0x08
+#define AIC31XX_BDIVCLK_MASK		0x03
+#define AIC31XX_DAC2BCLK		0x00
+#define AIC31XX_DACMOD2BCLK		0x01
+#define AIC31XX_ADC2BCLK		0x02
+#define AIC31XX_ADCMOD2BCLK		0x03
+
+/* AIC31XX_ADCFLAG */
+#define AIC31XX_ADCPWRSTATUS_MASK		0x40
+
+/* AIC31XX_DACFLAG1 */
+#define AIC31XX_LDACPWRSTATUS_MASK		0x80
+#define AIC31XX_RDACPWRSTATUS_MASK		0x08
+#define AIC31XX_HPLDRVPWRSTATUS_MASK		0x20
+#define AIC31XX_HPRDRVPWRSTATUS_MASK		0x02
+#define AIC31XX_SPLDRVPWRSTATUS_MASK		0x10
+#define AIC31XX_SPRDRVPWRSTATUS_MASK		0x01
+
+/* AIC31XX_INTRDACFLAG */
+#define AIC31XX_HPSCDETECT_MASK			0x80
+#define AIC31XX_BUTTONPRESS_MASK		0x20
+#define AIC31XX_HSPLUG_MASK			0x10
+#define AIC31XX_LDRCTHRES_MASK			0x08
+#define AIC31XX_RDRCTHRES_MASK			0x04
+#define AIC31XX_DACSINT_MASK			0x02
+#define AIC31XX_DACAINT_MASK			0x01
+
+/* AIC31XX_INT1CTRL */
+#define AIC31XX_HSPLUGDET_MASK			0x80
+#define AIC31XX_BUTTONPRESSDET_MASK		0x40
+#define AIC31XX_DRCTHRES_MASK			0x20
+#define AIC31XX_AGCNOISE_MASK			0x10
+#define AIC31XX_OC_MASK				0x08
+#define AIC31XX_ENGINE_MASK			0x04
+
+/* AIC31XX_DACSETUP */
+#define AIC31XX_SOFTSTEP_MASK			0x03
+
+/* AIC31XX_DACMUTE */
+#define AIC31XX_DACMUTE_MASK			0x0C
+
+/* AIC31XX_MICBIAS */
+#define AIC31XX_MICBIAS_MASK			0x03
+#define AIC31XX_MICBIAS_SHIFT			0
+
+#endif	/* _TLV320AIC31XX_H */
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH RFC 2/5] ASoC: tlv320aic31xx: Add codec driver to Makefile and Kconfig
From: Jyri Sarha @ 2014-02-26  9:14 UTC (permalink / raw)
  To: linux-omap, alsa-devel, devicetree, bcousson, broonie
  Cc: peter.ujfalusi, detheridge, Jyri Sarha
In-Reply-To: <cover.1393405575.git.jsarha@ti.com>

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 sound/soc/codecs/Kconfig  |    4 ++++
 sound/soc/codecs/Makefile |    2 ++
 2 files changed, 6 insertions(+)

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 983d087a..ead9dc5 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -74,6 +74,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_TLV320AIC23 if I2C
 	select SND_SOC_TLV320AIC26 if SPI_MASTER
 	select SND_SOC_TLV320AIC32X4 if I2C
+	select SND_SOC_TLV320AIC31XX if I2C
 	select SND_SOC_TLV320AIC3X if I2C
 	select SND_SOC_TPA6130A2 if I2C
 	select SND_SOC_TLV320DAC33 if I2C
@@ -364,6 +365,9 @@ config SND_SOC_TLV320AIC26
 config SND_SOC_TLV320AIC32X4
 	tristate
 
+config SND_SOC_TLV320AIC31XX
+        tristate
+
 config SND_SOC_TLV320AIC3X
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc12676..23f8042 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -64,6 +64,7 @@ snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
+snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
 snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
 snd-soc-tlv320dac33-objs := tlv320dac33.o
@@ -194,6 +195,7 @@ obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
+obj-$(CONFIG_SND_SOC_TLV320AIC31XX)     += snd-soc-tlv320aic31xx.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
 obj-$(CONFIG_SND_SOC_TLV320AIC32X4)     += snd-soc-tlv320aic32x4.o
 obj-$(CONFIG_SND_SOC_TLV320DAC33)	+= snd-soc-tlv320dac33.o
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH RFC 3/5] ASoC: tlv320aic31xx: Add DT binding document
From: Jyri Sarha @ 2014-02-26  9:14 UTC (permalink / raw)
  To: linux-omap, alsa-devel, devicetree, bcousson, broonie
  Cc: peter.ujfalusi, detheridge, Jyri Sarha
In-Reply-To: <cover.1393405575.git.jsarha@ti.com>

Initial version of tlv320aic31xx device tree bindings document.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 .../devicetree/bindings/sound/tlv320aic31xx.txt    |   57 ++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic31xx.txt

diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
new file mode 100644
index 0000000..a512b4e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
@@ -0,0 +1,57 @@
+Texas Instruments - tlv320aic31xx Codec module
+
+The tlv320aic31xx serial control bus communicates through I2C protocols
+
+Required properties:
+
+- compatible - "string" - One of:
+    "ti,tlv320aic310x" - Generic TLV320AIC31xx with mono speaker amp
+    "ti,tlv320aic311x" - Generic TLV320AIC31xx with stereo speaker amp
+    "ti,tlv320aic3100" - TLV320AIC3100 (mono speaker amp, no MiniDSP)
+    "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP)
+    "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP)
+    "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP)
+
+- reg - <int> -  I2C slave address
+
+
+Optional properties:
+
+- gpio-reset - gpio pin number used for codec reset
+- ai31xx-micbias-vg - MicBias Voltage required.
+	1 - MICBIAS output is powered to 2.0V,
+	2 - MICBIAS output is powered to 2.5V,
+	3 - MICBIAS output is connected to AVDD,
+	If this node is not mentioned or if the value is incorrect, then MicBias
+	is powered down.
+- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply,
+  DVDD-supply : power supplies for the device as covered in
+  Documentation/devicetree/bindings/regulator/regulator.txt
+
+CODEC output pins:
+  * HPL
+  * HPR
+  * SPL, devices with stereo speaker amp
+  * SPR, devices with stereo speaker amp
+  * SPK, devices with mono speaker amp
+
+CODEC input pins:
+  * MIC1LP
+  * MIC1RP
+  * MIC1LM
+
+The pins can be used in referring sound node's audio-routing property.
+
+Example:
+
+tlv320aic31xx: tlv320aic31xx@18 {
+	compatible = "ti,tlv320aic311x";
+	reg = <0x18>;
+
+	HPVDD-supply = <&regulator>;
+	SPRVDD-supply = <&regulator>;
+	SPLVDD-supply = <&regulator>;
+	AVDD-supply = <&regulator>;
+	IOVDD-supply = <&regulator>;
+	DVDD-supply = <&regulator>;
+};
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH RFC 4/5] ASoC: davinci-evm: Add AM43xx-EPOS-EVM audio support
From: Jyri Sarha @ 2014-02-26  9:14 UTC (permalink / raw)
  To: linux-omap, alsa-devel, devicetree, bcousson, broonie
  Cc: peter.ujfalusi, detheridge, Jyri Sarha
In-Reply-To: <cover.1393405575.git.jsarha@ti.com>

Add machine driver support for AM43xx-ePOS-EVM and update associated
device tree binding document.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 .../bindings/sound/davinci-evm-audio.txt           |    9 +++--
 sound/soc/davinci/davinci-evm.c                    |   41 ++++++++++++++++++++
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
index 865178d..356cba1 100644
--- a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
@@ -2,8 +2,10 @@
 
 Required properties:
 - compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx
+  	     : "ti,am43xx-epos-evm-audio" : for am43xx-epos-evm
 - ti,model : The user-visible name of this sound complex.
-- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
+- ti,audio-codec : The phandle of the TLV320AIC3x audio codec,
+  		   or the TLV320AIC31xx audio codec.
 - ti,mcasp-controller : The phandle of the McASP controller
 - ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
 - ti,audio-routing : A list of the connections between audio components.
@@ -14,9 +16,10 @@ Required properties:
   Board connectors:
 
   * Headphone Jack
-  * Line Out
+  * Line Out - "ti,da830-evm-audio" only
   * Mic Jack
-  * Line In
+  * Line In - "ti,da830-evm-audio" only
+  * Speaker - "ti,am43xx-epos-evm-audio" only
 
 
 Example:
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 5e3bc3c..d4d965e 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -128,6 +128,33 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 }
 
+static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+/* Logic for EVMs with an aic31xx */
+static int evm_aic31xx_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct device_node *np = codec->card->dev->of_node;
+	int ret;
+
+	snd_soc_dapm_new_controls(dapm, aic31xx_dapm_widgets,
+				  ARRAY_SIZE(aic31xx_dapm_widgets));
+
+	if (np) {
+		ret = snd_soc_of_parse_audio_routing(codec->card,
+						     "ti,audio-routing");
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 /* davinci-evm digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link dm6446_evm_dai = {
 	.name = "TLV320AIC3X",
@@ -326,11 +353,25 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
 		   SND_SOC_DAIFMT_IB_NF,
 };
 
+static struct snd_soc_dai_link evm_dai_tlv320aic3111 = {
+	.name		= "TLV320AIC3111",
+	.stream_name	= "AIC3111",
+	.codec_dai_name	= "tlv320aic31xx-hifi",
+	.ops		= &evm_ops,
+	.init		= evm_aic31xx_init,
+	.dai_fmt	= (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_DSP_B |
+			   SND_SOC_DAIFMT_IB_NF),
+};
+
 static const struct of_device_id davinci_evm_dt_ids[] = {
 	{
 		.compatible = "ti,da830-evm-audio",
 		.data = (void *) &evm_dai_tlv320aic3x,
 	},
+	{
+		.compatible = "ti,am43xx-epos-evm-audio",
+		.data = &evm_dai_tlv320aic3111,
+	},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH RFC 5/5] ASoC: davinci: Add SND_AM43XX_SOC_EPOS_EVM build option
From: Jyri Sarha @ 2014-02-26  9:14 UTC (permalink / raw)
  To: linux-omap, alsa-devel, devicetree, bcousson, broonie
  Cc: peter.ujfalusi, detheridge, Jyri Sarha
In-Reply-To: <cover.1393405575.git.jsarha@ti.com>

Add support for am335x and am43x based boards with tlv320aic31xx
compatible codec connected to McASP.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 sound/soc/davinci/Kconfig  |   12 ++++++++++++
 sound/soc/davinci/Makefile |    1 +
 2 files changed, 13 insertions(+)

diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index a8ec1fc..e1e3663 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -26,6 +26,18 @@ config SND_AM33XX_SOC_EVM
 	  AM335X-EVMSK, and BeagelBone with AudioCape boards have this
 	  setup.
 
+config SND_AM43XX_SOC_EPOS_EVM
+	tristate "SoC Audio for the AM33XX/AM43XX and TLV320AIC31XX based board"
+	depends on SND_DAVINCI_SOC
+	depends on SOC_AM33XX || SOC_AM43XX
+	select SND_SOC_TLV320AIC31XX
+	select SND_DAVINCI_SOC_MCASP
+	help
+	  Say Y or M if you want to add support for SoC audio on
+	  AM335X/AM43XX boards using McASP to connect to a codec of
+	  TLV320AIC31XX series. For example AM43XX-EPOS-EVM has such a
+	  setup.
+
 config SND_DAVINCI_SOC_EVM
 	tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
 	depends on SND_DAVINCI_SOC
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index 744d4d9..d61998f 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
 snd-soc-evm-objs := davinci-evm.o
 
 obj-$(CONFIG_SND_DAVINCI_SOC_GENERIC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_AM43XX_SOC_EPOS_EVM) += snd-soc-evm.o
-- 
1.7.9.5


^ permalink raw reply related

* Re: devicetree repository separation/migration
From: Sascha Hauer @ 2014-02-26  9:18 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Frank Rowand, Jason Cooper, Grant Likely, Rob Herring,
	pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	devicetree-spec-u79uwXL29TY76Z2rM5mHXA,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1393405232.16570.106.camel-ommiHX4a84BXesXXhkcM7miJhflN2719@public.gmane.org>

On Wed, Feb 26, 2014 at 09:00:32AM +0000, Ian Campbell wrote:
> On Tue, 2014-02-25 at 07:36 +0000, Ian Campbell wrote:
> > On Tue, 2014-02-25 at 08:26 +0100, Sascha Hauer wrote:
> > > On Mon, Feb 24, 2014 at 03:59:17PM +0000, Ian Campbell wrote:
> > > > On Fri, 2014-02-21 at 15:11 +0100, Sascha Hauer wrote:
> > > > > Ians dts repository is a good start, but it contains a complete kernel
> > > > > history and this is not very suitable as a submodule for other
> > > > > projects. 
> > > > 
> > > > It only contains the full history for the files which it contains, not a
> > > > complete kernel history. This is deliberate so that "git annotate" etc
> > > > still works to tell you where a particular line came from.
> > > 
> > > I have cloned git://xenbits.xen.org/people/ianc/device-tree-rebasing.git.
> > > .git is 843MB in size and after a 'git checkout v3.13' I see a vanilla v3.13
> > > checked out. I may have done something wrong, but I don't see what it
> > > could be.
> > 
> > There is a branch with the full Linux stuff in there too. It is needed
> > in the tree doing the conversion but doesn't really need to be
> > published. I pushed it in the early days without really thinking about
> > the size impact. I'll remove that stuff from the published tree.
> 
> Done. The tree now has only a master branch and the vX.Y-dts tags (it is
> still pushing the historical ones, they'll be there soon).
> 
> .git of a fresh clone is now 22M, which is more like it ;-)

I just cloned it. This is much more managable now. Thanks for doing
this.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe devicetree-spec" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFCv3 2/7] mfd: twl4030-madc: Add DT support and convert to IIO framework
From: Lee Jones @ 2014-02-26  9:26 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Sebastian Reichel, Marek Belisko, Jonathan Cameron, Samuel Ortiz,
	Lars-Peter Clausen, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1393374270-20079-3-git-send-email-sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>

> This converts twl4030-madc module to use the Industrial IO ADC
> framework and adds device tree support.
> 
> Signed-off-by: Sebastian Reichel <sre-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>
> ---
>  drivers/mfd/twl4030-madc.c | 122 ++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 115 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
> index 5458561..81484ee 100644
> --- a/drivers/mfd/twl4030-madc.c
> +++ b/drivers/mfd/twl4030-madc.c
> @@ -47,6 +47,8 @@
>  #include <linux/gfp.h>
>  #include <linux/err.h>
>  
> +#include <linux/iio/iio.h>
> +
>  /*
>   * struct twl4030_madc_data - a container for madc info
>   * @dev - pointer to device structure for madc
> @@ -59,10 +61,74 @@ struct twl4030_madc_data {
>  	struct device *dev;
>  	struct mutex lock;	/* mutex protecting this data structure */
>  	struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
> +	bool use_second_irq;

This should go into the same patch that adds the header doc, or visa
versa.

>  	int imr;
>  	int isr;
>  };
>  
> +static int twl4030_madc_read(struct iio_dev *iio_dev,
> +			     const struct iio_chan_spec *chan,
> +			     int *val, int *val2, long mask)
> +{
> +	struct twl4030_madc_data *madc = iio_priv(iio_dev);
> +	struct twl4030_madc_request req;
> +	int channel = chan->channel;

Does this really add anything you save 6 chars.

<snip>

>  	/*
>  	 * Phoenix provides 2 interrupt lines. The first one is connected to
>  	 * the OMAP. The other one can be connected to the other processor such
>  	 * as modem. Hence two separate ISR and IMR registers.
>  	 */
> -	madc->imr = (pdata->irq_line == 1) ?
> +	if (pdata)
> +		madc->use_second_irq = pdata->irq_line != 1;

Unconventional an unclear.

Stick the comparison in the if statement.

> +	else
> +		madc->use_second_irq = of_property_read_bool(np,
> +				       "ti,system-uses-second-madc-irq");
> +
> +	madc->imr = (madc->use_second_irq == 1) ?

madc->imr = madc->use_second_irq ? <blah> : <blah>;

>  	    TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
> -	madc->isr = (pdata->irq_line == 1) ?
> +	madc->isr = (madc->use_second_irq == 1) ?

Same here.

<snip>

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH RESEND v10 3/4] PHY: add APM X-Gene SoC 15Gbps Multi-purpose PHY driver
From: Kishon Vijay Abraham I @ 2014-02-26  9:42 UTC (permalink / raw)
  To: Loc Ho, tj
  Cc: devicetree, Suman Tripathi, arnd, jcm, patches, linux-kernel,
	ddutile, olof, Tuan Phan, linux-arm-kernel
In-Reply-To: <1393308882-3964-4-git-send-email-lho@apm.com>

On Tuesday 25 February 2014 11:44 AM, Loc Ho wrote:
> This patch adds support for APM X-Gene SoC 15Gbps Multi-purpose PHY.
> This is the physical layer interface for the corresponding host
> controller. Currently, only external clock and SATA mode
> are supported.
>
> Signed-off-by: Loc Ho <lho@apm.com>
> Signed-off-by: Tuan Phan <tphan@apm.com>
> Signed-off-by: Suman Tripathi <stripathi@apm.com>
> ---
>  drivers/phy/Kconfig     |    7 +
>  drivers/phy/Makefile    |    2 +
>  drivers/phy/phy-xgene.c | 1826 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1835 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/phy/phy-xgene.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index afa2354..229db49 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -64,4 +64,11 @@ config BCM_KONA_USB2_PHY
>  	help
>  	  Enable this to support the Broadcom Kona USB 2.0 PHY.
>
> +config PHY_XGENE
> +	tristate "APM X-Gene 15Gbps PHY support"
> +	depends on ARM64 || COMPILE_TEST
> +	select GENERIC_PHY

depends on HAS_IOMEM and CONFIG_OF..
> +	help
> +	  This option enables support for APM X-Gene SoC multi-purpose PHY.
> +
>  endmenu
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index b57c253..dee70f4 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -9,3 +9,5 @@ obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
>  obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
>  obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
>  obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
> +obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
> +
> diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c
> new file mode 100644
> index 0000000..653868d
> --- /dev/null
> +++ b/drivers/phy/phy-xgene.c
> @@ -0,0 +1,1826 @@
> +/*
> + * AppliedMicro X-Gene Multi-purpose PHY driver
> + *
> + * Copyright (c) 2014, Applied Micro Circuits Corporation
> + * Author: Loc Ho <lho@apm.com>
> + *         Tuan Phan <tphan@apm.com>
> + *         Suman Tripathi <stripathi@apm.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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * The APM X-Gene PHY consists of two PLL clock macro's (CMU) and lanes.
> + * The first PLL clock macro is used for internal reference clock. The second
> + * PLL clock macro is used to generate the clock for the PHY. This driver
> + * configures the first PLL CMU, the second PLL CMU, and programs the PHY to
> + * operate according to the mode of operation. The first PLL CMU is only
> + * required if internal clock is enabled.
> + *
> + * Logical Layer Out Of HW module units:
> + *
> + * -----------------
> + * | Internal      |    |------|
> + * | Ref PLL CMU   |----|      |     -------------    ---------
> + * ------------ ----    | MUX  |-----|PHY PLL CMU|----| Serdes|
> + *                      |      |     |           |    ---------
> + * External Clock ------|      |     -------------
> + *                      |------|
> + *
> + * The Ref PLL CMU CSR (Configureation System Registers) is accessed

%s/Configureation/Configuration
> + * indirectly from the SDS offset at 0x2000. It is only required for
> + * internal reference clock.
> + * The PHY PLL CMU CSR is accessed indirectly from the SDS offset at 0x0000.
> + * The Serdes CSR is accessed indirectly from the SDS offset at 0x0400.
> + *
> + * The Ref PLL CMU can be located within the same PHY IP or outside the PHY IP
> + * due to shared Ref PLL CMU. For PHY with Ref PLL CMU shared with another IP,
> + * it is located outside the PHY IP. This is the case for the PHY located
> + * at 0x1f23a000 (SATA Port 4/5). For such PHY, another resource is required
> + * to located the SDS/Ref PLL CMU module and its clock for that IP enabled.
> + *
> + * Currently, this driver only supports SATA mode with external clock.
> + */
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/delay.h>
> +#include <linux/phy/phy.h>
> +#include <linux/clk.h>
> +
> +/* Max 2 lanes per a PHY unit */
> +#define MAX_LANE			2
> +
> +/* Register offset inside the PHY */
> +#define SERDES_PLL_INDIRECT_OFFSET	0x0000
> +#define SERDES_PLL_REF_INDIRECT_OFFSET	0x2000
> +#define SERDES_INDIRECT_OFFSET		0x0400
> +#define SERDES_LANE_STRIDE		0x0200
> +
> +/* Some default Serdes parameters */
> +#define DEFAULT_SATA_TXBOOST_GAIN	{ 0x1e, 0x1e, 0x1e }
> +#define DEFAULT_SATA_TXEYEDIRECTION	{ 0x0, 0x0, 0x0 }
> +#define DEFAULT_SATA_TXEYETUNING	{ 0xa, 0xa, 0xa }
> +#define DEFAULT_SATA_SPD_SEL		{ 0x1, 0x3, 0x7 }
> +#define DEFAULT_SATA_TXAMP		{ 0x8, 0x8, 0x8 }
> +#define DEFAULT_SATA_TXCN1		{ 0x2, 0x2, 0x2 }
> +#define DEFAULT_SATA_TXCN2		{ 0x0, 0x0, 0x0 }
> +#define DEFAULT_SATA_TXCP1		{ 0xa, 0xa, 0xa }
> +
> +#define SATA_SPD_SEL_GEN3		0x7
> +#define SATA_SPD_SEL_GEN2		0x3
> +#define SATA_SPD_SEL_GEN1		0x1
> +
> +#define SSC_DISABLE			0
> +#define SSC_ENABLE			1
> +
> +#define FBDIV_VAL_50M			0x77
> +#define REFDIV_VAL_50M			0x1
> +#define FBDIV_VAL_100M			0x3B
> +#define REFDIV_VAL_100M			0x0
> +
> +/* SATA Clock/Reset CSR */
> +#define SATACLKENREG			0x00000000
> +#define  SATA0_CORE_CLKEN		0x00000002
> +#define  SATA1_CORE_CLKEN		0x00000004
> +#define SATASRESETREG			0x00000004
> +#define  SATA_MEM_RESET_MASK		0x00000020
> +#define  SATA_MEM_RESET_RD(src)		(((src) & 0x00000020) >> 5)
> +#define  SATA_SDS_RESET_MASK		0x00000004
> +#define  SATA_CSR_RESET_MASK		0x00000001
> +#define  SATA_CORE_RESET_MASK		0x00000002
> +#define  SATA_PMCLK_RESET_MASK		0x00000010
> +#define  SATA_PCLK_RESET_MASK		0x00000008
> +
> +/* SDS CSR used for PHY Indirect access */
> +#define SATA_ENET_SDS_PCS_CTL0		0x00000000
> +#define  REGSPEC_CFG_I_TX_WORDMODE0_SET(dst, src) \
> +		(((dst) & ~0x00070000) | (((u32)(src)<<16) & 0x00070000))
> +#define  REGSPEC_CFG_I_RX_WORDMODE0_SET(dst, src) \
> +		(((dst) & ~0x00e00000) | (((u32)(src)<<21) & 0x00e00000))
> +#define SATA_ENET_SDS_CTL0		0x0000000c
> +#define  REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(dst, src) \
> +		(((dst) & ~0x00007fff) | (((u32)(src)) & 0x00007fff))
> +#define SATA_ENET_SDS_CTL1		0x00000010
> +#define  CFG_I_SPD_SEL_CDR_OVR1_SET(dst, src) \
> +		(((dst) & ~0x0000000f) | (((u32)(src)) & 0x0000000f))
> +#define SATA_ENET_SDS_RST_CTL		0x00000024
> +#define SATA_ENET_SDS_IND_CMD_REG	0x0000003c
> +#define  CFG_IND_WR_CMD_MASK		0x00000001
> +#define  CFG_IND_RD_CMD_MASK		0x00000002
> +#define  CFG_IND_CMD_DONE_MASK		0x00000004
> +#define  CFG_IND_ADDR_SET(dst, src) \
> +		(((dst) & ~0x003ffff0) | (((u32)(src)<<4) & 0x003ffff0))
> +#define SATA_ENET_SDS_IND_RDATA_REG	0x00000040
> +#define SATA_ENET_SDS_IND_WDATA_REG	0x00000044
> +#define SATA_ENET_CLK_MACRO_REG		0x0000004c
> +#define  I_RESET_B_SET(dst, src) \
> +		(((dst) & ~0x00000001) | (((u32)(src)) & 0x00000001))
> +#define  I_PLL_FBDIV_SET(dst, src) \
> +		(((dst) & ~0x001ff000) | (((u32)(src)<<12) & 0x001ff000))
> +#define  I_CUSTOMEROV_SET(dst, src) \
> +		(((dst) & ~0x00000f80) | (((u32)(src)<<7) & 0x00000f80))
> +#define  O_PLL_LOCK_RD(src)		(((src) & 0x40000000)>>30)
> +#define  O_PLL_READY_RD(src)		(((src) & 0x80000000)>>31)
> +
> +/* PLL Clock Macro Unit (CMU) CSR accessing from SDS indirectly */
> +#define CMU_REG0			0x00000
> +#define  CMU_REG0_PLL_REF_SEL_MASK	0x00002000
> +#define  CMU_REG0_PLL_REF_SEL_SET(dst, src)	\
> +		(((dst) & ~0x00002000) | (((u32)(src) << 0xd) & 0x00002000))

using decimals for shift value would be better. No strong feeling though.
> +#define  CMU_REG0_PDOWN_MASK		0x00004000
> +#define  CMU_REG0_CAL_COUNT_RESOL_SET(dst, src) \
> +		(((dst) & ~0x000000e0) | (((u32)(src) << 0x5) & 0x000000e0))
> +#define CMU_REG1			0x00002
> +#define  CMU_REG1_PLL_CP_SET(dst, src) \
> +		(((dst) & ~0x00003c00) | (((u32)(src) << 0xa) & 0x00003c00))
> +#define  CMU_REG1_PLL_MANUALCAL_SET(dst, src) \
> +		(((dst) & ~0x00000008) | (((u32)(src) << 0x3) & 0x00000008))
> +#define  CMU_REG1_PLL_CP_SEL_SET(dst, src) \
> +		(((dst) & ~0x000003e0) | (((u32)(src) << 0x5) & 0x000003e0))
> +#define  CMU_REG1_REFCLK_CMOS_SEL_MASK	0x00000001
> +#define  CMU_REG1_REFCLK_CMOS_SEL_SET(dst, src)	\
> +		(((dst) & ~0x00000001) | (((u32)(src) << 0x0) & 0x00000001))
> +#define CMU_REG2			0x00004
> +#define  CMU_REG2_PLL_REFDIV_SET(dst, src) \
> +		(((dst) & ~0x0000c000) | (((u32)(src) << 0xe) & 0x0000c000))
> +#define  CMU_REG2_PLL_LFRES_SET(dst, src) \
> +		(((dst) & ~0x0000001e) | (((u32)(src) << 0x1) & 0x0000001e))
> +#define  CMU_REG2_PLL_FBDIV_SET(dst, src) \
> +		(((dst) & ~0x00003fe0) | (((u32)(src) << 0x5) & 0x00003fe0))
> +#define CMU_REG3			0x00006
> +#define  CMU_REG3_VCOVARSEL_SET(dst, src) \
> +		(((dst) & ~0x0000000f) | (((u32)(src) << 0x0) & 0x0000000f))
> +#define  CMU_REG3_VCO_MOMSEL_INIT_SET(dst, src) \
> +		(((dst) & ~0x000003f0) | (((u32)(src) << 0x4) & 0x000003f0))
> +#define  CMU_REG3_VCO_MANMOMSEL_SET(dst, src) \
> +		(((dst) & ~0x0000fc00) | (((u32)(src) << 0xa) & 0x0000fc00))
> +#define CMU_REG4			0x00008
> +#define CMU_REG5			0x0000a
> +#define  CMU_REG5_PLL_LFSMCAP_SET(dst, src) \
> +		(((dst) & ~0x0000c000) | (((u32)(src) << 0xe) & 0x0000c000))
> +#define  CMU_REG5_PLL_LOCK_RESOLUTION_SET(dst, src) \
> +		(((dst) & ~0x0000000e) | (((u32)(src) << 0x1) & 0x0000000e))
> +#define  CMU_REG5_PLL_LFCAP_SET(dst, src) \
> +		(((dst) & ~0x00003000) | (((u32)(src) << 0xc) & 0x00003000))
> +#define  CMU_REG5_PLL_RESETB_MASK	0x00000001
> +#define CMU_REG6			0x0000c
> +#define  CMU_REG6_PLL_VREGTRIM_SET(dst, src) \
> +		(((dst) & ~0x00000600) | (((u32)(src) << 0x9) & 0x00000600))
> +#define  CMU_REG6_MAN_PVT_CAL_SET(dst, src) \
> +		(((dst) & ~0x00000004) | (((u32)(src) << 0x2) & 0x00000004))
> +#define CMU_REG7			0x0000e
> +#define  CMU_REG7_PLL_CALIB_DONE_RD(src) \
> +		((0x00004000 & (u32)(src)) >> 0xe)
> +#define  CMU_REG7_VCO_CAL_FAIL_RD(src) \
> +		((0x00000c00 & (u32)(src)) >> 0xa)
> +#define CMU_REG8			0x00010
> +#define CMU_REG9			0x00012
> +#define  CMU_REG9_WORD_LEN_8BIT		0x000
> +#define  CMU_REG9_WORD_LEN_10BIT	0x001
> +#define  CMU_REG9_WORD_LEN_16BIT	0x002
> +#define  CMU_REG9_WORD_LEN_20BIT	0x003
> +#define  CMU_REG9_WORD_LEN_32BIT	0x004
> +#define  CMU_REG9_WORD_LEN_40BIT	0x005
> +#define  CMU_REG9_WORD_LEN_64BIT	0x006
> +#define  CMU_REG9_WORD_LEN_66BIT	0x007
> +#define  CMU_REG9_TX_WORD_MODE_CH1_SET(dst, src) \
> +		(((dst) & ~0x00000380) | (((u32)(src) << 0x7) & 0x00000380))
> +#define  CMU_REG9_TX_WORD_MODE_CH0_SET(dst, src) \
> +		(((dst) & ~0x00000070) | (((u32)(src) << 0x4) & 0x00000070))
> +#define  CMU_REG9_PLL_POST_DIVBY2_SET(dst, src) \
> +		(((dst) & ~0x00000008) | (((u32)(src) << 0x3) & 0x00000008))
> +#define  CMU_REG9_VBG_BYPASSB_SET(dst, src) \
> +		(((dst) & ~0x00000004) | (((u32)(src) << 0x2) & 0x00000004))
> +#define  CMU_REG9_IGEN_BYPASS_SET(dst, src) \
> +		(((dst) & ~0x00000002) | (((u32)(src) << 0x1) & 0x00000002))
> +#define CMU_REG10			0x00014
> +#define  CMU_REG10_VREG_REFSEL_SET(dst, src) \
> +		(((dst) & ~0x00000001) | (((u32)(src) << 0x0) & 0x00000001))
> +#define CMU_REG11			0x00016
> +#define CMU_REG12			0x00018
> +#define  CMU_REG12_STATE_DELAY9_SET(dst, src) \
> +		(((dst) & ~0x000000f0) | (((u32)(src) << 0x4) & 0x000000f0))
> +#define CMU_REG13			0x0001a
> +#define CMU_REG14			0x0001c
> +#define CMU_REG15			0x0001e
> +#define CMU_REG16			0x00020
> +#define  CMU_REG16_PVT_DN_MAN_ENA_MASK	0x00000001
> +#define  CMU_REG16_PVT_UP_MAN_ENA_MASK	0x00000002
> +#define  CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(dst, src) \
> +		(((dst) & ~0x0000001c) | (((u32)(src) << 0x2) & 0x0000001c))
> +#define  CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(dst, src) \
> +		(((dst) & ~0x00000040) | (((u32)(src) << 0x6) & 0x00000040))
> +#define  CMU_REG16_BYPASS_PLL_LOCK_SET(dst, src) \
> +		(((dst) & ~0x00000020) | (((u32)(src) << 0x5) & 0x00000020))
> +#define CMU_REG17			0x00022
> +#define  CMU_REG17_PVT_CODE_R2A_SET(dst, src) \
> +		(((dst) & ~0x00007f00) | (((u32)(src) << 0x8) & 0x00007f00))
> +#define  CMU_REG17_RESERVED_7_SET(dst, src) \
> +		(((dst) & ~0x000000e0) | (((u32)(src) << 0x5) & 0x000000e0))
> +#define  CMU_REG17_PVT_TERM_MAN_ENA_MASK	0x00008000
> +#define CMU_REG18			0x00024
> +#define CMU_REG19			0x00026
> +#define CMU_REG20			0x00028
> +#define CMU_REG21			0x0002a
> +#define CMU_REG22			0x0002c
> +#define CMU_REG23			0x0002e
> +#define CMU_REG24			0x00030
> +#define CMU_REG25			0x00032
> +#define CMU_REG26			0x00034
> +#define  CMU_REG26_FORCE_PLL_LOCK_SET(dst, src) \
> +		(((dst) & ~0x00000001) | (((u32)(src) << 0x0) & 0x00000001))
> +#define CMU_REG27			0x00036
> +#define CMU_REG28			0x00038
> +#define CMU_REG29			0x0003a
> +#define CMU_REG30			0x0003c
> +#define  CMU_REG30_LOCK_COUNT_SET(dst, src) \
> +		(((dst) & ~0x00000006) | (((u32)(src) << 0x1) & 0x00000006))
> +#define  CMU_REG30_PCIE_MODE_SET(dst, src) \
> +		(((dst) & ~0x00000008) | (((u32)(src) << 0x3) & 0x00000008))
> +#define CMU_REG31			0x0003e
> +#define CMU_REG32			0x00040
> +#define  CMU_REG32_FORCE_VCOCAL_START_MASK	0x00004000
> +#define  CMU_REG32_PVT_CAL_WAIT_SEL_SET(dst, src) \
> +		(((dst) & ~0x00000006) | (((u32)(src) << 0x1) & 0x00000006))
> +#define  CMU_REG32_IREF_ADJ_SET(dst, src) \
> +		(((dst) & ~0x00000180) | (((u32)(src) << 0x7) & 0x00000180))
> +#define CMU_REG33			0x00042
> +#define CMU_REG34			0x00044
> +#define  CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(dst, src) \
> +		(((dst) & ~0x0000000f) | (((u32)(src) << 0x0) & 0x0000000f))
> +#define  CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(dst, src) \
> +		(((dst) & ~0x00000f00) | (((u32)(src) << 0x8) & 0x00000f00))
> +#define  CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(dst, src) \
> +		(((dst) & ~0x000000f0) | (((u32)(src) << 0x4) & 0x000000f0))
> +#define  CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(dst, src) \
> +		(((dst) & ~0x0000f000) | (((u32)(src) << 0xc) & 0x0000f000))
> +#define CMU_REG35			0x00046
> +#define  CMU_REG35_PLL_SSC_MOD_SET(dst, src) \
> +		(((dst) & ~0x0000fe00) | (((u32)(src) << 0x9) & 0x0000fe00))
> +#define CMU_REG36				0x00048
> +#define  CMU_REG36_PLL_SSC_EN_SET(dst, src) \
> +		(((dst) & ~0x00000010) | (((u32)(src) << 0x4) & 0x00000010))
> +#define  CMU_REG36_PLL_SSC_VSTEP_SET(dst, src) \
> +		(((dst) & ~0x0000ffc0) | (((u32)(src) << 0x6) & 0x0000ffc0))
> +#define  CMU_REG36_PLL_SSC_DSMSEL_SET(dst, src) \
> +		(((dst) & ~0x00000020) | (((u32)(src) << 0x5) & 0x00000020))
> +#define CMU_REG37			0x0004a
> +#define CMU_REG38			0x0004c
> +#define CMU_REG39			0x0004e
> +
> +/* PHY lane CSR accessing from SDS indirectly */
> +#define RXTX_REG0			0x000
> +#define  RXTX_REG0_CTLE_EQ_HR_SET(dst, src) \
> +		(((dst) & ~0x0000f800) | (((u32)(src) << 0xb) & 0x0000f800))
> +#define  RXTX_REG0_CTLE_EQ_QR_SET(dst, src) \
> +		(((dst) & ~0x000007c0) | (((u32)(src) << 0x6) & 0x000007c0))
> +#define  RXTX_REG0_CTLE_EQ_FR_SET(dst, src) \
> +		(((dst) & ~0x0000003e) | (((u32)(src) << 0x1) & 0x0000003e))
> +#define RXTX_REG1			0x002
> +#define  RXTX_REG1_RXACVCM_SET(dst, src) \
> +		(((dst) & ~0x0000f000) | (((u32)(src) << 0xc) & 0x0000f000))
> +#define  RXTX_REG1_CTLE_EQ_SET(dst, src) \
> +		(((dst) & ~0x00000f80) | (((u32)(src) << 0x7) & 0x00000f80))
> +#define  RXTX_REG1_RXVREG1_SET(dst, src) \
> +                (((dst) & ~0x00000060) | (((u32)(src) << 0x5) & 0x00000060))
> +#define  RXTX_REG1_RXIREF_ADJ_SET(dst, src) \
> +               (((dst) & ~0x00000006) | (((u32)(src) << 0x1) &  0x00000006))
> +#define RXTX_REG2			0x004
> +#define  RXTX_REG2_VTT_ENA_SET(dst, src) \
> +		(((dst) & ~0x00000100) | (((u32)(src) << 0x8) & 0x00000100))
> +#define  RXTX_REG2_TX_FIFO_ENA_SET(dst, src) \
> +		(((dst) & ~0x00000020) | (((u32)(src) << 0x5) & 0x00000020))
> +#define  RXTX_REG2_VTT_SEL_SET(dst, src) \
> +		(((dst) & ~0x000000c0) | (((u32)(src) << 0x6) & 0x000000c0))
> +#define RXTX_REG4			0x008
> +#define  RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK	0x00000040
> +#define  RXTX_REG4_TX_DATA_RATE_SET(dst, src) \
> +		(((dst) & ~0x0000c000) | (((u32)(src) << 0xe) & 0x0000c000))
> +#define  RXTX_REG4_TX_WORD_MODE_SET(dst, src) \
> +		(((dst) & ~0x00003800) | (((u32)(src) << 0xb) & 0x00003800))
> +#define RXTX_REG5			0x00a
> +#define  RXTX_REG5_TX_CN1_SET(dst, src) \
> +		(((dst) & ~0x0000f800) | (((u32)(src) << 0xb) & 0x0000f800))
> +#define  RXTX_REG5_TX_CP1_SET(dst, src) \
> +		(((dst) & ~0x000007e0) | (((u32)(src) << 0x5) & 0x000007e0))
> +#define  RXTX_REG5_TX_CN2_SET(dst, src) \
> +		(((dst) & ~0x0000001f) | (((u32)(src) << 0x0) & 0x0000001f))
> +#define RXTX_REG6			0x00c
> +#define  RXTX_REG6_TXAMP_CNTL_SET(dst, src) \
> +		(((dst) & ~0x00000780) | (((u32)(src) << 0x7) & 0x00000780))
> +#define  RXTX_REG6_TXAMP_ENA_SET(dst, src) \
> +		(((dst) & ~0x00000040) | (((u32)(src) << 0x6) & 0x00000040))
> +#define  RXTX_REG6_RX_BIST_ERRCNT_RD_SET(dst, src) \
> +		(((dst) & ~0x00000001) | (((u32)(src) << 0x0) & 0x00000001))
> +#define  RXTX_REG6_TX_IDLE_SET(dst, src) \
> +		(((dst) & ~0x00000008) | (((u32)(src) << 0x3) & 0x00000008))
> +#define  RXTX_REG6_RX_BIST_RESYNC_SET(dst, src) \
> +		(((dst) & ~0x00000002) | (((u32)(src) << 0x1) & 0x00000002))
> +#define RXTX_REG7			0x00e
> +#define  RXTX_REG7_RESETB_RXD_MASK	0x00000100
> +#define  RXTX_REG7_RESETB_RXA_MASK	0x00000080
> +#define  RXTX_REG7_BIST_ENA_RX_SET(dst, src) \
> +		(((dst) & ~0x00000040) | (((u32)(src) << 0x6) & 0x00000040))
> +#define  RXTX_REG7_RX_WORD_MODE_SET(dst, src) \
> +		(((dst) & ~0x00003800) | (((u32)(src) << 0xb) & 0x00003800))
> +#define RXTX_REG8			0x010
> +#define  RXTX_REG8_CDR_LOOP_ENA_SET(dst, src) \
> +		(((dst) & ~0x00004000) | (((u32)(src) << 0xe) & 0x00004000))
> +#define  RXTX_REG8_CDR_BYPASS_RXLOS_SET(dst, src) \
> +		(((dst) & ~0x00000800) | (((u32)(src) << 0xb) & 0x00000800))
> +#define  RXTX_REG8_SSC_ENABLE_SET(dst, src) \
> +		(((dst) & ~0x00000200) | (((u32)(src) << 0x9) & 0x00000200))
> +#define  RXTX_REG8_SD_VREF_SET(dst, src) \
> +		(((dst) & ~0x000000f0) | (((u32)(src) << 0x4) & 0x000000f0))
> +#define  RXTX_REG8_SD_DISABLE_SET(dst, src) \
> +		(((dst) & ~0x00000100) | (((u32)(src) << 0x8) & 0x00000100))
> +#define RXTX_REG7			0x00e
> +#define  RXTX_REG7_RESETB_RXD_SET(dst, src) \
> +		(((dst) & ~0x00000100) | (((u32)(src) << 0x8) & 0x00000100))
> +#define  RXTX_REG7_RESETB_RXA_SET(dst, src) \
> +		(((dst) & ~0x00000080) | (((u32)(src) << 0x7) & 0x00000080))
> +#define  RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK	0x00004000
> +#define  RXTX_REG7_LOOP_BACK_ENA_CTLE_SET(dst, src) \
> +		(((dst) & ~0x00004000) | (((u32)(src) << 0xe) & 0x00004000))
> +#define RXTX_REG11			0x016
> +#define  RXTX_REG11_PHASE_ADJUST_LIMIT_SET(dst, src) \
> +		(((dst) & ~0x0000f800) | (((u32)(src) << 0xb) & 0x0000f800))
> +#define RXTX_REG12			0x018
> +#define  RXTX_REG12_LATCH_OFF_ENA_SET(dst, src) \
> +		(((dst) & ~0x00002000) | (((u32)(src) << 0xd) & 0x00002000))
> +#define  RXTX_REG12_SUMOS_ENABLE_SET(dst, src) \
> +		(((dst) & ~0x00000004) | (((u32)(src) << 0x2) & 0x00000004))
> +#define  RXTX_REG12_RX_DET_TERM_ENABLE_MASK	0x00000002
> +#define  RXTX_REG12_RX_DET_TERM_ENABLE_SET(dst, src) \
> +		(((dst) & ~0x00000002) | (((u32)(src) << 0x1) & 0x00000002))
> +#define RXTX_REG13			0x01a
> +#define RXTX_REG14			0x01c
> +#define  RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(dst, src) \
> +		(((dst) & ~0x0000003f) | (((u32)(src) << 0x0) & 0x0000003f))
> +#define  RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(dst, src) \
> +		(((dst) & ~0x00000040) | (((u32)(src) << 0x6) & 0x00000040))
> +#define RXTX_REG26			0x034
> +#define  RXTX_REG26_PERIOD_ERROR_LATCH_SET(dst, src) \
> +		(((dst) & ~0x00003800) | (((u32)(src) << 0xb) & 0x00003800))
> +#define  RXTX_REG26_BLWC_ENA_SET(dst, src) \
> +		(((dst) & ~0x00000008) | (((u32)(src) << 0x3) & 0x00000008))
> +#define RXTX_REG21			0x02a
> +#define  RXTX_REG21_DO_LATCH_CALOUT_RD(src) \
> +		((0x0000fc00 & (u32)(src)) >> 0xa)
> +#define  RXTX_REG21_XO_LATCH_CALOUT_RD(src) \
> +		((0x000003f0 & (u32)(src)) >> 0x4)
> +#define  RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(src) \
> +		((0x0000000f & (u32)(src)))
> +#define RXTX_REG22			0x02c
> +#define  RXTX_REG22_SO_LATCH_CALOUT_RD(src) \
> +		((0x000003f0 & (u32)(src)) >> 0x4)
> +#define  RXTX_REG22_EO_LATCH_CALOUT_RD(src) \
> +		((0x0000fc00 & (u32)(src)) >> 0xa)
> +#define  RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(src) \
> +		((0x0000000f & (u32)(src)))
> +#define RXTX_REG23			0x02e
> +#define  RXTX_REG23_DE_LATCH_CALOUT_RD(src) \
> +		((0x0000fc00 & (u32)(src)) >> 0xa)
> +#define  RXTX_REG23_XE_LATCH_CALOUT_RD(src) \
> +		((0x000003f0 & (u32)(src)) >> 0x4)
> +#define RXTX_REG24			0x030
> +#define  RXTX_REG24_EE_LATCH_CALOUT_RD(src) \
> +		((0x0000fc00 & (u32)(src)) >> 0xa)
> +#define  RXTX_REG24_SE_LATCH_CALOUT_RD(src) \
> +		((0x000003f0 & (u32)(src)) >> 0x4)
> +#define RXTX_REG27			0x036
> +#define RXTX_REG28			0x038
> +#define RXTX_REG31			0x03e
> +#define RXTX_REG38			0x04c
> +#define  RXTX_REG38_CUSTOMER_PINMODE_INV_SET(dst, src) \
> +		(((dst) & 0x0000fffe) | (((u32)(src) << 0x1) & 0x0000fffe))
> +#define RXTX_REG39			0x04e
> +#define RXTX_REG40			0x050
> +#define RXTX_REG41			0x052
> +#define RXTX_REG42			0x054
> +#define RXTX_REG43			0x056
> +#define RXTX_REG44			0x058
> +#define RXTX_REG45			0x05a
> +#define RXTX_REG46			0x05c
> +#define RXTX_REG47			0x05e
> +#define RXTX_REG48			0x060
> +#define RXTX_REG49			0x062
> +#define RXTX_REG50			0x064
> +#define RXTX_REG51			0x066
> +#define RXTX_REG52			0x068
> +#define RXTX_REG53			0x06a
> +#define RXTX_REG54			0x06c
> +#define RXTX_REG55			0x06e
> +#define RXTX_REG61			0x07a
> +#define  RXTX_REG61_ISCAN_INBERT_SET(dst, src) \
> +		(((dst) & ~0x00000010) | (((u32)(src) << 0x4) & 0x00000010))
> +#define  RXTX_REG61_LOADFREQ_SHIFT_SET(dst, src) \
> +		(((dst) & ~0x00000008) | (((u32)(src) << 0x3) & 0x00000008))
> +#define  RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(dst, src) \
> +		(((dst) & ~0x000000c0) | (((u32)(src) << 0x6) & 0x000000c0))
> +#define  RXTX_REG61_SPD_SEL_CDR_SET(dst, src) \
> +		(((dst) & ~0x00003c00) | (((u32)(src) << 0xa) & 0x00003c00))
> +#define RXTX_REG62			0x07c
> +#define  RXTX_REG62_PERIOD_H1_QLATCH_SET(dst, src) \
> +		(((dst) & ~0x00003800) | (((u32)(src) << 0xb) & 0x00003800))
> +#define RXTX_REG81			0x0a2
> +#define  RXTX_REG89_MU_TH7_SET(dst, src) \
> +		(((dst) & ~0x0000f800) | (((u32)(src) << 0xb) & 0x0000f800))
> +#define  RXTX_REG89_MU_TH8_SET(dst, src) \
> +		(((dst) & ~0x000007c0) | (((u32)(src) << 0x6) & 0x000007c0))
> +#define  RXTX_REG89_MU_TH9_SET(dst, src) \
> +		(((dst) & ~0x0000003e) | (((u32)(src) << 0x1) & 0x0000003e))
> +#define RXTX_REG96			0x0c0
> +#define  RXTX_REG96_MU_FREQ1_SET(dst, src) \
> +		(((dst) & ~0x0000f800) | (((u32)(src) << 0xb) & 0x0000f800))
> +#define  RXTX_REG96_MU_FREQ2_SET(dst, src) \
> +		(((dst) & ~0x000007c0) | (((u32)(src) << 0x6) & 0x000007c0))
> +#define  RXTX_REG96_MU_FREQ3_SET(dst, src) \
> +		(((dst) & ~0x0000003e) | (((u32)(src) << 0x1) & 0x0000003e))
> +#define RXTX_REG99			0x0c6
> +#define  RXTX_REG99_MU_PHASE1_SET(dst, src) \
> +		(((dst) & ~0x0000f800) | (((u32)(src) << 0xb) & 0x0000f800))
> +#define  RXTX_REG99_MU_PHASE2_SET(dst, src) \
> +		(((dst) & ~0x000007c0) | (((u32)(src) << 0x6) & 0x000007c0))
> +#define  RXTX_REG99_MU_PHASE3_SET(dst, src) \
> +		(((dst) & ~0x0000003e) | (((u32)(src) << 0x1) & 0x0000003e))
> +#define RXTX_REG102			0x0cc
> +#define  RXTX_REG102_FREQLOOP_LIMIT_SET(dst, src) \
> +		(((dst) & ~0x00000060) | (((u32)(src) << 0x5) & 0x00000060))
> +#define RXTX_REG114			0x0e4
> +#define RXTX_REG121			0x0f2
> +#define  RXTX_REG121_SUMOS_CAL_CODE_RD(src) \
> +		((0x0000003e & (u32)(src)) >> 0x1)
> +#define RXTX_REG125			0x0fa
> +#define  RXTX_REG125_PQ_REG_SET(dst, src) \
> +		(((dst) & ~0x0000fe00) | (((u32)(src) << 0x9) & 0x0000fe00))
> +#define  RXTX_REG125_SIGN_PQ_SET(dst, src) \
> +		(((dst) & ~0x00000100) | (((u32)(src) << 0x8) & 0x00000100))
> +#define  RXTX_REG125_SIGN_PQ_2C_SET(dst, src) \
> +		(((dst) & ~0x00000080) | (((u32)(src) << 0x7) & 0x00000080))
> +#define  RXTX_REG125_PHZ_MANUALCODE_SET(dst, src) \
> +		(((dst) & ~0x0000007c) | (((u32)(src) << 0x2) & 0x0000007c))
> +#define  RXTX_REG125_PHZ_MANUAL_SET(dst, src) \
> +		(((dst) & ~0x00000002) | (((u32)(src) << 0x1) & 0x00000002))
> +#define RXTX_REG127			0x0fe
> +#define  RXTX_REG127_FORCE_SUM_CAL_START_MASK	0x00000002
> +#define  RXTX_REG127_FORCE_LAT_CAL_START_MASK	0x00000004
> +#define  RXTX_REG127_FORCE_SUM_CAL_START_SET(dst, src) \
> +		(((dst) & ~0x00000002) | (((u32)(src) << 0x1) & 0x00000002))
> +#define  RXTX_REG127_FORCE_LAT_CAL_START_SET(dst, src) \
> +		(((dst) & ~0x00000004) | (((u32)(src) << 0x2) & 0x00000004))
> +#define  RXTX_REG127_LATCH_MAN_CAL_ENA_SET(dst, src) \
> +		(((dst) & ~0x00000008) | (((u32)(src) << 0x3) & 0x00000008))
> +#define  RXTX_REG127_DO_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x0000fc00) | (((u32)(src) << 0xa) & 0x0000fc00))
> +#define  RXTX_REG127_XO_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x000003f0) | (((u32)(src) << 0x4) & 0x000003f0))
> +#define RXTX_REG128			0x100
> +#define  RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(dst, src) \
> +		(((dst) & ~0x0000000c) | (((u32)(src) << 0x2) & 0x0000000c))
> +#define  RXTX_REG128_EO_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x0000fc00) | (((u32)(src) << 0xa) & 0x0000fc00))
> +#define  RXTX_REG128_SO_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x000003f0) | (((u32)(src) << 0x4) & 0x000003f0))
> +#define RXTX_REG129			0x102
> +#define  RXTX_REG129_DE_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x0000fc00) | (((u32)(src) << 0xa) & 0x0000fc00))
> +#define  RXTX_REG129_XE_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x000003f0) | (((u32)(src) << 0x4) & 0x000003f0))
> +#define RXTX_REG130			0x104
> +#define  RXTX_REG130_EE_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x0000fc00) | (((u32)(src) << 0xa) & 0x0000fc00))
> +#define  RXTX_REG130_SE_LATCH_MANCAL_SET(dst, src) \
> +		(((dst) & ~0x000003f0) | (((u32)(src) << 0x4) & 0x000003f0))
> +#define RXTX_REG145			0x122
> +#define  RXTX_REG145_TX_IDLE_SATA_SET(dst, src) \
> +		(((dst) & ~0x00000001) | (((u32)(src) << 0x0) & 0x00000001))
> +#define  RXTX_REG145_RXES_ENA_SET(dst, src) \
> +		(((dst) & ~0x00000002) | (((u32)(src) << 0x1) & 0x00000002))
> +#define  RXTX_REG145_RXDFE_CONFIG_SET(dst, src) \
> +		(((dst) & ~0x0000c000) | (((u32)(src) << 0xe) & 0x0000c000))
> +#define  RXTX_REG145_RXVWES_LATENA_SET(dst, src) \
> +		(((dst) & ~0x00000004) | (((u32)(src) << 0x2) & 0x00000004))
> +#define RXTX_REG147			0x126
> +#define RXTX_REG148			0x128
> +
> +/* Clock macro type */
> +enum cmu_type_t {
> +	REF_CMU = 0,	/* Clock macro is the internal reference clock */
> +	PHY_CMU = 1,	/* Clock macro is the PLL for the Serdes */
> +};
> +
> +enum mux_type_t {
> +	MUX_SELECT_ATA = 0,	/* Switch the MUX to ATA */
> +	MUX_SELECT_SGMMII = 0,	/* Switch the MUX to SGMII */
> +};
> +
> +enum clk_type_t {
> +	CLK_EXT_DIFF = 0,	/* External differential */
> +	CLK_INT_DIFF = 1,	/* Internal differential */
> +	CLK_INT_SING = 2,	/* Internal single ended */
> +};
> +
> +enum phy_mode {
> +	MODE_SATA	= 0,	/* List them for simple reference */
> +	MODE_SGMII	= 1,
> +	MODE_PCIE	= 2,
> +	MODE_USB	= 3,
> +	MODE_XFI	= 4,
> +	MODE_MAX
> +};
> +
> +struct xgene_sata_override_param {
> +	u32 speed[MAX_LANE]; /* Index for override parameter per lane */
> +	u32 txspeed[3]; 		/* Tx speed */
> +	u32 txboostgain[MAX_LANE*3];	/* Tx freq boost and gain control */
> +	u32 txeyetuning[MAX_LANE*3]; 	/* Tx eye tuning */
> +	u32 txeyedirection[MAX_LANE*3]; /* Tx eye tuning direction */
> +	u32 txamplitude[MAX_LANE*3];	/* Tx amplitude control */
> +	u32 txprecursor_cn1[MAX_LANE*3]; /* Tx emphasis taps 1st pre-cursor */
> +	u32 txprecursor_cn2[MAX_LANE*3]; /* Tx emphasis taps 2nd pre-cursor */
> +	u32 txpostcursor_cp1[MAX_LANE*3]; /* Tx emphasis taps post-cursor */
> +};
> +
> +struct xgene_phy_ctx {
> +	struct device *dev;
> +	struct phy *phy;
> +	enum phy_mode mode;		/* Mode of operation */
> +	enum clk_type_t clk_type;	/* Input clock selection */
> +	void __iomem *sds_base;		/* PHY CSR base addr */
> +	struct clk *clk;		/* Optional clock */
> +
> +	/* Override Serdes parameters */
> +	struct xgene_sata_override_param sata_param;
> +};
> +
> +/*
> + * For chip earlier than A3 version, enable this flag.
> + * To enable, pass boot argument phy_xgene.preA3Chip=1
> + */
> +static int preA3Chip;
> +MODULE_PARM_DESC(preA3Chip, "Enable pre-A3 chip support (1=enable 0=disable)");
> +module_param_named(preA3Chip, preA3Chip, int, 0444);

Do we need to have module param for this? I mean we can differentiate 
between
different chip versions in dt data only.
> +
> +static void sds_wr(void __iomem *csr_base, u32 indirect_cmd_reg,
> +		   u32 indirect_data_reg, u32 addr, u32 data)
> +{
> +	u32 val;
> +	u32 cmd;
> +
> +	cmd = CFG_IND_WR_CMD_MASK | CFG_IND_CMD_DONE_MASK;
> +	cmd = CFG_IND_ADDR_SET(cmd, addr);

This looks hacky. If 'CFG_IND_WR_CMD_MASK | CFG_IND_CMD_DONE_MASK' 
should be set then it should be part of the second argument. From the 
macro 'CFG_IND_ADDR_SET' the first argument should be more like the 
current value present in the register right? I feel the macro 
(CFG_IND_ADDR_SET) is not used in the way it is intended to.


> +	writel(data, csr_base + indirect_data_reg);
> +	readl(csr_base + indirect_data_reg); /* Force a barrier */
> +	writel(cmd, csr_base + indirect_cmd_reg);
> +	readl(csr_base + indirect_cmd_reg); /* Force a barrier */
> +	do {
> +		val = readl(csr_base + indirect_cmd_reg);

better to have a timeout here and return error so we don't loop 
infinitively.
> +	} while (!(val & CFG_IND_CMD_DONE_MASK));
> +}
> +
> +static void sds_rd(void __iomem *csr_base, u32 indirect_cmd_reg,
> +		   u32 indirect_data_reg, u32 addr, u32 *data)
> +{
> +	u32 val;
> +	u32 cmd;
> +
> +	cmd = CFG_IND_RD_CMD_MASK | CFG_IND_CMD_DONE_MASK;
> +	cmd = CFG_IND_ADDR_SET(cmd, addr);
> +	writel(cmd, csr_base + indirect_cmd_reg);
> +	readl(csr_base + indirect_cmd_reg); /* Force a barrier */
> +	do {
> +		val = readl(csr_base + indirect_cmd_reg);

same here.
> +	} while (!(val & CFG_IND_CMD_DONE_MASK));
> +	*data = readl(csr_base + indirect_data_reg);
> +}
> +
> +static void cmu_wr(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
> +		   u32 reg, u32 data)
> +{
> +	void __iomem *sds_base = ctx->sds_base;
> +	u32 val;
> +
> +	if (cmu_type == REF_CMU)
> +		reg += SERDES_PLL_REF_INDIRECT_OFFSET;
> +	else
> +		reg += SERDES_PLL_INDIRECT_OFFSET;
> +	sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG,
> +		SATA_ENET_SDS_IND_WDATA_REG, reg, data);
> +	sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
> +		SATA_ENET_SDS_IND_RDATA_REG, reg, &val);
> +	pr_debug("CMU WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, val);
> +}
> +
.
.
<snip>
.
.
> +
> +static int xgene_phy_probe(struct platform_device *pdev)
> +{
> +	struct phy_provider *phy_provider;
> +	struct xgene_phy_ctx *ctx;
> +	struct resource *res;
> +	int rc = 0;
> +	u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
> +	u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
> +	u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
> +	u32 default_txeye_tuning[] = DEFAULT_SATA_TXEYETUNING;
> +	u32 default_txamp[] = DEFAULT_SATA_TXAMP;
> +	u32 default_txcn1[] = DEFAULT_SATA_TXCN1;
> +	u32 default_txcn2[] = DEFAULT_SATA_TXCN2;
> +	u32 default_txcp1[] = DEFAULT_SATA_TXCP1;
> +	int i;
> +
> +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx) {
> +		dev_err(&pdev->dev, "can't allocate PHY context\n");
> +		return -ENOMEM;
> +	}
> +	ctx->dev = &pdev->dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		dev_err(&pdev->dev, "no PHY resource address\n");
> +		goto error;
> +	}
> +	ctx->sds_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (!ctx->sds_base) {
> +		dev_err(&pdev->dev, "can't map PHY resource\n");
> +		rc = -ENOMEM;
> +		goto error;
> +	}
> +
> +	/* Retrieve optional clock */
> +	ctx->clk = clk_get(&pdev->dev, NULL);
> +
> +	/* Load override paramaters */
> +	xgene_phy_get_param(pdev, "apm,tx-eye-tuning",
> +		ctx->sata_param.txeyetuning, 6, default_txeye_tuning, 1);
> +	xgene_phy_get_param(pdev, "apm,tx-eye-direction",
> +		ctx->sata_param.txeyedirection, 6, default_txeye_direction, 1);
> +	xgene_phy_get_param(pdev, "apm,tx-boost-gain",
> +		ctx->sata_param.txboostgain, 6, default_txboost_gain, 1);
> +	xgene_phy_get_param(pdev, "apm,tx-amplitude",
> +		ctx->sata_param.txamplitude, 6, default_txamp, 13300);
> +	xgene_phy_get_param(pdev, "apm,tx-pre-cursor1",
> +		ctx->sata_param.txprecursor_cn1, 6, default_txcn1, 18200);
> +	xgene_phy_get_param(pdev, "apm,tx-pre-cursor2",
> +		ctx->sata_param.txprecursor_cn2, 6, default_txcn2, 18200);
> +	xgene_phy_get_param(pdev, "apm,tx-post-cursor",
> +		ctx->sata_param.txpostcursor_cp1, 6, default_txcp1, 18200);
> +	xgene_phy_get_param(pdev, "apm,tx-speed",
> +		ctx->sata_param.txspeed, 3, default_spd, 1);
> +	for (i = 0; i < MAX_LANE; i++)
> +		ctx->sata_param.speed[i] = 2; /* Default to Gen3 */
> +
> +	ctx->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, ctx);
> +
> +	phy_provider = devm_of_phy_provider_register(ctx->dev,
> +						     xgene_phy_xlate);
> +	if (IS_ERR(phy_provider)) {
> +		rc = PTR_ERR(phy_provider);
> +		goto error;
> +	}

phy_provider_register should be the last step in registering the PHY 
with the framework.
> +
> +	ctx->phy = devm_phy_create(ctx->dev, &xgene_phy_ops, NULL);
> +	if (IS_ERR(ctx->phy)) {
> +		dev_dbg(&pdev->dev, "Failed to create PHY\n");
> +		return PTR_ERR(ctx->phy);
> +	}
> +
> +	phy_set_drvdata(ctx->phy, ctx);
> +
> +	dev_info(&pdev->dev, "X-Gene PHY registered\n");

lets not make the boot log noisy.
> +	return 0;
> +
> +error:
> +	return rc;
> +}
> +
> +static const struct of_device_id xgene_phy_of_match[] = {
> +	{.compatible = "apm,xgene-phy",},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, xgene_phy_of_match);
> +
> +static struct platform_driver xgene_phy_driver = {
> +	.probe = xgene_phy_probe,
> +	.driver = {
> +		   .name = "xgene-phy",
> +		   .owner = THIS_MODULE,
> +		   .of_match_table = xgene_phy_of_match,
> +	},
> +};
> +
> +static int __init xgene_phy_init(void)
> +{
> +	return platform_driver_register(&xgene_phy_driver);
> +}
> +module_init(xgene_phy_init);
> +
> +static void __exit xgene_phy_exit(void)
> +{
> +	platform_driver_unregister(&xgene_phy_driver);
> +}
> +module_exit(xgene_phy_exit);

This can simply be replaced with 'module_platform_driver'.
> +
> +MODULE_DESCRIPTION("APM X-Gene Multi-Purpose PHY driver");
> +MODULE_AUTHOR("Loc Ho <lho@apm.com>");
> +MODULE_LICENSE("GPL");

GPL v2?

Thanks
Kishon

^ permalink raw reply

* Re: [PATCH 00/10] pinctrl: mvebu: remove hard-coded addresses from Dove pinctrl
From: Linus Walleij @ 2014-02-26  9:43 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Mark Rutland, Andrew Lunn, Russell King, Pawel Moll, Ian Campbell,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	devicetree@vger.kernel.org, Rob Herring, Rob Landley, Kumar Gala,
	Gregory Clement, linux-arm-kernel@lists.infradead.org,
	Sebastian Hesselbarth
In-Reply-To: <20140226000940.GF1872@titan.lakedaemon.net>

On Wed, Feb 26, 2014 at 1:09 AM, Jason Cooper <jason@lakedaemon.net> wrote:

> Sebastian has now re-organized the branches as I asked, and I confirmed
> that the final result is the exact same as mine (diff is null).

Okay!

> Usually when I submit pull requests to arm-soc, they like to see the
> branches.  That way if there is an error in one of them, they just drop
> the one branch and the others remain.
>
> Would you like them the same way?  If so, I'll send the pulls to you
> tomorrow.

Send me one big branch with everything on it. Actually, I'd prefer
to pull it in, rebase and sign off each patch individually in my tree
if that is not causing you problems. That way it is visible that the
patches were funneled through pin control.

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCHv3 1/2] net: stmmac: Add SOCFPGA glue driver
From: Giuseppe CAVALLARO @ 2014-02-26  9:44 UTC (permalink / raw)
  To: Dinh Nguyen, David Miller, dinguyen
  Cc: netdev, devicetree, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak, vbridgers2013
In-Reply-To: <52FC4B0A.4010406@gmail.com>

On 2/13/2014 5:33 AM, Dinh Nguyen wrote:
>
> On 2/12/14 6:35 PM, David Miller wrote:
>> From: <dinguyen@altera.com>
>> Date: Mon, 10 Feb 2014 13:48:16 -0600
>>
>>> From: Dinh Nguyen <dinguyen@altera.com>
>>>
>>> Like the STi series SOCs, Altera's SOCFPGA also needs a glue layer on top of the
>>> Synopsys gmac IP.
>>>
>>> This patch adds the platform driver for the glue layer which configures the IP
>>> before the generic STMMAC driver takes over.
>>>
>>> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
>>> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>>> Cc: Rob Herring <robh+dt@kernel.org>
>>> Cc: Pawel Moll <pawel.moll@arm.com>
>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
>>> Cc: Kumar Gala <galak@codeaurora.org>
>>> Cc: Vince Bridgers <vbridgers2013@gmail.com>
>>> ---
>>> v3: Remove stray empty line at end of dwmac-socfpga.c.
>>> v2: Use the dwmac-sti as an example for a glue layer and split patch up
>>> to have dts as a separate patch. Also cc dts maintainers since there is
>>> a new binding.
>> The second patch for the DTS update doesn't apply cleanly at all to
>> mainline.
> Yes, I'm planning to take the DTS bindings patch through arm-soc/next-dt
> tree, so that is where patch 2 is based on.
>>
>> Why don't you push both of these patches through whatever tree that
>> file is maintained under.  You can add my ack:
> I'm not sure if Peppe has a tree, but it should go into his tree
> if there is one. If not, can you apply patch 1 to your tree?

Hello

I have not own tree but I am using net.git and net-next to do my patches
and experiments.

I ask you to keep these patches aligned to net-next.

Also I ask you to review the glue-layer that is not in-line with what
have been currently added for dwmac-sti and dwmac-sunxi.c.

BR
Peppe


>>
>> Acked-by: David S. Miller <davem@davemloft.net>
> Thanks,
> Dinh
>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox