* Re: [PATCH v2 0/7] soc: renesas: Identify SoC and register with the SoC bus
From: Geert Uytterhoeven @ 2016-11-09 13:34 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greg Kroah-Hartman, Yangbo Lu, Simon Horman, Magnus Damm,
Rob Herring, Mark Rutland, Dirk Behme, Linux-Renesas,
linux-arm-kernel@lists.infradead.org,
linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, Pankaj Dubey,
linux-samsung-soc@vger.kernel.org
In-Reply-To: <CAMuHMdV4HG0aOr4Qp_OZXU=3jLeOJ2QaMKp09a3v4489ABbRcA@mail.gmail.com>
Hi Arnd,
On Mon, Nov 7, 2016 at 10:35 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Mon, Oct 31, 2016 at 12:30 PM, Geert Uytterhoeven
> <geert+renesas@glider.be> wrote:
>> Some Renesas SoCs may exist in different revisions, providing slightly
>> different functionalities (e.g. R-Car H3 ES1.x and ES2.0), and behavior
>> (errate and quirks). This needs to be catered for by drivers and/or
>> platform code. The recently proposed soc_device_match() API seems like
>> a good fit to handle this.
>>
>> This patch series implements the core infrastructure to provide SoC and
>> revision information through the SoC bus for Renesas ARM SoCs. It
>> consists of 7 patches:
>> - Patches 1-4 provide soc_device_match(), with some related fixes,
>> - Patches 5-7 implement identification of Renesas SoCs and
>> registration with the SoC bus,
>>
>> Changes compared to v1:
>> - Add Acked-by,
>> - New patches:
>> - "[4/7] base: soc: Provide a dummy implementation of
>> soc_device_match()",
>> - "[5/7] ARM: shmobile: Document DT bindings for CCCR and PRR",
>> - "[6/7] arm64: dts: r8a7795: Add device node for PRR"
>> (more similar patches available, I'm not yet spamming you all
>> with them),
>> - Drop SoC families and family names; use fixed "Renesas" instead,
>> - Drop EMEV2, which doesn't have a chip ID register, and doesn't share
>> devices with other SoCs,
>> - Drop RZ/A1H and R-CAR M1A, which don't have chip ID registers (for
>> M1A: not accessible from the ARM core?),
>> - On arm, move "select SOC_BUS" from ARCH_RENESAS to Kconfig symbols
>> for SoCs that provide a chip ID register,
>> - Build renesas-soc only if SOC_BUS is enabled,
>> - Use "renesas,prr" and "renesas,cccr" device nodes in DT if
>> available, else fall back to hardcoded addresses for compatibility
>> with existing DTBs,
>> - Remove verification of product IDs; just print the ID instead,
>> - Don't register the SoC bus if the chip ID register is missing,
>> - Change R-Mobile APE6 fallback to use PRR instead of CCCR (it has
>> both).
>>
>> Merge strategy:
>> - In theory, patches 1-4 should go through Greg's driver core tree.
>> But it's a hard dependency for all users.
>> If people agree, I can provide an immutable branch in my
>> renesas-drivers repository, to be merged by all interested parties.
>> So far I'm aware of Freescale/NXP, and Renesas.
>
> And Samsung.
> Shall I create the immutable branch now?
Arnd: are you happy with the new patches and changes?
Thanks again!
>> - Patches 5-7 obviously have to go through Simon's Renesas tree (after
>> merging the soc_device_match() core), and arm-soc.
>>
>> Tested on (machine, soc_id, optional revision):
>> EMEV2 KZM9D Board, emev2
>> Genmai, r7s72100
>> APE6EVM, r8a73a4, ES1.0
>> armadillo 800 eva, r8a7740, ES2.0
>> bockw, r8a7778
>> marzen, r8a7779, ES1.0
>> Lager, r8a7790, ES1.0
>> Koelsch, r8a7791, ES1.0
>> Porter, r8a7791, ES3.0
>> Blanche, r8a7792, ES1.1
>> Gose, r8a7793, ES1.0
>> Alt, r8a7794, ES1.0
>> Renesas Salvator-X board based on r8a7795, r8a7795, ES1.0
>> Renesas Salvator-X board based on r8a7795, r8a7795, ES1.1
>> Renesas Salvator-X board based on r8a7796, r8a7796, ES1.0
>> KZM-A9-GT, sh73a0, ES2.0
>>
>> For your convenience, this series (incl. more DT updates to add device
>> nodes for CCCR and PRR to all other Renesas ARM SoCs) is also available
>> in the topic/renesas-soc-id-v2 branch of my renesas-drivers git
>> repository at
>> git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git
>> Its first user is support for R-Car H3 ES2.0 in branch
>> topic/r8a7795-es2-v1-rebased2.
>>
>> Thanks for your comments!
>>
>> Arnd Bergmann (1):
>> base: soc: Introduce soc_device_match() interface
>>
>> Geert Uytterhoeven (6):
>> base: soc: Early register bus when needed
>> base: soc: Check for NULL SoC device attributes
>> base: soc: Provide a dummy implementation of soc_device_match()
>> ARM: shmobile: Document DT bindings for CCCR and PRR
>> arm64: dts: r8a7795: Add device node for PRR
>> soc: renesas: Identify SoC and register with the SoC bus
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 2/2] ASoC: axentia: tse850: add ASoC driver for the Axentia TSE-850
From: Mark Brown @ 2016-11-09 13:38 UTC (permalink / raw)
To: Peter Rosin
Cc: linux-kernel, Liam Girdwood, Rob Herring, Mark Rutland,
Jaroslav Kysela, Takashi Iwai, alsa-devel, devicetree
In-Reply-To: <1478622057-12426-3-git-send-email-peda@axentia.se>
[-- Attachment #1: Type: text/plain, Size: 2753 bytes --]
On Tue, Nov 08, 2016 at 05:20:57PM +0100, Peter Rosin wrote:
> +++ b/sound/soc/axentia/Kconfig
> @@ -0,0 +1,10 @@
> +config SND_SOC_AXENTIA_TSE850_PCM5142
> + tristate "ASoC driver for the Axentia TSE-850"
> + depends on ARCH_AT91 && OF
> + select ATMEL_SSC
> + select SND_ATMEL_SOC
> + select SND_ATMEL_SOC_SSC_DMA
> + select SND_SOC_PCM512x_I2C
> + help
> + Say Y if you want to add support for the ASoC driver for the
> + Axentia TSE-850 with a PCM5142 codec.
This just looks like a normal machine driver for an Atmel system which
would usually go in the atemel directory - why is a new directory being
created?
> +static int tse850_get_mux2(struct snd_kcontrol *kctrl,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
> + struct snd_soc_card *card = dapm->card;
> + struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
> + int ret;
> +
> + ret = gpiod_get_value(tse850->loop2);
> + if (ret < 0)
> + return ret;
We can't reliably read the value of output GPIOs (though in practice the
majority do support it) so it'd be better practice to use a state
variable to remember what we set. I'd also expect this to use the
_cansleep() GPIO calls as it's not in a context where sleeping would be
a problem.
> +int tse850_get_ana(struct snd_kcontrol *kctrl,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
> + struct snd_soc_card *card = dapm->card;
> + struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
> + int ret;
> +
> + ret = regulator_get_voltage(tse850->ana);
> + if (ret < 0)
> + return ret;
> +
> + if (ret < 11000000)
> + ret = 11000000;
> + else if (ret > 20000000)
> + ret = 20000000;
This needs some comments...
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct device *dev = rtd->dev;
> + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
> + int dir = substream->stream != SNDRV_PCM_STREAM_PLAYBACK;
> + int div_id = dir ? ATMEL_SSC_RCMR_PERIOD : ATMEL_SSC_TCMR_PERIOD;
> + int period = snd_soc_params_to_frame_size(params) / 2 - 1;
Please write the logic out as normal if statements for legibility. It's
a bit concerning that we even need this function, it looks like pretty
basic stuff that I'd expect the CPU DAI to just be doing - why can't
this be the default behaviour of the CPU DAI?
> +static int tse850_init(struct snd_soc_pcm_runtime *rtd)
> +{
> + struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
> +
> + return snd_soc_dapm_add_routes(dapm, tse850_intercon,
> + ARRAY_SIZE(tse850_intercon));
Set this up in the card data structure rather than open coding the call,
you can register DAPM routes there too.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: One Thousand Gnomes @ 2016-11-09 13:54 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Mark Rutland, zhichang.yuan, catalin.marinas, will.deacon,
robh+dt, bhelgaas, olof, linux-arm-kernel, lorenzo.pieralisi,
linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
minyard, benh, liviu.dudau, zourongrong, john.garry,
gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5, marc.zyngier
In-Reply-To: <2368890.jTbyGqYR0M@wuerfel>
> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses
It's not a safe assumption for x86 at least. There are a few systems with
multiple ISA busses particularly older laptops with a docking station.
> when talking to an ISA device, so having multiple instances is
> already problematic.
PCMCIA devices handle it themselves so are ok. I'm not clear how the dual
PIIX4 configuration used in the older IBM laptop docks actually worked so
I assume the transaction went out of both bridges and providing one of
them responded the other kept silent as you simply stuffed the card into
the dock and it worked.
Alan
^ permalink raw reply
* Re: [PATCH 2/2] regulator: rn5t618: add RC5T619 PMIC support
From: Mark Brown @ 2016-11-09 14:02 UTC (permalink / raw)
To: Pierre-Hugues Husson
Cc: lee.jones-QSEj5FYQhm4dnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, lgirdwood-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161105161925.14910-3-phh-8tEavu1zA38@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 263 bytes --]
On Sat, Nov 05, 2016 at 05:19:25PM +0100, Pierre-Hugues Husson wrote:
> Extend the driver to support Ricoh RC5T619.
> Support the additional regulators and slightly different voltage ranges.
Acked-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* Re: [PATCH 11/13] ARM: dts: rockchip: replace to "max-frequency" instead of "clock-freq-min-max"
From: Heiko Stuebner @ 2016-11-09 14:05 UTC (permalink / raw)
To: Jaehoon Chung
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-kernel,
linux-samsung-soc, linux-rockchip, ulf.hansson, robh+dt, krzk,
shawn.lin
In-Reply-To: <20161103062135.10697-12-jh80.chung@samsung.com>
Am Donnerstag, 3. November 2016, 15:21:33 CET schrieb Jaehoon Chung:
> In drivers/mmc/core/host.c, there is "max-frequency" property.
> It should be same behavior. So use the "max-frequency" instead of
> "clock-freq-min-max".
>
> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
looks good, my veyron-pinky and rk3036-kylin still seem to work and hopefully
I haven't missed any spelling errors in the properties :-), so applied to my
dts32 branch for 4.10
Thanks
Heiko
^ permalink raw reply
* [PATCH] of/irq: improve error message on irq discovery process failure
From: Guilherme G. Piccoli @ 2016-11-09 14:05 UTC (permalink / raw)
To: devicetree; +Cc: linuxppc-dev, linux-pci, frowand.list, robh+dt, gpiccoli
On PowerPC machines some PCI slots might not have Level-triggered
interrupts capability (also know as Level Signaled Interrupts - LSI),
leading of_irq_parse_pci() to complain by presenting error messages
on the kernel log - in this case, the properties "interrupt-map" and
"interrupt-map-mask" are not present on the device's node on device
tree.
This patch introduces a different message for this specific case,
and it also reduces the level of the message from error to warning.
Before this patch, when an adapter was plugged in a slot without Level
interrupts capabilities, we saw generic error messages like this:
[54.239] pci 002d:70:00.0: of_irq_parse_pci() failed with rc=-22
Now, with this applied, we see the following specific message:
[19.947] pci 0014:60:00.0: of_irq_parse_pci() gave up. The slot of this
device has no Level-triggered Interrupts capability.
No functional changes were introduced.
Signed-off-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
---
drivers/of/irq.c | 5 ++++-
drivers/of/of_pci_irq.c | 8 +++++++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 393fea8..1ad6882 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -275,7 +275,10 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
of_node_put(ipar);
of_node_put(newpar);
- return -EINVAL;
+ /* Positive non-zero return means no Level-triggered Interrupts
+ * capability was found.
+ */
+ return ENOENT;
}
EXPORT_SYMBOL_GPL(of_irq_parse_raw);
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
index 2306313..9b6f387 100644
--- a/drivers/of/of_pci_irq.c
+++ b/drivers/of/of_pci_irq.c
@@ -89,8 +89,14 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
laddr[1] = laddr[2] = cpu_to_be32(0);
rc = of_irq_parse_raw(laddr, out_irq);
- if (rc)
+
+ if (rc < 0) {
goto err;
+ } else if (rc > 0) {
+ dev_warn(&pdev->dev,
+ "of_irq_parse_pci() gave up. The slot of this device has no Level-triggered Interrupts capability.\n");
+ return -rc;
+ }
return 0;
err:
dev_err(&pdev->dev, "of_irq_parse_pci() failed with rc=%d\n", rc);
--
2.1.0
^ permalink raw reply related
* Re: [PATCH 2/3] ipmi/bt-bmc: maintain a request expiry list
From: Cédric Le Goater @ 2016-11-09 14:30 UTC (permalink / raw)
To: minyard, openipmi-developer, Joel Stanley
Cc: devicetree, Rob Herring, Brendan Higgins, linux-arm-kernel,
Arnd Bergmann
In-Reply-To: <a7aea2a7-6cb4-655e-3c69-1a156945e27b@acm.org>
On 11/07/2016 08:04 PM, Corey Minyard wrote:
> On 11/02/2016 02:57 AM, Cédric Le Goater wrote:
>> Regarding the response expiration handling, the IPMI spec says :
>>
>> The BMC must not return a given response once the corresponding
>> Request-to-Response interval has passed. The BMC can ensure this
>> by maintaining its own internal list of outstanding requests through
>> the interface. The BMC could age and expire the entries in the list
>> by expiring the entries at an interval that is somewhat shorter than
>> the specified Request-to-Response interval....
>>
>> To handle such case, we maintain list of received requests using the
>> seq number of the BT message to identify them. The list is updated
>> each time a request is received and a response is sent. The expiration
>> of the reponses is handled at each updates but also with a timer.
>
> This looks correct, but it seems awfully complicated.
>
> Why can't you get the current time before the wait_event_interruptible()
> and then compare the time before you do the write? That would seem to
> accomplish the same thing without any lists or extra locks.
Well, the expiry list needs a request identifier and it is currently using
the Seq byte for this purpose. So the BT message needs to be read to grab
that byte. The request is added to a list and that involves some locking.
When the response is written, the first matching request is removed from
the list and a garbage collector loop is also run. Then, as we might not
get any responses to run that loop, we use a timer to empty the list from
any expired requests.
The read/write ops of the driver are protected with a mutex, the list and
the timer add their share of locking. That could have been done with RCU
surely but we don't really need performance in this driver.
Caveats :
bt_bmc_remove_request() should not be done in the writing loop though.
It needs a fix.
The request identifier is currently Seq but the spec say we should use
Seq, NetFn, and Command or an internal Seq value as a request identifier.
Google is also working on an OEM/Group extension (Brendan in CC: )
which has a different message format. I need to look closer at what
should be done in this case.
> Also, if you are going to have multiple writers on this interface, I don't
> think the interface will work correctly. I think you need to claim the
> mutex first. Otherwise you might get into a situation where two writers
> will wake up at the same time, the first writes and releases the mutex,
> then the second will find that the interface is busy and fail.
yes. that is a current problem in the driver and it is not really an
elegant way to handle concurrency. We are fine for the moment as we
only have one single threaded process using the device.
> If I am correct, the mutex will need to become interruptible and come
> first, I think. (And the timing would have to start before the mutex,
> of course.) This applies to both the read and write interface.
OK. I will look into fixing this problem first.
> Another thing is that this is request-to-release time. If a request takes
> a long time to process (say, a write to a flash device) the timeout would
> need to be decreased by the processing time.
Hmm, how would that fit with the "BT Interface Capabilities" which
defines :
BMC Request-to-Response time, in seconds, 1 based. 30 seconds, maximum.
This is a fixed value. And the spec only say :
The BMC could age and expire the entries in the list by expiring
the entries at an interval that is somewhat shorter than the
specified Request-to-Response interval.
May be I am misunderstanding.
> It's probably ok to not do that for the moment, but you may want to add
> a note. Fixing that would require adding a timeout for each message.
Thanks,
C.
> -corey
>
>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>> drivers/char/ipmi/bt-bmc.c | 132 +++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 132 insertions(+)
>>
>> diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
>> index fc9e8891eae3..e751e4a754b7 100644
>> --- a/drivers/char/ipmi/bt-bmc.c
>> +++ b/drivers/char/ipmi/bt-bmc.c
>> @@ -17,6 +17,7 @@
>> #include <linux/platform_device.h>
>> #include <linux/poll.h>
>> #include <linux/sched.h>
>> +#include <linux/slab.h>
>> #include <linux/timer.h>
>> /*
>> @@ -57,6 +58,15 @@
>> #define BT_BMC_BUFFER_SIZE 256
>> +#define BT_BMC_RESPONSE_TIME 5 /* seconds */
>> +
>> +struct ipmi_request {
>> + struct list_head list;
>> +
>> + u8 seq;
>> + unsigned long expires;
>> +};
>> +
>> struct bt_bmc {
>> struct device dev;
>> struct miscdevice miscdev;
>> @@ -65,6 +75,11 @@ struct bt_bmc {
>> wait_queue_head_t queue;
>> struct timer_list poll_timer;
>> struct mutex mutex;
>> +
>> + unsigned int response_time;
>> + struct timer_list requests_timer;
>> + spinlock_t requests_lock;
>> + struct list_head requests;
>> };
>> static atomic_t open_count = ATOMIC_INIT(0);
>> @@ -163,6 +178,94 @@ static int bt_bmc_open(struct inode *inode, struct file *file)
>> }
>> /*
>> + * lock should be held
>> + */
>> +static void drop_expired_requests(struct bt_bmc *bt_bmc)
>> +{
>> + unsigned long flags = 0;
>> + struct ipmi_request *req, *next;
>> + unsigned long next_expires = 0;
>> + int start_timer = 0;
>> +
>> + spin_lock_irqsave(&bt_bmc->requests_lock, flags);
>> + list_for_each_entry_safe(req, next, &bt_bmc->requests, list) {
>> + if (time_after_eq(jiffies, req->expires)) {
>> + pr_warn("BT: request seq:%d has expired. dropping\n",
>> + req->seq);
>> + list_del(&req->list);
>> + kfree(req);
>> + continue;
>> + }
>> + if (!start_timer) {
>> + start_timer = 1;
>> + next_expires = req->expires;
>> + } else {
>> + next_expires = min(next_expires, req->expires);
>> + }
>> + }
>> + spin_unlock_irqrestore(&bt_bmc->requests_lock, flags);
>> +
>> + /* and possibly restart */
>> + if (start_timer)
>> + mod_timer(&bt_bmc->requests_timer, next_expires);
>> +}
>> +
>> +static void requests_timer(unsigned long data)
>> +{
>> + struct bt_bmc *bt_bmc = (void *)data;
>> +
>> + drop_expired_requests(bt_bmc);
>> +}
>> +
>> +static int bt_bmc_add_request(struct bt_bmc *bt_bmc, u8 seq)
>> +{
>> + struct ipmi_request *req;
>> +
>> + req = kmalloc(sizeof(*req), GFP_KERNEL);
>> + if (!req)
>> + return -ENOMEM;
>> +
>> + req->seq = seq;
>> + req->expires = jiffies +
>> + msecs_to_jiffies(bt_bmc->response_time * 1000);
>> +
>> + spin_lock(&bt_bmc->requests_lock);
>> + list_add(&req->list, &bt_bmc->requests);
>> + spin_unlock(&bt_bmc->requests_lock);
>> +
>> + drop_expired_requests(bt_bmc);
>> + return 0;
>> +}
>> +
>> +static int bt_bmc_remove_request(struct bt_bmc *bt_bmc, u8 seq)
>> +{
>> + struct ipmi_request *req, *next;
>> + int ret = -EBADRQC; /* Invalid request code */
>> +
>> + spin_lock(&bt_bmc->requests_lock);
>> + list_for_each_entry_safe(req, next, &bt_bmc->requests, list) {
>> + /*
>> + * The sequence number should be unique, so remove the
>> + * first matching request found. If there are others,
>> + * they should expire
>> + */
>> + if (req->seq == seq) {
>> + list_del(&req->list);
>> + kfree(req);
>> + ret = 0;
>> + break;
>> + }
>> + }
>> + spin_unlock(&bt_bmc->requests_lock);
>> +
>> + if (ret)
>> + pr_warn("BT: request seq:%d is invalid\n", seq);
>> +
>> + drop_expired_requests(bt_bmc);
>> + return ret;
>> +}
>> +
>> +/*
>> * The BT (Block Transfer) interface means that entire messages are
>> * buffered by the host before a notification is sent to the BMC that
>> * there is data to be read. The first byte is the length and the
>> @@ -231,6 +334,13 @@ static ssize_t bt_bmc_read(struct file *file, char __user *buf,
>> len_byte = 0;
>> }
>> + if (ret > 0) {
>> + int ret2 = bt_bmc_add_request(bt_bmc, kbuffer[2]);
>> +
>> + if (ret2)
>> + ret = ret2;
>> + }
>> +
>> clr_b_busy(bt_bmc);
>> out_unlock:
>> @@ -283,12 +393,20 @@ static ssize_t bt_bmc_write(struct file *file, const char __user *buf,
>> clr_wr_ptr(bt_bmc);
>> while (count) {
>> + int ret2;
>> +
>> nwritten = min_t(ssize_t, count, sizeof(kbuffer));
>> if (copy_from_user(&kbuffer, buf, nwritten)) {
>> ret = -EFAULT;
>> break;
>> }
>> + ret2 = bt_bmc_remove_request(bt_bmc, kbuffer[2]);
>> + if (ret2) {
>> + ret = ret2;
>> + break;
>> + }
>> +
>> bt_writen(bt_bmc, kbuffer, nwritten);
>> count -= nwritten;
>> @@ -438,6 +556,8 @@ static int bt_bmc_probe(struct platform_device *pdev)
>> mutex_init(&bt_bmc->mutex);
>> init_waitqueue_head(&bt_bmc->queue);
>> + INIT_LIST_HEAD(&bt_bmc->requests);
>> + spin_lock_init(&bt_bmc->requests_lock);
>> bt_bmc->miscdev.minor = MISC_DYNAMIC_MINOR,
>> bt_bmc->miscdev.name = DEVICE_NAME,
>> @@ -451,6 +571,8 @@ static int bt_bmc_probe(struct platform_device *pdev)
>> bt_bmc_config_irq(bt_bmc, pdev);
>> + bt_bmc->response_time = BT_BMC_RESPONSE_TIME;
>> +
>> if (bt_bmc->irq) {
>> dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
>> } else {
>> @@ -468,6 +590,9 @@ static int bt_bmc_probe(struct platform_device *pdev)
>> BT_CR0_ENABLE_IBT,
>> bt_bmc->base + BT_CR0);
>> + setup_timer(&bt_bmc->requests_timer, requests_timer,
>> + (unsigned long)bt_bmc);
>> +
>> clr_b_busy(bt_bmc);
>> return 0;
>> @@ -476,10 +601,17 @@ static int bt_bmc_probe(struct platform_device *pdev)
>> static int bt_bmc_remove(struct platform_device *pdev)
>> {
>> struct bt_bmc *bt_bmc = dev_get_drvdata(&pdev->dev);
>> + struct ipmi_request *req, *next;
>> misc_deregister(&bt_bmc->miscdev);
>> if (!bt_bmc->irq)
>> del_timer_sync(&bt_bmc->poll_timer);
>> +
>> + del_timer_sync(&bt_bmc->requests_timer);
>> + list_for_each_entry_safe(req, next, &bt_bmc->requests, list) {
>> + list_del(&req->list);
>> + kfree(req);
>> + }
>> return 0;
>> }
>>
>
>
------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi
_______________________________________________
Openipmi-developer mailing list
Openipmi-developer@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openipmi-developer
^ permalink raw reply
* Re: [PATCH 1/6] dt-bindings: mdio-mux: Add documentation for mdio mux for NSP SoC
From: Andrew Lunn @ 2016-11-09 14:34 UTC (permalink / raw)
To: Yendapally Reddy Dhananjaya Reddy
Cc: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I,
bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <1478683994-12008-2-git-send-email-yendapally.reddy@broadcom.com>
On Wed, Nov 09, 2016 at 04:33:09AM -0500, Yendapally Reddy Dhananjaya Reddy wrote:
> Add documentation for mdio mux available in Broadcom NSP SoC
>
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
> ---
> .../devicetree/bindings/net/brcm,mdio-mux-nsp.txt | 57 ++++++++++++++++++++++
> 1 file changed, 57 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
>
> diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
> new file mode 100644
> index 0000000..b749a2b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
> @@ -0,0 +1,57 @@
> +Properties for an MDIO bus multiplexer available in Broadcom NSP SoC.
> +
> +This MDIO bus multiplexer defines buses that could access the internal
> +phys as well as external to SoCs. When child bus is selected, one needs
Hi Yendapally
Since we are in the networking subsystem, when we see phy, we think
Ethernet PHY. But broadcom mdio mux is generic and can have any sort
of PHY or device connected to it. To avoid confusion and
missunderstanding, please could you try to prefix each 'PHY' in the
with an indication of what type it is, 'Ethernet PHY', 'USB phy',
'SERDES PHY', or 'generic PHY/mdio device'.
And i mean this in general, not just this patch.
Thanks
Andrew
^ permalink raw reply
* Re: [PATCH 12/13] ARM64: dts: rockchip: replace to "max-frequency" instead of "clock-freq-min-max"
From: Heiko Stuebner @ 2016-11-09 14:37 UTC (permalink / raw)
To: Jaehoon Chung
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-kernel,
linux-samsung-soc, linux-rockchip, ulf.hansson, robh+dt, krzk,
shawn.lin
In-Reply-To: <20161103062135.10697-13-jh80.chung@samsung.com>
Am Donnerstag, 3. November 2016, 15:21:34 CET schrieb Jaehoon Chung:
> In drivers/mmc/core/host.c, there is "max-freqeuncy" property.
> It should be same behavior, So Use the "max-frequency" instead of
> "clock-freq-min-max".
>
> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
applied to my dts64 branch for 4.10
Thanks
Heiko
^ permalink raw reply
* Re: [PATCH 3/3] ipmi/bt-bmc: add a sysfs file to configure a maximum response time
From: Cédric Le Goater @ 2016-11-09 14:42 UTC (permalink / raw)
To: minyard, openipmi-developer, Joel Stanley
Cc: devicetree, Rob Herring, linux-arm-kernel, Arnd Bergmann
In-Reply-To: <3a1f8e6d-c935-3404-ffa0-81b19d170731@acm.org>
On 11/07/2016 07:37 PM, Corey Minyard wrote:
> Sorry, I was at Plumbers and extra busy with other stuff. Just getting around to reviewing this.
>
> On 11/02/2016 02:57 AM, Cédric Le Goater wrote:
>> We could also use an ioctl for that purpose. sysfs seems a better
>> approach.
>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>> drivers/char/ipmi/bt-bmc.c | 31 +++++++++++++++++++++++++++++++
>> 1 file changed, 31 insertions(+)
>>
>> diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
>> index e751e4a754b7..d7146f0e900e 100644
>> --- a/drivers/char/ipmi/bt-bmc.c
>> +++ b/drivers/char/ipmi/bt-bmc.c
>> @@ -84,6 +84,33 @@ struct bt_bmc {
>> static atomic_t open_count = ATOMIC_INIT(0);
>> +static ssize_t bt_bmc_show_response_time(struct device *dev,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct bt_bmc *bt_bmc = dev_get_drvdata(dev);
>> +
>> + return snprintf(buf, PAGE_SIZE - 1, "%d\n", bt_bmc->response_time);
>> +}
>> +
>> +static ssize_t bt_bmc_set_response_time(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct bt_bmc *bt_bmc = dev_get_drvdata(dev);
>> + unsigned long val;
>> + int err;
>> +
>> + err = kstrtoul(buf, 0, &val);
>> + if (err)
>> + return err;
>> + bt_bmc->response_time = val;
>> + return count;
>> +}
>> +
>> +static DEVICE_ATTR(response_time, 0644,
>> + bt_bmc_show_response_time, bt_bmc_set_response_time);
>> +
>> static u8 bt_inb(struct bt_bmc *bt_bmc, int reg)
>> {
>> return ioread8(bt_bmc->base + reg);
>> @@ -572,6 +599,10 @@ static int bt_bmc_probe(struct platform_device *pdev)
>> bt_bmc_config_irq(bt_bmc, pdev);
>> bt_bmc->response_time = BT_BMC_RESPONSE_TIME;
>> + rc = device_create_file(&pdev->dev, &dev_attr_response_time);
>> + if (rc)
>> + dev_warn(&pdev->dev, "can't create response_time file\n");
>> +
>
> You added an extra space here.
yes. I will remove it in the next version.
The patch raises a few questions on the "BT Interface Capabilities" :
- should we use sysfs or a specific ioctl to configure the driver ?
- should the driver handle directly the response to the "Get BT
Interface Capabilities" command ?
What is your opinion ?
Thanks,
C.
>> if (bt_bmc->irq) {
>> dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
>
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] soc: qcom: Add SoC info driver
From: Geert Uytterhoeven @ 2016-11-09 14:44 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Arnd Bergmann, Imran Khan, Andy Gross, David Brown, Rob Herring,
Mark Rutland, open list:ARM/QUALCOMM SUPPORT,
open list:ARM/QUALCOMM SUPPORT,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list, Geert Uytterhoeven
In-Reply-To: <20161102162811.GN25787@tuxbot>
Hi Bjorn,
On Wed, Nov 2, 2016 at 5:28 PM, Bjorn Andersson
<bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On Wed 26 Oct 07:05 PDT 2016, Arnd Bergmann wrote:
>> On Wednesday, October 26, 2016 7:20:42 PM CEST Imran Khan wrote:
>> > On 10/26/2016 2:19 AM, Arnd Bergmann wrote:
>> > > On Tuesday, October 25, 2016 3:23:34 PM CEST Imran Khan wrote:
>> > >> On 10/21/2016 4:03 PM, Arnd Bergmann wrote:
>> > >> Okay. I will go for human readable IDs. Can we add 2 more fields
>> > >> in the generic structure.
>> > >> These 2 fields would be:
>> > >>
>> > >> vendor: A string for vendor name
>> > >> serial_number: A string containing serial number for the platform
>> > >
>> > >
>> > > serial_number seems straightforward, adding this seems like a good
>> > > idea. I don't understand yet what would go into the vendor field
>> > > though. For this particular driver, is it always "Qualcomm", or
>> > > would it be a third-party that makes a device based on that chip?
>> >
>> > As we are talking about generic soc_device_attribute fields, I was hoping that
>> > having a vendor field would be helpful as along with family it would provide
>> > a more thorough information. Also as more than one foundries may be used for
>> > a soc, can we have a field say foundry_id to provide this information.
>>
>> My first feeling is that this 'vendor' information can should be
>> derived from the family.
>
> In [1] Geert just put the vendor directly into "family", while Imran
> uses "Snapdragon" (which I find reasonable in the Qualcomm case). But it
> seems like Geert would like a "vendor" as well, rather than a "family".
>
> And if "family" really is supposed to contain the "SoC family name" and
> we're trying to provide user space with some useful information (for
> some reason), should we just rely on the unlikeliness of two vendors
> using the same family name?
>
> [1] http://www.mail-archive.com/linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg1261742.html
I think vendor is slightly less volatile than family. Family may
change overnight
if marketing had a good dream. Well, vendor may change, too...
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
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: [PATCH 3/6] net: mdio-mux: Add MDIO mux driver for NSP SoC
From: Andrew Lunn @ 2016-11-09 14:45 UTC (permalink / raw)
To: Yendapally Reddy Dhananjaya Reddy
Cc: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I,
bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <1478683994-12008-4-git-send-email-yendapally.reddy@broadcom.com>
> +#define NSP_MDIO_EXT_BUS_START_ADDR 16
> +#define NSP_MDIO_EXT_SELECT_BIT BIT(9)
> +
> +static int mdio_mux_nsp_switch_fn(int current_child, int desired_child,
> + void *priv)
> +{
> + struct nsp_mdiomux_desc *md = priv;
> + u32 data, bus_id;
> +
> + /* select internal or external bus */
> + data = readl(md->mgmt_ctrl);
> + if (desired_child == NSP_MDIO_EXT_BUS_START_ADDR)
> + data |= NSP_MDIO_EXT_SELECT_BIT;
> + else
> + data &= ~NSP_MDIO_EXT_SELECT_BIT;
> + writel(data, md->mgmt_ctrl);
> +
> + /* select bus number */
> + if (md->bus_ctrl) {
> + bus_id = desired_child & (NSP_MDIO_EXT_BUS_START_ADDR - 1);
> + writel(bus_id, md->bus_ctrl);
> + }
> +
> + return 0;
So address 16 is external. What happens which you try to access
address 16 internally? Does the chip raise an abort? Reads just give
0xffff?
I'm wondering if it would be better to implement this as two nested
muxes. One mux doing internal/external, and the other doing the bus.
If you do that, you can use the existing mdio-mux-mmioreg.c and don't
need any new code at all.
Andrew
^ permalink raw reply
* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Gabriele Paoloni @ 2016-11-09 14:51 UTC (permalink / raw)
To: One Thousand Gnomes, Arnd Bergmann
Cc: Mark Rutland, Yuanzhichang,
catalin.marinas-5wv7dgnIgG8@public.gmane.org,
will.deacon-5wv7dgnIgG8@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linuxarm,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
minyard-HInyCGIudOg@public.gmane.org, benh-XVmvHMARGAQRh2imMr4xaA
In-Reply-To: <20161109135453.2e5402bd-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
> -----Original Message-----
> From: One Thousand Gnomes [mailto:gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org]
> Sent: 09 November 2016 13:55
> To: Arnd Bergmann
> Cc: Mark Rutland; Yuanzhichang; catalin.marinas-5wv7dgnIgG8@public.gmane.org;
> will.deacon-5wv7dgnIgG8@public.gmane.org; robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org;
> olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Linuxarm;
> devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-
> serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org; benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org;
> liviu.dudau-5wv7dgnIgG8@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; John Garry; Gabriele
> Paoloni; zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; kantyzc-9Onoh4P/yGk@public.gmane.org; xuwei (O);
> marc.zyngier-5wv7dgnIgG8@public.gmane.org
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
>
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
>
> It's not a safe assumption for x86 at least. There are a few systems
> with
> multiple ISA busses particularly older laptops with a docking station.
Mmmm right...now the point is that this kind of special devices appearing
as a special ISA bus will probably never appear on x86 platforms (I guess).
So maybe it is a safe assumption because of this...?
Thanks
Gab
>
> > when talking to an ISA device, so having multiple instances is
> > already problematic.
>
> PCMCIA devices handle it themselves so are ok. I'm not clear how the
> dual
> PIIX4 configuration used in the older IBM laptop docks actually worked
> so
> I assume the transaction went out of both bridges and providing one of
> them responded the other kept silent as you simply stuffed the card
> into
> the dock and it worked.
>
> Alan
--
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: [PATCH 1/2] iio: bmi160: Support hardware fifo
From: Marcin Niestroj @ 2016-11-09 14:52 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Daniel Baluta, Gregor Boirie, Sanchayan Maity, Rob Herring,
Mark Rutland, linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <b7dd5694-b757-c0d1-3400-46e92b8deb58-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Hi,
Thanks for review. I agree with all of the comments and will fix these
in next patch version. Below is just a comment on hwfifo_* sysfs access.
On 06.11.2016 13:35, Jonathan Cameron wrote:
> On 03/11/16 11:25, Marcin Niestroj wrote:
>> This patch was developed primarily based on bmc150_accel hardware fifo
>> implementation.
>>
>> IRQ handler was added, which for now is responsible only for handling
>> watermark interrupts. The BMI160 chip has two interrupt outputs. By
>> default INT is considered to be connected. If INT2 is used instead, the
>> interrupt-names device-tree property can be used to specify that.
>>
>> Signed-off-by: Marcin Niestroj <m.niestroj-z3quKL4iOrmQ6ZAhV5LmOA@public.gmane.org>
> I agree with Peter that there should have been a few precursor patches
> to this one doing various cleanups and reworking bits that you have
> in here. Would have made it easier to review (always a good thing :)
>
> In general the resulting code looks good to me. A few little
> additional comments inline from me. Mostly about small code ordering things
> and function rename suggestions that would make the code more 'obviously'
> correct.
>
> Thanks,
>
> Jonathan
>> ---
>> drivers/iio/imu/bmi160/bmi160.h | 3 +-
>> drivers/iio/imu/bmi160/bmi160_core.c | 633 +++++++++++++++++++++++++++++++++--
>> drivers/iio/imu/bmi160/bmi160_i2c.c | 7 +-
>> drivers/iio/imu/bmi160/bmi160_spi.c | 3 +-
>> 4 files changed, 618 insertions(+), 28 deletions(-)
<snip>
>> +
>> +static IIO_CONST_ATTR(hwfifo_watermark_min, "1");
>> +static IIO_CONST_ATTR(hwfifo_watermark_max,
>> + __stringify(BMI160_FIFO_LENGTH));
>> +static IIO_DEVICE_ATTR(hwfifo_enabled, S_IRUGO,
>> + bmi160_get_fifo_state, NULL, 0);
>> +static IIO_DEVICE_ATTR(hwfifo_watermark, S_IRUGO,
>> + bmi160_get_fifo_watermark, NULL, 0);
>> +
>> +static const struct attribute *bmi160_fifo_attributes[] = {
>> + &iio_const_attr_hwfifo_watermark_min.dev_attr.attr,
>> + &iio_const_attr_hwfifo_watermark_max.dev_attr.attr,
>> + &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
>> + &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
> There are enough of these drivers now that sometimes soon we should
> revisit the question of pulling these into the core. Can certainly
> concieve of downstream consumer devices (in particular the iio_input
> bridge when that finally resurfaces - my fault) wanting to be able to
> manipulate or at least have visibilty of these.
One more thing to consider is setting hwfifo_watermark to other value
than "userspace" watermark. It would be nice to set hwfifo_watermark to
a *safe* value to be able to get all data from hardware to kfifo. By
safe I mean that the chance of hardware fifo overflow will be small. On
the other hand there might be no reason to have such small watermark for
userspace application, so we can save scheduler cycles.
<snip>
--
Marcin Niestroj
^ permalink raw reply
* Re: [PATCH V3 1/9] PM / OPP: Reword binding supporting multiple regulators per device
From: Mark Brown @ 2016-11-09 14:58 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, nm, sboyd, Viresh Kumar, linaro-kernel, linux-pm,
linux-kernel, Vincent Guittot, robh, d-gerlach, devicetree
In-Reply-To: <28119b44689921f3c3cc00be49bff2bb99b32162.1477463128.git.viresh.kumar@linaro.org>
[-- Attachment #1: Type: text/plain, Size: 710 bytes --]
On Wed, Oct 26, 2016 at 12:02:56PM +0530, Viresh Kumar wrote:
> + Entries for multiple regulators shall be provided in the same field separated
> + by angular brackets <>. The OPP binding doesn't provide any provisions to
> + relate the values to their power supplies or the order in which the supplies
> + need to be configured.
I don't understand how this works. If we have an unordered list of
values to set for regulators how will we make sense of them?
> - cpu-supply = <&cpu_supply0>, <&cpu_supply1>, <&cpu_supply2>;
> + vcc0-supply = <&cpu_supply0>;
> + vcc1-supply = <&cpu_supply1>;
> + vcc2-supply = <&cpu_supply2>;
This change doesn't seem to correspond to the documentation change.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* Applied "ASoC: sun4i-codec: Add support for optional reset control to quirks" to the asoc tree
From: Mark Brown @ 2016-11-09 14:59 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: Maxime Ripard, Mark Brown, Liam Girdwood
In-Reply-To: <20161103075556.29018-6-wens-jdAy2FN1RRM@public.gmane.org>
The patch
ASoC: sun4i-codec: Add support for optional reset control to quirks
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 9aead156c0665a362c8b007b51fe3396fea4d346 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Date: Mon, 7 Nov 2016 18:06:58 +0800
Subject: [PATCH] ASoC: sun4i-codec: Add support for optional reset control to
quirks
The later Allwinner SoCs have a dedicated reset controller, and
peripherals have dedicated reset controls which need to be deasserted
before the associated peripheral can be used.
Add support for this to the quirks structure and probe/remove functions.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
sound/soc/sunxi/sun4i-codec.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 735115244b17..6379efd21f00 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -30,6 +30,7 @@
#include <linux/of_platform.h>
#include <linux/clk.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/gpio/consumer.h>
#include <sound/core.h>
@@ -217,6 +218,7 @@ struct sun4i_codec {
struct regmap *regmap;
struct clk *clk_apb;
struct clk *clk_module;
+ struct reset_control *rst;
struct gpio_desc *gpio_pa;
/* ADC_FIFOC register is at different offset on different SoCs */
@@ -1232,6 +1234,7 @@ struct sun4i_codec_quirks {
struct reg_field reg_adc_fifoc; /* used for regmap_field */
unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */
unsigned int reg_adc_rxdata; /* RX FIFO offset for DMA config */
+ bool has_reset;
};
static const struct sun4i_codec_quirks sun4i_codec_quirks = {
@@ -1327,6 +1330,14 @@ static int sun4i_codec_probe(struct platform_device *pdev)
return PTR_ERR(scodec->clk_module);
}
+ if (quirks->has_reset) {
+ scodec->rst = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(scodec->rst)) {
+ dev_err(&pdev->dev, "Failed to get reset control\n");
+ return PTR_ERR(scodec->rst);
+ }
+ };
+
scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
GPIOD_OUT_LOW);
if (IS_ERR(scodec->gpio_pa)) {
@@ -1353,6 +1364,16 @@ static int sun4i_codec_probe(struct platform_device *pdev)
return -EINVAL;
}
+ /* Deassert the reset control */
+ if (scodec->rst) {
+ ret = reset_control_deassert(scodec->rst);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to deassert the reset control\n");
+ goto err_clk_disable;
+ }
+ }
+
/* DMA configuration for TX FIFO */
scodec->playback_dma_data.addr = res->start + quirks->reg_dac_txdata;
scodec->playback_dma_data.maxburst = 8;
@@ -1367,7 +1388,7 @@ static int sun4i_codec_probe(struct platform_device *pdev)
&sun4i_codec_dai, 1);
if (ret) {
dev_err(&pdev->dev, "Failed to register our codec\n");
- goto err_clk_disable;
+ goto err_assert_reset;
}
ret = devm_snd_soc_register_component(&pdev->dev,
@@ -1404,6 +1425,9 @@ static int sun4i_codec_probe(struct platform_device *pdev)
err_unregister_codec:
snd_soc_unregister_codec(&pdev->dev);
+err_assert_reset:
+ if (scodec->rst)
+ reset_control_assert(scodec->rst);
err_clk_disable:
clk_disable_unprepare(scodec->clk_apb);
return ret;
@@ -1416,6 +1440,8 @@ static int sun4i_codec_remove(struct platform_device *pdev)
snd_soc_unregister_card(card);
snd_soc_unregister_codec(&pdev->dev);
+ if (scodec->rst)
+ reset_control_assert(scodec->rst);
clk_disable_unprepare(scodec->clk_apb);
return 0;
--
2.10.2
^ permalink raw reply related
* Applied "ASoC: sun4i-codec: Add support for A31 ADC capture path" to the asoc tree
From: Mark Brown @ 2016-11-09 14:59 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: Maxime Ripard, Mark Brown, Liam Girdwood
In-Reply-To: <20161003110804.28235-10-wens@csie.org>
The patch
ASoC: sun4i-codec: Add support for A31 ADC capture path
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 24c99f843208df70ec7d1e04aa405f7e4c36f228 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 7 Nov 2016 18:06:59 +0800
Subject: [PATCH] ASoC: sun4i-codec: Add support for A31 ADC capture path
The A31's internal codec capture path has a mixer in front of the ADC
for each channel, capable of selecting various inputs, including
microphones, line in, phone in, and the main output mixer.
This patch adds the various controls, widgets and routes needed for
audio capture from the already supported inputs on the A31.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-codec.c | 65 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 1934db29b2b5..735115244b17 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -786,6 +786,30 @@ static const struct snd_kcontrol_new sun6i_codec_mixer_controls[] = {
SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC2, 1, 0),
};
+/* ADC mixer controls */
+static const struct snd_kcontrol_new sun6i_codec_adc_mixer_controls[] = {
+ SOC_DAPM_DOUBLE("Mixer Capture Switch",
+ SUN6I_CODEC_ADC_ACTL,
+ SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXL,
+ SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXR, 1, 0),
+ SOC_DAPM_DOUBLE("Mixer Reversed Capture Switch",
+ SUN6I_CODEC_ADC_ACTL,
+ SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXR,
+ SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXL, 1, 0),
+ SOC_DAPM_DOUBLE("Line In Capture Switch",
+ SUN6I_CODEC_ADC_ACTL,
+ SUN6I_CODEC_ADC_ACTL_LADCMIX_LINEINL,
+ SUN6I_CODEC_ADC_ACTL_RADCMIX_LINEINR, 1, 0),
+ SOC_DAPM_DOUBLE("Mic1 Capture Switch",
+ SUN6I_CODEC_ADC_ACTL,
+ SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC1,
+ SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC1, 1, 0),
+ SOC_DAPM_DOUBLE("Mic2 Capture Switch",
+ SUN6I_CODEC_ADC_ACTL,
+ SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC2,
+ SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC2, 1, 0),
+};
+
/* headphone controls */
static const char * const sun6i_codec_hp_src_enum_text[] = {
"DAC", "Mixer",
@@ -885,6 +909,10 @@ static const struct snd_kcontrol_new sun6i_codec_codec_widgets[] = {
SOC_SINGLE_TLV("Mic2 Boost Volume", SUN6I_CODEC_MIC_CTRL,
SUN6I_CODEC_MIC_CTRL_MIC2BOOST, 0x7, 0,
sun6i_codec_mic_gain_scale),
+ SOC_DOUBLE_TLV("ADC Capture Volume",
+ SUN6I_CODEC_ADC_ACTL, SUN6I_CODEC_ADC_ACTL_ADCLG,
+ SUN6I_CODEC_ADC_ACTL_ADCRG, 0x7, 0,
+ sun6i_codec_out_mixer_pregain_scale),
};
static const struct snd_soc_dapm_widget sun6i_codec_codec_dapm_widgets[] = {
@@ -910,6 +938,23 @@ static const struct snd_soc_dapm_widget sun6i_codec_codec_dapm_widgets[] = {
/* Line In */
SND_SOC_DAPM_INPUT("LINEIN"),
+ /* Digital parts of the ADCs */
+ SND_SOC_DAPM_SUPPLY("ADC Enable", SUN6I_CODEC_ADC_FIFOC,
+ SUN6I_CODEC_ADC_FIFOC_EN_AD, 0,
+ NULL, 0),
+
+ /* Analog parts of the ADCs */
+ SND_SOC_DAPM_ADC("Left ADC", "Codec Capture", SUN6I_CODEC_ADC_ACTL,
+ SUN6I_CODEC_ADC_ACTL_ADCLEN, 0),
+ SND_SOC_DAPM_ADC("Right ADC", "Codec Capture", SUN6I_CODEC_ADC_ACTL,
+ SUN6I_CODEC_ADC_ACTL_ADCREN, 0),
+
+ /* ADC Mixers */
+ SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
+ sun6i_codec_adc_mixer_controls),
+ SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
+ sun6i_codec_adc_mixer_controls),
+
/* Digital parts of the DACs */
SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
SUN4I_CODEC_DAC_DPC_EN_DA, 0,
@@ -973,6 +1018,20 @@ static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = {
{ "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
{ "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
+ /* Left ADC Mixer Routes */
+ { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
+ { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
+ { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
+ { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
+ { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
+
+ /* Right ADC Mixer Routes */
+ { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
+ { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
+ { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
+ { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
+ { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
+
/* Headphone Routes */
{ "Headphone Source Playback Route", "DAC", "Left DAC" },
{ "Headphone Source Playback Route", "DAC", "Right DAC" },
@@ -987,6 +1046,12 @@ static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = {
{ "Line Out Source Playback Route", "Stereo", "Right Mixer" },
{ "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
{ "LINEOUT", NULL, "Line Out Source Playback Route" },
+
+ /* ADC Routes */
+ { "Left ADC", NULL, "ADC Enable" },
+ { "Right ADC", NULL, "ADC Enable" },
+ { "Left ADC", NULL, "Left ADC Mixer" },
+ { "Right ADC", NULL, "Right ADC Mixer" },
};
static struct snd_soc_codec_driver sun6i_codec_codec = {
--
2.10.2
^ permalink raw reply related
* Applied "ASoC: cs42l42: Add devicetree bindings for CS42L42" to the asoc tree
From: Mark Brown @ 2016-11-09 14:59 UTC (permalink / raw)
To: James Schulman
Cc: Mark Brown, alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
brian.austin-jGc1dHjMKG3QT0dZR+AlfA
In-Reply-To: <139006a2-bc5f-4a49-8269-89c1adc3acf0-k7YZYYsDncjfk+Ne4bZl5AC/G2K4zDHf@public.gmane.org>
The patch
ASoC: cs42l42: Add devicetree bindings for CS42L42
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From da16c55793539a8c83c81240984915ce6d0140fe Mon Sep 17 00:00:00 2001
From: James Schulman <james.schulman-jGc1dHjMKG3QT0dZR+AlfA@public.gmane.org>
Date: Mon, 7 Nov 2016 14:38:38 -0600
Subject: [PATCH] ASoC: cs42l42: Add devicetree bindings for CS42L42
Add devicetree bindings documentation file for Cirrus
Logic CS42L42 codec.
Signed-off-by: James Schulman <james.schulman-jGc1dHjMKG3QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
.../devicetree/bindings/sound/cs42l42.txt | 110 +++++++++++++++++++++
1 file changed, 110 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/cs42l42.txt
diff --git a/Documentation/devicetree/bindings/sound/cs42l42.txt b/Documentation/devicetree/bindings/sound/cs42l42.txt
new file mode 100644
index 000000000000..9a2c5e2423d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cs42l42.txt
@@ -0,0 +1,110 @@
+CS42L42 audio CODEC
+
+Required properties:
+
+ - compatible : "cirrus,cs42l42"
+
+ - reg : the I2C address of the device for I2C.
+
+ - VP-supply, VCP-supply, VD_FILT-supply, VL-supply, VA-supply :
+ power supplies for the device, as covered in
+ Documentation/devicetree/bindings/regulator/regulator.txt.
+
+Optional properties:
+
+ - reset-gpios : a GPIO spec for the reset pin. If specified, it will be
+ deasserted before communication to the codec starts.
+
+ - interrupt-parent : Specifies the phandle of the interrupt controller to
+ which the IRQs from CS42L42 are delivered to.
+
+ - interrupts : IRQ line info CS42L42.
+ (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+ for further information relating to interrupt properties)
+
+ - cirrus,ts-inv : Boolean property. For jacks that invert the tip sense
+ polarity. Normal jacks will short tip sense pin to HS1 when headphones are
+ plugged in and leave tip sense floating when not plugged in. Inverting jacks
+ short tip sense when unplugged and float when plugged in.
+
+ 0 = (Default) Non-inverted
+ 1 = Inverted
+
+ - cirrus,ts-dbnc-rise : Debounce the rising edge of TIP_SENSE_PLUG. With no
+ debounce, the tip sense pin might be noisy on a plug event.
+
+ 0 - 0ms,
+ 1 - 125ms,
+ 2 - 250ms,
+ 3 - 500ms,
+ 4 - 750ms,
+ 5 - (Default) 1s,
+ 6 - 1.25s,
+ 7 - 1.5s,
+
+ - cirrus,ts-dbnc-fall : Debounce the falling edge of TIP_SENSE_UNPLUG.
+ With no debounce, the tip sense pin might be noisy on an unplug event.
+
+ 0 - 0ms,
+ 1 - 125ms,
+ 2 - 250ms,
+ 3 - 500ms,
+ 4 - 750ms,
+ 5 - (Default) 1s,
+ 6 - 1.25s,
+ 7 - 1.5s,
+
+ - cirrus,btn-det-init-dbnce : This sets how long the driver sleeps after
+ enabling button detection interrupts. After auto-detection and before
+ servicing button interrupts, the HS bias needs time to settle. If you
+ don't wait, there is possibility for erroneous button interrupt.
+
+ 0ms - 200ms,
+ Default = 100ms
+
+ - cirrus,btn-det-event-dbnce : This sets how long the driver delays after
+ receiving a button press interrupt. With level detect interrupts, you want
+ to wait a small amount of time to make sure the button press is making a
+ clean connection with the bias resistors.
+
+ 0ms - 20ms,
+ Default = 10ms
+
+ - cirrus,bias-lvls : For a level-detect headset button scheme, each button
+ will bias the mic pin to a certain voltage. To determine which button was
+ pressed, the driver will compare this biased voltage to sequential,
+ decreasing voltages and will stop when a comparator is tripped,
+ indicating a comparator voltage < bias voltage. This value represents a
+ percentage of the internally generated HS bias voltage. For different
+ hardware setups, a designer might want to tweak this. This is an array of
+ descending values for the comparator voltage.
+
+ Array of 4 values
+ Each 0-63
+ < x1 x2 x3 x4 >
+ Default = < 15 8 4 1>
+
+
+Example:
+
+cs42l42: cs42l42@48 {
+ compatible = "cirrus,cs42l42";
+ reg = <0x48>;
+ VA-supply = <&dummy_vreg>;
+ VP-supply = <&dummy_vreg>;
+ VCP-supply = <&dummy_vreg>;
+ VD_FILT-supply = <&dummy_vreg>;
+ VL-supply = <&dummy_vreg>;
+
+ reset-gpios = <&axi_gpio_0 1 0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <55 8>
+
+ cirrus,ts-inv = <0x00>;
+ cirrus,ts-dbnc-rise = <0x05>;
+ cirrus,ts-dbnc-fall = <0x00>;
+ cirrus,btn-det-init-dbnce = <100>;
+ cirrus,btn-det-event-dbnce = <10>;
+ cirrus,bias-lvls = <0x0F 0x08 0x04 0x01>;
+ cirrus,hs-bias-ramp-rate = <0x02>;
+};
\ No newline at end of file
--
2.10.2
--
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 related
* Re: [PATCH v4 8/8] iio: envelope-detector: ADC driver based on a DAC and a comparator
From: Peter Rosin @ 2016-11-09 15:01 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron,
Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <alpine.DEB.2.20.1611082146560.3501@nanos>
On 2016-11-08 22:47, Thomas Gleixner wrote:
> On Tue, 8 Nov 2016, Peter Rosin wrote:
>> So, to sum up, in order for this to work with threaded oneshot
>> interrupts, I still need to either keep the enable/sync/enable-dance
>> or tweak the irq core to handle my case better. The only gain would
>> be that I could fire the next step of the search from the threaded
>> irq handler directly (but it needs some new race-killing code).
>> Or am I missing something? If not, there's no pressing reason to
>> switch to threaded oneshot interrupts, right?
>
> There is no pressing reason, but that misfire prevention dance looks
> fragile and overly complex to me.
I don't see any fragility? But I wouldn't complain if there was some
simpler way to enable an irq in such a way that only new and fresh
irqs are considered.
> The completely untested patch below should block the replay for edge
[it is missing a ')', see inline comment below]
> interrupts from the core code. It also makes sure that the edge interrupt
> is masked until the thread handler returns. All you have to do is
> requesting your threaded handler with IRQF_ONESHOT | IRQF_NO_REPLAY.
It doesn't appear to work. I still get irqs that reasonably should
only have happened *during* the handling of a previous irq. And I
still need to dance when enabling the irq, otherwise I get spurious
hits.
> I don't think you need extra race handling with that, but I might be wrong
> as usual.
There's obviously no way to determine which of the timeout or the
interrupt that happens first without some race handling, so I don't
know what you mean? If the timeout happens first, there is also a
need to handle late hits from the irq that might come in during the
preparation for the next step in the binary search. It gets messy
quickly compared to the simplicity of the current implementation.
Cheers,
Peter
> 8<------------------
> --- a/include/linux/interrupt.h
> +++ b/include/linux/interrupt.h
> @@ -74,6 +74,7 @@
> #define IRQF_NO_THREAD 0x00010000
> #define IRQF_EARLY_RESUME 0x00020000
> #define IRQF_COND_SUSPEND 0x00040000
> +#define IRQF_NO_REPLAY 0x00080000
>
> #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
>
> --- a/kernel/irq/internals.h
> +++ b/kernel/irq/internals.h
> @@ -57,6 +57,7 @@ enum {
> IRQS_WAITING = 0x00000080,
> IRQS_PENDING = 0x00000200,
> IRQS_SUSPENDED = 0x00000800,
> + IRQS_NO_REPLAY = 0x00001000,
> };
>
> #include "debug.h"
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
> @@ -1212,7 +1212,8 @@ static int
> */
> if (!((old->flags & new->flags) & IRQF_SHARED) ||
> ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
> - ((old->flags ^ new->flags) & IRQF_ONESHOT))
> + ((old->flags ^ new->flags) & IRQF_ONESHOT) ||
> + ((old->flags ^ new->flags) & IRQF_NO_REPLAY))
> goto mismatch;
>
> /* All handlers must agree on per-cpuness */
> @@ -1324,6 +1325,9 @@ static int
> if (new->flags & IRQF_ONESHOT)
> desc->istate |= IRQS_ONESHOT;
>
> + if (new->flags & IRQF_NO_REPLAY)
> + desc->istate |= IRQS_NO_REPLAY;
> +
> if (irq_settings_can_autoenable(desc))
> irq_startup(desc, true);
> else
> --- a/kernel/irq/resend.c
> +++ b/kernel/irq/resend.c
> @@ -56,12 +56,12 @@ static DECLARE_TASKLET(resend_tasklet, r
> void check_irq_resend(struct irq_desc *desc)
> {
> /*
> - * We do not resend level type interrupts. Level type
> - * interrupts are resent by hardware when they are still
> - * active. Clear the pending bit so suspend/resume does not
> - * get confused.
> + * We do not resend level type interrupts. Level type interrupts
> + * are resent by hardware when they are still active. Also prevent
> + * resend when the user requested so. Clear the pending bit so
> + * suspend/resume does not get confused.
> */
> - if (irq_settings_is_level(desc)) {
> + if (irq_settings_is_level(desc) || (desc->istate & IRQS_NO_REPLAY)) {
> desc->istate &= ~IRQS_PENDING;
> return;
> }
> --- a/kernel/irq/chip.c
> +++ b/kernel/irq/chip.c
> @@ -643,7 +643,10 @@ void handle_edge_irq(struct irq_desc *de
> kstat_incr_irqs_this_cpu(desc);
>
> /* Start handling the irq */
> - desc->irq_data.chip->irq_ack(&desc->irq_data);
> + if (!(desc->istate & (IRQS_NO_REPLAY | IRQS_ONESHOT))
Missing ')' at the end.
> + desc->irq_data.chip->irq_ack(&desc->irq_data);
> + else
> + mask_ack_irq(desc);
>
> do {
> if (unlikely(!desc->action)) {
>
>
--
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: [PATCH v4 8/8] iio: envelope-detector: ADC driver based on a DAC and a comparator
From: Thomas Gleixner @ 2016-11-09 15:06 UTC (permalink / raw)
To: Peter Rosin
Cc: linux-kernel, Jonathan Cameron, Hartmut Knaack,
Lars-Peter Clausen, Peter Meerwald-Stadler, Rob Herring,
Mark Rutland, Daniel Baluta, Slawomir Stepien, linux-iio,
devicetree
In-Reply-To: <ac908a97-77b8-046a-a0e9-74cc97f56c9b@axentia.se>
On Wed, 9 Nov 2016, Peter Rosin wrote:
> On 2016-11-08 22:47, Thomas Gleixner wrote:
> > I don't think you need extra race handling with that, but I might be wrong
> > as usual.
>
> There's obviously no way to determine which of the timeout or the
> interrupt that happens first without some race handling, so I don't
> know what you mean? If the timeout happens first, there is also a
> need to handle late hits from the irq that might come in during the
> preparation for the next step in the binary search. It gets messy
> quickly compared to the simplicity of the current implementation.
Gah, forgot about that timeout thingy. Fair enough.
Feel free to add an
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH 2/2] Documentation: DT: Add bmi160 imu binding
From: Marcin Niestroj @ 2016-11-09 15:18 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Daniel Baluta, Gregor Boirie, Sanchayan Maity, Rob Herring,
Mark Rutland, linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <e46a4b5e-a347-f268-80f4-0ee1edc77aac-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On 06.11.2016 13:41, Jonathan Cameron wrote:
> On 03/11/16 11:25, Marcin Niestroj wrote:
>> This adds documentation for Bosch BMI160 Inertial Measurement Unit
>> device-tree bindings.
>>
>> Signed-off-by: Marcin Niestroj <m.niestroj-z3quKL4iOrmQ6ZAhV5LmOA@public.gmane.org>
> Unless I missed it in the previous patch we should also have of tables
> added to the i2c and spi files (which is why the various tests haven't
> been screaming at me that this device doesn't have documented bindings).
Ok, I will add them.
>
> Otherwise, the use of interrupt names to indicate which pin on the chip
> is a little unusual (if you cribbed this from somewhere I've forgotten
> about then do say so!), so will want a devicetree bindings maintainer
> input on this.
I have used interrupt names similar as in other driver. Please see [1]
for it's DT documentation and [2] for implementation.
[1] Documentation/devicetree/bindings/iio/accel/mma8452.txt
[2] drivers/iio/accel/mma8452.c
>
> Thanks,
>
> Jonathan
>> ---
>> .../devicetree/bindings/iio/imu/bmi160.txt | 34 ++++++++++++++++++++++
>> 1 file changed, 34 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/iio/imu/bmi160.txt
>>
>> diff --git a/Documentation/devicetree/bindings/iio/imu/bmi160.txt b/Documentation/devicetree/bindings/iio/imu/bmi160.txt
>> new file mode 100644
>> index 0000000..b02ef3e
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iio/imu/bmi160.txt
>> @@ -0,0 +1,34 @@
>> +Bosch BMI160 - Inertial Measurement Unit with Accelerometer, Gyroscope
>> +and externally connectable Magnetometer
>> +
>> +https://www.bosch-sensortec.com/bst/products/all_products/bmi160
>> +
>> +Required properties:
>> + - compatible : should be "bosch,bmi160"
>> + - reg : the I2C address or SPI chip select number of the sensor
>> + - spi-max-frequency : set maximum clock frequency (only for SPI)
>> +
>> +Optional properties:
>> + - interrupt-parent : should be the phandle of the interrupt controller
>> + - interrupts : interrupt mapping for GPIO IRQ, must be IRQ_TYPE_LEVEL_LOW
>> + - interrupt-names : set to "INT2" if using INT2 pin
>> +
>> +Examples:
>> +
>> +bmi160@68 {
>> + compatible = "bosch,bmi160";
>> + reg = <0x68>;
>> +
>> + interrupt-parent = <&gpio4>;
>> + interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
>> +};
>> +
>> +bmi160@0 {
>> + compatible = "bosch,bmi160";
>> + reg = <0>;
>> + spi-max-frequency = <10000000>;
>> +
>> + interrupt-parent = <&gpio2>;
>> + interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
>> + interrupt-names = "INT2";
>> +};
>>
>
--
Marcin Niestroj
^ permalink raw reply
* [PATCH 0/5] Add V4L2 SDR (DRIF & MAX2175) driver
From: Ramesh Shanmugasundaram @ 2016-11-09 15:44 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
mchehab-DgEjT+Ai2ygdnm+yROfE0A, hverkuil-qWit8jRvyhVmR6Xm/wNWPw,
sakari.ailus-VuQAYsv1563Yd54FQh9/CA, crope-X3B1VOXEql0
Cc: chris.paterson2-zM6kxYcvzFBBDgjK7y7TUQ,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Ramesh Shanmugasundaram
Hi All,
This patch set contains two drivers
- R-Car Digital Radio Interface (DRIF) driver
- Maxim's MAX2175 RF to Bits tuner driver
These patches were based on top of media-next repo
commit: 778de01402328ca88cda84491d819bfc949935ff
These two drivers combined together expose a V4L2 SDR device that is compliant
with the V4L2 framework [1]. The RFC series of these two drivers were
published few weeks ago and the discussion thread is here [2]. Agreed review
comments are incorporated in this series.
Brief description of devices below
DRIF:
-----
This is a receive only slave controller that receives data into a FIFO from a
master device and uses DMA engine to move it from device to memory. It is a
serial I/O like controller with a design goal to act as digital radio receiver
targeting SDR solutions.
MAX2175:
--------
This is a RF front end tuner device that supports tuning to different bands &
frequency. It supports I2S output with programmable word lengths & single/dual
data lines usage based on selected receive mode. Each receive mode is
designated with a sample rate.
+---------------------+ +---------------------+
| |-----SCK------->| |
| MAX2175 (master) |-----SS-------->| DRIF (slave) |
| |-----SD0------->| |
| |-----SD1------->| |
+---------------------+ +---------------------+
New SDR formats:
----------------
The combined driver exposes new SDR formats. DRIF as such requires the receive
word length as the only programmable parameter in a normal case. Otherwise it is
agnostic of the tuner.
V4L2 framework requires publishing SDR formats about position of I & Q data
within the buffers. I have published three such formats to give an example. More
such formats are possible and will be added when needed.
References:
------------
[1] v4l2-compliance test report
root@salvator-x:~# v4l2-compliance -S /dev/swradio0
v4l2-compliance SHA : 788b674f3827607c09c31be11c91638f816aa6ae
Driver Info:
Driver name : rcar_drif
Card type : R-Car DRIF
Bus info : platform:R-Car DRIF
Driver version: 4.9.0
Capabilities : 0x85310000
SDR Capture
Tuner
Read/Write
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x05310000
SDR Capture
Tuner
Read/Write
Streaming
Extended Pix Format
Compliance test for device /dev/swradio0 (not using libv4l2):
Required ioctls:
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second sdr open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK
test VIDIOC_G/S_FREQUENCY: OK
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 1
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 5 Private Controls: 4
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK (Not Supported)
Test input 0:
Total: 43, Succeeded: 43, Failed: 0, Warnings: 0
root@salvator-x:~#
[2] RFC patch set discussion thread
https://www.mail-archive.com/linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg07968.html
Ramesh Shanmugasundaram (5):
media: v4l2-ctrls: Reserve controls for MAX217X
media: i2c: max2175: Add MAX2175 support
media: Add new SDR formats SC16, SC18 & SC20
doc_rst: media: New SDR formats SC16, SC18 & SC20
media: platform: rcar_drif: Add DRIF support
.../devicetree/bindings/media/i2c/max2175.txt | 61 +
.../devicetree/bindings/media/renesas,drif.txt | 136 ++
.../media/uapi/v4l/pixfmt-sdr-scu16be.rst | 80 +
.../media/uapi/v4l/pixfmt-sdr-scu18be.rst | 80 +
.../media/uapi/v4l/pixfmt-sdr-scu20be.rst | 80 +
Documentation/media/uapi/v4l/sdr-formats.rst | 3 +
drivers/media/i2c/Kconfig | 4 +
drivers/media/i2c/Makefile | 2 +
drivers/media/i2c/max2175/Kconfig | 8 +
drivers/media/i2c/max2175/Makefile | 4 +
drivers/media/i2c/max2175/max2175.c | 1558 +++++++++++++++++++
drivers/media/i2c/max2175/max2175.h | 108 ++
drivers/media/platform/Kconfig | 25 +
drivers/media/platform/Makefile | 1 +
drivers/media/platform/rcar_drif.c | 1574 ++++++++++++++++++++
drivers/media/v4l2-core/v4l2-ioctl.c | 3 +
include/uapi/linux/v4l2-controls.h | 5 +
include/uapi/linux/videodev2.h | 3 +
18 files changed, 3735 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/max2175.txt
create mode 100644 Documentation/devicetree/bindings/media/renesas,drif.txt
create mode 100644 Documentation/media/uapi/v4l/pixfmt-sdr-scu16be.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-sdr-scu18be.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-sdr-scu20be.rst
create mode 100644 drivers/media/i2c/max2175/Kconfig
create mode 100644 drivers/media/i2c/max2175/Makefile
create mode 100644 drivers/media/i2c/max2175/max2175.c
create mode 100644 drivers/media/i2c/max2175/max2175.h
create mode 100644 drivers/media/platform/rcar_drif.c
--
1.9.1
--
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
* [PATCH 1/5] media: v4l2-ctrls: Reserve controls for MAX217X
From: Ramesh Shanmugasundaram @ 2016-11-09 15:44 UTC (permalink / raw)
To: robh+dt, mark.rutland, mchehab, hverkuil, sakari.ailus, crope
Cc: chris.paterson2, laurent.pinchart, geert+renesas, linux-media,
devicetree, linux-renesas-soc, Ramesh Shanmugasundaram
In-Reply-To: <1478706284-59134-1-git-send-email-ramesh.shanmugasundaram@bp.renesas.com>
Reserve controls for MAX217X RF to Bits tuner (family) chips. These hybrid
radio receiver chips are highly programmable and hence reserving 32
controls.
Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
---
include/uapi/linux/v4l2-controls.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index b6a357a..b7404c9 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -180,6 +180,11 @@ enum v4l2_colorfx {
* We reserve 16 controls for this driver. */
#define V4L2_CID_USER_TC358743_BASE (V4L2_CID_USER_BASE + 0x1080)
+/* The base for the max217x driver controls.
+ * We reserve 32 controls for this driver
+ */
+#define V4L2_CID_USER_MAX217X_BASE (V4L2_CID_USER_BASE + 0x1090)
+
/* MPEG-class control IDs */
/* The MPEG controls are applicable to all codec controls
* and the 'MPEG' part of the define is historical */
--
1.9.1
^ permalink raw reply related
* [PATCH 2/5] media: i2c: max2175: Add MAX2175 support
From: Ramesh Shanmugasundaram @ 2016-11-09 15:44 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
mchehab-DgEjT+Ai2ygdnm+yROfE0A, hverkuil-qWit8jRvyhVmR6Xm/wNWPw,
sakari.ailus-VuQAYsv1563Yd54FQh9/CA, crope-X3B1VOXEql0
Cc: chris.paterson2-zM6kxYcvzFBBDgjK7y7TUQ,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Ramesh Shanmugasundaram
In-Reply-To: <1478706284-59134-1-git-send-email-ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
This patch adds driver support for MAX2175 chip. This is Maxim
Integrated's RF to Bits tuner front end chip designed for software-defined
radio solutions. This driver exposes the tuner as a sub-device instance
with standard and custom controls to configure the device.
Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
---
.../devicetree/bindings/media/i2c/max2175.txt | 61 +
drivers/media/i2c/Kconfig | 4 +
drivers/media/i2c/Makefile | 2 +
drivers/media/i2c/max2175/Kconfig | 8 +
drivers/media/i2c/max2175/Makefile | 4 +
drivers/media/i2c/max2175/max2175.c | 1558 ++++++++++++++++++++
drivers/media/i2c/max2175/max2175.h | 108 ++
7 files changed, 1745 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/max2175.txt
create mode 100644 drivers/media/i2c/max2175/Kconfig
create mode 100644 drivers/media/i2c/max2175/Makefile
create mode 100644 drivers/media/i2c/max2175/max2175.c
create mode 100644 drivers/media/i2c/max2175/max2175.h
diff --git a/Documentation/devicetree/bindings/media/i2c/max2175.txt b/Documentation/devicetree/bindings/media/i2c/max2175.txt
new file mode 100644
index 0000000..69f0dad
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/max2175.txt
@@ -0,0 +1,61 @@
+Maxim Integrated MAX2175 RF to Bits tuner
+-----------------------------------------
+
+The MAX2175 IC is an advanced analog/digital hybrid-radio receiver with
+RF to Bits® front-end designed for software-defined radio solutions.
+
+Required properties:
+--------------------
+- compatible: "maxim,max2175" for MAX2175 RF-to-bits tuner.
+- clocks: phandle to the fixed xtal clock.
+- clock-names: name of the fixed xtal clock.
+- port: child port node of a tuner that defines the local and remote
+ endpoints. The remote endpoint is assumed to be an SDR device
+ that is capable of receiving the digital samples from the tuner.
+
+Optional properties:
+--------------------
+- maxim,slave : empty property indicates this is a slave of
+ another master tuner. This is used to define two
+ tuners in diversity mode (1 master, 1 slave). By
+ default each tuner is an individual master.
+- maxim,refout-load-pF: load capacitance value (in pF) on reference
+ output drive level. The possible load values are
+ 0pF (default - refout disabled)
+ 10pF
+ 20pF
+ 30pF
+ 40pF
+ 60pF
+ 70pF
+- maxim,am-hiz : empty property indicates AM Hi-Z filter path is
+ selected for AM antenna input. By default this
+ filter path is not used.
+
+Example:
+--------
+
+Board specific DTS file
+
+/* Fixed XTAL clock node */
+maxim_xtal: maximextal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <36864000>;
+};
+
+/* A tuner device instance under i2c bus */
+max2175_0: tuner@60 {
+ compatible = "maxim,max2175";
+ reg = <0x60>;
+ clocks = <&maxim_xtal>;
+ clock-names = "xtal";
+ maxim,refout-load-pF = <10>;
+
+ port {
+ max2175_0_ep: endpoint {
+ remote-endpoint = <&slave_rx_v4l2_sdr_device>;
+ };
+ };
+
+};
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 2669b4b..66c73b0 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -749,6 +749,10 @@ config VIDEO_SAA6752HS
To compile this driver as a module, choose M here: the
module will be called saa6752hs.
+comment "SDR tuner chips"
+
+source "drivers/media/i2c/max2175/Kconfig"
+
comment "Miscellaneous helper chips"
config VIDEO_THS7303
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 92773b2..cfae721 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_VIDEO_CX25840) += cx25840/
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
obj-y += soc_camera/
+obj-$(CONFIG_SDR_MAX2175) += max2175/
+
obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
diff --git a/drivers/media/i2c/max2175/Kconfig b/drivers/media/i2c/max2175/Kconfig
new file mode 100644
index 0000000..93a8f83
--- /dev/null
+++ b/drivers/media/i2c/max2175/Kconfig
@@ -0,0 +1,8 @@
+config SDR_MAX2175
+ tristate "Maxim 2175 RF to Bits tuner"
+ depends on VIDEO_V4L2 && MEDIA_SDR_SUPPORT && I2C
+ ---help---
+ Support for Maxim 2175 tuner
+
+ To compile this driver as a module, choose M here; the
+ module will be called max2175.
diff --git a/drivers/media/i2c/max2175/Makefile b/drivers/media/i2c/max2175/Makefile
new file mode 100644
index 0000000..9bb46ac
--- /dev/null
+++ b/drivers/media/i2c/max2175/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for Maxim RF to Bits tuner device
+#
+obj-$(CONFIG_SDR_MAX2175) += max2175.o
diff --git a/drivers/media/i2c/max2175/max2175.c b/drivers/media/i2c/max2175/max2175.c
new file mode 100644
index 0000000..ec45b52
--- /dev/null
+++ b/drivers/media/i2c/max2175/max2175.c
@@ -0,0 +1,1558 @@
+/*
+ * Maxim Integrated MAX2175 RF to Bits tuner driver
+ *
+ * This driver & most of the hard coded values are based on the reference
+ * application delivered by Maxim for this chip.
+ *
+ * Copyright (C) 2016 Maxim Integrated Products
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-of.h>
+
+#include "max2175.h"
+
+#define DRIVER_NAME "max2175"
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activate debug info");
+
+#define mxm_dbg(ctx, fmt, arg...) v4l2_dbg(1, debug, &ctx->sd, fmt, ## arg)
+
+/* Rx mode */
+struct max2175_rxmode {
+ enum max2175_band band; /* Associated band */
+ u32 freq; /* Default freq in Hz */
+ u8 i2s_word_size; /* Bit value */
+ u8 i2s_modes[4]; /* Supported modes */
+};
+
+/* Register map to define preset values */
+struct max2175_reg_map {
+ u8 idx; /* Register index */
+ u8 val; /* Register value */
+};
+
+static const struct max2175_rxmode eu_rx_modes[] = {
+ /* EU modes */
+ [MAX2175_EU_FM_1_2] = { MAX2175_BAND_FM,
+ 98256000, 1, { 0, 0, 0, 0 } },
+ [MAX2175_DAB_1_2] = { MAX2175_BAND_VHF,
+ 182640000, 0, { 0, 0, 0, 0 } },
+};
+
+static const struct max2175_rxmode na_rx_modes[] = {
+ /* NA modes */
+ [MAX2175_NA_FM_1_0] = { MAX2175_BAND_FM,
+ 98255520, 1, { 0, 0, 0, 0 } },
+ [MAX2175_NA_FM_2_0] = { MAX2175_BAND_FM,
+ 98255520, 6, { 0, 0, 0, 0 } },
+};
+
+/*
+ * Preset values:
+ * Based on Maxim MAX2175 Register Table revision: 130p10
+ */
+static const u8 full_fm_eu_1p0[] = {
+ 0x15, 0x04, 0xb8, 0xe3, 0x35, 0x18, 0x7c, 0x00,
+ 0x00, 0x7d, 0x40, 0x08, 0x70, 0x7a, 0x88, 0x91,
+ 0x61, 0x61, 0x61, 0x61, 0x5a, 0x0f, 0x34, 0x1c,
+ 0x14, 0x88, 0x33, 0x02, 0x00, 0x09, 0x00, 0x65,
+ 0x9f, 0x2b, 0x80, 0x00, 0x95, 0x05, 0x2c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x4a, 0x08, 0xa8, 0x0e, 0x0e, 0x2f, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5e, 0xa9,
+ 0xae, 0xbb, 0x57, 0x18, 0x3b, 0x03, 0x3b, 0x64,
+ 0x40, 0x60, 0x00, 0x2a, 0xbf, 0x3f, 0xff, 0x9f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0xff, 0xfc, 0xef, 0x1c, 0x40, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00,
+ 0x00, 0x47, 0x00, 0x00, 0x11, 0x3f, 0x22, 0x00,
+ 0xf1, 0x00, 0x41, 0x03, 0xb0, 0x00, 0x00, 0x00,
+ 0x1b,
+};
+
+static const u8 full_fm_na_1p0[] = {
+ 0x13, 0x08, 0x8d, 0xc0, 0x35, 0x18, 0x7d, 0x3f,
+ 0x7d, 0x75, 0x40, 0x08, 0x70, 0x7a, 0x88, 0x91,
+ 0x61, 0x61, 0x61, 0x61, 0x5c, 0x0f, 0x34, 0x1c,
+ 0x14, 0x88, 0x33, 0x02, 0x00, 0x01, 0x00, 0x65,
+ 0x9f, 0x2b, 0x80, 0x00, 0x95, 0x05, 0x2c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x4a, 0x08, 0xa8, 0x0e, 0x0e, 0xaf, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5e, 0xa9,
+ 0xae, 0xbb, 0x57, 0x18, 0x3b, 0x03, 0x3b, 0x64,
+ 0x40, 0x60, 0x00, 0x2a, 0xbf, 0x3f, 0xff, 0x9f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0xff, 0xfc, 0xef, 0x1c, 0x40, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00,
+ 0x00, 0x35, 0x00, 0x00, 0x11, 0x3f, 0x22, 0x00,
+ 0xf1, 0x00, 0x41, 0x03, 0xb0, 0x00, 0x00, 0x00,
+ 0x1b,
+};
+
+/* DAB1.2 settings */
+static const struct max2175_reg_map dab12_map[] = {
+ { 0x01, 0x13 }, { 0x02, 0x0d }, { 0x03, 0x15 }, { 0x04, 0x55 },
+ { 0x05, 0x0a }, { 0x06, 0xa0 }, { 0x07, 0x40 }, { 0x08, 0x00 },
+ { 0x09, 0x00 }, { 0x0a, 0x7d }, { 0x0b, 0x4a }, { 0x0c, 0x28 },
+ { 0x0e, 0x43 }, { 0x0f, 0xb5 }, { 0x10, 0x31 }, { 0x11, 0x9e },
+ { 0x12, 0x68 }, { 0x13, 0x9e }, { 0x14, 0x68 }, { 0x15, 0x58 },
+ { 0x16, 0x2f }, { 0x17, 0x3f }, { 0x18, 0x40 }, { 0x1a, 0x88 },
+ { 0x1b, 0xaa }, { 0x1c, 0x9a }, { 0x1d, 0x00 }, { 0x1e, 0x00 },
+ { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x00 }, { 0x26, 0x00 },
+ { 0x27, 0x00 }, { 0x32, 0x08 }, { 0x33, 0xf8 }, { 0x36, 0x2d },
+ { 0x37, 0x7e }, { 0x55, 0xaf }, { 0x56, 0x3f }, { 0x57, 0xf8 },
+ { 0x58, 0x99 }, { 0x76, 0x00 }, { 0x77, 0x00 }, { 0x78, 0x02 },
+ { 0x79, 0x40 }, { 0x82, 0x00 }, { 0x83, 0x00 }, { 0x85, 0x00 },
+ { 0x86, 0x20 },
+};
+
+/* EU FM 1.2 settings */
+static const struct max2175_reg_map fmeu1p2_map[] = {
+ { 0x01, 0x15 }, { 0x02, 0x04 }, { 0x03, 0xb8 }, { 0x04, 0xe3 },
+ { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7c }, { 0x08, 0x00 },
+ { 0x09, 0x00 }, { 0x0a, 0x73 }, { 0x0b, 0x40 }, { 0x0c, 0x08 },
+ { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
+ { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5a },
+ { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
+ { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
+ { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
+ { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0x2f },
+ { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
+ { 0x58, 0x9f }, { 0x76, 0xac }, { 0x77, 0x40 }, { 0x78, 0x00 },
+ { 0x79, 0x00 }, { 0x82, 0x47 }, { 0x83, 0x00 }, { 0x85, 0x11 },
+ { 0x86, 0x3f },
+};
+
+/* FM NA 1.0 settings */
+static const struct max2175_reg_map fmna1p0_map[] = {
+ { 0x01, 0x13 }, { 0x02, 0x08 }, { 0x03, 0x8d }, { 0x04, 0xc0 },
+ { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7d }, { 0x08, 0x3f },
+ { 0x09, 0x7d }, { 0x0a, 0x75 }, { 0x0b, 0x40 }, { 0x0c, 0x08 },
+ { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
+ { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5c },
+ { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
+ { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
+ { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
+ { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0xaf },
+ { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
+ { 0x58, 0x9f }, { 0x76, 0xa6 }, { 0x77, 0x40 }, { 0x78, 0x00 },
+ { 0x79, 0x00 }, { 0x82, 0x35 }, { 0x83, 0x00 }, { 0x85, 0x11 },
+ { 0x86, 0x3f },
+};
+
+/* FM NA 2.0 settings */
+static const struct max2175_reg_map fmna2p0_map[] = {
+ { 0x01, 0x13 }, { 0x02, 0x08 }, { 0x03, 0x8d }, { 0x04, 0xc0 },
+ { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7c }, { 0x08, 0x54 },
+ { 0x09, 0xa7 }, { 0x0a, 0x55 }, { 0x0b, 0x42 }, { 0x0c, 0x48 },
+ { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
+ { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5c },
+ { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
+ { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
+ { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
+ { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0xaf },
+ { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
+ { 0x58, 0x9f }, { 0x76, 0xac }, { 0x77, 0xc0 }, { 0x78, 0x00 },
+ { 0x79, 0x00 }, { 0x82, 0x6b }, { 0x83, 0x00 }, { 0x85, 0x11 },
+ { 0x86, 0x3f },
+};
+
+static const u16 ch_coeff_dab1[] = {
+ 0x001c, 0x0007, 0xffcd, 0x0056, 0xffa4, 0x0033, 0x0027, 0xff61,
+ 0x010e, 0xfec0, 0x0106, 0xffb8, 0xff1c, 0x023c, 0xfcb2, 0x039b,
+ 0xfd4e, 0x0055, 0x036a, 0xf7de, 0x0d21, 0xee72, 0x1499, 0x6a51,
+};
+
+static const u16 ch_coeff_fmeu[] = {
+ 0x0000, 0xffff, 0x0001, 0x0002, 0xfffa, 0xffff, 0x0015, 0xffec,
+ 0xffde, 0x0054, 0xfff9, 0xff52, 0x00b8, 0x00a2, 0xfe0a, 0x00af,
+ 0x02e3, 0xfc14, 0xfe89, 0x089d, 0xfa2e, 0xf30f, 0x25be, 0x4eb6,
+};
+
+static const u16 eq_coeff_fmeu1_ra02_m6db[] = {
+ 0x0040, 0xffc6, 0xfffa, 0x002c, 0x000d, 0xff90, 0x0037, 0x006e,
+ 0xffc0, 0xff5b, 0x006a, 0x00f0, 0xff57, 0xfe94, 0x0112, 0x0252,
+ 0xfe0c, 0xfc6a, 0x0385, 0x0553, 0xfa49, 0xf789, 0x0b91, 0x1a10,
+};
+
+static const u16 ch_coeff_fmna[] = {
+ 0x0001, 0x0003, 0xfffe, 0xfff4, 0x0000, 0x001f, 0x000c, 0xffbc,
+ 0xffd3, 0x007d, 0x0075, 0xff33, 0xff01, 0x0131, 0x01ef, 0xfe60,
+ 0xfc7a, 0x020e, 0x0656, 0xfd94, 0xf395, 0x02ab, 0x2857, 0x3d3f,
+};
+
+static const u16 eq_coeff_fmna1_ra02_m6db[] = {
+ 0xfff1, 0xffe1, 0xffef, 0x000e, 0x0030, 0x002f, 0xfff6, 0xffa7,
+ 0xff9d, 0x000a, 0x00a2, 0x00b5, 0xffea, 0xfed9, 0xfec5, 0x003d,
+ 0x0217, 0x021b, 0xff5a, 0xfc2b, 0xfcbd, 0x02c4, 0x0ac3, 0x0e85,
+};
+
+static const u8 adc_presets[2][23] = {
+ {
+ 0x83, 0x00, 0xcf, 0xb4, 0x0f, 0x2c, 0x0c, 0x49,
+ 0x00, 0x00, 0x00, 0x8c, 0x02, 0x02, 0x00, 0x04,
+ 0xec, 0x82, 0x4b, 0xcc, 0x01, 0x88, 0x0c,
+ },
+ {
+ 0x83, 0x00, 0xcf, 0xb4, 0x0f, 0x2c, 0x0c, 0x49,
+ 0x00, 0x00, 0x00, 0x8c, 0x02, 0x20, 0x33, 0x8c,
+ 0x57, 0xd7, 0x59, 0xb7, 0x65, 0x0e, 0x0c,
+ },
+};
+
+/* Custom controls */
+#define V4L2_CID_MAX2175_I2S_ENABLE (V4L2_CID_USER_MAX217X_BASE + 0x01)
+#define V4L2_CID_MAX2175_I2S_MODE (V4L2_CID_USER_MAX217X_BASE + 0x02)
+#define V4L2_CID_MAX2175_HSLS (V4L2_CID_USER_MAX217X_BASE + 0x03)
+#define V4L2_CID_MAX2175_RX_MODE (V4L2_CID_USER_MAX217X_BASE + 0x04)
+
+/* Tuner bands */
+static const struct v4l2_frequency_band eu_bands_rf = {
+ .tuner = 0,
+ .type = V4L2_TUNER_RF,
+ .index = 0,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 65000000,
+ .rangehigh = 240000000,
+};
+
+static const struct v4l2_frequency_band na_bands_rf = {
+ .tuner = 0,
+ .type = V4L2_TUNER_RF,
+ .index = 0,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 65000000,
+ .rangehigh = 108000000,
+};
+
+/* Regmap settings */
+static const struct regmap_range max2175_regmap_volatile_range[] = {
+ regmap_reg_range(0x30, 0x35),
+ regmap_reg_range(0x3a, 0x45),
+ regmap_reg_range(0x59, 0x5e),
+ regmap_reg_range(0x73, 0x75),
+};
+
+static const struct regmap_access_table max2175_volatile_regs = {
+ .yes_ranges = max2175_regmap_volatile_range,
+ .n_yes_ranges = ARRAY_SIZE(max2175_regmap_volatile_range),
+};
+
+static const struct reg_default max2175_reg_defaults[] = {
+ { 0x00, 0x07},
+};
+
+static const struct regmap_config max2175_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ .reg_defaults = max2175_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(max2175_reg_defaults),
+ .volatile_table = &max2175_volatile_regs,
+ .cache_type = REGCACHE_FLAT,
+};
+
+struct max2175 {
+ struct v4l2_subdev sd; /* Sub-device */
+ struct i2c_client *client; /* I2C client */
+
+ /* Controls */
+ struct v4l2_ctrl_handler ctrl_hdl;
+ struct v4l2_ctrl *lna_gain; /* LNA gain value */
+ struct v4l2_ctrl *if_gain; /* I/F gain value */
+ struct v4l2_ctrl *pll_lock; /* PLL lock */
+ struct v4l2_ctrl *i2s_en; /* I2S output enable */
+ struct v4l2_ctrl *i2s_mode; /* I2S mode value */
+ struct v4l2_ctrl *hsls; /* High-side/Low-side polarity */
+ struct v4l2_ctrl *rx_mode; /* Receive mode */
+
+ /* Regmap */
+ struct regmap *regmap;
+
+ /* Cached configuration */
+ u32 freq; /* Tuned freq In Hz */
+ const struct max2175_rxmode *rx_modes; /* EU or NA modes */
+ const struct v4l2_frequency_band *bands_rf; /* EU or NA bands */
+
+ /* Device settings */
+ unsigned long xtal_freq; /* Ref Oscillator freq in Hz */
+ u32 decim_ratio;
+ bool master; /* Master/Slave */
+ bool am_hiz; /* AM Hi-Z filter usage */
+
+ /* ROM values */
+ u8 rom_bbf_bw_am;
+ u8 rom_bbf_bw_fm;
+ u8 rom_bbf_bw_dab;
+
+ /* Local copy of old setting */
+ u8 i2s_test;
+
+ /* Driver private variables */
+ bool mode_resolved; /* Flag to sanity check settings */
+};
+
+static inline struct max2175 *max2175_from_sd(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct max2175, sd);
+}
+
+static inline struct max2175 *max2175_from_ctrl_hdl(struct v4l2_ctrl_handler *h)
+{
+ return container_of(h, struct max2175, ctrl_hdl);
+}
+
+/* Get bitval of a given val */
+static inline u8 max2175_get_bitval(u8 val, u8 msb, u8 lsb)
+{
+ return (val & GENMASK(msb, lsb)) >> lsb;
+}
+
+/* Read/Write bit(s) on top of regmap */
+static int max2175_read(struct max2175 *ctx, u8 idx, u8 *val)
+{
+ u32 regval;
+ int ret = regmap_read(ctx->regmap, idx, ®val);
+
+ if (ret)
+ v4l2_err(ctx->client, "read ret(%d): idx 0x%02x\n", ret, idx);
+
+ *val = regval;
+ return ret;
+}
+
+static int max2175_write(struct max2175 *ctx, u8 idx, u8 val)
+{
+ int ret = regmap_write(ctx->regmap, idx, val);
+
+ if (ret)
+ v4l2_err(ctx->client, "write ret(%d): idx 0x%02x val 0x%02x\n",
+ ret, idx, val);
+ return ret;
+}
+
+static u8 max2175_read_bits(struct max2175 *ctx, u8 idx, u8 msb, u8 lsb)
+{
+ u8 val;
+
+ if (max2175_read(ctx, idx, &val))
+ return 0;
+
+ return max2175_get_bitval(val, msb, lsb);
+}
+
+static bool max2175_read_bit(struct max2175 *ctx, u8 idx, u8 bit)
+{
+ return !!max2175_read_bits(ctx, idx, bit, bit);
+}
+
+static int max2175_write_bits(struct max2175 *ctx, u8 idx,
+ u8 msb, u8 lsb, u8 newval)
+{
+ int ret = regmap_update_bits(ctx->regmap, idx, GENMASK(msb, lsb),
+ newval << lsb);
+
+ if (ret)
+ v4l2_err(ctx->client, "wbits ret(%d): idx 0x%02x\n", ret, idx);
+
+ return ret;
+}
+
+static int max2175_write_bit(struct max2175 *ctx, u8 idx, u8 bit, u8 newval)
+{
+ return max2175_write_bits(ctx, idx, bit, bit, newval);
+}
+
+/* Checks expected pattern every msec until timeout */
+static int max2175_poll_timeout(struct max2175 *ctx, u8 idx, u8 msb, u8 lsb,
+ u8 exp_bitval, u32 timeout_ms)
+{
+ unsigned int val;
+
+ return regmap_read_poll_timeout(ctx->regmap, idx, val,
+ (max2175_get_bitval(val, msb, lsb) == exp_bitval),
+ 1000, timeout_ms * 1000);
+}
+
+static int max2175_poll_csm_ready(struct max2175 *ctx)
+{
+ int ret;
+
+ ret = max2175_poll_timeout(ctx, 69, 1, 1, 0, 50);
+ if (ret)
+ v4l2_err(ctx->client, "csm not ready\n");
+
+ return ret;
+}
+
+#define MAX2175_IS_BAND_AM(ctx) \
+ (max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_AM)
+
+#define MAX2175_IS_BAND_VHF(ctx) \
+ (max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_VHF)
+
+#define MAX2175_IS_FM_MODE(ctx) \
+ (max2175_read_bits(ctx, 12, 5, 4) == 0)
+
+#define MAX2175_IS_FMHD_MODE(ctx) \
+ (max2175_read_bits(ctx, 12, 5, 4) == 1)
+
+#define MAX2175_IS_DAB_MODE(ctx) \
+ (max2175_read_bits(ctx, 12, 5, 4) == 2)
+
+static int max2175_band_from_freq(u32 freq)
+{
+ if (freq >= 144000 && freq <= 26100000)
+ return MAX2175_BAND_AM;
+ else if (freq >= 65000000 && freq <= 108000000)
+ return MAX2175_BAND_FM;
+ else
+ return MAX2175_BAND_VHF;
+}
+
+static int max2175_update_i2s_mode(struct max2175 *ctx, u32 rx_mode,
+ u32 i2s_mode)
+{
+ max2175_write_bits(ctx, 29, 2, 0, i2s_mode);
+
+ /* Based on I2S mode value I2S_WORD_CNT values change */
+ switch (i2s_mode) {
+ case MAX2175_I2S_MODE3:
+ max2175_write_bits(ctx, 30, 6, 0, 1);
+ break;
+ case MAX2175_I2S_MODE2:
+ case MAX2175_I2S_MODE4:
+ max2175_write_bits(ctx, 30, 6, 0, 0);
+ break;
+ case MAX2175_I2S_MODE0:
+ max2175_write_bits(ctx, 30, 6, 0,
+ ctx->rx_modes[rx_mode].i2s_word_size);
+ break;
+ }
+ mxm_dbg(ctx, "update_i2s_mode %u, rx_mode %u\n", i2s_mode, rx_mode);
+ return 0;
+}
+
+static void max2175_i2s_enable(struct max2175 *ctx, bool enable)
+{
+ if (enable) {
+ /* Use old setting */
+ max2175_write_bits(ctx, 104, 3, 0, ctx->i2s_test);
+ } else {
+ /* Cache old setting */
+ ctx->i2s_test = max2175_read_bits(ctx, 104, 3, 0);
+ max2175_write_bits(ctx, 104, 3, 0, 9); /* Keep SCK alive */
+ }
+ mxm_dbg(ctx, "i2s %sabled: old val %u\n", enable ? "en" : "dis",
+ ctx->i2s_test);
+}
+
+static void max2175_set_filter_coeffs(struct max2175 *ctx, u8 m_sel,
+ u8 bank, const u16 *coeffs)
+{
+ unsigned int i;
+ u8 coeff_addr, upper_address = 24;
+
+ mxm_dbg(ctx, "set_filter_coeffs: m_sel %d bank %d\n", m_sel, bank);
+ max2175_write_bits(ctx, 114, 5, 4, m_sel);
+
+ if (m_sel == 2)
+ upper_address = 12;
+
+ for (i = 0; i < upper_address; i++) {
+ coeff_addr = i + bank * 24;
+ max2175_write(ctx, 115, coeffs[i] >> 8);
+ max2175_write(ctx, 116, coeffs[i]);
+ max2175_write(ctx, 117, coeff_addr | 1 << 7);
+ }
+ max2175_write_bit(ctx, 117, 7, 0);
+}
+
+static void max2175_load_fmeu_1p2(struct max2175 *ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(fmeu1p2_map); i++)
+ max2175_write(ctx, fmeu1p2_map[i].idx, fmeu1p2_map[i].val);
+
+ ctx->decim_ratio = 36;
+
+ /* Load the Channel Filter Coefficients into channel filter bank #2 */
+ max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0, ch_coeff_fmeu);
+ max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
+ eq_coeff_fmeu1_ra02_m6db);
+}
+
+static void max2175_load_dab_1p2(struct max2175 *ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(dab12_map); i++)
+ max2175_write(ctx, dab12_map[i].idx, dab12_map[i].val);
+
+ ctx->decim_ratio = 1;
+
+ /* Load the Channel Filter Coefficients into channel filter bank #2 */
+ max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 2, ch_coeff_dab1);
+}
+
+static void max2175_load_fmna_1p0(struct max2175 *ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(fmna1p0_map); i++)
+ max2175_write(ctx, fmna1p0_map[i].idx, fmna1p0_map[i].val);
+}
+
+static void max2175_load_fmna_2p0(struct max2175 *ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(fmna2p0_map); i++)
+ max2175_write(ctx, fmna2p0_map[i].idx, fmna2p0_map[i].val);
+}
+
+static void max2175_set_bbfilter(struct max2175 *ctx)
+{
+ if (MAX2175_IS_BAND_AM(ctx)) {
+ max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_am);
+ mxm_dbg(ctx, "set_bbfilter AM: rom %d\n", ctx->rom_bbf_bw_am);
+ } else if (MAX2175_IS_DAB_MODE(ctx)) {
+ max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_dab);
+ mxm_dbg(ctx, "set_bbfilter DAB: rom %d\n", ctx->rom_bbf_bw_dab);
+ } else {
+ max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_fm);
+ mxm_dbg(ctx, "set_bbfilter FM: rom %d\n", ctx->rom_bbf_bw_fm);
+ }
+}
+
+static bool max2175_set_csm_mode(struct max2175 *ctx,
+ enum max2175_csm_mode new_mode)
+{
+ int ret = max2175_poll_csm_ready(ctx);
+
+ if (ret)
+ return ret;
+
+ max2175_write_bits(ctx, 0, 2, 0, new_mode);
+ mxm_dbg(ctx, "set csm new mode %d\n", new_mode);
+
+ /* Wait for a fixed settle down time depending on new mode */
+ switch (new_mode) {
+ case MAX2175_PRESET_TUNE:
+ usleep_range(51100, 51500); /* 51.1ms */
+ break;
+ /*
+ * Other mode switches need different sleep values depending on band &
+ * mode
+ */
+ default:
+ break;
+ }
+
+ return max2175_poll_csm_ready(ctx);
+}
+
+static int max2175_csm_action(struct max2175 *ctx,
+ enum max2175_csm_mode action)
+{
+ int ret;
+
+ mxm_dbg(ctx, "csm_action: %d\n", action);
+
+ /* Other actions can be added in future when needed */
+ ret = max2175_set_csm_mode(ctx, MAX2175_LOAD_TO_BUFFER);
+ if (ret)
+ return ret;
+ return max2175_set_csm_mode(ctx, MAX2175_PRESET_TUNE);
+}
+
+static int max2175_set_lo_freq(struct max2175 *ctx, u64 lo_freq)
+{
+ u64 scaled_lo_freq, scaled_npf, scaled_integer, scaled_fraction;
+ u32 frac_desired, int_desired, lo_mult = 1;
+ const u32 scale_factor = 1000000U;
+ u8 loband_bits = 0, vcodiv_bits = 0;
+ enum max2175_band band;
+ int ret;
+
+ /* Scale to larger number for precision */
+ scaled_lo_freq = lo_freq * scale_factor * 100;
+ band = max2175_read_bits(ctx, 5, 1, 0);
+
+ mxm_dbg(ctx, "set_lo_freq: scaled lo_freq %llu lo_freq %llu band %d\n",
+ scaled_lo_freq, lo_freq, band);
+
+ switch (band) {
+ case MAX2175_BAND_AM:
+ if (max2175_read_bit(ctx, 5, 7) == 0)
+ lo_mult = 16;
+ break;
+ case MAX2175_BAND_FM:
+ if (lo_freq <= 74700000) {
+ lo_mult = 16;
+ } else if (lo_freq > 74700000 && lo_freq <= 110000000) {
+ loband_bits = 1;
+ } else {
+ loband_bits = 1;
+ vcodiv_bits = 3;
+ }
+ lo_mult = 8;
+ break;
+ case MAX2175_BAND_VHF:
+ if (lo_freq <= 210000000) {
+ loband_bits = 2;
+ vcodiv_bits = 2;
+ } else {
+ loband_bits = 2;
+ vcodiv_bits = 1;
+ }
+ lo_mult = 4;
+ break;
+ default:
+ loband_bits = 3;
+ vcodiv_bits = 2;
+ lo_mult = 2;
+ break;
+ }
+
+ if (band == MAX2175_BAND_L)
+ scaled_npf = div_u64(div_u64(scaled_lo_freq, ctx->xtal_freq),
+ lo_mult);
+ else
+ scaled_npf = div_u64(scaled_lo_freq, ctx->xtal_freq) * lo_mult;
+
+ scaled_npf = div_u64(scaled_npf, 100);
+ scaled_integer = div_u64(scaled_npf, scale_factor) * scale_factor;
+ int_desired = div_u64(scaled_npf, scale_factor);
+ scaled_fraction = scaled_npf - scaled_integer;
+ frac_desired = div_u64(scaled_fraction << 20, scale_factor);
+
+ /* Check CSM is not busy */
+ ret = max2175_poll_csm_ready(ctx);
+ if (ret)
+ return ret;
+
+ mxm_dbg(ctx, "loband %u vcodiv %u lo_mult %u scaled_npf %llu\n",
+ loband_bits, vcodiv_bits, lo_mult, scaled_npf);
+ mxm_dbg(ctx, "scaled int %llu frac %llu desired int %u frac %u\n",
+ scaled_integer, scaled_fraction, int_desired, frac_desired);
+
+ /* Write the calculated values to the appropriate registers */
+ max2175_write(ctx, 1, int_desired);
+ max2175_write_bits(ctx, 2, 3, 0, (frac_desired >> 16) & 0xf);
+ max2175_write(ctx, 3, frac_desired >> 8);
+ max2175_write(ctx, 4, frac_desired);
+ max2175_write_bits(ctx, 5, 3, 2, loband_bits);
+ max2175_write_bits(ctx, 6, 7, 6, vcodiv_bits);
+ return ret;
+}
+
+static int max2175_set_nco_freq(struct max2175 *ctx, s64 nco_freq_desired)
+{
+ s64 nco_freq, nco_val_desired;
+ u64 abs_nco_freq;
+ const u32 scale_factor = 1000000U;
+ u32 clock_rate, nco_reg;
+ int ret;
+
+ mxm_dbg(ctx, "set_nco_freq: freq %lld\n", nco_freq_desired);
+ clock_rate = ctx->xtal_freq / ctx->decim_ratio;
+ nco_freq = -nco_freq_desired;
+
+ if (nco_freq < 0)
+ abs_nco_freq = -nco_freq;
+ else
+ abs_nco_freq = nco_freq;
+
+ /* Scale up the values for precision */
+ if (abs_nco_freq < (clock_rate / 2)) {
+ nco_val_desired = div_s64(2 * nco_freq * scale_factor,
+ clock_rate);
+ } else {
+ if (nco_freq < 0)
+ nco_val_desired =
+ div_s64(-2 * (clock_rate - abs_nco_freq) * scale_factor,
+ clock_rate);
+ else
+ nco_val_desired =
+ div_s64(2 * (clock_rate - abs_nco_freq) * scale_factor,
+ clock_rate);
+ }
+
+ /* Scale down to get the fraction */
+ if (nco_freq < 0)
+ nco_reg = 0x200000 + div_s64(nco_val_desired << 20,
+ scale_factor);
+ else
+ nco_reg = div_s64(nco_val_desired << 20, scale_factor);
+
+ /* Check CSM is not busy */
+ ret = max2175_poll_csm_ready(ctx);
+ if (ret)
+ return ret;
+
+ mxm_dbg(ctx, "clk %u decim %u abs %llu desired %lld reg %u\n",
+ clock_rate, ctx->decim_ratio, abs_nco_freq,
+ nco_val_desired, nco_reg);
+
+ /* Write the calculated values to the appropriate registers */
+ max2175_write_bits(ctx, 7, 4, 0, (nco_reg >> 16) & 0x1f);
+ max2175_write(ctx, 8, nco_reg >> 8);
+ max2175_write(ctx, 9, nco_reg);
+ return ret;
+}
+
+static int max2175_set_rf_freq_non_am_bands(struct max2175 *ctx, u64 freq,
+ u32 lo_pos)
+{
+ s64 adj_freq;
+ u64 low_if_freq;
+ int ret;
+
+ mxm_dbg(ctx, "rf_freq: non AM bands\n");
+
+ if (MAX2175_IS_FM_MODE(ctx))
+ low_if_freq = 128000;
+ else if (MAX2175_IS_FMHD_MODE(ctx))
+ low_if_freq = 228000;
+ else
+ return max2175_set_lo_freq(ctx, freq);
+
+ if (MAX2175_IS_BAND_VHF(ctx) == (lo_pos == MAX2175_LO_ABOVE_DESIRED))
+ adj_freq = freq + low_if_freq;
+ else
+ adj_freq = freq - low_if_freq;
+
+ ret = max2175_set_lo_freq(ctx, adj_freq);
+ if (ret)
+ return ret;
+
+ return max2175_set_nco_freq(ctx, low_if_freq);
+}
+
+static int max2175_set_rf_freq(struct max2175 *ctx, u64 freq, u32 lo_pos)
+{
+ int ret;
+
+ if (MAX2175_IS_BAND_AM(ctx))
+ ret = max2175_set_nco_freq(ctx, freq);
+ else
+ ret = max2175_set_rf_freq_non_am_bands(ctx, freq, lo_pos);
+
+ mxm_dbg(ctx, "set_rf_freq: ret %d freq %llu\n", ret, freq);
+ return ret;
+}
+
+static int max2175_tune_rf_freq(struct max2175 *ctx, u64 freq, u32 hsls)
+{
+ int ret;
+
+ ret = max2175_set_rf_freq(ctx, freq, hsls);
+ if (ret)
+ return ret;
+
+ ret = max2175_csm_action(ctx, MAX2175_BUFFER_PLUS_PRESET_TUNE);
+ if (ret)
+ return ret;
+
+ mxm_dbg(ctx, "tune_rf_freq: old %u new %llu\n", ctx->freq, freq);
+ ctx->freq = freq;
+ return ret;
+}
+
+static void max2175_set_hsls(struct max2175 *ctx, u32 lo_pos)
+{
+ mxm_dbg(ctx, "set_hsls: lo_pos %u\n", lo_pos);
+
+ if ((lo_pos == MAX2175_LO_BELOW_DESIRED) == MAX2175_IS_BAND_VHF(ctx))
+ max2175_write_bit(ctx, 5, 4, 1);
+ else
+ max2175_write_bit(ctx, 5, 4, 0);
+}
+
+static void max2175_set_eu_rx_mode(struct max2175 *ctx, u32 rx_mode)
+{
+ switch (rx_mode) {
+ case MAX2175_EU_FM_1_2:
+ max2175_load_fmeu_1p2(ctx);
+ break;
+
+ case MAX2175_DAB_1_2:
+ max2175_load_dab_1p2(ctx);
+ break;
+ }
+ /* Master is the default setting */
+ if (!ctx->master)
+ max2175_write_bit(ctx, 30, 7, 1);
+
+ /* Cache i2s_test value at this point */
+ ctx->i2s_test = max2175_read_bits(ctx, 104, 3, 0);
+}
+
+static void max2175_set_na_rx_mode(struct max2175 *ctx, u32 rx_mode)
+{
+ switch (rx_mode) {
+ case MAX2175_NA_FM_1_0:
+ max2175_load_fmna_1p0(ctx);
+ break;
+ case MAX2175_NA_FM_2_0:
+ max2175_load_fmna_2p0(ctx);
+ break;
+ }
+ /* Master is the default setting */
+ if (!ctx->master)
+ max2175_write_bit(ctx, 30, 7, 1);
+
+ /* Cache i2s_test value at this point */
+ ctx->i2s_test = max2175_read_bits(ctx, 104, 3, 0);
+ ctx->decim_ratio = 27;
+
+ /* Load the Channel Filter Coefficients into channel filter bank #2 */
+ max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0, ch_coeff_fmna);
+ max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
+ eq_coeff_fmna1_ra02_m6db);
+}
+
+static int max2175_set_rx_mode(struct max2175 *ctx, u32 rx_mode, u32 hsls)
+{
+ mxm_dbg(ctx, "set_rx_mode: %u am_hiz %u\n", rx_mode, ctx->am_hiz);
+ if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ)
+ max2175_set_eu_rx_mode(ctx, rx_mode);
+ else
+ max2175_set_na_rx_mode(ctx, rx_mode);
+
+ if (ctx->am_hiz) {
+ mxm_dbg(ctx, "setting AM HiZ related config\n");
+ max2175_write_bit(ctx, 50, 5, 1);
+ max2175_write_bit(ctx, 90, 7, 1);
+ max2175_write_bits(ctx, 73, 1, 0, 2);
+ max2175_write_bits(ctx, 80, 5, 0, 33);
+ }
+
+ /* Load BB filter trim values saved in ROM */
+ max2175_set_bbfilter(ctx);
+
+ /* Set HSLS */
+ max2175_set_hsls(ctx, hsls);
+
+ ctx->mode_resolved = true;
+ return 0;
+}
+
+static bool max2175_i2s_rx_mode_valid(struct max2175 *ctx,
+ u32 mode, u32 i2s_mode)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->rx_modes[mode].i2s_modes); i++)
+ if (ctx->rx_modes[mode].i2s_modes[i] == i2s_mode)
+ return true;
+
+ v4l2_err(ctx->client, "i2s_mode %u not suitable for cur rx mode %u\n",
+ i2s_mode, mode);
+ return false;
+}
+
+static int max2175_rx_mode_from_freq(struct max2175 *ctx, u32 freq, u32 *mode)
+{
+ unsigned int i;
+ int band = max2175_band_from_freq(freq);
+
+ /* Pick the first match always */
+ for (i = 0; i <= ctx->rx_mode->maximum; i++) {
+ if (ctx->rx_modes[i].band == band) {
+ *mode = i;
+ mxm_dbg(ctx, "rx_mode_from_freq: freq %u mode %d\n",
+ freq, *mode);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static bool max2175_freq_rx_mode_valid(struct max2175 *ctx,
+ u32 mode, u32 freq)
+{
+ int band = max2175_band_from_freq(freq);
+
+ return (ctx->rx_modes[mode].band == band);
+}
+
+static void max2175_load_adc_presets(struct max2175 *ctx)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 23; j++)
+ max2175_write(ctx, 146 + j + i * 55, adc_presets[i][j]);
+}
+
+static int max2175_init_power_manager(struct max2175 *ctx)
+{
+ int ret;
+
+ /* Execute on-chip power-up/calibration */
+ max2175_write_bit(ctx, 99, 2, 0);
+ usleep_range(1000, 1500);
+ max2175_write_bit(ctx, 99, 2, 1);
+
+ /* Wait for the power manager to finish. */
+ ret = max2175_poll_timeout(ctx, 69, 7, 7, 1, 50);
+ if (ret)
+ v4l2_err(ctx->client, "init pm failed\n");
+ return ret;
+}
+
+static int max2175_recalibrate_adc(struct max2175 *ctx)
+{
+ int ret;
+
+ /* ADC Re-calibration */
+ max2175_write(ctx, 150, 0xff);
+ max2175_write(ctx, 205, 0xff);
+ max2175_write(ctx, 147, 0x20);
+ max2175_write(ctx, 147, 0x00);
+ max2175_write(ctx, 202, 0x20);
+ max2175_write(ctx, 202, 0x00);
+
+ ret = max2175_poll_timeout(ctx, 69, 4, 3, 3, 50);
+ if (ret)
+ v4l2_err(ctx->client, "adc recalibration failed\n");
+ return ret;
+}
+
+static u8 max2175_read_rom(struct max2175 *ctx, u8 row)
+{
+ u8 data;
+
+ max2175_write_bit(ctx, 56, 4, 0);
+ max2175_write_bits(ctx, 56, 3, 0, row);
+
+ usleep_range(2000, 2500);
+ max2175_read(ctx, 58, &data);
+
+ max2175_write_bits(ctx, 56, 3, 0, 0);
+
+ mxm_dbg(ctx, "read_rom: row %d data 0x%02x\n", row, data);
+ return data;
+}
+
+static void max2175_load_from_rom(struct max2175 *ctx)
+{
+ u8 data = 0;
+
+ data = max2175_read_rom(ctx, 0);
+ ctx->rom_bbf_bw_am = data & 0x0f;
+ max2175_write_bits(ctx, 81, 3, 0, data >> 4);
+
+ data = max2175_read_rom(ctx, 1);
+ ctx->rom_bbf_bw_fm = data & 0x0f;
+ ctx->rom_bbf_bw_dab = data >> 4;
+
+ data = max2175_read_rom(ctx, 2);
+ max2175_write_bits(ctx, 82, 4, 0, data & 0x1f);
+ max2175_write_bits(ctx, 82, 7, 5, data >> 5);
+
+ data = max2175_read_rom(ctx, 3);
+ if (ctx->am_hiz) {
+ data &= 0x0f;
+ data |= max2175_read_rom(ctx, 7) & 0x40 >> 2;
+ if (!data)
+ data |= 2;
+ } else {
+ data = data & 0xf0 >> 4;
+ data |= max2175_read_rom(ctx, 7) & 0x80 >> 3;
+ if (!data)
+ data |= 30;
+ }
+ max2175_write_bits(ctx, 80, 5, 0, data + 31);
+
+ data = max2175_read_rom(ctx, 6);
+ max2175_write_bits(ctx, 81, 7, 6, data >> 6);
+}
+
+static void max2175_load_full_fm_eu_1p0(struct max2175 *ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(full_fm_eu_1p0); i++)
+ max2175_write(ctx, i + 1, full_fm_eu_1p0[i]);
+
+ usleep_range(5000, 5500);
+ ctx->decim_ratio = 36;
+}
+
+static void max2175_load_full_fm_na_1p0(struct max2175 *ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(full_fm_na_1p0); i++)
+ max2175_write(ctx, i + 1, full_fm_na_1p0[i]);
+
+ usleep_range(5000, 5500);
+ ctx->decim_ratio = 27;
+}
+
+static int max2175_core_init(struct max2175 *ctx, u32 refout_bits)
+{
+ int ret;
+
+ /* MAX2175 uses 36.864MHz clock for EU & 40.154MHz for NA region */
+ if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ)
+ max2175_load_full_fm_eu_1p0(ctx);
+ else
+ max2175_load_full_fm_na_1p0(ctx);
+
+ /* The default settings assume master */
+ if (!ctx->master)
+ max2175_write_bit(ctx, 30, 7, 1);
+
+ mxm_dbg(ctx, "refout_bits %u\n", refout_bits);
+
+ /* Set REFOUT */
+ max2175_write_bits(ctx, 56, 7, 5, refout_bits);
+
+ /* ADC Reset */
+ max2175_write_bit(ctx, 99, 1, 0);
+ usleep_range(1000, 1500);
+ max2175_write_bit(ctx, 99, 1, 1);
+
+ /* Load ADC preset values */
+ max2175_load_adc_presets(ctx);
+
+ /* Initialize the power management state machine */
+ ret = max2175_init_power_manager(ctx);
+ if (ret)
+ return ret;
+
+ /* Recalibrate ADC */
+ ret = max2175_recalibrate_adc(ctx);
+ if (ret)
+ return ret;
+
+ /* Load ROM values to appropriate registers */
+ max2175_load_from_rom(ctx);
+
+ if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
+ /* Load FIR coefficients into bank 0 */
+ max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0,
+ ch_coeff_fmeu);
+ max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
+ eq_coeff_fmeu1_ra02_m6db);
+ } else {
+ /* Load FIR coefficients into bank 0 */
+ max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0,
+ ch_coeff_fmna);
+ max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
+ eq_coeff_fmna1_ra02_m6db);
+ }
+ mxm_dbg(ctx, "core initialized\n");
+ return 0;
+}
+
+static void max2175_s_ctrl_i2s_mode(struct max2175 *ctx, u32 i2s_mode)
+{
+ mxm_dbg(ctx, "s_ctrl_i2s_mode: %u resolved %d\n", i2s_mode,
+ ctx->mode_resolved);
+
+ /*
+ * Update i2s mode on device only when mode is resolved & it is valid
+ * for the configured mode
+ */
+ if (ctx->mode_resolved &&
+ max2175_i2s_rx_mode_valid(ctx, ctx->rx_mode->val, i2s_mode))
+ max2175_update_i2s_mode(ctx, ctx->rx_mode->val, i2s_mode);
+}
+
+static void max2175_s_ctrl_rx_mode(struct max2175 *ctx, u32 rx_mode)
+{
+ /* Load mode. Range check already done */
+ max2175_set_rx_mode(ctx, rx_mode, ctx->hsls->val);
+
+ /* Get current i2s_mode and update if needed for given rx_mode */
+ if (max2175_i2s_rx_mode_valid(ctx, rx_mode, ctx->i2s_mode->val))
+ max2175_update_i2s_mode(ctx, rx_mode, ctx->i2s_mode->val);
+ else
+ ctx->i2s_mode->val = max2175_read_bits(ctx, 29, 2, 0);
+
+ mxm_dbg(ctx, "s_ctrl_rx_mode: %u curr freq %u\n", rx_mode, ctx->freq);
+
+ /* Check if current freq valid for mode & update */
+ if (max2175_freq_rx_mode_valid(ctx, rx_mode, ctx->freq))
+ max2175_tune_rf_freq(ctx, ctx->freq, ctx->hsls->val);
+ else
+ /* Use default freq of mode if current freq is not valid */
+ max2175_tune_rf_freq(ctx, ctx->rx_modes[rx_mode].freq,
+ ctx->hsls->val);
+}
+
+static int max2175_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct max2175 *ctx = max2175_from_ctrl_hdl(ctrl->handler);
+ int ret = 0;
+
+ mxm_dbg(ctx, "s_ctrl: id 0x%x, val %u\n", ctrl->id, ctrl->val);
+ switch (ctrl->id) {
+ case V4L2_CID_MAX2175_I2S_ENABLE:
+ max2175_i2s_enable(ctx, ctrl->val == 1);
+ break;
+ case V4L2_CID_MAX2175_I2S_MODE:
+ max2175_s_ctrl_i2s_mode(ctx, ctrl->val);
+ break;
+ case V4L2_CID_MAX2175_HSLS:
+ max2175_set_hsls(ctx, ctx->hsls->val);
+ break;
+ case V4L2_CID_MAX2175_RX_MODE:
+ max2175_s_ctrl_rx_mode(ctx, ctrl->val);
+ break;
+ }
+
+ return ret;
+}
+
+static int max2175_get_lna_gain(struct max2175 *ctx)
+{
+ int gain = 0;
+ enum max2175_band band = max2175_read_bits(ctx, 5, 1, 0);
+
+ switch (band) {
+ case MAX2175_BAND_AM:
+ gain = max2175_read_bits(ctx, 51, 3, 1);
+ break;
+ case MAX2175_BAND_FM:
+ gain = max2175_read_bits(ctx, 50, 3, 1);
+ break;
+ case MAX2175_BAND_VHF:
+ gain = max2175_read_bits(ctx, 52, 3, 0);
+ break;
+ default:
+ break;
+ }
+ return gain;
+}
+
+static int max2175_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct max2175 *ctx = max2175_from_ctrl_hdl(ctrl->handler);
+
+ switch (ctrl->id) {
+ case V4L2_CID_RF_TUNER_LNA_GAIN:
+ ctrl->val = max2175_get_lna_gain(ctx);
+ break;
+ case V4L2_CID_RF_TUNER_IF_GAIN:
+ ctrl->val = max2175_read_bits(ctx, 49, 4, 0);
+ break;
+ case V4L2_CID_RF_TUNER_PLL_LOCK:
+ ctrl->val = (max2175_read_bits(ctx, 60, 7, 6) == 3);
+ break;
+ }
+ mxm_dbg(ctx, "g_volatile_ctrl: id 0x%x val %d\n", ctrl->id, ctrl->val);
+ return 0;
+};
+
+static int max2175_set_freq_and_mode(struct max2175 *ctx, u32 freq)
+{
+ u32 rx_mode;
+ int ret;
+
+ /* Get band from frequency */
+ ret = max2175_rx_mode_from_freq(ctx, freq, &rx_mode);
+ if (ret)
+ return ret;
+
+ mxm_dbg(ctx, "set_freq_and_mode: freq %u rx_mode %d\n", freq, rx_mode);
+
+ /* Load mode */
+ max2175_set_rx_mode(ctx, rx_mode, ctx->hsls->val);
+ ctx->rx_mode->val = rx_mode;
+
+ /* Get current i2s_mode and update if needed for given rx_mode */
+ if (max2175_i2s_rx_mode_valid(ctx, rx_mode, ctx->i2s_mode->val))
+ max2175_update_i2s_mode(ctx, rx_mode, ctx->i2s_mode->val);
+ else
+ ctx->i2s_mode->val = max2175_read_bits(ctx, 29, 2, 0);
+
+ /* Tune to the new freq given */
+ return max2175_tune_rf_freq(ctx, freq, ctx->hsls->val);
+}
+
+static int max2175_s_frequency(struct v4l2_subdev *sd,
+ const struct v4l2_frequency *vf)
+{
+ struct max2175 *ctx = max2175_from_sd(sd);
+ u32 freq;
+ int ret = 0;
+
+ mxm_dbg(ctx, "s_freq: new %u curr %u, mode_resolved %d\n",
+ vf->frequency, ctx->freq, ctx->mode_resolved);
+
+ if (vf->tuner != 0)
+ return -EINVAL;
+
+ freq = clamp(vf->frequency, ctx->bands_rf->rangelow,
+ ctx->bands_rf->rangehigh);
+
+ /* Check new freq valid for rx_mode if already resolved */
+ if (ctx->mode_resolved &&
+ max2175_freq_rx_mode_valid(ctx, ctx->rx_mode->val, freq))
+ ret = max2175_tune_rf_freq(ctx, freq, ctx->hsls->val);
+ else
+ /* Find default rx_mode for freq and tune to it */
+ ret = max2175_set_freq_and_mode(ctx, freq);
+
+ mxm_dbg(ctx, "s_freq: ret %d curr %u mode_resolved %d mode %u\n",
+ ret, ctx->freq, ctx->mode_resolved, ctx->rx_mode->val);
+ return ret;
+}
+
+static int max2175_g_frequency(struct v4l2_subdev *sd,
+ struct v4l2_frequency *vf)
+{
+ struct max2175 *ctx = max2175_from_sd(sd);
+ int ret = 0;
+
+ if (vf->tuner != 0)
+ return -EINVAL;
+
+ /* RF freq */
+ vf->type = V4L2_TUNER_RF;
+ vf->frequency = ctx->freq;
+ return ret;
+}
+
+static int max2175_enum_freq_bands(struct v4l2_subdev *sd,
+ struct v4l2_frequency_band *band)
+{
+ struct max2175 *ctx = max2175_from_sd(sd);
+
+ if (band->tuner == 0 && band->index == 0)
+ *band = *ctx->bands_rf;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int max2175_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+ struct max2175 *ctx = max2175_from_sd(sd);
+
+ if (vt->index > 0)
+ return -EINVAL;
+
+ strlcpy(vt->name, "RF", sizeof(vt->name));
+ vt->type = V4L2_TUNER_RF;
+ vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ vt->rangelow = ctx->bands_rf->rangelow;
+ vt->rangehigh = ctx->bands_rf->rangehigh;
+ return 0;
+}
+
+static int max2175_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
+{
+ /* Check tuner index is valid */
+ if (vt->index > 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_tuner_ops max2175_tuner_ops = {
+ .s_frequency = max2175_s_frequency,
+ .g_frequency = max2175_g_frequency,
+ .enum_freq_bands = max2175_enum_freq_bands,
+ .g_tuner = max2175_g_tuner,
+ .s_tuner = max2175_s_tuner,
+};
+
+static const struct v4l2_subdev_ops max2175_ops = {
+ .tuner = &max2175_tuner_ops,
+};
+
+static const struct v4l2_ctrl_ops max2175_ctrl_ops = {
+ .s_ctrl = max2175_s_ctrl,
+ .g_volatile_ctrl = max2175_g_volatile_ctrl,
+};
+
+static const struct v4l2_ctrl_config max2175_i2s_en = {
+ .ops = &max2175_ctrl_ops,
+ .id = V4L2_CID_MAX2175_I2S_ENABLE,
+ .name = "I2S Enable",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static const char * const max2175_ctrl_i2s_modes[] = {
+ [MAX2175_I2S_MODE0] = "i2s mode 0",
+ [MAX2175_I2S_MODE1] = "i2s mode 1 (skipped)",
+ [MAX2175_I2S_MODE2] = "i2s mode 2",
+ [MAX2175_I2S_MODE3] = "i2s mode 3",
+ [MAX2175_I2S_MODE4] = "i2s mode 4",
+};
+
+static const struct v4l2_ctrl_config max2175_i2s_mode = {
+ .ops = &max2175_ctrl_ops,
+ .id = V4L2_CID_MAX2175_I2S_MODE,
+ .name = "I2S MODE value",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .max = ARRAY_SIZE(max2175_ctrl_i2s_modes) - 1,
+ .def = 0,
+ .menu_skip_mask = 0x02,
+ .qmenu = max2175_ctrl_i2s_modes,
+};
+
+static const struct v4l2_ctrl_config max2175_hsls = {
+ .ops = &max2175_ctrl_ops,
+ .id = V4L2_CID_MAX2175_HSLS,
+ .name = "HSLS above/below desired",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static const char * const max2175_ctrl_eu_rx_modes[] = {
+ [MAX2175_EU_FM_1_2] = "EU FM 1.2",
+ [MAX2175_DAB_1_2] = "DAB 1.2",
+};
+
+static const char * const max2175_ctrl_na_rx_modes[] = {
+ [MAX2175_NA_FM_1_0] = "NA FM 1.0",
+ [MAX2175_NA_FM_2_0] = "NA FM 2.0",
+};
+
+static const struct v4l2_ctrl_config max2175_eu_rx_mode = {
+ .ops = &max2175_ctrl_ops,
+ .id = V4L2_CID_MAX2175_RX_MODE,
+ .name = "RX MODE",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .max = ARRAY_SIZE(max2175_ctrl_eu_rx_modes) - 1,
+ .def = 0,
+ .qmenu = max2175_ctrl_eu_rx_modes,
+};
+
+static const struct v4l2_ctrl_config max2175_na_rx_mode = {
+ .ops = &max2175_ctrl_ops,
+ .id = V4L2_CID_MAX2175_RX_MODE,
+ .name = "RX MODE",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .max = ARRAY_SIZE(max2175_ctrl_na_rx_modes) - 1,
+ .def = 0,
+ .qmenu = max2175_ctrl_na_rx_modes,
+};
+
+static int max2175_refout_load_to_bits(struct i2c_client *client, u32 load,
+ u32 *bits)
+{
+ if (load >= 0 && load <= 40)
+ *bits = load / 10;
+ else if (load >= 60 && load <= 70)
+ *bits = load / 10 - 1;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int max2175_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max2175 *ctx;
+ struct v4l2_subdev *sd;
+ struct v4l2_ctrl_handler *hdl;
+ struct clk *clk;
+ struct regmap *regmap;
+ bool master = true, am_hiz = false;
+ u32 refout_load, refout_bits = 0; /* REFOUT disabled */
+ int ret;
+
+ /* Parse DT properties */
+ if (of_find_property(client->dev.of_node, "maxim,slave", NULL))
+ master = false;
+
+ if (of_find_property(client->dev.of_node, "maxim,am-hiz", NULL))
+ am_hiz = true;
+
+ if (!of_property_read_u32(client->dev.of_node, "maxim,refout-load-pF",
+ &refout_load)) {
+ ret = max2175_refout_load_to_bits(client, refout_load,
+ &refout_bits);
+ if (ret) {
+ dev_err(&client->dev, "invalid refout_load %u\n",
+ refout_load);
+ return -EINVAL;
+ }
+ }
+
+ clk = devm_clk_get(&client->dev, "xtal");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(&client->dev, "cannot get xtal clock %d\n", ret);
+ return -ENODEV;
+ }
+
+ regmap = devm_regmap_init_i2c(client, &max2175_regmap_config);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&client->dev, "regmap init failed %d\n", ret);
+ return -ENODEV;
+ }
+
+ /* Alloc tuner context */
+ ctx = devm_kzalloc(&client->dev, sizeof(*ctx), GFP_KERNEL);
+ if (ctx == NULL)
+ return -ENOMEM;
+
+ sd = &ctx->sd;
+ ctx->master = master;
+ ctx->am_hiz = am_hiz;
+ ctx->mode_resolved = false;
+ ctx->regmap = regmap;
+ ctx->xtal_freq = clk_get_rate(clk);
+ dev_info(&client->dev, "xtal freq %luHz\n", ctx->xtal_freq);
+
+ v4l2_i2c_subdev_init(sd, client, &max2175_ops);
+ ctx->client = client;
+
+ sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ /* Controls */
+ hdl = &ctx->ctrl_hdl;
+ ret = v4l2_ctrl_handler_init(hdl, 7);
+ if (ret) {
+ dev_err(&client->dev, "ctrl handler init failed\n");
+ goto err;
+ }
+
+ ctx->lna_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
+ V4L2_CID_RF_TUNER_LNA_GAIN,
+ 0, 15, 1, 2);
+ ctx->lna_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
+ V4L2_CTRL_FLAG_READ_ONLY);
+ ctx->if_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
+ V4L2_CID_RF_TUNER_IF_GAIN,
+ 0, 31, 1, 0);
+ ctx->if_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
+ V4L2_CTRL_FLAG_READ_ONLY);
+ ctx->pll_lock = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
+ V4L2_CID_RF_TUNER_PLL_LOCK,
+ 0, 1, 1, 0);
+ ctx->pll_lock->flags |= (V4L2_CTRL_FLAG_VOLATILE |
+ V4L2_CTRL_FLAG_READ_ONLY);
+ ctx->i2s_en = v4l2_ctrl_new_custom(hdl, &max2175_i2s_en, NULL);
+ ctx->i2s_mode = v4l2_ctrl_new_custom(hdl, &max2175_i2s_mode, NULL);
+ ctx->hsls = v4l2_ctrl_new_custom(hdl, &max2175_hsls, NULL);
+
+ if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
+ ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
+ &max2175_eu_rx_mode, NULL);
+ ctx->rx_modes = eu_rx_modes;
+ ctx->bands_rf = &eu_bands_rf;
+ } else {
+ ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
+ &max2175_na_rx_mode, NULL);
+ ctx->rx_modes = na_rx_modes;
+ ctx->bands_rf = &na_bands_rf;
+ }
+ ctx->sd.ctrl_handler = &ctx->ctrl_hdl;
+
+ /* Set the defaults */
+ ctx->freq = ctx->bands_rf->rangelow;
+
+ /* Register subdev */
+ ret = v4l2_async_register_subdev(sd);
+ if (ret) {
+ dev_err(&client->dev, "register subdev failed\n");
+ goto err_reg;
+ }
+
+ /* Initialize device */
+ ret = max2175_core_init(ctx, refout_bits);
+ if (ret)
+ goto err_init;
+
+ dev_info(&client->dev, "probed\n");
+ return 0;
+
+err_init:
+ v4l2_async_unregister_subdev(sd);
+err_reg:
+ v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+err:
+ return ret;
+}
+
+static int max2175_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct max2175 *ctx = max2175_from_sd(sd);
+
+ v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+ v4l2_async_unregister_subdev(sd);
+ dev_info(&client->dev, "removed\n");
+ return 0;
+}
+
+static const struct i2c_device_id max2175_id[] = {
+ { DRIVER_NAME, 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, max2175_id);
+
+static const struct of_device_id max2175_of_ids[] = {
+ { .compatible = "maxim, max2175", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max2175_of_ids);
+
+static struct i2c_driver max2175_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = max2175_of_ids,
+ },
+ .probe = max2175_probe,
+ .remove = max2175_remove,
+ .id_table = max2175_id,
+};
+
+module_i2c_driver(max2175_driver);
+
+MODULE_DESCRIPTION("Maxim MAX2175 RF to Bits tuner driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Ramesh Shanmugasundaram <ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>");
diff --git a/drivers/media/i2c/max2175/max2175.h b/drivers/media/i2c/max2175/max2175.h
new file mode 100644
index 0000000..2d858aa
--- /dev/null
+++ b/drivers/media/i2c/max2175/max2175.h
@@ -0,0 +1,108 @@
+/*
+ * Maxim Integrated MAX2175 RF to Bits tuner driver
+ *
+ * This driver & most of the hard coded values are based on the reference
+ * application delivered by Maxim for this chip.
+ *
+ * Copyright (C) 2016 Maxim Integrated Products
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __MAX2175_H__
+#define __MAX2175_H__
+
+#define MAX2175_EU_XTAL_FREQ 36864000 /* In Hz */
+#define MAX2175_NA_XTAL_FREQ 40186125 /* In Hz */
+
+enum max2175_region {
+ MAX2175_REGION_EU = 0, /* Europe */
+ MAX2175_REGION_NA, /* North America */
+};
+
+
+enum max2175_band {
+ MAX2175_BAND_AM = 0,
+ MAX2175_BAND_FM,
+ MAX2175_BAND_VHF,
+ MAX2175_BAND_L,
+};
+
+enum max2175_eu_mode {
+ /* EU modes */
+ MAX2175_EU_FM_1_2 = 0,
+ MAX2175_DAB_1_2,
+
+ /* Other possible modes to add in future
+ * MAX2175_DAB_1_0,
+ * MAX2175_DAB_1_3,
+ * MAX2175_EU_FM_2_2,
+ * MAX2175_EU_FMHD_4_0,
+ * MAX2175_EU_AM_1_0,
+ * MAX2175_EU_AM_2_2,
+ */
+};
+
+enum max2175_na_mode {
+ /* NA modes */
+ MAX2175_NA_FM_1_0 = 0,
+ MAX2175_NA_FM_2_0,
+
+ /* Other possible modes to add in future
+ * MAX2175_NA_FMHD_1_0,
+ * MAX2175_NA_FMHD_1_2,
+ * MAX2175_NA_AM_1_0,
+ * MAX2175_NA_AM_1_2,
+ */
+};
+
+/* Supported I2S modes */
+enum {
+ MAX2175_I2S_MODE0 = 0,
+ MAX2175_I2S_MODE1,
+ MAX2175_I2S_MODE2,
+ MAX2175_I2S_MODE3,
+ MAX2175_I2S_MODE4,
+};
+
+/* Coefficient table groups */
+enum {
+ MAX2175_CH_MSEL = 0,
+ MAX2175_EQ_MSEL,
+ MAX2175_AA_MSEL,
+};
+
+/* HSLS LO injection polarity */
+enum {
+ MAX2175_LO_BELOW_DESIRED = 0,
+ MAX2175_LO_ABOVE_DESIRED,
+};
+
+/* Channel FSM modes */
+enum max2175_csm_mode {
+ MAX2175_LOAD_TO_BUFFER = 0,
+ MAX2175_PRESET_TUNE,
+ MAX2175_SEARCH,
+ MAX2175_AF_UPDATE,
+ MAX2175_JUMP_FAST_TUNE,
+ MAX2175_CHECK,
+ MAX2175_LOAD_AND_SWAP,
+ MAX2175_END,
+ MAX2175_BUFFER_PLUS_PRESET_TUNE,
+ MAX2175_BUFFER_PLUS_SEARCH,
+ MAX2175_BUFFER_PLUS_AF_UPDATE,
+ MAX2175_BUFFER_PLUS_JUMP_FAST_TUNE,
+ MAX2175_BUFFER_PLUS_CHECK,
+ MAX2175_BUFFER_PLUS_LOAD_AND_SWAP,
+ MAX2175_NO_ACTION
+};
+
+#endif /* __MAX2175_H__ */
--
1.9.1
--
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 related
* [PATCH 3/5] media: Add new SDR formats SC16, SC18 & SC20
From: Ramesh Shanmugasundaram @ 2016-11-09 15:44 UTC (permalink / raw)
To: robh+dt, mark.rutland, mchehab, hverkuil, sakari.ailus, crope
Cc: chris.paterson2, laurent.pinchart, geert+renesas, linux-media,
devicetree, linux-renesas-soc, Ramesh Shanmugasundaram
In-Reply-To: <1478706284-59134-1-git-send-email-ramesh.shanmugasundaram@bp.renesas.com>
This patch adds support for the three new SDR formats. These formats
were prefixed with "sliced" indicating I data constitutes the top half and
Q data constitutes the bottom half of the received buffer.
V4L2_SDR_FMT_SCU16BE - 14-bit complex (I & Q) unsigned big-endian sample
inside 16-bit. V4L2 FourCC: SC16
V4L2_SDR_FMT_SCU18BE - 16-bit complex (I & Q) unsigned big-endian sample
inside 18-bit. V4L2 FourCC: SC18
V4L2_SDR_FMT_SCU20BE - 18-bit complex (I & Q) unsigned big-endian sample
inside 20-bit. V4L2 FourCC: SC20
Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
---
drivers/media/v4l2-core/v4l2-ioctl.c | 3 +++
include/uapi/linux/videodev2.h | 3 +++
2 files changed, 6 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 181381d..d36b386 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1207,6 +1207,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_SDR_FMT_CS8: descr = "Complex S8"; break;
case V4L2_SDR_FMT_CS14LE: descr = "Complex S14LE"; break;
case V4L2_SDR_FMT_RU12LE: descr = "Real U12LE"; break;
+ case V4L2_SDR_FMT_SCU16BE: descr = "Sliced Complex U16BE"; break;
+ case V4L2_SDR_FMT_SCU18BE: descr = "Sliced Complex U18BE"; break;
+ case V4L2_SDR_FMT_SCU20BE: descr = "Sliced Complex U20BE"; break;
case V4L2_TCH_FMT_DELTA_TD16: descr = "16-bit signed deltas"; break;
case V4L2_TCH_FMT_DELTA_TD08: descr = "8-bit signed deltas"; break;
case V4L2_TCH_FMT_TU16: descr = "16-bit unsigned touch data"; break;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 4364ce6..34a9c30 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -666,6 +666,9 @@ struct v4l2_pix_format {
#define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8') /* complex s8 */
#define V4L2_SDR_FMT_CS14LE v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */
#define V4L2_SDR_FMT_RU12LE v4l2_fourcc('R', 'U', '1', '2') /* real u12le */
+#define V4L2_SDR_FMT_SCU16BE v4l2_fourcc('S', 'C', '1', '6') /* sliced complex u16be */
+#define V4L2_SDR_FMT_SCU18BE v4l2_fourcc('S', 'C', '1', '8') /* sliced complex u18be */
+#define V4L2_SDR_FMT_SCU20BE v4l2_fourcc('S', 'C', '2', '0') /* sliced complex u20be */
/* Touch formats - used for Touch devices */
#define V4L2_TCH_FMT_DELTA_TD16 v4l2_fourcc('T', 'D', '1', '6') /* 16-bit signed deltas */
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox