Re: [PATCH 1/2] [media] v4l2: SI476X MFD - Do not use binary constants
On Wed, May 8, 2013 at 1:23 PM, Geert Uytterhoeven wrote: > Gcc < 4.3 doesn't understand binary constanrs (0b*): > > drivers/media/radio/radio-si476x.c:862:20: error: invalid suffix "b1000" > on integer constant > > Hence use a hexadecimal constant (0x*) instead. > > Signed-off-by: Geert Uytterhoeven > Cc: Mauro Carvalho Chehab > Cc: linux-media@vger.kernel.org Acked-by: Andrey Smirnov > --- > drivers/media/radio/radio-si476x.c |2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/drivers/media/radio/radio-si476x.c > b/drivers/media/radio/radio-si476x.c > index 9430c6a..9dc8baf 100644 > --- a/drivers/media/radio/radio-si476x.c > +++ b/drivers/media/radio/radio-si476x.c > @@ -44,7 +44,7 @@ > > #define FREQ_MUL (1000 / 625) > > -#define SI476X_PHDIV_STATUS_LINK_LOCKED(status) (0b1000 & (status)) > +#define SI476X_PHDIV_STATUS_LINK_LOCKED(status) (0x80 & (status)) > > #define DRIVER_NAME "si476x-radio" > #define DRIVER_CARD "SI476x AM/FM Receiver" > -- > 1.7.0.4 > -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v9 00/12] Driver for Si476x series of chips
On Sun, Apr 21, 2013 at 2:33 AM, Mauro Carvalho Chehab wrote: > Em 21-04-2013 02:53, Andrey Smirnov escreveu: > >>> I applied all the MFD patches from this patchset (All 4 first ones), plus >>> a >>> follow up one for fixing the i2c related warning. >>> I also squashed the REGMAP_I2C dependency into patch #4. >>> It's all in mfd-next now, I'd appreciate if you could double check it's >>> all >>> fine. >> >> >> I checked out latest >> git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git and >> applied patches 5 - 10, 12. There doesn't seem to be any problems, so >> I think MFD part of the driver is good to go. >> >>> >>> Mauro will take the rest, we made sure there won't be any merge conflict >>> between our trees. >> >> >> Mauro, I am not sure if you need me to rebase any of the patches(it >> doesn't seem like you had a chance to make any further changes related >> to this driver in media tree), but if you do, ping me and I'll get on >> it. > > > No, I don't need. The V4L parts are on my experimental tree: > > http://git.linuxtv.org/mchehab/experimental.git/shortlog/refs/heads/si476x > > I'll just merge it at the main tree or as a topic branch later today > or (more likely) tomorrow. > > Please ping me today if you find anything wrong there. It looks like everything is there(it's only one patch without mfd part, after all) except patch #12 https://patchwork.kernel.org/patch/2461631/ of this patchset which is a modified version of this guy https://patchwork-mail.kernel.org/patch/2420751/ Other than that I think everything is fine. > > Regards, > Mauro -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v9 00/12] Driver for Si476x series of chips
> I applied all the MFD patches from this patchset (All 4 first ones), plus a > follow up one for fixing the i2c related warning. > I also squashed the REGMAP_I2C dependency into patch #4. > It's all in mfd-next now, I'd appreciate if you could double check it's all > fine. I checked out latest git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git and applied patches 5 - 10, 12. There doesn't seem to be any problems, so I think MFD part of the driver is good to go. > > Mauro will take the rest, we made sure there won't be any merge conflict > between our trees. Mauro, I am not sure if you need me to rebase any of the patches(it doesn't seem like you had a chance to make any further changes related to this driver in media tree), but if you do, ping me and I'll get on it. > > Cheers, > Samuel. > > -- > Intel Open Source Technology Centre > http://oss.intel.com/ -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v9 00/12] Driver for Si476x series of chips
On Fri, Apr 19, 2013 at 2:31 PM, Samuel Ortiz wrote: > Hi Andrey, > > On Thu, Apr 18, 2013 at 09:58:26AM -0700, Andrey Smirnov wrote: >> Driver for Si476x series of chips >> >> This is a eight version of the patchset originaly posted here: >> https://lkml.org/lkml/2012/9/13/590 >> >> Second version of the patch was posted here: >> https://lkml.org/lkml/2012/10/5/598 >> >> Third version of the patch was posted here: >> https://lkml.org/lkml/2012/10/23/510 >> >> Fourth version of the patch was posted here: >> https://lkml.org/lkml/2013/2/18/572 >> >> Fifth version of the patch was posted here: >> https://lkml.org/lkml/2013/2/26/45 >> >> Sixth version of the patch was posted here: >> https://lkml.org/lkml/2013/2/26/257 >> >> Seventh version of the patch was posted here: >> https://lkml.org/lkml/2013/2/27/22 >> >> Eighth version of the patch was posted here: >> https://lkml.org/lkml/2013/3/26/891 >> >> To save everyone's time I'll repost the original description of it: >> >> This patchset contains a driver for a Silicon Laboratories 476x series >> of radio tuners. The driver itself is implemented as an MFD devices >> comprised of three parts: >> 1. Core device that provides all the other devices with basic >> functionality and locking scheme. >> 2. Radio device that translates between V4L2 subsystem requests into >> Core device commands. >> 3. Codec device that does similar to the earlier described task, but >> for ALSA SoC subsystem. >> >> v9 of this driver has following changes: >>- MFD part of the driver no longer depends on the header file added >> by the radio driver(media/si476x.h) which should potential >> restore the bisectability of the patches > I applied all the MFD patches from this patchset (All 4 first ones), plus a > follow up one for fixing the i2c related warning. > I also squashed the REGMAP_I2C dependency into patch #4. > It's all in mfd-next now, I'd appreciate if you could double check it's all > fine. > > Mauro will take the rest, we made sure there won't be any merge conflict > between our trees. > Thanks, I will try to test it today or tomorrow(20/04) at the latest. > Cheers, > Samuel. > > -- > Intel Open Source Technology Centre > http://oss.intel.com/ -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/12] mfd: Add commands abstraction layer for SI476X MFD
From: Andrey Smirnov This patch adds all the functions used for exchanging commands with the chip. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1553 ++ 1 file changed, 1553 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..de48b4e --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1553 @@ +/* + * drivers/mfd/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD
[PATCH 04/12] mfd: Add header files and Kbuild plumbing for SI476x MFD core
From: Andrey Smirnov This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Acked-by: Hans Verkuil Acked-by: Sam Ravnborg Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 12 + drivers/mfd/Makefile|4 + include/linux/mfd/si476x-core.h | 533 +++ include/linux/mfd/si476x-platform.h | 267 ++ include/linux/mfd/si476x-reports.h | 163 +++ 5 files changed, 979 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/linux/mfd/si476x-platform.h create mode 100644 include/linux/mfd/si476x-reports.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4..3cd8f21 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -970,6 +970,18 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + help + This is the core driver for the SI476x series of AM/FM + radio. This MFD driver connects the radio-si476x V4L2 module + and the si476x audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core and TLL driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8..ca87ae8 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -131,6 +131,10 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855)+= vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o + +si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o + obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST)+= omap-usb-host.o omap-usb-tll.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..ede3022 --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,533 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Command Timeouts */ +#define SI476X_DEFAULT_TIMEOUT 10 +#define SI476X_TIMEOUT_TUNE70 +#define SI476X_TIMEOUT_POWER_UP33 +#define SI476X_STATUS_POLL_US 0 + +/* si476x-i2c.c --- */ + +enum si476x_freq_supported_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, +}; + +enum si476x_part_revisions { + SI476X_REVISION_A10 = 0, + SI476X_REVISION_A20 = 1, + SI476X_REVISION_A30 = 2, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsistent, meaning some of the regulators were + * not turned down and thus use of the device, without power-cycling + * is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP
[PATCH 06/12] v4l2: Add standard controls for FM receivers
This commit introduces new class of standard controls V4L2_CTRL_CLASS_FM_RX. This class is intended to all controls pertaining to FM receiver chips. Also, two controls belonging to said class are added as a part of this commit: V4L2_CID_TUNE_DEEMPHASIS and V4L2_CID_RDS_RECEPTION. This patch is based on the code found in the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641307-new-control-class-and-features-for-fm-rx.html Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/media/v4l2-core/v4l2-ctrls.c | 14 +++--- include/uapi/linux/v4l2-controls.h | 13 + 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 6b28b58..8b89fb8 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -297,8 +297,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Text", NULL }; - static const char * const tune_preemphasis[] = { - "No Preemphasis", + static const char * const tune_emphasis[] = { + "None", "50 Microseconds", "75 Microseconds", NULL, @@ -508,7 +508,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_SCENE_MODE: return scene_mode; case V4L2_CID_TUNE_PREEMPHASIS: - return tune_preemphasis; + return tune_emphasis; + case V4L2_CID_TUNE_DEEMPHASIS: + return tune_emphasis; case V4L2_CID_FLASH_LED_MODE: return flash_led_mode; case V4L2_CID_FLASH_STROBE_SOURCE: @@ -799,6 +801,9 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; + case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; + case V4L2_CID_RDS_RECEPTION:return "RDS Reception"; default: return NULL; } @@ -846,6 +851,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: case V4L2_CID_WIDE_DYNAMIC_RANGE: case V4L2_CID_IMAGE_STABILIZATION: + case V4L2_CID_RDS_RECEPTION: *type = V4L2_CTRL_TYPE_BOOLEAN; *min = 0; *max = *step = 1; @@ -904,6 +910,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: case V4L2_CID_TEST_PATTERN: + case V4L2_CID_TUNE_DEEMPHASIS: *type = V4L2_CTRL_TYPE_MENU; break; case V4L2_CID_LINK_FREQ: @@ -926,6 +933,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_IMAGE_SOURCE_CLASS: case V4L2_CID_IMAGE_PROC_CLASS: case V4L2_CID_DV_CLASS: + case V4L2_CID_FM_RX_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read not write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index dcd6374..3e985be 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -59,6 +59,7 @@ #define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e /* Image source controls */ #define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f /* Image processing controls */ #define V4L2_CTRL_CLASS_DV 0x00a0 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a1 /* Digital Video controls */ /* User-class control IDs */ @@ -825,4 +826,16 @@ enum v4l2_dv_rgb_range { #defineV4L2_CID_DV_RX_POWER_PRESENT(V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) +#define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) + +#define V4L2_CID_TUNE_DEEMPHASIS (V4L2_CID_FM_RX_CLASS_BASE + 1) +enum v4l2_deemphasis { + V4L2_DEEMPHASIS_DISABLED= V4L2_PREEMPHASIS_DISABLED, + V4L2_DEEMPHASIS_50_uS = V4L2_PREEMPHASIS_50_uS, + V4L2_DEEMPHASIS_75_uS = V4L2_PREEMPHASIS_75_uS, +}; + +#define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2) + #endif -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/12] mfd: Add the main bulk of core driver for SI476x code
From: Andrey Smirnov This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 886 ++ 1 file changed, 886 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..118c6b1 --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,886 @@ +/* + * drivers/mfd/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SI476X_MAX_IO_ERRORS 10 +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_core_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(SI476X_STATUS_POLL_US)); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tuner + * + * Perform required startup sequence to correctly power + * up the chip and perform initial configuration. It does the + * following sequence of actions:
[PATCH 05/12] v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation
Change the type of V4L2_CID_TUNE_PREEMPHASIS from 'integer' to 'enum v4l2_preemphasis' Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/controls.xml |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 9e8f854..1ad20cc 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -3848,7 +3848,7 @@ in Hz. The range and step are driver-specific. V4L2_CID_TUNE_PREEMPHASIS - integer + enum v4l2_preemphasis Configures the pre-emphasis value for broadcasting. A pre-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/12] mfd: Add chip properties handling code for SI476X MFD
From: Andrey Smirnov This patch adds code related to manipulation of the properties of SI476X chips. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 241 + 1 file changed, 241 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..cfeffa6 --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,241 @@ +/* + * drivers/mfd/si476x-prop.c -- Subroutines to access + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include + +struct si476x_property_range { + u16 low, high; +}; + +static bool si476x_core_element_is_in_array(u16 element, + const u16 array[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool si476x_core_element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x0718, + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a20(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071B, + 0x1006, + 0x2210, + 0x3401, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x2215, 0x2219 }, + }; + + return si476x_core_is_valid_property_a10(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a30(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071C, 0x071D, + 0x1007, 0x1008, + 0x220F, 0x2214, + 0x2301, + 0x3105, 0x3106, + 0x3402, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0405, 0x0411 }, + { 0x2008, 0x200B }, + { 0x2220, 0x2223 }, + { 0x3100, 0x3106 }, + }; + + return si476x_core_is_valid_property_a20(core, property) || + si476x_core
[PATCH 08/12] v4l2: Add private controls base for SI476X
Add a base to be used for allocation of all the SI476X specific controls in the corresponding driver. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- include/uapi/linux/v4l2-controls.h |4 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 3e985be..22e5170 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -147,6 +147,10 @@ enum v4l2_colorfx { * of controls. We reserve 16 controls for this driver. */ #define V4L2_CID_USER_MEYE_BASE(V4L2_CID_USER_BASE + 0x1000) +/* The base for the si476x driver controls. See include/media/si476x.h for the list + * of controls. Total of 16 controls is reserved for that driver */ +#define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1010) + /* MPEG-class control IDs */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 11/12] si476x: Fix some config dependencies and a compile warnings
From: Hans Verkuil radio-si476x depends on SND and SND_SOC, the mfd driver should select REGMAP_I2C. Also fix a small compile warning in a debug message: drivers/mfd/si476x-i2c.c: In function ‘si476x_core_drain_rds_fifo’: drivers/mfd/si476x-i2c.c:391:4: warning: field width specifier ‘*’ expects argument of type ‘int’, but argument 4 has type ‘long unsigned int’ [-Wformat] Acked-by: Andrey Smirnov Signed-off-by: Hans Verkuil --- drivers/media/radio/Kconfig |2 +- drivers/mfd/Kconfig |1 + drivers/mfd/si476x-i2c.c|2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 170460d..181a25f 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -20,7 +20,7 @@ source "drivers/media/radio/si470x/Kconfig" config RADIO_SI476X tristate "Silicon Laboratories Si476x I2C FM Radio" - depends on I2C && VIDEO_V4L2 + depends on I2C && VIDEO_V4L2 && SND && SND_SOC select MFD_CORE select MFD_SI476X_CORE select SND_SOC_SI476X diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3cd8f21..606e549 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -974,6 +974,7 @@ config MFD_SI476X_CORE tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." depends on I2C select MFD_CORE + select REGMAP_I2C help This is the core driver for the SI476x series of AM/FM radio. This MFD driver connects the radio-si476x V4L2 module diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index 118c6b1..f5bc8e4 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -389,7 +389,7 @@ static void si476x_core_drain_rds_fifo(struct work_struct *work) kfifo_in(&core->rds_fifo, report.rds, sizeof(report.rds)); dev_dbg(&core->client->dev, "RDS data:\n %*ph\n", - sizeof(report.rds), report.rds); + (int)sizeof(report.rds), report.rds); } dev_dbg(&core->client->dev, "Dained!\n"); wake_up_interruptible(&core->rds_read_queue); -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/12] radio-si476x: vidioc_s* now uses a const parameter
From: Mauro Carvalho Chehab vidioc_s_tuner, vidioc_s_frequency and vidioc_s_register now uses a constant argument. So, the driver reports warnings: drivers/media/radio/radio-si476x.c:1196:2: warning: initialization from incompatible pointer type [enabled by default] drivers/media/radio/radio-si476x.c:1196:2: warning: (near initialization for 'si4761_ioctl_ops.vidioc_s_tuner') [enabled by default] drivers/media/radio/radio-si476x.c:1199:2: warning: initialization from incompatible pointer type [enabled by default] drivers/media/radio/radio-si476x.c:1199:2: warning: (near initialization for 'si4761_ioctl_ops.vidioc_s_frequency') [enabled by default] drivers/media/radio/radio-si476x.c:1209:2: warning: initialization from incompatible pointer type [enabled by default] drivers/media/radio/radio-si476x.c:1209:2: warning: (near initialization for 'si4761_ioctl_ops.vidioc_s_register') [enabled by default] This is due to a (soft) merge conflict, as both this driver and the const patches were applied for the same Kernel version. Acked-by: Hans Verkuil Acked-by: Andrey Smirnov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-si476x.c | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 0895a0c..9430c6a 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -472,7 +472,7 @@ static int si476x_radio_g_tuner(struct file *file, void *priv, } static int si476x_radio_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *tuner) + const struct v4l2_tuner *tuner) { struct si476x_radio *radio = video_drvdata(file); @@ -699,15 +699,16 @@ static int si476x_radio_g_frequency(struct file *file, void *priv, } static int si476x_radio_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) + const struct v4l2_frequency *f) { int err; + u32 freq = f->frequency; struct si476x_tune_freq_args args; struct si476x_radio *radio = video_drvdata(file); const u32 midrange = (si476x_bands[SI476X_BAND_AM].rangehigh + si476x_bands[SI476X_BAND_FM].rangelow) / 2; - const int band = (f->frequency > midrange) ? + const int band = (freq > midrange) ? SI476X_BAND_FM : SI476X_BAND_AM; const enum si476x_func func = (band == SI476X_BAND_AM) ? SI476X_FUNC_AM_RECEIVER : SI476X_FUNC_FM_RECEIVER; @@ -718,11 +719,11 @@ static int si476x_radio_s_frequency(struct file *file, void *priv, si476x_core_lock(radio->core); - f->frequency = clamp(f->frequency, -si476x_bands[band].rangelow, -si476x_bands[band].rangehigh); + freq = clamp(freq, +si476x_bands[band].rangelow, +si476x_bands[band].rangehigh); - if (si476x_radio_freq_is_inside_of_the_band(f->frequency, + if (si476x_radio_freq_is_inside_of_the_band(freq, SI476X_BAND_AM) && (!si476x_core_has_am(radio->core) || si476x_core_is_a_secondary_tuner(radio->core))) { @@ -737,8 +738,7 @@ static int si476x_radio_s_frequency(struct file *file, void *priv, args.zifsr = false; args.hd = false; args.injside= SI476X_INJSIDE_AUTO; - args.freq = v4l2_to_si476x(radio->core, -f->frequency); + args.freq = v4l2_to_si476x(radio->core, freq); args.tunemode = SI476X_TM_VALIDATED_NORMAL_TUNE; args.smoothmetrics = SI476X_SM_INITIALIZE_AUDIO; args.antcap = 0; @@ -1046,7 +1046,7 @@ static int si476x_radio_g_register(struct file *file, void *fh, return err; } static int si476x_radio_s_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) + const struct v4l2_dbg_register *reg) { int err; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/12] v4l2: Add documentation for the FM RX controls
Add appropriate documentation for all the newly added standard controls. Based on the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641303-media-update-docs-for-v4l2-fm-new-features.html Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 72 .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 +++ 3 files changed, 84 insertions(+) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 104a1a2..f418bc3 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2310,6 +2310,9 @@ more information. Added FM Modulator (FM TX) Extended Control Class: V4L2_CTRL_CLASS_FM_TX and their Control IDs. + + Added FM Receiver (FM RX) Extended Control Class: V4L2_CTRL_CLASS_FM_RX and their Control IDs. + Added Remote Controller chapter, describing the default Remote Controller mapping for media devices. diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 1ad20cc..6aa647a 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -4687,4 +4687,76 @@ interface and may change in the future. + + + FM Receiver Control Reference + + The FM Receiver (FM_RX) class includes controls for common features of + FM Reception capable devices. + + + FM_RX Control IDs + + + + + + + + + + +ID +Type + Description + + + + + +V4L2_CID_FM_RX_CLASS +class + The FM_RX class +descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a +description of this control class. + + +V4L2_CID_RDS_RECEPTION +boolean + Enables/disables RDS + reception by the radio tuner + + + V4L2_CID_TUNE_DEEMPHASIS + enum v4l2_deemphasis + + Configures the de-emphasis value for reception. +A de-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. +Depending on the region, a time constant of either 50 or 75 useconds is used. The enum v4l2_deemphasis +defines possible values for de-emphasis. Here they are: + + + + + V4L2_DEEMPHASIS_DISABLED + No de-emphasis is applied. + + + V4L2_DEEMPHASIS_50_uS + A de-emphasis of 50 uS is used. + + + V4L2_DEEMPHASIS_75_uS + A de-emphasis of 75 uS is used. + + + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml index 4e16112..b3bb957 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml @@ -319,6 +319,15 @@ These controls are described in . + + + V4L2_CTRL_CLASS_FM_RX + 0xa1 + The class containing FM Receiver (FM RX) controls. +These controls are described in . + + -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 12/12] radio-si476x: Fix incorrect pointer checking
Fix incorrect pointer checking and make some minor code improvements: * Remove unnecessary elements from function pointer table(vtable), that includes all the elements that are FM-only, this allows for not checking of the fucntion pointer and calling of the function directly(THe check if the tuner is in FM mode has to be done anyway) * Fix incorrect function pointer checking where the code would check one pointer to be non-NULL, but would use other pointer, which would not be checked. * Remove code duplication in "si476x_radio_read_rsq_blob" and "si476x_radio_read_rsq_primary_blob". * Add some BUG_ON statements for function pointers that should never be NULL Signed-off-by: Andrey Smirnov Signed-off-by: Dan Carpenter --- drivers/media/radio/radio-si476x.c | 90 +--- 1 file changed, 33 insertions(+), 57 deletions(-) diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9430c6a..378c7f0 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -270,8 +270,6 @@ struct si476x_radio; * @seek_start: Star station seeking * @rsq_status: Get Recieved Signal Quality(RSQ) status * @rds_blckcnt: Get recived RDS blocks count - * @phase_diversity: Change phase diversity mode of the tuner - * @phase_div_status: Get phase diversity mode status * @acf_status: Get the status of Automatically Controlled * Features(ACF) * @agc_status: Get Automatic Gain Control(AGC) status @@ -281,16 +279,8 @@ struct si476x_radio_ops { int (*seek_start)(struct si476x_core *, bool, bool); int (*rsq_status)(struct si476x_core *, struct si476x_rsq_status_args *, struct si476x_rsq_status_report *); - int (*rds_blckcnt)(struct si476x_core *, bool, - struct si476x_rds_blockcount_report *); - - int (*phase_diversity)(struct si476x_core *, - enum si476x_phase_diversity_mode); - int (*phase_div_status)(struct si476x_core *); int (*acf_status)(struct si476x_core *, struct si476x_acf_status_report *); - int (*agc_status)(struct si476x_core *, - struct si476x_agc_status_report *); }; /** @@ -495,22 +485,14 @@ static int si476x_radio_init_vtable(struct si476x_radio *radio, .tune_freq = si476x_core_cmd_fm_tune_freq, .seek_start = si476x_core_cmd_fm_seek_start, .rsq_status = si476x_core_cmd_fm_rsq_status, - .rds_blckcnt= si476x_core_cmd_fm_rds_blockcount, - .phase_diversity= si476x_core_cmd_fm_phase_diversity, - .phase_div_status = si476x_core_cmd_fm_phase_div_status, .acf_status = si476x_core_cmd_fm_acf_status, - .agc_status = si476x_core_cmd_agc_status, }; static const struct si476x_radio_ops am_ops = { .tune_freq = si476x_core_cmd_am_tune_freq, .seek_start = si476x_core_cmd_am_seek_start, .rsq_status = si476x_core_cmd_am_rsq_status, - .rds_blckcnt= NULL, - .phase_diversity= NULL, - .phase_div_status = NULL, .acf_status = si476x_core_cmd_am_acf_status, - .agc_status = NULL, }; switch (func) { @@ -545,11 +527,15 @@ static int si476x_radio_pretune(struct si476x_radio *radio, case SI476X_FUNC_FM_RECEIVER: args.freq = v4l2_to_si476x(radio->core, 92 * FREQ_MUL); + + BUG_ON(!radio->ops->tune_freq); retval = radio->ops->tune_freq(radio->core, &args); break; case SI476X_FUNC_AM_RECEIVER: args.freq = v4l2_to_si476x(radio->core, 0.6 * FREQ_MUL); + + BUG_ON(!radio->ops->tune_freq); retval = radio->ops->tune_freq(radio->core, &args); break; default: @@ -599,7 +585,7 @@ static int si476x_radio_do_post_powerup_init(struct si476x_radio *radio, if (err < 0) return err; - if (func == SI476X_FUNC_FM_RECEIVER) { + if (!si476x_core_is_in_am_receiver_mode(radio->core)) { if (si476x_core_has_diversity(radio->core)) { err = si476x_core_cmd_fm_phase_diversity(radio->core, radio->core->diversity_mode); @@ -743,6 +729,7 @@ static int si476x_radio_s_frequency(struct file *file, void *priv, args.smoothmetrics = SI476X_SM_INITIALIZE_AUDIO; args.ant
[PATCH 09/12] v4l2: Add a V4L2 driver for SI476X MFD
From: Andrey Smirnov This commit adds a driver that exposes all the radio related functionality of the Si476x series of chips via the V4L2 subsystem. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- Documentation/video4linux/si476x.txt | 187 drivers/media/radio/Kconfig | 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1599 ++ include/media/si476x.h | 37 + 5 files changed, 1841 insertions(+) create mode 100644 Documentation/video4linux/si476x.txt create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 include/media/si476x.h diff --git a/Documentation/video4linux/si476x.txt b/Documentation/video4linux/si476x.txt new file mode 100644 index 000..d1a08db --- /dev/null +++ b/Documentation/video4linux/si476x.txt @@ -0,0 +1,187 @@ +SI476x Driver Readme + + Copyright (C) 2013 Andrey Smirnov + +TODO for the driver +-- + +- According to the SiLabs' datasheet it is possible to update the + firmware of the radio chip in the run-time, thus bringing it to the + most recent version. Unfortunately I couldn't find any mentioning of + the said firmware update for the old chips that I tested the driver + against, so for chips like that the driver only exposes the old + functionality. + + +Parameters exposed over debugfs +--- +SI476x allow user to get multiple characteristics that can be very +useful for EoL testing/RF performance estimation, parameters that have +very little to do with V4L2 subsystem. Such parameters are exposed via +debugfs and can be accessed via regular file I/O operations. + +The drivers exposes following files: + +* /sys/kernel/debug//acf + This file contains ACF(Automatically Controlled Features) status + information. The contents of the file is binary data of the + following layout: + + Offset | Name | Description + + 0x00 | blend_int | Flag, set when stereo separation has + | | crossed below the blend threshold + + 0x01 | hblend_int| Flag, set when HiBlend cutoff + | | frequency is lower than threshold + + 0x02 | hicut_int | Flag, set when HiCut cutoff + | | frequency is lower than threshold + + 0x03 | chbw_int | Flag, set when channel filter + | | bandwidth is less than threshold + + 0x04 | softmute_int | Flag indicating that softmute + | | attenuation has increased above + | | softmute threshold + + 0x05 | smute | 0 - Audio is not soft muted + | | 1 - Audio is soft muted + + 0x06 | smattn| Soft mute attenuation level in dB + + 0x07 | chbw | Channel filter bandwidth in kHz + + 0x08 | hicut | HiCut cutoff frequency in units of + | | 100Hz + + 0x09 | hiblend | HiBlend cutoff frequency in units + | | of 100 Hz + + 0x10 | pilot | 0 - Stereo pilot is not present + | | 1 - Stereo pilot is present + + 0x11 | stblend | Stereo blend in % + + + +* /sys/kernel/debug//rds_blckcnt + This file contains statistics about RDS receptions. It's binary data + has the following layout: + + Offset | Name | Description + + 0x00 | expected | Number of expected RDS blocks + + 0x02 | received | Number of received RDS blocks + + 0x04 | uncorrectable | Number of uncorrect
[PATCH v9 00/12] Driver for Si476x series of chips
Driver for Si476x series of chips This is a eight version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 Second version of the patch was posted here: https://lkml.org/lkml/2012/10/5/598 Third version of the patch was posted here: https://lkml.org/lkml/2012/10/23/510 Fourth version of the patch was posted here: https://lkml.org/lkml/2013/2/18/572 Fifth version of the patch was posted here: https://lkml.org/lkml/2013/2/26/45 Sixth version of the patch was posted here: https://lkml.org/lkml/2013/2/26/257 Seventh version of the patch was posted here: https://lkml.org/lkml/2013/2/27/22 Eighth version of the patch was posted here: https://lkml.org/lkml/2013/3/26/891 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. v9 of this driver has following changes: - MFD part of the driver no longer depends on the header file added by the radio driver(media/si476x.h) which should potential restore the bisectability of the patches Mauro, I am not sure if you reverted changes in patches 5 - 7, so I am including them just in case. Hans, some of the patches you gave your ACK to were changed, but since the only thing changed is the location of the original code(it was rearranged into different files) I did not remove your ACKs from the new commits. I hope you don't mind, but if you do, let me know and I'll post an updated version of the patchset so it would be clear that it is not ready to be merged. Please note, taht patch #12 is the modified version of https://patchwork-mail.kernel.org/patch/2420751/ It _was not_ ACKEd by anyone. Samuel, I couldn't just move media/si476x.h to mfd patches because it would also break bisectability since media/si476x.h depends on patch #8 in this patchset(whcih is the change that should go through 'media' tree) But I rearranged definitions and there shouldn't be any dependencies on media patches in MFD part. Andrey Smirnov (10): mfd: Add commands abstraction layer for SI476X MFD mfd: Add the main bulk of core driver for SI476x code mfd: Add chip properties handling code for SI476X MFD mfd: Add header files and Kbuild plumbing for SI476x MFD core v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation v4l2: Add standard controls for FM receivers v4l2: Add documentation for the FM RX controls v4l2: Add private controls base for SI476X v4l2: Add a V4L2 driver for SI476X MFD radio-si476x: Fix incorrect pointer checking Hans Verkuil (1): si476x: Fix some config dependencies and a compile warnings Mauro Carvalho Chehab (1): radio-si476x: vidioc_s* now uses a const parameter Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 74 +- .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 + Documentation/video4linux/si476x.txt | 187 +++ drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1575 drivers/media/v4l2-core/v4l2-ctrls.c | 14 +- drivers/mfd/Kconfig| 13 + drivers/mfd/Makefile |4 + drivers/mfd/si476x-cmd.c | 1553 +++ drivers/mfd/si476x-i2c.c | 886 +++ drivers/mfd/si476x-prop.c | 242 +++ include/linux/mfd/si476x-core.h| 533 +++ include/linux/mfd/si476x-platform.h| 267 include/linux/mfd/si476x-reports.h | 163 ++ include/media/si476x.h | 37 + include/uapi/linux/v4l2-controls.h | 17 + 18 files changed, 5591 insertions(+), 4 deletions(-) create mode 100644 Documentation/video4linux/si476x.txt create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 drivers/mfd/si476x-cmd.c create mode 100644 drivers/mfd/si476x-i2c.c create mode 100644 drivers/mfd/si476x-prop.c create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/linux/mfd/si476x-platform.h create mode 100644 include/linux/mfd/si476x-reports.h create mode 100644 include/media/si476x.h -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [patch] [media] radio-si476x: check different function pointers
On Thu, Apr 11, 2013 at 11:24 AM, Hans Verkuil wrote: > On Wed April 10 2013 13:40:51 Dan Carpenter wrote: >> This is a static checker where it complains if we check for one function >> pointer and then call a different function on the next line. >> >> In most cases, the code does the same thing before and after this patch. >> For example, when ->phase_diversity is non-NULL then ->phase_div_status >> is also non-NULL. >> >> The one place where that's not true is when we check ->rds_blckcnt >> instead of ->rsq_status. In those cases, we would want to call >> ->rsq_status but we instead return -ENOENT. >> >> Signed-off-by: Dan Carpenter >> --- >> Please review this carefully. I don't have the hardware to test it. > > Andrey, can you review this? I think the first two chunks are correct, but > the last two chunks are probably not what you want. In the case of an AM > receiver there is no RDS data, so an error is probably correct. > Sorry, I suck at gmail-ing and my response to this letter was bounced for having HTML in it and I guess you didn't receive it either, I'll just copy it below: On Wed, Apr 10, 2013 at 4:40 AM, Dan Carpenter wrote: > > This is a static checker where it complains if we check for one function > pointer and then call a different function on the next line. > > In most cases, the code does the same thing before and after this patch. > For example, when ->phase_diversity is non-NULL then ->phase_div_status > is also non-NULL. > > The one place where that's not true is when we check ->rds_blckcnt > instead of ->rsq_status. In those cases, we would want to call > ->rsq_status but we instead return -ENOENT. > > Signed-off-by: Dan Carpenter > --- > Please review this carefully. I don't have the hardware to test it. > > diff --git a/drivers/media/radio/radio-si476x.c > b/drivers/media/radio/radio-si476x.c > index 9430c6a..817fc0c 100644 > --- a/drivers/media/radio/radio-si476x.c > +++ b/drivers/media/radio/radio-si476x.c > @@ -854,7 +854,7 @@ static int si476x_radio_g_volatile_ctrl(struct v4l2_ctrl > *ctrl) > switch (ctrl->id) { > case V4L2_CID_SI476X_INTERCHIP_LINK: > if (si476x_core_has_diversity(radio->core)) { > - if (radio->ops->phase_diversity) { > + if (radio->ops->phase_div_status) { > retval = > radio->ops->phase_div_status(radio->core); > if (retval < 0) > break; I think I would prefer to use "si476x_core_is_in_am_receiver_mode" in the case above and then have additional BUG_ON(radio->ops->phase_div_status) for cases where it should not be NULL(tuner in FM mode, diversity feature present) also I probably should return -EINVAL in all the cases for this control. > @@ -1285,7 +1285,7 @@ static ssize_t si476x_radio_read_agc_blob(struct file > *file, > struct si476x_agc_status_report report; > > si476x_core_lock(radio->core); > - if (radio->ops->rds_blckcnt) > + if (radio->ops->agc_status) > err = radio->ops->agc_status(radio->core, &report); > else > err = -ENOENT; > @@ -1320,7 +1320,7 @@ static ssize_t si476x_radio_read_rsq_blob(struct file > *file, > }; > > si476x_core_lock(radio->core); > - if (radio->ops->rds_blckcnt) > + if (radio->ops->rsq_status) > err = radio->ops->rsq_status(radio->core, &args, &report); > else > err = -ENOENT; > @@ -1355,7 +1355,7 @@ static ssize_t > si476x_radio_read_rsq_primary_blob(struct file *file, > }; > > si476x_core_lock(radio->core); > - if (radio->ops->rds_blckcnt) > + if (radio->ops->rsq_status) > err = radio->ops->rsq_status(radio->core, &args, &report); > else > err = -ENOENT; This all looks like a dumb copy-paste screw up on my part. I think I copied the body of "si476x_radio_read_rds_blckcnt_blob" and used it to implement all the other functions and I guess forgot to change this bit of the code. Thank you for catching this, mistakes like this are just embarrassing. I'll make a patch based on this one and send it alongside the patches for MFD subsystem -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 2/9] mfd: Add the main bulk of core driver for SI476x code
From: Andrey Smirnov This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 886 ++ 1 file changed, 886 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..118c6b1 --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,886 @@ +/* + * drivers/mfd/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SI476X_MAX_IO_ERRORS 10 +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_core_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(SI476X_STATUS_POLL_US)); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tuner + * + * Perform required startup sequence to correctly power + * up the chip and perform initial configuration. It does the + * following sequence of actions:
[PATCH v8 4/9] mfd: Add header files and Kbuild plumbing for SI476x MFD core
From: Andrey Smirnov This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Acked-by: Hans Verkuil Acked-by: Sam Ravnborg Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 12 + drivers/mfd/Makefile|4 + include/linux/mfd/si476x-core.h | 525 +++ 3 files changed, 541 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4..3cd8f21 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -970,6 +970,18 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + help + This is the core driver for the SI476x series of AM/FM + radio. This MFD driver connects the radio-si476x V4L2 module + and the si476x audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core and TLL driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8..ca87ae8 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -131,6 +131,10 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855)+= vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o + +si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o + obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST)+= omap-usb-host.o omap-usb-tll.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..2136b26 --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,525 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Command Timeouts */ +#define SI476X_DEFAULT_TIMEOUT 10 +#define SI476X_TIMEOUT_TUNE70 +#define SI476X_TIMEOUT_POWER_UP33 +#define SI476X_STATUS_POLL_US 0 + +/* si476x-i2c.c --- */ + +enum si476x_freq_supported_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsistent, meaning some of the regulators were + * not turned down and thus use of the device, without power-cycling + * is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP_FULL= 1, + SI476X_POWER_INCONSISTENT = 2, +}; + +/** + * struct si476x_core - internal data structure representing the + * underlying "core" device which all the MFD cell-devices use. + * + * @client: Actual I2C client used to transfer commands to the chip. + * @chip_id: Last digit of the chip model(E.g. "1" for SI4761) + * @cells: MFD cell devices created by this driver. + * @c
[PATCH v8 7/9] v4l2: Add documentation for the FM RX controls
Add appropriate documentation for all the newly added standard controls. Based on the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641303-media-update-docs-for-v4l2-fm-new-features.html Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 72 .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 +++ 3 files changed, 84 insertions(+) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 104a1a2..f418bc3 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2310,6 +2310,9 @@ more information. Added FM Modulator (FM TX) Extended Control Class: V4L2_CTRL_CLASS_FM_TX and their Control IDs. + + Added FM Receiver (FM RX) Extended Control Class: V4L2_CTRL_CLASS_FM_RX and their Control IDs. + Added Remote Controller chapter, describing the default Remote Controller mapping for media devices. diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 1ad20cc..6aa647a 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -4687,4 +4687,76 @@ interface and may change in the future. + + + FM Receiver Control Reference + + The FM Receiver (FM_RX) class includes controls for common features of + FM Reception capable devices. + + + FM_RX Control IDs + + + + + + + + + + +ID +Type + Description + + + + + +V4L2_CID_FM_RX_CLASS +class + The FM_RX class +descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a +description of this control class. + + +V4L2_CID_RDS_RECEPTION +boolean + Enables/disables RDS + reception by the radio tuner + + + V4L2_CID_TUNE_DEEMPHASIS + enum v4l2_deemphasis + + Configures the de-emphasis value for reception. +A de-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. +Depending on the region, a time constant of either 50 or 75 useconds is used. The enum v4l2_deemphasis +defines possible values for de-emphasis. Here they are: + + + + + V4L2_DEEMPHASIS_DISABLED + No de-emphasis is applied. + + + V4L2_DEEMPHASIS_50_uS + A de-emphasis of 50 uS is used. + + + V4L2_DEEMPHASIS_75_uS + A de-emphasis of 75 uS is used. + + + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml index 4e16112..b3bb957 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml @@ -319,6 +319,15 @@ These controls are described in . + + + V4L2_CTRL_CLASS_FM_RX + 0xa1 + The class containing FM Receiver (FM RX) controls. +These controls are described in . + + -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 8/9] v4l2: Add private controls base for SI476X
Add a base to be used for allocation of all the SI476X specific controls in the corresponding driver. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- include/uapi/linux/v4l2-controls.h |4 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 3e985be..22e5170 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -147,6 +147,10 @@ enum v4l2_colorfx { * of controls. We reserve 16 controls for this driver. */ #define V4L2_CID_USER_MEYE_BASE(V4L2_CID_USER_BASE + 0x1000) +/* The base for the si476x driver controls. See include/media/si476x.h for the list + * of controls. Total of 16 controls is reserved for that driver */ +#define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1010) + /* MPEG-class control IDs */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 3/9] mfd: Add chip properties handling code for SI476X MFD
From: Andrey Smirnov This patch adds code related to manipulation of the properties of SI476X chips. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 242 + 1 file changed, 242 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..d1f548a --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,242 @@ +/* + * drivers/mfd/si476x-prop.c -- Subroutines to access + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include + +struct si476x_property_range { + u16 low, high; +}; + +static bool si476x_core_element_is_in_array(u16 element, + const u16 array[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool si476x_core_element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x0718, + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a20(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071B, + 0x1006, + 0x2210, + 0x3401, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x2215, 0x2219 }, + }; + + return si476x_core_is_valid_property_a10(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a30(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071C, 0x071D, + 0x1007, 0x1008, + 0x220F, 0x2214, + 0x2301, + 0x3105, 0x3106, + 0x3402, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0405, 0x0411 }, + { 0x2008, 0x200B }, + { 0x2220, 0x2223 }, + { 0x3100, 0x3106 }, + }; + + return si476x_core_is_valid_propert
[PATCH v8 6/9] v4l2: Add standard controls for FM receivers
This commit introduces new class of standard controls V4L2_CTRL_CLASS_FM_RX. This class is intended to all controls pertaining to FM receiver chips. Also, two controls belonging to said class are added as a part of this commit: V4L2_CID_TUNE_DEEMPHASIS and V4L2_CID_RDS_RECEPTION. This patch is based on the code found in the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641307-new-control-class-and-features-for-fm-rx.html Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/media/v4l2-core/v4l2-ctrls.c | 14 +++--- include/uapi/linux/v4l2-controls.h | 13 + 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 6b28b58..8b89fb8 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -297,8 +297,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Text", NULL }; - static const char * const tune_preemphasis[] = { - "No Preemphasis", + static const char * const tune_emphasis[] = { + "None", "50 Microseconds", "75 Microseconds", NULL, @@ -508,7 +508,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_SCENE_MODE: return scene_mode; case V4L2_CID_TUNE_PREEMPHASIS: - return tune_preemphasis; + return tune_emphasis; + case V4L2_CID_TUNE_DEEMPHASIS: + return tune_emphasis; case V4L2_CID_FLASH_LED_MODE: return flash_led_mode; case V4L2_CID_FLASH_STROBE_SOURCE: @@ -799,6 +801,9 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; + case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; + case V4L2_CID_RDS_RECEPTION:return "RDS Reception"; default: return NULL; } @@ -846,6 +851,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: case V4L2_CID_WIDE_DYNAMIC_RANGE: case V4L2_CID_IMAGE_STABILIZATION: + case V4L2_CID_RDS_RECEPTION: *type = V4L2_CTRL_TYPE_BOOLEAN; *min = 0; *max = *step = 1; @@ -904,6 +910,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: case V4L2_CID_TEST_PATTERN: + case V4L2_CID_TUNE_DEEMPHASIS: *type = V4L2_CTRL_TYPE_MENU; break; case V4L2_CID_LINK_FREQ: @@ -926,6 +933,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_IMAGE_SOURCE_CLASS: case V4L2_CID_IMAGE_PROC_CLASS: case V4L2_CID_DV_CLASS: + case V4L2_CID_FM_RX_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read not write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index dcd6374..3e985be 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -59,6 +59,7 @@ #define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e /* Image source controls */ #define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f /* Image processing controls */ #define V4L2_CTRL_CLASS_DV 0x00a0 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a1 /* Digital Video controls */ /* User-class control IDs */ @@ -825,4 +826,16 @@ enum v4l2_dv_rgb_range { #defineV4L2_CID_DV_RX_POWER_PRESENT(V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) +#define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) + +#define V4L2_CID_TUNE_DEEMPHASIS (V4L2_CID_FM_RX_CLASS_BASE + 1) +enum v4l2_deemphasis { + V4L2_DEEMPHASIS_DISABLED= V4L2_PREEMPHASIS_DISABLED, + V4L2_DEEMPHASIS_50_uS = V4L2_PREEMPHASIS_50_uS, + V4L2_DEEMPHASIS_75_uS = V4L2_PREEMPHASIS_75_uS, +}; + +#define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2) + #endif -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 0/9] Driver for Si476x series of chips
Driver for Si476x series of chips This is a eight version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 Second version of the patch was posted here: https://lkml.org/lkml/2012/10/5/598 Third version of the patch was posted here: https://lkml.org/lkml/2012/10/23/510 Fourth version of the patch was posted here: https://lkml.org/lkml/2013/2/18/572 Fifth version of the patch was posted here: https://lkml.org/lkml/2013/2/26/45 Sixth version of the patch was posted here: https://lkml.org/lkml/2013/2/26/257 Seventh version of the patch was posted here: https://lkml.org/lkml/2013/2/27/22 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. v8 of this driver has following changes: - checkpatch.pl fixes Pleas note that patches are not completely warning free, as far as checkpatch.pl is concerned, because I skipped all the places where 80-character compliance can be acheived only by means of weird indentation. Andrey Smirnov (9): mfd: Add commands abstraction layer for SI476X MFD mfd: Add the main bulk of core driver for SI476x code mfd: Add chip properties handling code for SI476X MFD mfd: Add header files and Kbuild plumbing for SI476x MFD core v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation v4l2: Add standard controls for FM receivers v4l2: Add documentation for the FM RX controls v4l2: Add private controls base for SI476X v4l2: Add a V4L2 driver for SI476X MFD Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 74 +- .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 + Documentation/video4linux/si476x.txt | 187 +++ drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1599 drivers/media/v4l2-core/v4l2-ctrls.c | 14 +- drivers/mfd/Kconfig| 12 + drivers/mfd/Makefile |4 + drivers/mfd/si476x-cmd.c | 1554 +++ drivers/mfd/si476x-i2c.c | 886 +++ drivers/mfd/si476x-prop.c | 242 +++ include/linux/mfd/si476x-core.h| 525 +++ include/media/si476x.h | 426 ++ include/uapi/linux/v4l2-controls.h | 17 + 16 files changed, 5566 insertions(+), 4 deletions(-) create mode 100644 Documentation/video4linux/si476x.txt create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 drivers/mfd/si476x-cmd.c create mode 100644 drivers/mfd/si476x-i2c.c create mode 100644 drivers/mfd/si476x-prop.c create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 5/9] v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation
Change the type of V4L2_CID_TUNE_PREEMPHASIS from 'integer' to 'enum v4l2_preemphasis' Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/controls.xml |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 9e8f854..1ad20cc 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -3848,7 +3848,7 @@ in Hz. The range and step are driver-specific. V4L2_CID_TUNE_PREEMPHASIS - integer + enum v4l2_preemphasis Configures the pre-emphasis value for broadcasting. A pre-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 1/9] mfd: Add commands abstraction layer for SI476X MFD
From: Andrey Smirnov This patch adds all the functions used for exchanging commands with the chip. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1554 ++ 1 file changed, 1554 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..71ac2e8 --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1554 @@ +/* + * drivers/mfd/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD
Re: [PATCH v7 1/9] mfd: Add commands abstraction layer for SI476X MFD
On Mon, Mar 18, 2013 at 1:11 PM, Mauro Carvalho Chehab wrote: > Em Tue, 26 Feb 2013 22:06:45 -0800 > Andrey Smirnov escreveu: > >> This patch adds all the functions used for exchanging commands with >> the chip. > > Please run checkpatch.pl over those patches. There are a number of compliants > on those patches: > OK, will do shortly and send updated patch-set. > WARNING: line over 80 characters > #328: FILE: drivers/mfd/si476x-cmd.c:298: > + err = si476x_core_i2c_xfer(core, SI476X_I2C_SEND, (char *) data, argn > + 1); > > WARNING: line over 80 characters > #378: FILE: drivers/mfd/si476x-cmd.c:348: > + dev_err(&core->client->dev, "[CMD 0x%02x] Chip set error > flag\n", command); > I do have a question about this particular warning though. Weird indentation that I had to use in order to calm checkpatch.pl about that issue has been a topic of discussion and complaints once already(see https://lkml.org/lkml/2012/9/21/67) To my understanding the consensus was as far as it improves readability > 80 character lines are OK. What would you like me do with those extra long lines ignore all/fix all/use discretion and fix some? -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 0/9] Driver for Si476x series of chips
This is a fourth version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 Second version of the patch was posted here: https://lkml.org/lkml/2012/10/5/598 Third version of the patch was posted here: https://lkml.org/lkml/2012/10/23/510 Fourth version of the patch was posted here: https://lkml.org/lkml/2013/2/18/572 Fifth version of the patch was posted here: https://lkml.org/lkml/2013/2/26/45 Sixth version of the patch was posted here; https://lkml.org/lkml/2013/2/26/257 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. v7 of this driver has following changes: - Minor Makefile/Kconfig changes - MFD driver commit reordering as per suggestions from Sam Ravnborg Andrey Smirnov (9): mfd: Add commands abstraction layer for SI476X MFD mfd: Add the main bulk of core driver for SI476x code mfd: Add chip properties handling code for SI476X MFD mfd: Add header files and Kbuild plumbing for SI476x MFD core v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation v4l2: Add standard controls for FM receivers v4l2: Add documentation for the FM RX controls v4l2: Add private controls base for SI476X v4l2: Add a V4L2 driver for SI476X MFD Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 74 +- .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 + Documentation/video4linux/si476x.txt | 187 +++ drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1574 drivers/media/v4l2-core/v4l2-ctrls.c | 14 +- drivers/mfd/Kconfig| 12 + drivers/mfd/Makefile |4 + drivers/mfd/si476x-cmd.c | 1553 +++ drivers/mfd/si476x-i2c.c | 878 +++ drivers/mfd/si476x-prop.c | 234 +++ include/linux/mfd/si476x-core.h| 525 +++ include/media/si476x.h | 426 ++ include/uapi/linux/v4l2-controls.h | 17 + 16 files changed, 5524 insertions(+), 4 deletions(-) create mode 100644 Documentation/video4linux/si476x.txt create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 drivers/mfd/si476x-cmd.c create mode 100644 drivers/mfd/si476x-i2c.c create mode 100644 drivers/mfd/si476x-prop.c create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 2/9] mfd: Add the main bulk of core driver for SI476x code
This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 878 ++ 1 file changed, 878 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..053a6a3 --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,878 @@ +/* + * drivers/mfd/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SI476X_MAX_IO_ERRORS 10 +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_core_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(SI476X_STATUS_POLL_US)); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tuner + * + * Perform required startup sequence to correctly power + * up the chip and perform initial configuration. It does the + * following sequence of actions: + * 1. Claims an
[PATCH v7 3/9] mfd: Add chip properties handling code for SI476X MFD
This patch adds code related to manipulation of the properties of SI476X chips. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 234 + 1 file changed, 234 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..d2b5cc0 --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,234 @@ +/* + * drivers/mfd/si476x-prop.c -- Subroutines to manipulate with + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include + +struct si476x_property_range { + u16 low, high; +}; + +static bool si476x_core_element_is_in_array(u16 element, const u16 array[], size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool si476x_core_element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x0718, + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a20(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071B, + 0x1006, + 0x2210, + 0x3401, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x2215, 0x2219 }, + }; + + return si476x_core_is_valid_property_a10(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a30(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071C, 0x071D, + 0x1007, 0x1008, + 0x220F, 0x2214, + 0x2301, + 0x3105, 0x3106, + 0x3402, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0405, 0x0411 }, + { 0x2008, 0x200B }, + { 0x2220, 0x2223 }, + { 0x3100, 0x3106 }, + }; + + return si476x_core_is_valid_property_a20(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, +
[PATCH v7 5/9] v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation
Change the type of V4L2_CID_TUNE_PREEMPHASIS from 'integer' to 'enum v4l2_preemphasis' Acked-by: Hans Verkuil Singed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/controls.xml |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 9e8f854..1ad20cc 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -3848,7 +3848,7 @@ in Hz. The range and step are driver-specific. V4L2_CID_TUNE_PREEMPHASIS - integer + enum v4l2_preemphasis Configures the pre-emphasis value for broadcasting. A pre-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 1/9] mfd: Add commands abstraction layer for SI476X MFD
This patch adds all the functions used for exchanging commands with the chip. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1553 ++ 1 file changed, 1553 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..0ae1b63 --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1553 @@ +/* + * drivers/mfd/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD_AM_SEEK_START
[PATCH v7 6/9] v4l2: Add standard controls for FM receivers
This commit introduces new class of standard controls V4L2_CTRL_CLASS_FM_RX. This class is intended to all controls pertaining to FM receiver chips. Also, two controls belonging to said class are added as a part of this commit: V4L2_CID_TUNE_DEEMPHASIS and V4L2_CID_RDS_RECEPTION. This patch is based on the code found in the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641307-new-control-class-and-features-for-fm-rx.html Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/media/v4l2-core/v4l2-ctrls.c | 14 +++--- include/uapi/linux/v4l2-controls.h | 13 + 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 6b28b58..8b89fb8 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -297,8 +297,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Text", NULL }; - static const char * const tune_preemphasis[] = { - "No Preemphasis", + static const char * const tune_emphasis[] = { + "None", "50 Microseconds", "75 Microseconds", NULL, @@ -508,7 +508,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_SCENE_MODE: return scene_mode; case V4L2_CID_TUNE_PREEMPHASIS: - return tune_preemphasis; + return tune_emphasis; + case V4L2_CID_TUNE_DEEMPHASIS: + return tune_emphasis; case V4L2_CID_FLASH_LED_MODE: return flash_led_mode; case V4L2_CID_FLASH_STROBE_SOURCE: @@ -799,6 +801,9 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; + case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; + case V4L2_CID_RDS_RECEPTION:return "RDS Reception"; default: return NULL; } @@ -846,6 +851,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: case V4L2_CID_WIDE_DYNAMIC_RANGE: case V4L2_CID_IMAGE_STABILIZATION: + case V4L2_CID_RDS_RECEPTION: *type = V4L2_CTRL_TYPE_BOOLEAN; *min = 0; *max = *step = 1; @@ -904,6 +910,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: case V4L2_CID_TEST_PATTERN: + case V4L2_CID_TUNE_DEEMPHASIS: *type = V4L2_CTRL_TYPE_MENU; break; case V4L2_CID_LINK_FREQ: @@ -926,6 +933,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_IMAGE_SOURCE_CLASS: case V4L2_CID_IMAGE_PROC_CLASS: case V4L2_CID_DV_CLASS: + case V4L2_CID_FM_RX_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read not write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index dcd6374..3e985be 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -59,6 +59,7 @@ #define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e /* Image source controls */ #define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f /* Image processing controls */ #define V4L2_CTRL_CLASS_DV 0x00a0 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a1 /* Digital Video controls */ /* User-class control IDs */ @@ -825,4 +826,16 @@ enum v4l2_dv_rgb_range { #defineV4L2_CID_DV_RX_POWER_PRESENT(V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) +#define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) + +#define V4L2_CID_TUNE_DEEMPHASIS (V4L2_CID_FM_RX_CLASS_BASE + 1) +enum v4l2_deemphasis { + V4L2_DEEMPHASIS_DISABLED= V4L2_PREEMPHASIS_DISABLED, + V4L2_DEEMPHASIS_50_uS = V4L2_PREEMPHASIS_50_uS, + V4L2_DEEMPHASIS_75_uS = V4L2_PREEMPHASIS_75_uS, +}; + +#define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2) + #endif -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 8/9] v4l2: Add private controls base for SI476X
Add a base to be used for allocation of all the SI476X specific controls in the corresponding driver. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- include/uapi/linux/v4l2-controls.h |4 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 3e985be..22e5170 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -147,6 +147,10 @@ enum v4l2_colorfx { * of controls. We reserve 16 controls for this driver. */ #define V4L2_CID_USER_MEYE_BASE(V4L2_CID_USER_BASE + 0x1000) +/* The base for the si476x driver controls. See include/media/si476x.h for the list + * of controls. Total of 16 controls is reserved for that driver */ +#define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1010) + /* MPEG-class control IDs */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 7/9] v4l2: Add documentation for the FM RX controls
Add appropriate documentation for all the newly added standard controls. Based on the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641303-media-update-docs-for-v4l2-fm-new-features.html Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 72 .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 +++ 3 files changed, 84 insertions(+) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 104a1a2..f418bc3 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2310,6 +2310,9 @@ more information. Added FM Modulator (FM TX) Extended Control Class: V4L2_CTRL_CLASS_FM_TX and their Control IDs. + + Added FM Receiver (FM RX) Extended Control Class: V4L2_CTRL_CLASS_FM_RX and their Control IDs. + Added Remote Controller chapter, describing the default Remote Controller mapping for media devices. diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 1ad20cc..6aa647a 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -4687,4 +4687,76 @@ interface and may change in the future. + + + FM Receiver Control Reference + + The FM Receiver (FM_RX) class includes controls for common features of + FM Reception capable devices. + + + FM_RX Control IDs + + + + + + + + + + +ID +Type + Description + + + + + +V4L2_CID_FM_RX_CLASS +class + The FM_RX class +descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a +description of this control class. + + +V4L2_CID_RDS_RECEPTION +boolean + Enables/disables RDS + reception by the radio tuner + + + V4L2_CID_TUNE_DEEMPHASIS + enum v4l2_deemphasis + + Configures the de-emphasis value for reception. +A de-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. +Depending on the region, a time constant of either 50 or 75 useconds is used. The enum v4l2_deemphasis +defines possible values for de-emphasis. Here they are: + + + + + V4L2_DEEMPHASIS_DISABLED + No de-emphasis is applied. + + + V4L2_DEEMPHASIS_50_uS + A de-emphasis of 50 uS is used. + + + V4L2_DEEMPHASIS_75_uS + A de-emphasis of 75 uS is used. + + + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml index 4e16112..b3bb957 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml @@ -319,6 +319,15 @@ These controls are described in . + + + V4L2_CTRL_CLASS_FM_RX + 0xa1 + The class containing FM Receiver (FM RX) controls. +These controls are described in . + + -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 4/9] mfd: Add header files and Kbuild plumbing for SI476x MFD core
This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Acked-by: Hans Verkuil Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 12 + drivers/mfd/Makefile|4 + include/linux/mfd/si476x-core.h | 525 +++ 3 files changed, 541 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4..3cd8f21 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -970,6 +970,18 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + help + This is the core driver for the SI476x series of AM/FM + radio. This MFD driver connects the radio-si476x V4L2 module + and the si476x audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core and TLL driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8..ca87ae8 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -131,6 +131,10 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855)+= vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o + +si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o + obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST)+= omap-usb-host.o omap-usb-tll.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..2136b26 --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,525 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Command Timeouts */ +#define SI476X_DEFAULT_TIMEOUT 10 +#define SI476X_TIMEOUT_TUNE70 +#define SI476X_TIMEOUT_POWER_UP33 +#define SI476X_STATUS_POLL_US 0 + +/* si476x-i2c.c --- */ + +enum si476x_freq_supported_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsistent, meaning some of the regulators were + * not turned down and thus use of the device, without power-cycling + * is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP_FULL= 1, + SI476X_POWER_INCONSISTENT = 2, +}; + +/** + * struct si476x_core - internal data structure representing the + * underlying "core" device which all the MFD cell-devices use. + * + * @client: Actual I2C client used to transfer commands to the chip. + * @chip_id: Last digit of the chip model(E.g. "1" for SI4761) + * @cells: MFD cell devices created by this driver. + * @cmd_lock: Mutex used to serialize all the requests t
[PATCH v6 2/9] mfd: Add commands abstraction layer for SI476X MFD
From: Andrey Smirnov This patch adds all the functions used for exchanging commands with the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1553 ++ 1 file changed, 1553 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..0ae1b63 --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1553 @@ +/* + * drivers/mfd/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD_AM_SEEK_START
[PATCH v6 3/9] mfd: Add the main bulk of core driver for SI476x code
From: Andrey Smirnov This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 878 ++ 1 file changed, 878 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..053a6a3 --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,878 @@ +/* + * drivers/mfd/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SI476X_MAX_IO_ERRORS 10 +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_core_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(SI476X_STATUS_POLL_US)); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tuner + * + * Perform required startup sequence to correctly power + * up the chip and perform initial configuration. It does the + * following sequence of actions: + * 1. Claims an
[PATCH v6 1/9] mfd: Add header files and Kbuild plumbing for SI476x MFD core
From: Andrey Smirnov This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 13 + drivers/mfd/Makefile|4 + include/linux/mfd/si476x-core.h | 525 +++ 3 files changed, 542 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4..3214927 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -970,6 +970,19 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + default n + help + This is the core driver for the SI476x series of AM/FM + radio. This MFD driver connects the radio-si476x V4L2 module + and the si476x audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core and TLL driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8..bf7627b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -131,6 +131,10 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855)+= vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o + +si476x-core-objs := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o + obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST)+= omap-usb-host.o omap-usb-tll.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..2136b26 --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,525 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Command Timeouts */ +#define SI476X_DEFAULT_TIMEOUT 10 +#define SI476X_TIMEOUT_TUNE70 +#define SI476X_TIMEOUT_POWER_UP33 +#define SI476X_STATUS_POLL_US 0 + +/* si476x-i2c.c --- */ + +enum si476x_freq_supported_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsistent, meaning some of the regulators were + * not turned down and thus use of the device, without power-cycling + * is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP_FULL= 1, + SI476X_POWER_INCONSISTENT = 2, +}; + +/** + * struct si476x_core - internal data structure representing the + * underlying "core" device which all the MFD cell-devices use. + * + * @client: Actual I2C client used to transfer commands to the chip. + * @chip_id: Last digit of the chip model(E.g. "1" for SI4761) + * @cells: MFD cell devices created by this driver. + * @cmd_lock: Mutex used to serialize
[PATCH v6 0/9] Driver for Si476x series of chips
This is a fourth version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 Second version of the patch was posted here: https://lkml.org/lkml/2012/10/5/598 Third version of the patch was posted here: https://lkml.org/lkml/2012/10/23/510 Fourth version of the patch was posted here: https://lkml.org/lkml/2013/2/18/572 Fifth version of the patch was posted here: https://lkml.org/lkml/2013/2/26/45 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. v6 of this driver has following changes: - Minor corrections Andrey Smirnov (9): mfd: Add header files and Kbuild plumbing for SI476x MFD core mfd: Add commands abstraction layer for SI476X MFD mfd: Add the main bulk of core driver for SI476x code mfd: Add chip properties handling code for SI476X MFD v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation v4l2: Add standard controls for FM receivers v4l2: Add documentation for the FM RX controls v4l2: Add private controls base for SI476X v4l2: Add a V4L2 driver for SI476X MFD Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 74 +- .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 + Documentation/video4linux/si476x.txt | 187 +++ drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1574 drivers/media/v4l2-core/v4l2-ctrls.c | 14 +- drivers/mfd/Kconfig| 13 + drivers/mfd/Makefile |4 + drivers/mfd/si476x-cmd.c | 1553 +++ drivers/mfd/si476x-i2c.c | 878 +++ drivers/mfd/si476x-prop.c | 234 +++ include/linux/mfd/si476x-core.h| 525 +++ include/media/si476x.h | 426 ++ include/uapi/linux/v4l2-controls.h | 17 + 16 files changed, 5525 insertions(+), 4 deletions(-) create mode 100644 Documentation/video4linux/si476x.txt create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 drivers/mfd/si476x-cmd.c create mode 100644 drivers/mfd/si476x-i2c.c create mode 100644 drivers/mfd/si476x-prop.c create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 4/9] mfd: Add chip properties handling code for SI476X MFD
From: Andrey Smirnov This patch adds code related to manipulation of the properties of SI476X chips. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 234 + 1 file changed, 234 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..d2b5cc0 --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,234 @@ +/* + * drivers/mfd/si476x-prop.c -- Subroutines to manipulate with + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include + +struct si476x_property_range { + u16 low, high; +}; + +static bool si476x_core_element_is_in_array(u16 element, const u16 array[], size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool si476x_core_element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x0718, + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a20(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071B, + 0x1006, + 0x2210, + 0x3401, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x2215, 0x2219 }, + }; + + return si476x_core_is_valid_property_a10(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a30(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071C, 0x071D, + 0x1007, 0x1008, + 0x220F, 0x2214, + 0x2301, + 0x3105, 0x3106, + 0x3402, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0405, 0x0411 }, + { 0x2008, 0x200B }, + { 0x2220, 0x2223 }, + { 0x3100, 0x3106 }, + }; + + return si476x_core_is_valid_property_a20(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, +
[PATCH v6 5/9] v4l2: Fix the type of V4L2_CID_TUNE_PREEMPHASIS in the documentation
Change the type of V4L2_CID_TUNE_PREEMPHASIS from 'integer' to 'enum v4l2_preemphasis' Singed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/controls.xml |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 9e8f854..1ad20cc 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -3848,7 +3848,7 @@ in Hz. The range and step are driver-specific. V4L2_CID_TUNE_PREEMPHASIS - integer + enum v4l2_preemphasis Configures the pre-emphasis value for broadcasting. A pre-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 7/9] v4l2: Add documentation for the FM RX controls
Add appropriate documentation for all the newly added standard controls. Based on the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641303-media-update-docs-for-v4l2-fm-new-features.html Signed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 72 .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml |9 +++ 3 files changed, 84 insertions(+) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 104a1a2..f418bc3 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2310,6 +2310,9 @@ more information. Added FM Modulator (FM TX) Extended Control Class: V4L2_CTRL_CLASS_FM_TX and their Control IDs. + + Added FM Receiver (FM RX) Extended Control Class: V4L2_CTRL_CLASS_FM_RX and their Control IDs. + Added Remote Controller chapter, describing the default Remote Controller mapping for media devices. diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 1ad20cc..6aa647a 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -4687,4 +4687,76 @@ interface and may change in the future. + + + FM Receiver Control Reference + + The FM Receiver (FM_RX) class includes controls for common features of + FM Reception capable devices. + + + FM_RX Control IDs + + + + + + + + + + +ID +Type + Description + + + + + +V4L2_CID_FM_RX_CLASS +class + The FM_RX class +descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a +description of this control class. + + +V4L2_CID_RDS_RECEPTION +boolean + Enables/disables RDS + reception by the radio tuner + + + V4L2_CID_TUNE_DEEMPHASIS + enum v4l2_deemphasis + + Configures the de-emphasis value for reception. +A de-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. +Depending on the region, a time constant of either 50 or 75 useconds is used. The enum v4l2_deemphasis +defines possible values for de-emphasis. Here they are: + + + + + V4L2_DEEMPHASIS_DISABLED + No de-emphasis is applied. + + + V4L2_DEEMPHASIS_50_uS + A de-emphasis of 50 uS is used. + + + V4L2_DEEMPHASIS_75_uS + A de-emphasis of 75 uS is used. + + + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml index 4e16112..b3bb957 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml @@ -319,6 +319,15 @@ These controls are described in . + + + V4L2_CTRL_CLASS_FM_RX + 0xa1 + The class containing FM Receiver (FM RX) controls. +These controls are described in . + + -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 8/9] v4l2: Add private controls base for SI476X
Add a base to be used for allocation of all the SI476X specific controls in the corresponding driver. Signed-off-by: Andrey Smirnov --- include/uapi/linux/v4l2-controls.h |4 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 3e985be..22e5170 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -147,6 +147,10 @@ enum v4l2_colorfx { * of controls. We reserve 16 controls for this driver. */ #define V4L2_CID_USER_MEYE_BASE(V4L2_CID_USER_BASE + 0x1000) +/* The base for the si476x driver controls. See include/media/si476x.h for the list + * of controls. Total of 16 controls is reserved for that driver */ +#define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1010) + /* MPEG-class control IDs */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 6/9] v4l2: Add standard controls for FM receivers
This commit introduces new class of standard controls V4L2_CTRL_CLASS_FM_RX. This class is intended to all controls pertaining to FM receiver chips. Also, two controls belonging to said class are added as a part of this commit: V4L2_CID_TUNE_DEEMPHASIS and V4L2_CID_RDS_RECEPTION. This patch is based on the code found in the patch by Manjunatha Halli [1] [1] http://lists-archives.com/linux-kernel/27641307-new-control-class-and-features-for-fm-rx.html Signed-off-by: Andrey Smirnov --- drivers/media/v4l2-core/v4l2-ctrls.c | 14 +++--- include/uapi/linux/v4l2-controls.h | 13 + 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 6b28b58..8b89fb8 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -297,8 +297,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Text", NULL }; - static const char * const tune_preemphasis[] = { - "No Preemphasis", + static const char * const tune_emphasis[] = { + "None", "50 Microseconds", "75 Microseconds", NULL, @@ -508,7 +508,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_SCENE_MODE: return scene_mode; case V4L2_CID_TUNE_PREEMPHASIS: - return tune_preemphasis; + return tune_emphasis; + case V4L2_CID_TUNE_DEEMPHASIS: + return tune_emphasis; case V4L2_CID_FLASH_LED_MODE: return flash_led_mode; case V4L2_CID_FLASH_STROBE_SOURCE: @@ -799,6 +801,9 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; + case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; + case V4L2_CID_RDS_RECEPTION:return "RDS Reception"; default: return NULL; } @@ -846,6 +851,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: case V4L2_CID_WIDE_DYNAMIC_RANGE: case V4L2_CID_IMAGE_STABILIZATION: + case V4L2_CID_RDS_RECEPTION: *type = V4L2_CTRL_TYPE_BOOLEAN; *min = 0; *max = *step = 1; @@ -904,6 +910,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: case V4L2_CID_TEST_PATTERN: + case V4L2_CID_TUNE_DEEMPHASIS: *type = V4L2_CTRL_TYPE_MENU; break; case V4L2_CID_LINK_FREQ: @@ -926,6 +933,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_IMAGE_SOURCE_CLASS: case V4L2_CID_IMAGE_PROC_CLASS: case V4L2_CID_DV_CLASS: + case V4L2_CID_FM_RX_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read not write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index dcd6374..3e985be 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -59,6 +59,7 @@ #define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e /* Image source controls */ #define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f /* Image processing controls */ #define V4L2_CTRL_CLASS_DV 0x00a0 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a1 /* Digital Video controls */ /* User-class control IDs */ @@ -825,4 +826,16 @@ enum v4l2_dv_rgb_range { #defineV4L2_CID_DV_RX_POWER_PRESENT(V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) +#define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) + +#define V4L2_CID_TUNE_DEEMPHASIS (V4L2_CID_FM_RX_CLASS_BASE + 1) +enum v4l2_deemphasis { + V4L2_DEEMPHASIS_DISABLED= V4L2_PREEMPHASIS_DISABLED, + V4L2_DEEMPHASIS_50_uS = V4L2_PREEMPHASIS_50_uS, + V4L2_DEEMPHASIS_75_uS = V4L2_PREEMPHASIS_75_uS, +}; + +#define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2) + #endif -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 8/8] v4l2: Add a V4L2 driver for SI476X MFD
>> + >> +enum phase_diversity_modes_idx { >> + SI476X_IDX_PHDIV_DISABLED, >> + SI476X_IDX_PHDIV_PRIMARY_COMBINING, >> + SI476X_IDX_PHDIV_PRIMARY_ANTENNA, >> + SI476X_IDX_PHDIV_SECONDARY_ANTENNA, >> + SI476X_IDX_PHDIV_SECONDARY_COMBINING, >> +}; >> + >> +static const char * const phase_diversity_modes[] = { >> + [SI476X_IDX_PHDIV_DISABLED] = "Disabled", > > Question: what does it mean if this is disabled? That none of the antennas > are working? That would imply that you get no reception at all. I am not an expert on these chips and, unfortunately, never had anyone from SiLabs to talk to all the time I worked on this driver. But from my understanding from working with the chip/reading of the datasheet, when working in diversity mode two chips are connected to two different antennas and interconnected between each other so that secondary tuner can pass semi-processed signal to the primary one. So to the best of my understanding those sttings cause the following mode of operation: * Disabled -- no link is established, tuner acts no differently than if other tuner didn't exist. * Primary combinig -- link is established, tuner is configured to be a primary tuner using signal from both itself and a secondary one * Primary antenna -- link is established, tuner is configured to be a primary tuner using signal from its own antenna * Secondary antenna -- link is established, tuner is configured to be a primary tuner using signal from secondary tuner's antenna * Secondary -- link is established, tuner is configured to be a secondary tuner feeding the signal from its antenna to the primary one It seems that "Disabled" setting is the setting one would want to use if the chip is used in a non diversity-mode enabled system. > >> + [SI476X_IDX_PHDIV_PRIMARY_COMBINING]= "Primary W/Secondary", > > Just write in full: "Primary with Secondary" > >> + [SI476X_IDX_PHDIV_PRIMARY_ANTENNA] = "Primary(Primary Antenna)", > > This becomes: "Primary Antenna" > >> + [SI476X_IDX_PHDIV_SECONDARY_ANTENNA]= "Primary(Seconadary >> Antenna)", > > "Secondary Antenna" > >> + [SI476X_IDX_PHDIV_SECONDARY_COMBINING] = "Secondary W/Primary", > > "Secondary with Primary" > >> +}; >> + >> +static inline enum phase_diversity_modes_idx >> +si476x_phase_diversity_mode_to_idx(enum si476x_phase_diversity_mode mode) >> +{ >> + switch (mode) { >> + default:/* FALLTHROUGH */ >> + case SI476X_PHDIV_DISABLED: >> + return SI476X_IDX_PHDIV_DISABLED; >> + case SI476X_PHDIV_PRIMARY_COMBINING: >> + return SI476X_IDX_PHDIV_PRIMARY_COMBINING; >> + case SI476X_PHDIV_PRIMARY_ANTENNA: >> + return SI476X_IDX_PHDIV_PRIMARY_ANTENNA; >> + case SI476X_PHDIV_SECONDARY_ANTENNA: >> + return SI476X_IDX_PHDIV_SECONDARY_ANTENNA; >> + case SI476X_PHDIV_SECONDARY_COMBINING: >> + return SI476X_IDX_PHDIV_SECONDARY_COMBINING; >> + } >> +} >> + >> +static inline enum si476x_phase_diversity_mode >> +si476x_phase_diversity_idx_to_mode(enum phase_diversity_modes_idx idx) >> +{ >> + static const int idx_to_value[] = { >> + [SI476X_IDX_PHDIV_DISABLED] = >> SI476X_PHDIV_DISABLED, >> + [SI476X_IDX_PHDIV_PRIMARY_COMBINING]= >> SI476X_PHDIV_PRIMARY_COMBINING, >> + [SI476X_IDX_PHDIV_PRIMARY_ANTENNA] = >> SI476X_PHDIV_PRIMARY_ANTENNA, >> + [SI476X_IDX_PHDIV_SECONDARY_ANTENNA]= >> SI476X_PHDIV_SECONDARY_ANTENNA, >> + [SI476X_IDX_PHDIV_SECONDARY_COMBINING] = >> SI476X_PHDIV_SECONDARY_COMBINING, >> + }; >> + >> + return idx_to_value[idx]; >> +} >> + >> +static const struct v4l2_ctrl_ops si476x_ctrl_ops = { >> + .g_volatile_ctrl= si476x_radio_g_volatile_ctrl, >> + .s_ctrl = si476x_radio_s_ctrl, >> +}; >> + >> + >> +enum si476x_ctrl_idx { >> + SI476X_IDX_RSSI_THRESHOLD, >> + SI476X_IDX_SNR_THRESHOLD, >> + SI476X_IDX_MAX_TUNE_ERROR, >> + SI476X_IDX_HARMONICS_COUNT, >> + SI476X_IDX_DIVERSITY_MODE, >> + SI476X_IDX_INTERCHIP_LINK, >> +}; >> +static struct v4l2_ctrl_config si476x_ctrls[] = { >> + >> + /** >> + * SI476X during its station seeking(or tuning) process uses several >> + * parameters to detrmine if "the station" is valid: >> + * >> + * - Signal's SNR(in dBuV) must be lower than >> + * #V4L2_CID_SI476X_SNR_THRESHOLD >> + * - Signal's RSSI(in dBuV) must be greater than >> + * #V4L2_CID_SI476X_RSSI_THRESHOLD >> + * - Signal's frequency deviation(in units of 2ppm) must not be >> + * more than #V4L2_CID_SI476X_MAX_TUNE_ERROR >> + */ >> + [SI476X_IDX_RSSI_THRESHOLD] = { >> + .ops= &si476x_ctrl_ops, >> + .id = V4L2_CID_SI476X_RSSI_THRESHOLD, >> + .name = "Valid RSSI Threshold", >> + .type = V4L2_CTRL_TYPE_INTEGER, >> +
[PATCH v5 1/8] mfd: Add header files and Kbuild plumbing for SI476x MFD core
From: Andrey Smirnov This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 13 + drivers/mfd/Makefile|4 + include/linux/mfd/si476x-core.h | 525 +++ 3 files changed, 542 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4..3214927 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -970,6 +970,19 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + default n + help + This is the core driver for the SI476x series of AM/FM + radio. This MFD driver connects the radio-si476x V4L2 module + and the si476x audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core and TLL driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8..bf7627b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -131,6 +131,10 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855)+= vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o + +si476x-core-objs := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o + obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST)+= omap-usb-host.o omap-usb-tll.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..2136b26 --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,525 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Command Timeouts */ +#define SI476X_DEFAULT_TIMEOUT 10 +#define SI476X_TIMEOUT_TUNE70 +#define SI476X_TIMEOUT_POWER_UP33 +#define SI476X_STATUS_POLL_US 0 + +/* si476x-i2c.c --- */ + +enum si476x_freq_supported_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsistent, meaning some of the regulators were + * not turned down and thus use of the device, without power-cycling + * is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP_FULL= 1, + SI476X_POWER_INCONSISTENT = 2, +}; + +/** + * struct si476x_core - internal data structure representing the + * underlying "core" device which all the MFD cell-devices use. + * + * @client: Actual I2C client used to transfer commands to the chip. + * @chip_id: Last digit of the chip model(E.g. "1" for SI4761) + * @cells: MFD cell devices created by this driver. + * @cmd_lock: Mutex used to serialize
[PATCH v5 4/8] mfd: Add chip properties handling code for SI476X MFD
From: Andrey Smirnov This patch adds code related to manipulation of the properties of SI476X chips. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 234 + 1 file changed, 234 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..d2b5cc0 --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,234 @@ +/* + * drivers/mfd/si476x-prop.c -- Subroutines to manipulate with + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include + +struct si476x_property_range { + u16 low, high; +}; + +static bool si476x_core_element_is_in_array(u16 element, const u16 array[], size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool si476x_core_element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x0718, + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a20(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071B, + 0x1006, + 0x2210, + 0x3401, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x2215, 0x2219 }, + }; + + return si476x_core_is_valid_property_a10(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a30(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071C, 0x071D, + 0x1007, 0x1008, + 0x220F, 0x2214, + 0x2301, + 0x3105, 0x3106, + 0x3402, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0405, 0x0411 }, + { 0x2008, 0x200B }, + { 0x2220, 0x2223 }, + { 0x3100, 0x3106 }, + }; + + return si476x_core_is_valid_property_a20(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, +
[PATCH v5 2/8] mfd: Add commands abstraction layer for SI476X MFD
From: Andrey Smirnov This patch adds all the functions used for exchanging commands with the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1553 ++ 1 file changed, 1553 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..0ae1b63 --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1553 @@ +/* + * drivers/mfd/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD_AM_SEEK_START
[PATCH v5 0/8] Driver for Si476x series of chips
This is a fourth version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 Second version of the patch was posted here: https://lkml.org/lkml/2012/10/5/598 Third version of the patch was posted here: https://lkml.org/lkml/2012/10/23/510 Fourth version of the patch was posted here: https://lkml.org/lkml/2013/2/18/572 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. v5 of this driver has following changes: - Generic controls are converted to standard ones - Custom controls use a differend offest as base - Added documentation with controls description Andrey Smirnov (8): mfd: Add header files and Kbuild plumbing for SI476x MFD core mfd: Add commands abstraction layer for SI476X MFD mfd: Add the main bulk of core driver for SI476x code mfd: Add chip properties handling code for SI476X MFD v4l2: Add standard controls for FM receivers v4l2: Add documentation for the FM RX controls v4l2: Add private controls base for SI476X v4l2: Add a V4L2 driver for SI476X MFD Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 72 + .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml | 11 +- Documentation/video4linux/si476x.txt | 187 +++ drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1581 drivers/media/v4l2-core/v4l2-ctrls.c | 14 +- drivers/mfd/Kconfig| 13 + drivers/mfd/Makefile |4 + drivers/mfd/si476x-cmd.c | 1553 +++ drivers/mfd/si476x-i2c.c | 878 +++ drivers/mfd/si476x-prop.c | 234 +++ include/linux/mfd/si476x-core.h| 525 +++ include/media/si476x.h | 426 ++ include/uapi/linux/v4l2-controls.h | 17 +- 16 files changed, 5531 insertions(+), 5 deletions(-) create mode 100644 Documentation/video4linux/si476x.txt create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 drivers/mfd/si476x-cmd.c create mode 100644 drivers/mfd/si476x-i2c.c create mode 100644 drivers/mfd/si476x-prop.c create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 5/8] v4l2: Add standard controls for FM receivers
This commit introduces new class of standard controls V4L2_CTRL_CLASS_FM_RX. This class is intended to all controls pertaining to FM receiver chips. Also, two controls belonging to said class are added as a part of this commit: V4L2_CID_TUNE_DEEMPHASIS and V4L2_CID_RDS_RECEPTION. Signed-off-by: Andrey Smirnov --- drivers/media/v4l2-core/v4l2-ctrls.c | 14 +++--- include/uapi/linux/v4l2-controls.h | 13 - 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 6b28b58..8b89fb8 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -297,8 +297,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Text", NULL }; - static const char * const tune_preemphasis[] = { - "No Preemphasis", + static const char * const tune_emphasis[] = { + "None", "50 Microseconds", "75 Microseconds", NULL, @@ -508,7 +508,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_SCENE_MODE: return scene_mode; case V4L2_CID_TUNE_PREEMPHASIS: - return tune_preemphasis; + return tune_emphasis; + case V4L2_CID_TUNE_DEEMPHASIS: + return tune_emphasis; case V4L2_CID_FLASH_LED_MODE: return flash_led_mode; case V4L2_CID_FLASH_STROBE_SOURCE: @@ -799,6 +801,9 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; + case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; + case V4L2_CID_RDS_RECEPTION:return "RDS Reception"; default: return NULL; } @@ -846,6 +851,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: case V4L2_CID_WIDE_DYNAMIC_RANGE: case V4L2_CID_IMAGE_STABILIZATION: + case V4L2_CID_RDS_RECEPTION: *type = V4L2_CTRL_TYPE_BOOLEAN; *min = 0; *max = *step = 1; @@ -904,6 +910,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: case V4L2_CID_TEST_PATTERN: + case V4L2_CID_TUNE_DEEMPHASIS: *type = V4L2_CTRL_TYPE_MENU; break; case V4L2_CID_LINK_FREQ: @@ -926,6 +933,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_IMAGE_SOURCE_CLASS: case V4L2_CID_IMAGE_PROC_CLASS: case V4L2_CID_DV_CLASS: + case V4L2_CID_FM_RX_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read not write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index dcd6374..296d20e 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -59,6 +59,7 @@ #define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e /* Image source controls */ #define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f /* Image processing controls */ #define V4L2_CTRL_CLASS_DV 0x00a0 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a1 /* Digital Video controls */ /* User-class control IDs */ @@ -711,10 +712,14 @@ enum v4l2_auto_focus_range { #define V4L2_CID_PILOT_TONE_FREQUENCY (V4L2_CID_FM_TX_CLASS_BASE + 98) #define V4L2_CID_TUNE_PREEMPHASIS (V4L2_CID_FM_TX_CLASS_BASE + 112) -enum v4l2_preemphasis { +enum v4l2_xemphasis { V4L2_PREEMPHASIS_DISABLED = 0, V4L2_PREEMPHASIS_50_uS = 1, V4L2_PREEMPHASIS_75_uS = 2, + V4L2_DEEMPHASIS_DISABLED= V4L2_PREEMPHASIS_DISABLED, + V4L2_DEEMPHASIS_50_uS = V4L2_PREEMPHASIS_50_uS, + V4L2_DEEMPHASIS_75_uS = V4L2_PREEMPHASIS_75_uS, + }; #define V4L2_CID_TUNE_POWER_LEVEL (V4L2_CID_FM_TX_CLASS_BASE + 113) #define V4L2_CID_TUNE_ANTENNA_CAPACITOR (V4L2_CID_FM_TX_CLASS_BASE + 114) @@ -825,4 +830,10 @@ enum v4l2_dv_rgb_range { #defineV4L2_CID_DV_RX_POWER_PRESENT(V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) +#define V4
[PATCH v5 7/8] v4l2: Add private controls base for SI476X
Add a base to be used for allocation of all the SI476X specific controls in the corresponding driver. Signed-off-by: Andrey Smirnov --- include/uapi/linux/v4l2-controls.h |4 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 296d20e..133703d 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -147,6 +147,10 @@ enum v4l2_colorfx { * of controls. We reserve 16 controls for this driver. */ #define V4L2_CID_USER_MEYE_BASE(V4L2_CID_USER_BASE + 0x1000) +/* The base for the si476x driver controls. See include/media/si476x.h for the list + * of controls. */ +#define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x2000) + /* MPEG-class control IDs */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 6/8] v4l2: Add documentation for the FM RX controls
Add appropriate documentation for all the newly added standard controls. Signed-off-by: Andrey Smirnov --- Documentation/DocBook/media/v4l/compat.xml |3 + Documentation/DocBook/media/v4l/controls.xml | 72 .../DocBook/media/v4l/vidioc-g-ext-ctrls.xml | 11 ++- 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 104a1a2..f418bc3 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2310,6 +2310,9 @@ more information. Added FM Modulator (FM TX) Extended Control Class: V4L2_CTRL_CLASS_FM_TX and their Control IDs. + + Added FM Receiver (FM RX) Extended Control Class: V4L2_CTRL_CLASS_FM_RX and their Control IDs. + Added Remote Controller chapter, describing the default Remote Controller mapping for media devices. diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 9e8f854..e8fe005 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -4687,4 +4687,76 @@ interface and may change in the future. + + + FM Receiver Control Reference + + The FM Receiver (FM_RX) class includes controls for common features of + FM Reception capable devices. + + + FM_RX Control IDs + + + + + + + + + + +ID +Type + Description + + + + + +V4L2_CID_FM_RX_CLASS +class + The FM_RX class +descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a +description of this control class. + + +V4L2_CID_RDS_RECEPTION +boolean + Enables/disables RDS + reception by the radio tuner + + + V4L2_CID_TUNE_DEEMPHASIS + integer + + Configures the de-emphasis value for reception. +A de-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. +Depending on the region, a time constant of either 50 or 75 useconds is used. The enum v4l2_emphasis +defines possible values for de-emphasis. Here they are: + + + + + V4L2_PREEMPHASIS_DISABLED + No de-emphasis is applied. + + + V4L2_PREEMPHASIS_50_uS + A de-emphasis of 50 uS is used. + + + V4L2_PREEMPHASIS_75_uS + A de-emphasis of 75 uS is used. + + + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml index 4e16112..b03a57b 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml @@ -9,7 +9,7 @@ VIDIOC_TRY_EXT_CTRLS VIDIOC_G_EXT_CTRLS VIDIOC_S_EXT_CTRLS VIDIOC_TRY_EXT_CTRLS -Get or set the value of several controls, try control + Get or set the value of several controls, try control values @@ -319,6 +319,15 @@ These controls are described in . + + + V4L2_CTRL_CLASS_FM_RX + 0xa1 + The class containing FM Receiver (FM RX) controls. +These controls are described in . + + -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 3/8] mfd: Add the main bulk of core driver for SI476x code
From: Andrey Smirnov This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 878 ++ 1 file changed, 878 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..053a6a3 --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,878 @@ +/* + * drivers/mfd/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SI476X_MAX_IO_ERRORS 10 +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_core_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(SI476X_STATUS_POLL_US)); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tuner + * + * Perform required startup sequence to correctly power + * up the chip and perform initial configuration. It does the + * following sequence of actions: + * 1. Claims an
[PATCH v4 3/7] mfd: Add the main bulk of core driver for SI476x code
From: Andrey Smirnov This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 878 ++ 1 file changed, 878 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..053a6a3 --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,878 @@ +/* + * drivers/mfd/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SI476X_MAX_IO_ERRORS 10 +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_core_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(SI476X_STATUS_POLL_US)); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tuner + * + * Perform required startup sequence to correctly power + * up the chip and perform initial configuration. It does the + * following sequence of actions: + * 1. Claims an
[PATCH v4 2/7] mfd: Add commands abstraction layer for SI476X MFD
From: Andrey Smirnov This patch adds all the functions used for exchanging commands with the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1553 ++ 1 file changed, 1553 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..0ae1b63 --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1553 @@ +/* + * drivers/mfd/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD_AM_SEEK_START
[PATCH v4 4/7] mfd: Add chip properties handling code for SI476X MFD
From: Andrey Smirnov This patch adds code related to manipulation of the properties of SI476X chips. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 234 + 1 file changed, 234 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..d2b5cc0 --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,234 @@ +/* + * drivers/mfd/si476x-prop.c -- Subroutines to manipulate with + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include + +struct si476x_property_range { + u16 low, high; +}; + +static bool si476x_core_element_is_in_array(u16 element, const u16 array[], size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool si476x_core_element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x0718, + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a20(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071B, + 0x1006, + 0x2210, + 0x3401, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x2215, 0x2219 }, + }; + + return si476x_core_is_valid_property_a10(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a30(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071C, 0x071D, + 0x1007, 0x1008, + 0x220F, 0x2214, + 0x2301, + 0x3105, 0x3106, + 0x3402, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0405, 0x0411 }, + { 0x2008, 0x200B }, + { 0x2220, 0x2223 }, + { 0x3100, 0x3106 }, + }; + + return si476x_core_is_valid_property_a20(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, +
[PATCH v4 0/7] Driver for Si476x series of chips
This is a fourth version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 Second version of the patch was posted here: https://lkml.org/lkml/2012/10/5/598 Third version of the patch was posted here: https://lkml.org/lkml/2012/10/23/510 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. v4 of this driver has following changes: - All of the adjustable timeouts(expose via sysfs) are gone - Names of the controls are changes as was requested - Added documentation for exposed debugfs files - Minor fix in si476x_radio_fops_poll - DBG_BUFFER is removed - Tested for compilation w/o debugfs enabled This version still has all the radio controls being private. The reason for that is because I am not sure how that should be handled. Hans, do you want me to move all the controls to be standard, that is exted V4L's with the needed controls? Should I pick up the parts of http://lists-archives.com/linux-kernel/27641304-radio-fixes-and-new-features-for-fm.html and take relevants bits and pieces of it? How do you want that to be handled? Here is v4l2-compliance output for one of the tuners: sudo v4l2-compliance -r /dev/radio0 is radio Driver Info: Driver name : si476x-radio0 Card type : SI476x AM/FM Receiver Bus info : platform:si476x-radio0 Driver version: 3.1.0 Capabilities : 0x81050500 RDS Capture Tuner Radio Read/Write Device Capabilities Device Caps : 0x01050500 RDS Capture Tuner Radio Read/Write Compliance test for device /dev/radio0 (not using libv4l2): Required ioctls: test VIDIOC_QUERYCAP: OK Allow for multiple opens: test second radio open: OK test VIDIOC_QUERYCAP: OK test VIDIOC_G/S_PRIORITY: OK Debug ioctls: test VIDIOC_DBG_G_CHIP_IDENT: OK test VIDIOC_DBG_G/S_REGISTER: OK test VIDIOC_LOG_STATUS: OK (Not Supported) Input ioctls: test VIDIOC_G/S_TUNER: OK test VIDIOC_G/S_FREQUENCY: OK test VIDIOC_S_HW_FREQ_SEEK: OK 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 Control ioctls: test VIDIOC_QUERYCTRL/MENU: 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: 2 Private Controls: 8 Input/Output configuration ioctls: test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported) test VIDIOC_ENUM/G/S/QUERY_DV_PRESETS: OK (Not Supported) test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported) test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported) Format ioctls: test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported) test VIDIOC_G/S_PARM: OK (Not Supported) test VIDIOC_G_FBUF: OK (Not Supported) test VIDIOC_G_FMT: OK (Not Supported) test VIDIOC_TRY_FMT: OK (Not Supported) test VIDIOC_S_FMT: OK (Not Supported) test VIDIOC_G_SLICED_VBI_CAP: 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 (Not Supported) Total: 38, Succeeded: 38, Failed: 0, Warnings: 0 Andrey Smirnov (7): mfd: Add header files and Kbuild plumbing for SI476x MFD core mfd: Add commands abstraction layer for SI476X MFD mfd: Add the main bulk of core driver for SI476x code mfd: Add chip properties handling code for SI476X MFD v4l2: Add a V4L2 driver for SI476X MFD sound/soc/codecs: Convert SI476X codec to use regmap sound/soc/codecs: Cosmetic changes to SI476X codec driver Documentation/video4linux/si476x.txt | 187 drivers/media/radio/Kconfig | 17 + drivers/media/radio/Makefile |1 + driv
[PATCH v4 7/7] sound/soc/codecs: Cosmetic changes to SI476X codec driver
- Add appropriate license header - Change email address in MODULE_AUTHOR - Remove trailing whitespaces Signed-off-by: Andrey Smirnov --- sound/soc/codecs/si476x.c | 25 ++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 30aebbe..68b648a 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -1,3 +1,22 @@ +/* + * sound/soc/codecs/si476x.c -- Codec driver for SI476X chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * Copyright (C) 2013 Andrey Smirnov + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 #include #include @@ -156,7 +175,7 @@ static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, dev_err(codec_dai->codec->dev, "Failed to set output format\n"); return err; } - + return 0; } @@ -197,7 +216,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream, err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK, - (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | + (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)); if (err < 0) { dev_err(dai->codec->dev, "Failed to set output width\n"); @@ -266,6 +285,6 @@ static struct platform_driver si476x_platform_driver = { }; module_platform_driver(si476x_platform_driver); -MODULE_AUTHOR("Andrey Smirnov "); +MODULE_AUTHOR("Andrey Smirnov "); MODULE_DESCRIPTION("ASoC Si4761/64 codec driver"); MODULE_LICENSE("GPL"); -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 1/7] mfd: Add header files and Kbuild plumbing for SI476x MFD core
From: Andrey Smirnov This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 13 + drivers/mfd/Makefile|4 + include/linux/mfd/si476x-core.h | 525 +++ 3 files changed, 542 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4..3214927 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -970,6 +970,19 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + default n + help + This is the core driver for the SI476x series of AM/FM + radio. This MFD driver connects the radio-si476x V4L2 module + and the si476x audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core and TLL driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8..bf7627b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -131,6 +131,10 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855)+= vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o + +si476x-core-objs := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o + obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST)+= omap-usb-host.o omap-usb-tll.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..2136b26 --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,525 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Command Timeouts */ +#define SI476X_DEFAULT_TIMEOUT 10 +#define SI476X_TIMEOUT_TUNE70 +#define SI476X_TIMEOUT_POWER_UP33 +#define SI476X_STATUS_POLL_US 0 + +/* si476x-i2c.c --- */ + +enum si476x_freq_supported_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsistent, meaning some of the regulators were + * not turned down and thus use of the device, without power-cycling + * is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP_FULL= 1, + SI476X_POWER_INCONSISTENT = 2, +}; + +/** + * struct si476x_core - internal data structure representing the + * underlying "core" device which all the MFD cell-devices use. + * + * @client: Actual I2C client used to transfer commands to the chip. + * @chip_id: Last digit of the chip model(E.g. "1" for SI4761) + * @cells: MFD cell devices created by this driver. + * @cmd_lock: Mutex used to serialize
[PATCH v4 6/7] sound/soc/codecs: Convert SI476X codec to use regmap
From: Andrey Smirnov The latest radio and MFD drivers for SI476X radio chips use regmap API to provide access to the registers and allow for caching of their values when the actual chip is powered off. Convert the codec driver to do the same, so it would not loose the settings when the radio driver powers the chip down. Signed-off-by: Andrey Smirnov --- sound/soc/codecs/si476x.c | 22 +++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index f2d61a1..30aebbe 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -45,13 +45,23 @@ static unsigned int si476x_codec_read(struct snd_soc_codec *codec, unsigned int reg) { int err; + unsigned int val; struct si476x_core *core = codec->control_data; si476x_core_lock(core); - err = si476x_core_cmd_get_property(core, reg); + if (!si476x_core_is_powered_up(core)) + regcache_cache_only(core->regmap, true); + + err = regmap_read(core->regmap, reg, &val); + + if (!si476x_core_is_powered_up(core)) + regcache_cache_only(core->regmap, false); si476x_core_unlock(core); - return err; + if (err < 0) + return err; + + return val; } static int si476x_codec_write(struct snd_soc_codec *codec, @@ -61,7 +71,13 @@ static int si476x_codec_write(struct snd_soc_codec *codec, struct si476x_core *core = codec->control_data; si476x_core_lock(core); - err = si476x_core_cmd_set_property(core, reg, val); + if (!si476x_core_is_powered_up(core)) + regcache_cache_only(core->regmap, true); + + err = regmap_write(core->regmap, reg, val); + + if (!si476x_core_is_powered_up(core)) + regcache_cache_only(core->regmap, false); si476x_core_unlock(core); return err; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 1/6] Add header files and Kbuild plumbing for SI476x MFD core
On 12-12-18 11:37 AM, Mauro Carvalho Chehab wrote: Em Mon, 8 Oct 2012 11:38:01 -0700 Andrey Smirnov escreveu: On 10/08/2012 01:43 AM, Hans Verkuil wrote: On Sat October 6 2012 03:54:57 Andrey Smirnov wrote: This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 14 ++ drivers/mfd/Makefile|3 + include/linux/mfd/si476x-core.h | 529 +++ include/media/si476x.h | 449 + 4 files changed, 995 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b1a1462..3fab06d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -895,6 +895,20 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + default n + help + This is the core driver for the SI476x series of AM/FM radio. This MFD + driver connects the radio-si476x V4L2 module and the si476x + audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 79dd22d..942257b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -132,3 +132,6 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o obj-$(CONFIG_MFD_SEC_CORE)+= sec-core.o sec-irq.o obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o + +si476x-core-objs := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..eb6f52a --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,529 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef DEBUG +#define DBG_BUFFER(device, header, buffer, bcount) \ + do {\ + dev_info((device), header); \ + print_hex_dump_bytes("", \ +DUMP_PREFIX_OFFSET,\ +buffer, bcount); \ + } while (0) +#else +#define DBG_BUFFER(device, header, buffer, bcount) \ + do {} while (0) +#endif + +enum si476x_freq_suppoted_chips { typo: suppoted -> supported + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4762, + SI476X_CHIP_SI4763, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, + SI476X_CHIP_SI4769, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsisten meaning some of he regulators wer not + * turned down and thus the cons
Re: [PATCH v3 5/6] Add a V4L2 driver for SI476X MFD
On 11/16/2012 07:02 AM, Hans Verkuil wrote: > Hi Andrey, > > Some more comments... > > On Tue October 23 2012 20:44:31 Andrey Smirnov wrote: >> This commit adds a driver that exposes all the radio related >> functionality of the Si476x series of chips via the V4L2 subsystem. >> >> Signed-off-by: Andrey Smirnov >> --- >> drivers/media/radio/Kconfig| 17 + >> drivers/media/radio/Makefile |1 + >> drivers/media/radio/radio-si476x.c | 1549 >> >> 3 files changed, 1567 insertions(+) >> create mode 100644 drivers/media/radio/radio-si476x.c >> > > >> diff --git a/drivers/media/radio/radio-si476x.c >> b/drivers/media/radio/radio-si476x.c >> new file mode 100644 >> index 000..c8fa90f >> --- /dev/null >> +++ b/drivers/media/radio/radio-si476x.c >> @@ -0,0 +1,1549 @@ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> + >> +#include >> + >> +#define FM_FREQ_RANGE_LOW 6400 >> +#define FM_FREQ_RANGE_HIGH 10800 >> + >> +#define AM_FREQ_RANGE_LOW52 >> +#define AM_FREQ_RANGE_HIGH 3000 >> + >> +#define PWRLINEFLTR (1 << 8) >> + >> +#define FREQ_MUL (1000 / 625) >> + >> +#define SI476X_PHDIV_STATUS_LINK_LOCKED(status) (0b1000 & (status)) >> + >> +#define DRIVER_NAME "si476x-radio" >> +#define DRIVER_CARD "SI476x AM/FM Receiver" >> + >> +enum si476x_freq_bands { >> +SI476X_BAND_FM, >> +SI476X_BAND_AM, >> +}; >> + >> +static const struct v4l2_frequency_band si476x_bands[] = { >> +[SI476X_BAND_FM] = { >> +.type = V4L2_TUNER_RADIO, >> +.index = SI476X_BAND_FM, >> +.capability = V4L2_TUNER_CAP_LOW >> +| V4L2_TUNER_CAP_STEREO >> +| V4L2_TUNER_CAP_RDS >> +| V4L2_TUNER_CAP_RDS_BLOCK_IO >> +| V4L2_TUNER_CAP_FREQ_BANDS, >> +.rangelow = 64 * FREQ_MUL, >> +.rangehigh = 108 * FREQ_MUL, >> +.modulation = V4L2_BAND_MODULATION_FM, >> +}, >> +[SI476X_BAND_AM] = { >> +.type = V4L2_TUNER_RADIO, >> +.index = SI476X_BAND_AM, >> +.capability = V4L2_TUNER_CAP_LOW | >> V4L2_TUNER_CAP_FREQ_BANDS, >> +.rangelow = 0.52 * FREQ_MUL, >> +.rangehigh = 30 * FREQ_MUL, >> +.modulation = V4L2_BAND_MODULATION_AM, >> +}, >> +}; >> + >> +static inline bool si476x_radio_freq_is_inside_of_the_band(u32 freq, int >> band) >> +{ >> +return freq >= si476x_bands[band].rangelow && >> +freq <= si476x_bands[band].rangehigh; >> +} >> + >> +static inline bool si476x_radio_range_is_inside_of_the_band(u32 low, u32 >> high, int band) >> +{ >> +return low >= si476x_bands[band].rangelow && >> +high <= si476x_bands[band].rangehigh; >> +} >> + >> +#define PRIVATE_CTL_IDX(x) (x - V4L2_CID_PRIVATE_BASE) > No. The new control IDs need to be added to include/uapi/linux/v4l2-controls.h > with unique IDs. V4L2_CID_PRIVATE_BASE must not be used anymore for new > controls. > > Since Halli Manjunatha hasn't worked on a new version of his patch with the > new > fm controls it might be something you want to take on (I'm referring to the > FM RX > control class). Should I move all controls there, even chip specific ones, like SI476X_CID_HARMONICS_COUNT or SI476X_CID_DIVERSITY_MODE? -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/6] Add the main bulk of core driver for SI476x code
On 10/27/2012 02:31 PM, Mark Brown wrote: > On Thu, Oct 25, 2012 at 03:26:02PM -0700, Andrey Smirnov wrote: >> On 10/25/2012 12:45 PM, Mark Brown wrote: >>> This really makes little sense to me, why are you doing this? Does the >>> device *really* layer a byte stream on top of I2C for sending messages >>> that look like marshalled register reads and writes? >> The SI476x chips has a concept of a "property". Each property having >> 16-bit address and 16-bit value. At least a portion of a chip >> configuration is done by modifying those properties. In order to > Right, that's what I remembered from previous code. There's no way this > should be a regmap bus - a bus is something that gets data serialised by > the core into a byte stream, having the data rendered down into a byte > stream and then reparsing it is a bit silly. The device should be > hooking in before the data gets marshalled which we can't currently do > but it shouldn't be too hard to make it so that we can have register > read and write functions supplied in the regmap config. Oh, now I think I see what you mean. I have two agree with you, I don't think I like what I am doing in my code. I'll try to familiarize myself with 'regmap' code and come up with the way to extend the framework. And I just wanted to upstream my simple radio driver... :-) -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/6] Add the main bulk of core driver for SI476x code
On 10/25/2012 12:45 PM, Mark Brown wrote: > On Tue, Oct 23, 2012 at 11:44:28AM -0700, Andrey Smirnov wrote: > >> +core->regmap = devm_regmap_init_si476x(core); >> +if (IS_ERR(core->regmap)) { > This really makes little sense to me, why are you doing this? Does the > device *really* layer a byte stream on top of I2C for sending messages > that look like marshalled register reads and writes? The SI476x chips has a concept of a "property". Each property having 16-bit address and 16-bit value. At least a portion of a chip configuration is done by modifying those properties. In order to manipulate those properties user is expected to issue what is called a "command". For manipulating "properties" there are two "commands": - SET_PROPERTY which is I2C write of 6 bytes of the following layout: | 0x13 | 0x00 | Address High Byte | Address Low Byte | Property Data High Byte | Property Data Low Byte | After the command is finished being executed the 1 byte read would contain the status byte followed by 1 byte read which contain status byte - GET_PROPERTY which is I2C write of 4 bytes of the following layout: | 0x13 | 0x00 | Address High Byte | Address Low Byte | After the command is finished being executed the 4 byte read would have the following layout: | Status Byte | Reserved Byte | Property Value High Byte | Property Value Low Byte | The chip does not operate continuously in the AM/FM frequency range, instead the user is expected to power-down/power-up the chip in a certain "mode" which in my case can be either AM or FM tuner. There are two ways of doing that one is to send a power down command to the device, the second one is to toggle reset line of the chip. Both methods will reset the values of the aforementioned "properties". Because V4L2 user-space interface presents a tuner as the one continuously operating in the whole AM/FM range it is necessary for me to do those AM/FM switches transparently when handling tuning or seeking requests from the user. That means that I need to cache the values of the properties I care about in the driver and restore them when user switches to the mode(for example when AM->FM->AM transition happens) The other quirk of that chip is that some properties are only accessible in certain modes(for example it is impossible to configure RDS interrupt sources, which is FM specific, in AM mode), but some of the controls I expose to user-land change the values of the properties and since AM/FM switches happen transparently to the user in the situation when FM specific property is changed while tuner is in AM mode, the driver has to cache the value and write it when the switch to FM would take place. Also due to the way the driver uses the chip it is only powered up when the corresponding file in devfs(e.g. /dev/radio0) is opened at least by one user which means that unless there is a user who opened the file all the SET/GET_PROPERTY commands sent to it will be lost. The codec driver for that chip does not have any say in the power management policy(while all the audio configuration is done via "properties") if the chip is not powered up the driver has to cache the configuration values it has so that they can be applied later. So, since I have to implement a caching functionality in the driver, in order to avoid reinventing the wheel I opted for using 'regmap' API for this. Of course, It is possible that I misunderstood the purpose and capabilities of the 'regmap' framework, which would make my code look very silly indeed. If that is the case I'll just re-implement it using some sort of ad-hoc version of caching. -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 6/6] Add a codec driver for SI476X MFD
On 10/23/2012 12:24 PM, Mark Brown wrote: > On Tue, Oct 23, 2012 at 11:44:32AM -0700, Andrey Smirnov wrote: >> This commit add a sound codec driver for Silicon Laboratories 476x >> series of AM/FM radio chips. > I already merged a driver for this. If there are any changes you should > send incremental updates rather than a full new driver. OK, will do. -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/6] Add chip properties handling code for SI476X MFD
This patch adds code related to manipulation of the properties of SI476X chips. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 257 + 1 file changed, 257 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..3811eec --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,257 @@ +/* + * include/media/si476x-prop.c -- Subroutines to manipulate with + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include + +struct si476x_property_range { + u16 low, high; +}; + + + +static bool si476x_core_element_is_in_array(u16 element, const u16 array[], size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool si476x_core_element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x0718, + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a20(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071B, + 0x1006, + 0x2210, + 0x3401, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x2215, 0x2219 }, + }; + + return si476x_core_is_valid_property_a10(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core_element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_is_valid_property_a30(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x071C, 0x071D, + 0x1007, 0x1008, + 0x220F, 0x2214, + 0x2301, + 0x3105, 0x3106, + 0x3402, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0405, 0x0411 }, + { 0x2008, 0x200B }, + { 0x2220, 0x2223 }, + { 0x3100, 0x3106 }, + }; + + return si476x_core_is_valid_property_a20(core, property) || + si476x_core_element_is_in_range(property, valid_ranges, + ARRAY_SIZE(valid_ranges)) || + si476x_core
[PATCH v3 2/6] Add the main bulk of core driver for SI476x code
This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 966 ++ 1 file changed, 966 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..6d581bd --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,966 @@ +/* + * include/media/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Command Timeouts */ +#define DEFAULT_TIMEOUT10 +#define TIMEOUT_TUNE 70 +#define TIMEOUT_POWER_UP 33 + +#define MAX_IO_ERRORS 10 + +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +#define SI476X_STATUS_POLL_US 0 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_core_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(atomic_read(&core->polling_interval))); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tun
[PATCH v3 3/6] Add commands abstraction layer for SI476X MFD
This patch adds all the functions used for exchanging commands with the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1546 ++ 1 file changed, 1546 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..e2989bc --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1546 @@ +/* + * include/media/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD_AM_SEEK_START 0x41 +#define CMD_AM_SEEK_START_NARGS
[PATCH v3 1/6] Add header files and Kbuild plumbing for SI476x MFD core
This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 14 + drivers/mfd/Makefile|3 + include/linux/mfd/si476x-core.h | 539 +++ include/media/si476x.h | 427 +++ 4 files changed, 983 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b1a1462..3fab06d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -895,6 +895,20 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + default n + help + This is the core driver for the SI476x series of AM/FM radio. This MFD + driver connects the radio-si476x V4L2 module and the si476x + audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 79dd22d..942257b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -132,3 +132,6 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o + +si476x-core-objs := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..08bc5dd --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,539 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef DEBUG +#define DBG_BUFFER(device, header, buffer, bcount) \ + do {\ + dev_info((device), header); \ + print_hex_dump_bytes("",\ +DUMP_PREFIX_OFFSET,\ +buffer, bcount); \ + } while (0) +#else +#define DBG_BUFFER(device, header, buffer, bcount) \ + do {} while (0) +#endif + +/* si476x-i2c.c --- */ + +enum si476x_freq_supported_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsistent, meaning some of the regulators were + * not turned down and thus use of the device, without power-cycling + * is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP_FULL= 1, + SI476X_POWER_INCONSISTENT = 2, +}; + +/** + * struct si476x_
[PATCH v3 6/6] Add a codec driver for SI476X MFD
This commit add a sound codec driver for Silicon Laboratories 476x series of AM/FM radio chips. Signed-off-by: Andrey Smirnov --- sound/soc/codecs/Kconfig |4 + sound/soc/codecs/Makefile |2 + sound/soc/codecs/si476x.c | 259 + 3 files changed, 265 insertions(+) create mode 100644 sound/soc/codecs/si476x.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e859..37b2911 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM3008 select SND_SOC_RT5631 if I2C select SND_SOC_SGTL5000 if I2C + select SND_SOC_SI476X if MFD_SI476X_CORE select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI @@ -272,6 +273,9 @@ config SND_SOC_RT5631 config SND_SOC_SGTL5000 tristate +config SND_SOC_SI476X + tristate + config SND_SOC_SIGMADSP tristate select CRC32 diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb..d9ed4e4 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -44,6 +44,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o snd-soc-sigmadsp-objs := sigmadsp.o +snd-soc-si476x-objs := si476x.o snd-soc-sn95031-objs := sn95031.o snd-soc-spdif-tx-objs := spdif_transciever.o snd-soc-spdif-rx-objs := spdif_receiver.o @@ -161,6 +162,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o +obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o obj-$(CONFIG_SND_SOC_SPDIF)+= snd-soc-spdif-rx.o snd-soc-spdif-tx.o obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c new file mode 100644 index 000..1f34913 --- /dev/null +++ b/sound/soc/codecs/si476x.c @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include + +enum si476x_audio_registers { + SI476X_DIGITAL_IO_OUTPUT_FORMAT = 0x0203, + SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE= 0x0202, +}; + +enum si476x_digital_io_output_format { + SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT = 11, + SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT = 8, +}; + +#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \ + (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)) +#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b110) + +enum si476x_daudio_formats { + SI476X_DAUDIO_MODE_I2S = (0x0 << 1), + SI476X_DAUDIO_MODE_DSP_A= (0x6 << 1), + SI476X_DAUDIO_MODE_DSP_B= (0x7 << 1), + SI476X_DAUDIO_MODE_LEFT_J = (0x8 << 1), + SI476X_DAUDIO_MODE_RIGHT_J = (0x9 << 1), + + SI476X_DAUDIO_MODE_IB = (1 << 5), + SI476X_DAUDIO_MODE_IF = (1 << 6), +}; + +enum si476x_pcm_format { + SI476X_PCM_FORMAT_S8= 2, + SI476X_PCM_FORMAT_S16_LE= 4, + SI476X_PCM_FORMAT_S20_3LE = 5, + SI476X_PCM_FORMAT_S24_LE= 6, +}; + +static unsigned int si476x_codec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + int err; + unsigned int val; + struct si476x_core *core = codec->control_data; + + si476x_core_lock(core); + err = regmap_read(core->regmap, reg, &val); + si476x_core_unlock(core); + + if (err < 0) + return err; + + return val; +} + +static int si476x_codec_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int val) +{ + int err; + struct si476x_core *core = codec->control_data; + + si476x_core_lock(core); + err = regmap_write(core->regmap, reg, val); + si476x_core_unlock(core); + + return err; +} + +static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + int err; + u16 format = 0; + + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) + return -EINVAL; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + format |= SI476X_DAUDIO_MODE_DSP_A; + break; + case SND_SOC_DAIFMT_DSP_B: + format |= SI476X_DAUDIO_MODE_DSP_B; + break; + case SND_SOC_DAIFMT_I2S: + format |= SI476X_DAUDIO_MODE_I2S; + break; + case SND_SOC_DAIFMT_RIG
[PATCH v3 0/6] Driver for Si476x series of chips
This is a third version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 Second version of the patch was posted here: https://lkml.org/lkml/2012/10/5/598 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. v3 of this driver has following changes: - All custom ioctls were moved to be V4L2 controls or debugfs files - Chip properties handling was moved to regmap API, so this should allow for cleaner code, and hopefully more consistent behaviour of the driver during switch between AM/FM(wich involevs power-cycling of the chip) I was hoping to not touch the code of the codec driver, since Mark has already appplied the previous version, but because of the last item I had to. Unfotunately, since my ARM setup runs only 3.1 kernel, I was only able to test this driver on a standalone USB-connected board that has a dedicated Cortex M3 working as a transparent USB to I2C bridge which was connected to a off-the-shelf x86-64 laptop running Ubuntu with custom kernel compile form git.linuxtv.org/media_tree.git. Which means that I was unable to test the change in the codec code, except for the fact the it compiles. Here is v4l2-compliance output for one of the tuners(as per Hans' request): sudo v4l2-compliance -r /dev/radio0 is radio Driver Info: Driver name : si476x-radio0 Card type : SI476x AM/FM Receiver Bus info : platform:si476x-radio0 Driver version: 3.6.0 Capabilities : 0x81050500 RDS Capture Tuner Radio Read/Write Device Capabilities Device Caps : 0x01050500 RDS Capture Tuner Radio Read/Write Compliance test for device /dev/radio0 (not using libv4l2): Required ioctls: test VIDIOC_QUERYCAP: OK Allow for multiple opens: test second radio open: OK test VIDIOC_QUERYCAP: OK test VIDIOC_G/S_PRIORITY: OK Debug ioctls: test VIDIOC_DBG_G_CHIP_IDENT: OK test VIDIOC_DBG_G/S_REGISTER: OK test VIDIOC_LOG_STATUS: OK (Not Supported) Input ioctls: test VIDIOC_G/S_TUNER: OK test VIDIOC_G/S_FREQUENCY: OK test VIDIOC_S_HW_FREQ_SEEK: OK 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 Control ioctls: test VIDIOC_QUERYCTRL/MENU: 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: 2 Private Controls: 8 Input/Output configuration ioctls: test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported) test VIDIOC_ENUM/G/S/QUERY_DV_PRESETS: OK (Not Supported) test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported) test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported) Format ioctls: test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported) test VIDIOC_G/S_PARM: OK (Not Supported) test VIDIOC_G_FBUF: OK (Not Supported) test VIDIOC_G_FMT: OK (Not Supported) test VIDIOC_TRY_FMT: OK (Not Supported) test VIDIOC_S_FMT: OK (Not Supported) test VIDIOC_G_SLICED_VBI_CAP: 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 (Not Supported) Total: 38, Succeeded: 38, Failed: 0, Warnings: 0 Andrey Smirnov (6): Add header files and Kbuild plumbing for SI476x MFD core Add the main bulk of core driver for SI476x code Add commands abstraction layer for SI476X MFD Add chip properties handling code for SI476X MFD Add a V4L2 driver for SI476X MFD Add a codec driver for SI476X MFD drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-
[PATCH v3 5/6] Add a V4L2 driver for SI476X MFD
This commit adds a driver that exposes all the radio related functionality of the Si476x series of chips via the V4L2 subsystem. Signed-off-by: Andrey Smirnov --- drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1549 3 files changed, 1567 insertions(+) create mode 100644 drivers/media/radio/radio-si476x.c diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 8090b87..3c79d09 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -16,6 +16,23 @@ config RADIO_SI470X bool "Silicon Labs Si470x FM Radio Receiver support" depends on VIDEO_V4L2 +config RADIO_SI476X + tristate "Silicon Laboratories Si476x I2C FM Radio" + depends on I2C && VIDEO_V4L2 + select MFD_CORE + select MFD_SI476X_CORE + select SND_SOC_SI476X + ---help--- + Choose Y here if you have this FM radio chip. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux 2 API. Information on + this API and pointers to "v4l2" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called radio-si476x. + source "drivers/media/radio/si470x/Kconfig" config USB_MR800 diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index c03ce4f..c4618e0 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o +obj-$(CONFIG_RADIO_SI476X) += radio-si476x.o obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_RADIO_SI470X) += si470x/ diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c new file mode 100644 index 000..c8fa90f --- /dev/null +++ b/drivers/media/radio/radio-si476x.c @@ -0,0 +1,1549 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#define FM_FREQ_RANGE_LOW 6400 +#define FM_FREQ_RANGE_HIGH 10800 + +#define AM_FREQ_RANGE_LOW52 +#define AM_FREQ_RANGE_HIGH 3000 + +#define PWRLINEFLTR (1 << 8) + +#define FREQ_MUL (1000 / 625) + +#define SI476X_PHDIV_STATUS_LINK_LOCKED(status) (0b1000 & (status)) + +#define DRIVER_NAME "si476x-radio" +#define DRIVER_CARD "SI476x AM/FM Receiver" + +enum si476x_freq_bands { + SI476X_BAND_FM, + SI476X_BAND_AM, +}; + +static const struct v4l2_frequency_band si476x_bands[] = { + [SI476X_BAND_FM] = { + .type = V4L2_TUNER_RADIO, + .index = SI476X_BAND_FM, + .capability = V4L2_TUNER_CAP_LOW + | V4L2_TUNER_CAP_STEREO + | V4L2_TUNER_CAP_RDS + | V4L2_TUNER_CAP_RDS_BLOCK_IO + | V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 64 * FREQ_MUL, + .rangehigh = 108 * FREQ_MUL, + .modulation = V4L2_BAND_MODULATION_FM, + }, + [SI476X_BAND_AM] = { + .type = V4L2_TUNER_RADIO, + .index = SI476X_BAND_AM, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 0.52 * FREQ_MUL, + .rangehigh = 30 * FREQ_MUL, + .modulation = V4L2_BAND_MODULATION_AM, + }, +}; + +static inline bool si476x_radio_freq_is_inside_of_the_band(u32 freq, int band) +{ + return freq >= si476x_bands[band].rangelow && + freq <= si476x_bands[band].rangehigh; +} + +static inline bool si476x_radio_range_is_inside_of_the_band(u32 low, u32 high, int band) +{ + return low >= si476x_bands[band].rangelow && + high <= si476x_bands[band].rangehigh; +} + +#define PRIVATE_CTL_IDX(x) (x - V4L2_CID_PRIVATE_BASE) + +static int si476x_radio_s_ctrl(struct v4l2_ctrl *ctrl); +static int si476x_radio_g_volatile_ctrl(struct v4l2_ctrl *ctrl); + +static const char * const deemphasis[] = { + "75 us", + "50 us", +}; + +enum phase_diversity_modes_idx { + SI476X_IDX_PHDIV_DISABLED, + SI476X_IDX_PHDIV_PRIMARY_COMBINING, + SI476X_IDX_PHDIV_PRIMARY_ANTENNA, + SI476X_IDX_PHDIV_SECONDARY_ANTENNA, + SI476X_IDX_PHDIV_SECONDARY_COMBINING, +}; + +static const char * const phase_diversity_modes[] = { + [SI476X_IDX_PHDIV_DISABLED] = "disabled", + [SI476X_IDX_PHDIV_PRIMARY_COMBINING]= "pr
Re: [PATCH v2 2/6] Add the main bulk of core driver for SI476x code
On 10/08/2012 11:33 PM, Mark Brown wrote: > On Fri, Oct 05, 2012 at 06:54:58PM -0700, Andrey Smirnov wrote: > >> +err = regulator_enable(core->supplies.va); >> +if (err < 0) >> +break; >> + >> +err = regulator_enable(core->supplies.vio2); >> +if (err < 0) >> +goto disable_va; >> + >> +err = regulator_enable(core->supplies.vd); >> +if (err < 0) >> +goto disable_vio2; >> + >> +err = regulator_enable(core->supplies.vio1); >> +if (err < 0) >> +goto disable_vd; > If the sequencing is critical here you should have comments explaining > what the requirement is, otherwise this looks like a prime candidate > for conversion to regulator_bulk_enable() (and similarly for all the > other regulator usage, it appears that all the regulators are worked > with in a bulk fashion). > Unfortunately the datasheet is not very clear on the subject. My suspicion at the time of writing was that since there are multiple power domains that it was possible to power up only the ones required for specific subsystem in use. Unfortunately I didn't and still don't have the hardware to test it on(on the board I use there are no dedicated regulators and the chips are always powered on). I'll convert it to the code that uses regulators in bulk fashion. Andrey Smirnov -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 3/6] Add commands abstraction layer for SI476X MFD
On 10/08/2012 01:56 AM, Hans Verkuil wrote: > On Sat October 6 2012 03:54:59 Andrey Smirnov wrote: >> This patch adds all the functions used for exchanging commands with >> the chip. >> >> Signed-off-by: Andrey Smirnov >> --- >> drivers/mfd/si476x-cmd.c | 1493 >> ++ >> 1 file changed, 1493 insertions(+) >> create mode 100644 drivers/mfd/si476x-cmd.c >> >> diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c >> new file mode 100644 >> index 000..f11cf58 >> --- /dev/null >> +++ b/drivers/mfd/si476x-cmd.c >> @@ -0,0 +1,1493 @@ >> +/* >> + * include/media/si476x-cmd.c -- Subroutines implementing command >> + * protocol of si476x series of chips >> + * >> + * Copyright (C) 2012 Innovative Converged Devices(ICD) >> + * >> + * Author: Andrey Smirnov >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; version 2 of the License. >> + * >> + * 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 >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include >> +#include >> + >> +#define msb(x) ((u8)((u16) x >> 8)) >> +#define lsb(x) ((u8)((u16) x & 0x00FF)) >> + >> + >> + >> +#define CMD_POWER_UP0x01 >> +#define CMD_POWER_UP_A10_NRESP 1 >> +#define CMD_POWER_UP_A10_NARGS 5 >> + >> +#define CMD_POWER_UP_A20_NRESP 1 >> +#define CMD_POWER_UP_A20_NARGS 5 >> + >> +#define POWER_UP_DELAY_MS 110 >> + >> +#define CMD_POWER_DOWN 0x11 >> +#define CMD_POWER_DOWN_A10_NRESP1 >> + >> +#define CMD_POWER_DOWN_A20_NRESP1 >> +#define CMD_POWER_DOWN_A20_NARGS1 >> + >> +#define CMD_FUNC_INFO 0x12 >> +#define CMD_FUNC_INFO_NRESP 7 >> + >> +#define CMD_SET_PROPERTY0x13 >> +#define CMD_SET_PROPERTY_NARGS 5 >> +#define CMD_SET_PROPERTY_NRESP 1 >> + >> +#define CMD_GET_PROPERTY0x14 >> +#define CMD_GET_PROPERTY_NARGS 3 >> +#define CMD_GET_PROPERTY_NRESP 4 >> + >> +#define CMD_AGC_STATUS 0x17 >> +#define CMD_AGC_STATUS_NRESP_A102 >> +#define CMD_AGC_STATUS_NRESP_A206 >> + >> +#define PIN_CFG_BYTE(x) (0x7F & (x)) >> +#define CMD_DIG_AUDIO_PIN_CFG 0x18 >> +#define CMD_DIG_AUDIO_PIN_CFG_NARGS 4 >> +#define CMD_DIG_AUDIO_PIN_CFG_NRESP 5 >> + >> +#define CMD_ZIF_PIN_CFG 0x19 >> +#define CMD_ZIF_PIN_CFG_NARGS 4 >> +#define CMD_ZIF_PIN_CFG_NRESP 5 >> + >> +#define CMD_IC_LINK_GPO_CTL_PIN_CFG 0x1A >> +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 >> +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 >> + >> +#define CMD_ANA_AUDIO_PIN_CFG 0x1B >> +#define CMD_ANA_AUDIO_PIN_CFG_NARGS 1 >> +#define CMD_ANA_AUDIO_PIN_CFG_NRESP 2 >> + >> +#define CMD_INTB_PIN_CFG0x1C >> +#define CMD_INTB_PIN_CFG_NARGS 2 >> +#define CMD_INTB_PIN_CFG_A10_NRESP 6 >> +#define CMD_INTB_PIN_CFG_A20_NRESP 3 >> + >> +#define CMD_FM_TUNE_FREQ0x30 >> +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 >> +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 >> +#define CMD_FM_TUNE_FREQ_NRESP 1 >> + >> +#define CMD_FM_RSQ_STATUS 0x32 >> + >> +#define CMD_FM_RSQ_STATUS_A10_NARGS 1 >> +#define CMD_FM_RSQ_STATUS_A10_NRESP 17 >> +#define CMD_FM_RSQ_STATUS_A30_NARGS 1 >> +#define CMD_FM_RSQ_STATUS_A30_NRESP 23 >> + >> + >> +#define CMD_FM_SEEK_START
Re: [PATCH v2 1/6] Add header files and Kbuild plumbing for SI476x MFD core
On 10/08/2012 01:43 AM, Hans Verkuil wrote: > On Sat October 6 2012 03:54:57 Andrey Smirnov wrote: >> This patch adds all necessary header files and Kbuild plumbing for the >> core driver for Silicon Laboratories Si476x series of AM/FM tuner >> chips. >> >> The driver as a whole is implemented as an MFD device and this patch >> adds a core portion of it that provides all the necessary >> functionality to the two other drivers that represent radio and audio >> codec subsystems of the chip. >> >> Signed-off-by: Andrey Smirnov >> --- >> drivers/mfd/Kconfig | 14 ++ >> drivers/mfd/Makefile|3 + >> include/linux/mfd/si476x-core.h | 529 >> +++ >> include/media/si476x.h | 449 + >> 4 files changed, 995 insertions(+) >> create mode 100644 include/linux/mfd/si476x-core.h >> create mode 100644 include/media/si476x.h >> >> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig >> index b1a1462..3fab06d 100644 >> --- a/drivers/mfd/Kconfig >> +++ b/drivers/mfd/Kconfig >> @@ -895,6 +895,20 @@ config MFD_WL1273_CORE >>driver connects the radio-wl1273 V4L2 module and the wl1273 >>audio codec. >> >> +config MFD_SI476X_CORE >> +tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." >> +depends on I2C >> +select MFD_CORE >> +default n >> +help >> + This is the core driver for the SI476x series of AM/FM radio. This MFD >> + driver connects the radio-si476x V4L2 module and the si476x >> + audio codec. >> + >> + To compile this driver as a module, choose M here: the >> + module will be called si476x-core. >> + >> + >> config MFD_OMAP_USB_HOST >> bool "Support OMAP USBHS core driver" >> depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 >> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile >> index 79dd22d..942257b 100644 >> --- a/drivers/mfd/Makefile >> +++ b/drivers/mfd/Makefile >> @@ -132,3 +132,6 @@ obj-$(CONFIG_MFD_RC5T583)+= rc5t583.o >> rc5t583-irq.o >> obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o >> obj-$(CONFIG_MFD_ANATOP)+= anatop-mfd.o >> obj-$(CONFIG_MFD_LM3533)+= lm3533-core.o lm3533-ctrlbank.o >> + >> +si476x-core-objs := si476x-cmd.o si476x-prop.o si476x-i2c.o >> +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o >> diff --git a/include/linux/mfd/si476x-core.h >> b/include/linux/mfd/si476x-core.h >> new file mode 100644 >> index 000..eb6f52a >> --- /dev/null >> +++ b/include/linux/mfd/si476x-core.h >> @@ -0,0 +1,529 @@ >> +/* >> + * include/media/si476x-core.h -- Common definitions for si476x core >> + * device >> + * >> + * Copyright (C) 2012 Innovative Converged Devices(ICD) >> + * >> + * Author: Andrey Smirnov >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; version 2 of the License. >> + * >> + * 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 SI476X_CORE_H >> +#define SI476X_CORE_H >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include >> + >> +#ifdef DEBUG >> +#define DBG_BUFFER(device, header, buffer, bcount) \ >> +do {\ >> +dev_info((device), header); \ >> +print_hex_dump_bytes("",\ >> + DUMP_PREFIX_OFFSET,\ >> + buffer, bcount); \ >> +} while (0) >> +#else >> +#define DBG_BUFFER(device, header, buffer, bcount) \ >> +do {} while (0) >> +#endif >> + >> +enum si476x_freq_suppoted_chips { > typo: suppoted -> supported > >> +SI476X_CHIP_SI4761 = 1, >> +SI476X_CHIP_SI4762, >> +SI476X_CHIP_SI4763, >> +SI476X_CHIP_SI4764,
Re: [PATCH v2 5/6] Add a V4L2 driver for SI476X MFD
On 10/08/2012 02:30 AM, Hans Verkuil wrote: > On Sat October 6 2012 03:55:01 Andrey Smirnov wrote: >> This commit adds a driver that exposes all the radio related >> functionality of the Si476x series of chips via the V4L2 subsystem. >> >> Signed-off-by: Andrey Smirnov >> --- >> drivers/media/radio/Kconfig| 17 + >> drivers/media/radio/Makefile |1 + >> drivers/media/radio/radio-si476x.c | 1153 >> >> 3 files changed, 1171 insertions(+) >> create mode 100644 drivers/media/radio/radio-si476x.c >> >> diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig >> index 8090b87..3c79d09 100644 >> --- a/drivers/media/radio/Kconfig >> +++ b/drivers/media/radio/Kconfig >> @@ -16,6 +16,23 @@ config RADIO_SI470X >> bool "Silicon Labs Si470x FM Radio Receiver support" >> depends on VIDEO_V4L2 >> >> +config RADIO_SI476X >> +tristate "Silicon Laboratories Si476x I2C FM Radio" >> +depends on I2C && VIDEO_V4L2 >> +select MFD_CORE >> +select MFD_SI476X_CORE >> +select SND_SOC_SI476X >> +---help--- >> + Choose Y here if you have this FM radio chip. >> + >> + In order to control your radio card, you will need to use programs >> + that are compatible with the Video For Linux 2 API. Information on >> + this API and pointers to "v4l2" programs may be found at >> + . >> + >> + To compile this driver as a module, choose M here: the >> + module will be called radio-si476x. >> + >> source "drivers/media/radio/si470x/Kconfig" >> >> config USB_MR800 >> diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile >> index c03ce4f..c4618e0 100644 >> --- a/drivers/media/radio/Makefile >> +++ b/drivers/media/radio/Makefile >> @@ -19,6 +19,7 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o >> obj-$(CONFIG_RADIO_TRUST) += radio-trust.o >> obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o >> obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o >> +obj-$(CONFIG_RADIO_SI476X) += radio-si476x.o >> obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o >> obj-$(CONFIG_USB_DSBR) += dsbr100.o >> obj-$(CONFIG_RADIO_SI470X) += si470x/ >> diff --git a/drivers/media/radio/radio-si476x.c >> b/drivers/media/radio/radio-si476x.c >> new file mode 100644 >> index 000..2d943da >> --- /dev/null >> +++ b/drivers/media/radio/radio-si476x.c >> @@ -0,0 +1,1153 @@ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include >> + >> +#define FM_FREQ_RANGE_LOW 6400 >> +#define FM_FREQ_RANGE_HIGH 10800 >> + >> +#define AM_FREQ_RANGE_LOW52 >> +#define AM_FREQ_RANGE_HIGH 3000 >> + >> +#define PWRLINEFLTR (1 << 8) >> + >> +#define FREQ_MUL (1000 / 625) >> + >> +#define DRIVER_NAME "si476x-radio" >> +#define DRIVER_CARD "SI476x AM/FM Receiver" >> + >> +enum si476x_freq_bands { >> +SI476X_BAND_FM, >> +SI476X_BAND_AM, >> +}; >> + >> +static const struct v4l2_frequency_band si476x_bands[] = { >> +[SI476X_BAND_FM] = { >> +.type = V4L2_TUNER_RADIO, >> +.index = SI476X_BAND_FM, >> +.capability = V4L2_TUNER_CAP_LOW >> +| V4L2_TUNER_CAP_STEREO >> +| V4L2_TUNER_CAP_RDS >> +| V4L2_TUNER_CAP_RDS_BLOCK_IO >> +| V4L2_TUNER_CAP_FREQ_BANDS, >> +.rangelow = 64 * FREQ_MUL, >> +.rangehigh = 108 * FREQ_MUL, >> +.modulation = V4L2_BAND_MODULATION_FM, >> +}, >> +[SI476X_BAND_AM] = { >> +.type = V4L2_TUNER_RADIO, >> +.index = SI476X_BAND_AM, >> +.capability = V4L2_TUNER_CAP_LOW | >> V4L2_TUNER_CAP_FREQ_BANDS, >> +.rangelow = 0.52 * FREQ_MUL, >> +.rangehigh = 30 * FREQ_MUL, >> +.modulation = V4L2_BAND_MODULATION_AM, >> +}, >> +}; >> + >> +#define PRIVATE_CTL_IDX(x) (x - V4L2_CID_PRIVATE_BASE) >> + >> +static int si476x_s_ctrl(struct v4l2_ctrl *ctrl); >> + >> +static const char * const deemphasis[] = { >> +&q
[PATCH v2 2/6] Add the main bulk of core driver for SI476x code
This patch adds main part(out of three) of the I2C driver for the "core" of MFD device. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-i2c.c | 972 ++ 1 file changed, 972 insertions(+) create mode 100644 drivers/mfd/si476x-i2c.c diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c new file mode 100644 index 000..ec79da5 --- /dev/null +++ b/drivers/mfd/si476x-i2c.c @@ -0,0 +1,972 @@ +/* + * include/media/si476x-i2c.c -- Core device driver for si476x MFD + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Command Timeouts */ +#define DEFAULT_TIMEOUT10 +#define TIMEOUT_TUNE 70 +#define TIMEOUT_POWER_UP 33 + +#define MAX_IO_ERRORS 10 + +#define SI476X_DRIVER_RDS_FIFO_DEPTH 128 + +#define SI476X_STATUS_POLL_US 0 + +/** + * si476x_core_config_pinmux() - pin function configuration function + * + * @core: Core device structure + * + * Configure the functions of the pins of the radio chip. + * + * The function returns zero in case of succes or negative error code + * otherwise. + */ +static int si476x_core_config_pinmux(struct si476x_core *core) +{ + int err; + dev_dbg(&core->client->dev, "Configuring pinmux\n"); + err = si476x_core_cmd_dig_audio_pin_cfg(core, + core->pinmux.dclk, + core->pinmux.dfs, + core->pinmux.dout, + core->pinmux.xout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure digital audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_zif_pin_cfg(core, + core->pinmux.iqclk, + core->pinmux.iqfs, + core->pinmux.iout, + core->pinmux.qout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure ZIF pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core, + core->pinmux.icin, + core->pinmux.icip, + core->pinmux.icon, + core->pinmux.icop); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure IC-Link/GPO pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_ana_audio_pin_cfg(core, + core->pinmux.lrout); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure analog audio pins(err = %d)\n", + err); + return err; + } + + err = si476x_core_cmd_intb_pin_cfg(core, + core->pinmux.intb, + core->pinmux.a1); + if (err < 0) { + dev_err(&core->client->dev, + "Failed to configure interrupt pins(err = %d)\n", + err); + return err; + } + + return 0; +} + +static inline void si476x_schedule_polling_work(struct si476x_core *core) +{ + schedule_delayed_work(&core->status_monitor, + usecs_to_jiffies(atomic_read(&core->polling_interval))); +} + +/** + * si476x_core_start() - early chip startup function + * @core: Core device structure + * @soft: When set, this flag forces "soft" startup, where "soft" + * power down is the one done by sending appropriate command instead + * of using reset pin of the tun
[PATCH v2 4/6] Add chip properties handling code for SI476X MFD
This patch adds code related to manipulation of the properties of SI476X chips. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-prop.c | 477 + 1 file changed, 477 insertions(+) create mode 100644 drivers/mfd/si476x-prop.c diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c new file mode 100644 index 000..d633c08 --- /dev/null +++ b/drivers/mfd/si476x-prop.c @@ -0,0 +1,477 @@ +/* + * include/media/si476x-prop.c -- Subroutines to manipulate with + * properties of si476x chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + +#include +#include + + +enum si476x_common_receiver_properties { + SI476X_PROP_INT_CTL_ENABLE = 0x, + SI476X_PROP_DIGITAL_IO_INPUT_SAMPLE_RATE= 0x0200, + SI476X_PROP_DIGITAL_IO_INPUT_FORMAT = 0x0201, + SI476X_PROP_DIGITAL_IO_OUTPUT_SAMPLE_RATE = 0x0202, + SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT= 0x0203, + + SI476X_PROP_AUDIO_ANALOG_VOLUME = 0x0300, + SI476X_PROP_AUDIO_MUTE = 0x0301, + + SI476X_PROP_ZIF_OUTPUT_CFG = 0x0600, + + SI476X_PROP_SEEK_BAND_BOTTOM= 0x1100, + SI476X_PROP_SEEK_BAND_TOP = 0x1101, + SI476X_PROP_SEEK_FREQUENCY_SPACING = 0x1102, + + SI476X_PROP_VALID_MAX_TUNE_ERROR= 0x2000, + SI476X_PROP_VALID_SNR_THRESHOLD = 0x2003, + + SI476X_PROP_VALID_RSSI_THRESHOLD= 0x2004, +}; + +enum si476x_am_receiver_properties { + SI476X_PROP_AUDIO_PWR_LINE_FILTER = 0x0303, +}; + +enum si476x_fm_receiver_properties { + SI476X_PROP_AUDIO_DEEMPHASIS= 0x0302, + + SI476X_PROP_FM_VALID_RSSI_TIME = 0x2001, + SI476X_PROP_FM_VALID_SNR_TIME = 0x2002, + SI476X_PROP_FM_VALID_AF_TIME= 0x2007, + + SI476X_PROP_FM_RDS_INTERRUPT_SOURCE = 0x4000, + SI476X_PROP_FM_RDS_INTERRUPT_FIFO_COUNT = 0x4001, + SI476X_PROP_FM_RDS_CONFIG = 0x4002, +}; + +struct si476x_property_range { + u16 low, high; +}; + +static bool __element_is_in_array(u16 element, const u16 array[], size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element == array[i]) + return true; + + return false; +} + +static bool __element_is_in_range(u16 element, + const struct si476x_property_range range[], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) + if (element <= range[i].high && element >= range[i].low) + return true; + + return false; +} + +static bool si476x_core_is_valid_property_a10(struct si476x_core *core, + u16 property) +{ + static const u16 valid_properties[] = { + 0x, + 0x0500, 0x0501, + 0x0600, + 0x0709, 0x070C, 0x070D, 0x70E, 0x710, + 0x718, /* FIXME: Magic property */ + 0x1207, 0x1208, + 0x2007, + 0x2300, + }; + + static const struct si476x_property_range valid_ranges[] = { + { 0x0200, 0x0203 }, + { 0x0300, 0x0303 }, + { 0x0400, 0x0404 }, + { 0x0700, 0x0707 }, + { 0x1100, 0x1102 }, + { 0x1200, 0x1204 }, + { 0x1300, 0x1306 }, + { 0x2000, 0x2005 }, + { 0x2100, 0x2104 }, + { 0x2106, 0x2106 }, + { 0x2200, 0x220E }, + { 0x3100, 0x3104 }, + { 0x3207, 0x320F }, + { 0x3300, 0x3304 }, + { 0x3500, 0x3517 }, + { 0x3600, 0x3617 }, + { 0x3700, 0x3717 }, + { 0x4000, 0x4003 }, + }; + + return __element_is_in_range(property, valid_ranges, +ARRAY_SIZE(valid_ranges)) || + __element_is_in_array(property, valid_properties, + ARRAY_SIZE(valid_properties)); +} + +static bool si476x_core_i
[PATCH v2 1/6] Add header files and Kbuild plumbing for SI476x MFD core
This patch adds all necessary header files and Kbuild plumbing for the core driver for Silicon Laboratories Si476x series of AM/FM tuner chips. The driver as a whole is implemented as an MFD device and this patch adds a core portion of it that provides all the necessary functionality to the two other drivers that represent radio and audio codec subsystems of the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/Kconfig | 14 ++ drivers/mfd/Makefile|3 + include/linux/mfd/si476x-core.h | 529 +++ include/media/si476x.h | 449 + 4 files changed, 995 insertions(+) create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b1a1462..3fab06d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -895,6 +895,20 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_SI476X_CORE + tristate "Support for Silicon Laboratories 4761/64/68 AM/FM radio." + depends on I2C + select MFD_CORE + default n + help + This is the core driver for the SI476x series of AM/FM radio. This MFD + driver connects the radio-si476x V4L2 module and the si476x + audio codec. + + To compile this driver as a module, choose M here: the + module will be called si476x-core. + + config MFD_OMAP_USB_HOST bool "Support OMAP USBHS core driver" depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 79dd22d..942257b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -132,3 +132,6 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o + +si476x-core-objs := si476x-cmd.o si476x-prop.o si476x-i2c.o +obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h new file mode 100644 index 000..eb6f52a --- /dev/null +++ b/include/linux/mfd/si476x-core.h @@ -0,0 +1,529 @@ +/* + * include/media/si476x-core.h -- Common definitions for si476x core + * device + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 SI476X_CORE_H +#define SI476X_CORE_H + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef DEBUG +#define DBG_BUFFER(device, header, buffer, bcount) \ + do {\ + dev_info((device), header); \ + print_hex_dump_bytes("",\ +DUMP_PREFIX_OFFSET,\ +buffer, bcount); \ + } while (0) +#else +#define DBG_BUFFER(device, header, buffer, bcount) \ + do {} while (0) +#endif + +enum si476x_freq_suppoted_chips { + SI476X_CHIP_SI4761 = 1, + SI476X_CHIP_SI4762, + SI476X_CHIP_SI4763, + SI476X_CHIP_SI4764, + SI476X_CHIP_SI4768, + SI476X_CHIP_SI4769, +}; + +enum si476x_mfd_cells { + SI476X_RADIO_CELL = 0, + SI476X_CODEC_CELL, + SI476X_MFD_CELLS, +}; + + +/** + * enum si476x_power_state - possible power state of the si476x + * device. + * + * @SI476X_POWER_DOWN: In this state all regulators are turned off + * and the reset line is pulled low. The device is completely + * inactive. + * @SI476X_POWER_UP_FULL: In this state all the power regualtors are + * turned on, reset line pulled high, IRQ line is enabled(polling is + * active for polling use scenario) and device is turned on with + * POWER_UP command. The device is ready to be used. + * @SI476X_POWER_INCONSISTENT: This state indicates that previous + * power down was inconsisten meaning some of he regulators wer not + * turned down and thus the consequent use of the device, without + * power-cycling it is impossible. + */ +enum si476x_power_state { + SI476X_POWER_DOWN = 0, + SI476X_POWER_UP_FULL= 1, + SI476X_POWER_INCONSISTENT = 2, +}; + +/** + * stru
[PATCH v2 5/6] Add a V4L2 driver for SI476X MFD
This commit adds a driver that exposes all the radio related functionality of the Si476x series of chips via the V4L2 subsystem. Signed-off-by: Andrey Smirnov --- drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1153 3 files changed, 1171 insertions(+) create mode 100644 drivers/media/radio/radio-si476x.c diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 8090b87..3c79d09 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -16,6 +16,23 @@ config RADIO_SI470X bool "Silicon Labs Si470x FM Radio Receiver support" depends on VIDEO_V4L2 +config RADIO_SI476X + tristate "Silicon Laboratories Si476x I2C FM Radio" + depends on I2C && VIDEO_V4L2 + select MFD_CORE + select MFD_SI476X_CORE + select SND_SOC_SI476X + ---help--- + Choose Y here if you have this FM radio chip. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux 2 API. Information on + this API and pointers to "v4l2" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called radio-si476x. + source "drivers/media/radio/si470x/Kconfig" config USB_MR800 diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index c03ce4f..c4618e0 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o +obj-$(CONFIG_RADIO_SI476X) += radio-si476x.o obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_RADIO_SI470X) += si470x/ diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c new file mode 100644 index 000..2d943da --- /dev/null +++ b/drivers/media/radio/radio-si476x.c @@ -0,0 +1,1153 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FM_FREQ_RANGE_LOW 6400 +#define FM_FREQ_RANGE_HIGH 10800 + +#define AM_FREQ_RANGE_LOW52 +#define AM_FREQ_RANGE_HIGH 3000 + +#define PWRLINEFLTR (1 << 8) + +#define FREQ_MUL (1000 / 625) + +#define DRIVER_NAME "si476x-radio" +#define DRIVER_CARD "SI476x AM/FM Receiver" + +enum si476x_freq_bands { + SI476X_BAND_FM, + SI476X_BAND_AM, +}; + +static const struct v4l2_frequency_band si476x_bands[] = { + [SI476X_BAND_FM] = { + .type = V4L2_TUNER_RADIO, + .index = SI476X_BAND_FM, + .capability = V4L2_TUNER_CAP_LOW + | V4L2_TUNER_CAP_STEREO + | V4L2_TUNER_CAP_RDS + | V4L2_TUNER_CAP_RDS_BLOCK_IO + | V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 64 * FREQ_MUL, + .rangehigh = 108 * FREQ_MUL, + .modulation = V4L2_BAND_MODULATION_FM, + }, + [SI476X_BAND_AM] = { + .type = V4L2_TUNER_RADIO, + .index = SI476X_BAND_AM, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 0.52 * FREQ_MUL, + .rangehigh = 30 * FREQ_MUL, + .modulation = V4L2_BAND_MODULATION_AM, + }, +}; + +#define PRIVATE_CTL_IDX(x) (x - V4L2_CID_PRIVATE_BASE) + +static int si476x_s_ctrl(struct v4l2_ctrl *ctrl); + +static const char * const deemphasis[] = { + "75 us", + "50 us", +}; + +static const struct v4l2_ctrl_ops si476x_ctrl_ops = { + .s_ctrl = si476x_s_ctrl, +}; + +static const struct v4l2_ctrl_config si476x_ctrls[] = { + /* + Tuning parameters + 'max tune errors' is shared for both AM/FM mode of operation + */ + { + .ops= &si476x_ctrl_ops, + .id = SI476X_CID_RSSI_THRESHOLD, + .name = "valid rssi threshold", + .type = V4L2_CTRL_TYPE_INTEGER, + .min= -128, + .max= 127, + .step = 1, + }, + { + .ops= &si476x_ctrl_ops, + .id = SI476X_CID_SNR_THRESHOLD, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "valid snr threshold", + .min= -128, + .max= 127, + .step = 1, + }, + { + .ops= &si476x_ctrl_ops, + .id = SI476X_CID_MA
[PATCH v2 3/6] Add commands abstraction layer for SI476X MFD
This patch adds all the functions used for exchanging commands with the chip. Signed-off-by: Andrey Smirnov --- drivers/mfd/si476x-cmd.c | 1493 ++ 1 file changed, 1493 insertions(+) create mode 100644 drivers/mfd/si476x-cmd.c diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c new file mode 100644 index 000..f11cf58 --- /dev/null +++ b/drivers/mfd/si476x-cmd.c @@ -0,0 +1,1493 @@ +/* + * include/media/si476x-cmd.c -- Subroutines implementing command + * protocol of si476x series of chips + * + * Copyright (C) 2012 Innovative Converged Devices(ICD) + * + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) + + + +#define CMD_POWER_UP 0x01 +#define CMD_POWER_UP_A10_NRESP 1 +#define CMD_POWER_UP_A10_NARGS 5 + +#define CMD_POWER_UP_A20_NRESP 1 +#define CMD_POWER_UP_A20_NARGS 5 + +#define POWER_UP_DELAY_MS 110 + +#define CMD_POWER_DOWN 0x11 +#define CMD_POWER_DOWN_A10_NRESP 1 + +#define CMD_POWER_DOWN_A20_NRESP 1 +#define CMD_POWER_DOWN_A20_NARGS 1 + +#define CMD_FUNC_INFO 0x12 +#define CMD_FUNC_INFO_NRESP7 + +#define CMD_SET_PROPERTY 0x13 +#define CMD_SET_PROPERTY_NARGS 5 +#define CMD_SET_PROPERTY_NRESP 1 + +#define CMD_GET_PROPERTY 0x14 +#define CMD_GET_PROPERTY_NARGS 3 +#define CMD_GET_PROPERTY_NRESP 4 + +#define CMD_AGC_STATUS 0x17 +#define CMD_AGC_STATUS_NRESP_A10 2 +#define CMD_AGC_STATUS_NRESP_A206 + +#define PIN_CFG_BYTE(x) (0x7F & (x)) +#define CMD_DIG_AUDIO_PIN_CFG 0x18 +#define CMD_DIG_AUDIO_PIN_CFG_NARGS4 +#define CMD_DIG_AUDIO_PIN_CFG_NRESP5 + +#define CMD_ZIF_PIN_CFG0x19 +#define CMD_ZIF_PIN_CFG_NARGS 4 +#define CMD_ZIF_PIN_CFG_NRESP 5 + +#define CMD_IC_LINK_GPO_CTL_PIN_CFG0x1A +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS 4 +#define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP 5 + +#define CMD_ANA_AUDIO_PIN_CFG 0x1B +#define CMD_ANA_AUDIO_PIN_CFG_NARGS1 +#define CMD_ANA_AUDIO_PIN_CFG_NRESP2 + +#define CMD_INTB_PIN_CFG 0x1C +#define CMD_INTB_PIN_CFG_NARGS 2 +#define CMD_INTB_PIN_CFG_A10_NRESP 6 +#define CMD_INTB_PIN_CFG_A20_NRESP 3 + +#define CMD_FM_TUNE_FREQ 0x30 +#define CMD_FM_TUNE_FREQ_A10_NARGS 5 +#define CMD_FM_TUNE_FREQ_A20_NARGS 3 +#define CMD_FM_TUNE_FREQ_NRESP 1 + +#define CMD_FM_RSQ_STATUS 0x32 + +#define CMD_FM_RSQ_STATUS_A10_NARGS1 +#define CMD_FM_RSQ_STATUS_A10_NRESP17 +#define CMD_FM_RSQ_STATUS_A30_NARGS1 +#define CMD_FM_RSQ_STATUS_A30_NRESP23 + + +#define CMD_FM_SEEK_START 0x31 +#define CMD_FM_SEEK_START_NARGS1 +#define CMD_FM_SEEK_START_NRESP1 + +#define CMD_FM_RDS_STATUS 0x36 +#define CMD_FM_RDS_STATUS_NARGS1 +#define CMD_FM_RDS_STATUS_NRESP16 + +#define CMD_FM_RDS_BLOCKCOUNT 0x37 +#define CMD_FM_RDS_BLOCKCOUNT_NARGS1 +#define CMD_FM_RDS_BLOCKCOUNT_NRESP8 + +#define CMD_FM_PHASE_DIVERSITY 0x38 +#define CMD_FM_PHASE_DIVERSITY_NARGS 1 +#define CMD_FM_PHASE_DIVERSITY_NRESP 1 + +#define CMD_FM_PHASE_DIV_STATUS0x39 +#define CMD_FM_PHASE_DIV_STATUS_NRESP 2 + +#define CMD_AM_TUNE_FREQ 0x40 +#define CMD_AM_TUNE_FREQ_NARGS 3 +#define CMD_AM_TUNE_FREQ_NRESP 1 + +#define CMD_AM_RSQ_STATUS 0x42 +#define CMD_AM_RSQ_STATUS_NARGS1 +#define CMD_AM_RSQ_STATUS_NRESP13 + +#define CMD_AM_SEEK_START 0x41 +#define CMD_AM_SEEK_START_NARGS
[PATCH v2 6/6] Add a codec driver for SI476X MFD
This commit add a sound codec driver for Silicon Laboratories 476x series of AM/FM radio chips. Signed-off-by: Andrey Smirnov --- sound/soc/codecs/Kconfig |4 + sound/soc/codecs/Makefile |2 + sound/soc/codecs/si476x.c | 255 + 3 files changed, 261 insertions(+) create mode 100644 sound/soc/codecs/si476x.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e859..37b2911 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM3008 select SND_SOC_RT5631 if I2C select SND_SOC_SGTL5000 if I2C + select SND_SOC_SI476X if MFD_SI476X_CORE select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI @@ -272,6 +273,9 @@ config SND_SOC_RT5631 config SND_SOC_SGTL5000 tristate +config SND_SOC_SI476X + tristate + config SND_SOC_SIGMADSP tristate select CRC32 diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb..d9ed4e4 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -44,6 +44,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o snd-soc-sigmadsp-objs := sigmadsp.o +snd-soc-si476x-objs := si476x.o snd-soc-sn95031-objs := sn95031.o snd-soc-spdif-tx-objs := spdif_transciever.o snd-soc-spdif-rx-objs := spdif_receiver.o @@ -161,6 +162,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o +obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o obj-$(CONFIG_SND_SOC_SPDIF)+= snd-soc-spdif-rx.o snd-soc-spdif-tx.o obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c new file mode 100644 index 000..38145ba --- /dev/null +++ b/sound/soc/codecs/si476x.c @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include + +enum si476x_audio_registers { + SI476X_DIGITAL_IO_OUTPUT_FORMAT = 0x0203, + SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE= 0x0202, +}; + +enum si476x_digital_io_output_format { + SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT = 11, + SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT = 8, +}; + +#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \ + (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)) +#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b110) + +enum si476x_daudio_formats { + SI476X_DAUDIO_MODE_I2S = (0x0 << 1), + SI476X_DAUDIO_MODE_DSP_A= (0x6 << 1), + SI476X_DAUDIO_MODE_DSP_B= (0x7 << 1), + SI476X_DAUDIO_MODE_LEFT_J = (0x8 << 1), + SI476X_DAUDIO_MODE_RIGHT_J = (0x9 << 1), + + SI476X_DAUDIO_MODE_IB = (1 << 5), + SI476X_DAUDIO_MODE_IF = (1 << 6), +}; + +enum si476x_pcm_format { + SI476X_PCM_FORMAT_S8= 2, + SI476X_PCM_FORMAT_S16_LE= 4, + SI476X_PCM_FORMAT_S20_3LE = 5, + SI476X_PCM_FORMAT_S24_LE= 6, +}; + +static unsigned int si476x_codec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + int err; + struct si476x_core *core = codec->control_data; + + si476x_core_lock(core); + err = si476x_core_cmd_get_property(core, reg); + si476x_core_unlock(core); + + return err; +} + +static int si476x_codec_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int val) +{ + int err; + struct si476x_core *core = codec->control_data; + + si476x_core_lock(core); + err = si476x_core_cmd_set_property(core, reg, val); + si476x_core_unlock(core); + + return err; +} + +static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + int err; + u16 format = 0; + + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) + return -EINVAL; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + format |= SI476X_DAUDIO_MODE_DSP_A; + break; + case SND_SOC_DAIFMT_DSP_B: + format |= SI476X_DAUDIO_MODE_DSP_B; + break; + case SND_SOC_DAIFMT_I2S: + format |= SI476X_DAUDIO_MODE_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + format |= SI476X_DAUDIO_MODE_RIGHT_J; +
[PATCH v2 0/6] A driver for Si476x series of chips
This is a second version of the patchset originaly posted here: https://lkml.org/lkml/2012/9/13/590 To save everyone's time I'll repost the original description of it: This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. This driver has been tested to work in two different sytems: 1. A custom Tegra-based ARM board(design is based on Harmony board) running linux kernel 3.1.10 kernel 2. A standalone USB-connected board that has a dedicated Cortex M3 working as a transparent USB to I2C bridge which was connected to a off-the-shelf x86-64 laptop running Ubuntu with 3.2.0 kernel. As far as SubmitChecklist is concerned following criteria should be satisfied: 2b, 3, 5, 7, 9, 10 Now it is made against git.linuxtv.org/media_tree.git repository instead of linux-stable. I tried to take into account all the flaws pointed by Mark and Hans, but since the amount of changes I had to made was not trivial I wouldn't be surprized if I missed something that was shown to me. I would like to appologize in advance if this patchset contains some unfixed problems pointed out in the previous version. Andrey Smirnov (6): Add header files and Kbuild plumbing for SI476x MFD core Add the main bulk of core driver for SI476x code Add commands abstraction layer for SI476X MFD Add chip properties handling code for SI476X MFD Add a V4L2 driver for SI476X MFD Add a codec driver for SI476X MFD drivers/media/radio/Kconfig| 17 + drivers/media/radio/Makefile |1 + drivers/media/radio/radio-si476x.c | 1159 drivers/mfd/Kconfig| 14 + drivers/mfd/Makefile |3 + drivers/mfd/si476x-cmd.c | 1493 drivers/mfd/si476x-i2c.c | 974 +++ drivers/mfd/si476x-prop.c | 477 include/linux/mfd/si476x-core.h| 529 + include/media/si476x.h | 449 +++ sound/soc/codecs/Kconfig |4 + sound/soc/codecs/Makefile |2 + sound/soc/si476x.c | 255 ++ 13 files changed, 5377 insertions(+) create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 drivers/mfd/si476x-cmd.c create mode 100644 drivers/mfd/si476x-i2c.c create mode 100644 drivers/mfd/si476x-prop.c create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h create mode 100644 sound/soc/si476x.c -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] Add a V4L2 driver for SI476X MFD
This commit adds a driver that exposes all the radio related functionality of the Si476x series of chips via the V4L2 subsystem. Signed-off-by: Andrey Smirnov --- drivers/media/radio/Kconfig| 17 + drivers/media/radio/radio-si476x.c | 1307 2 files changed, 1324 insertions(+) create mode 100644 drivers/media/radio/radio-si476x.c diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 8090b87..3c79d09 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -16,6 +16,23 @@ config RADIO_SI470X bool "Silicon Labs Si470x FM Radio Receiver support" depends on VIDEO_V4L2 +config RADIO_SI476X + tristate "Silicon Laboratories Si476x I2C FM Radio" + depends on I2C && VIDEO_V4L2 + select MFD_CORE + select MFD_SI476X_CORE + select SND_SOC_SI476X + ---help--- + Choose Y here if you have this FM radio chip. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux 2 API. Information on + this API and pointers to "v4l2" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called radio-si476x. + source "drivers/media/radio/si470x/Kconfig" config USB_MR800 diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c new file mode 100644 index 000..f313005 --- /dev/null +++ b/drivers/media/radio/radio-si476x.c @@ -0,0 +1,1307 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FM_FREQ_RANGE_LOW 6400 +#define FM_FREQ_RANGE_HIGH 10800 + +#define AM_FREQ_RANGE_LOW52 +#define AM_FREQ_RANGE_HIGH 3000 + +#define PWRLINEFLTR (1 << 8) + +#define FREQ_MUL (1000 / 625) + +#define DRIVER_NAME "si476x-radio" +#define DRIVER_CARD "SI476x AM/FM Receiver" + +static const char * const deemphasis[] = { + "75 us", + "50 us", +}; + +static const char * const grid_frequency[] = { + "50 Hz", + "60 Hz", +}; + +#define PRIVATE_CTL_IDX(x) (x - V4L2_CID_PRIVATE_BASE) + +static const struct v4l2_queryctrl si476x_ctrls[] = { + /* + Tuning parameters + 'max tune errors' is shared for both AM/FM mode of operation + */ + { + .id = SI476X_CID_RSSI_THRESHOLD, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "valid rssi threshold", + .minimum= -128, + .maximum= 127, + .step = 1, + }, + { + .id = SI476X_CID_SNR_THRESHOLD, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "valid snr threshold", + .minimum= -128, + .maximum= 127, + .step = 1, + }, + { + .id = SI476X_CID_MAX_TUNE_ERROR, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "max tune errors", + .minimum= 0, + .maximum= 126 * 2, + .step = 2, + }, + /* + Region specific parameters + */ + { + .id = SI476X_CID_GRID_FREQUENCY, + .type = V4L2_CTRL_TYPE_MENU, + .name = "power grid frequency", + .minimum= 0, + .maximum= ARRAY_SIZE(grid_frequency) - 1, + .step = 1, + }, + { + .id = SI476X_CID_HARMONICS_COUNT, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "# of harmonics to reject", + .minimum= 0, + .maximum= 20, + .step = 1, + }, + { + .id = SI476X_CID_SEEK_SPACING, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "seek frequency spacing", + .minimum= 0, + .maximum= 0x, + .step = 1, + }, + { + .id = SI476X_CID_SEEK_BAND_TOP, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "seek band top", + .minimum= 0, + .maximum= 0x, + .step = 1, + }, + { + .id = SI476X_CID_SEEK_BAND_BOTTOM, + .type
[PATCH 0/3] A driver for Si476x series of chips
This patchset contains a driver for a Silicon Laboratories 476x series of radio tuners. The driver itself is implemented as an MFD devices comprised of three parts: 1. Core device that provides all the other devices with basic functionality and locking scheme. 2. Radio device that translates between V4L2 subsystem requests into Core device commands. 3. Codec device that does similar to the earlier described task, but for ALSA SoC subsystem. This driver has been tested to work in two different sytems: 1. A custom Tegra-based ARM board(design is based on Harmony board) running linux kernel 3.1.10 kernel 2. A standalone USB-connected board that has a dedicated Cortex M3 working as a transparent USB to I2C bridge which was connected to a off-the-shelf x86-64 laptop running Ubuntu with 3.2.0 kernel. As far as SubmitChecklist is concerned following criteria should be satisfied: 2b, 3, 5, 7, 9, 10 Andrey Smirnov (3): Add a core driver for SI476x MFD Add a V4L2 driver for SI476X MFD Add a codec driver for SI476X MFD drivers/media/radio/Kconfig| 17 + drivers/media/radio/radio-si476x.c | 1307 +++ drivers/mfd/Kconfig| 14 + drivers/mfd/Makefile |3 + drivers/mfd/si476x-cmd.c | 1509 drivers/mfd/si476x-i2c.c | 1033 drivers/mfd/si476x-prop.c | 477 include/linux/mfd/si476x-core.h| 532 + include/media/si476x.h | 461 +++ sound/soc/codecs/Kconfig |4 + sound/soc/codecs/Makefile |2 + sound/soc/codecs/si476x.c | 346 + 12 files changed, 5705 insertions(+) create mode 100644 drivers/media/radio/radio-si476x.c create mode 100644 drivers/mfd/si476x-cmd.c create mode 100644 drivers/mfd/si476x-i2c.c create mode 100644 drivers/mfd/si476x-prop.c create mode 100644 include/linux/mfd/si476x-core.h create mode 100644 include/media/si476x.h create mode 100644 sound/soc/codecs/si476x.c -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] Add a codec driver for SI476X MFD
This commit add a sound codec driver for Silicon Laboratories 476x series of AM/FM radio chips. Signed-off-by: Andrey Smirnov --- sound/soc/codecs/Kconfig |4 + sound/soc/codecs/Makefile |2 + sound/soc/codecs/si476x.c | 346 + 3 files changed, 352 insertions(+) create mode 100644 sound/soc/codecs/si476x.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e859..71ab390 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WL1273 if MFD_WL1273_CORE + select SND_SOC_SI476X if MFD_SI476X_CORE select SND_SOC_WM1250_EV1 if I2C select SND_SOC_WM2000 if I2C select SND_SOC_WM2200 if I2C @@ -326,6 +327,9 @@ config SND_SOC_UDA1380 config SND_SOC_WL1273 tristate +config SND_SOC_SI476X + tristate + config SND_SOC_WM1250_EV1 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb..aecf09b 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -61,6 +61,7 @@ snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wl1273-objs := wl1273.o +snd-soc-si476x-objs := si476x.o snd-soc-wm1250-ev1-objs := wm1250-ev1.o snd-soc-wm2000-objs := wm2000.o snd-soc-wm2200-objs := wm2200.o @@ -177,6 +178,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o +obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c new file mode 100644 index 000..beea2ca --- /dev/null +++ b/sound/soc/codecs/si476x.c @@ -0,0 +1,346 @@ +#include +#include +#include +#include +#include +#include + +#include + +#define SI476X_AUDIO_VOLUME0x0300 +#define SI476X_AUDIO_MUTE 0x0301 +#define SI476X_DIGITAL_IO_OUTPUT_FORMAT0x0203 +#define SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE 0x0202 + +#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK~((0b111 << 11) | (0b111 << 8)) +#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK ~(0b110) + + +/* codec private data */ +struct si476x_codec { + struct si476x_core *core; +}; + +static unsigned int si476x_codec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + int err; + struct si476x_codec *si476x = snd_soc_codec_get_drvdata(codec); + struct si476x_core *core = si476x->core; + + si476x_core_lock(core); + err = si476x_core_cmd_get_property(core, reg); + si476x_core_unlock(core); + + return err; +} + +static int si476x_codec_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int val) +{ + int err; + struct si476x_codec *si476x = snd_soc_codec_get_drvdata(codec); + struct si476x_core *core = si476x->core; + + si476x_core_lock(core); + err = si476x_core_cmd_set_property(core, reg, val); + si476x_core_unlock(core); + + return err; +} + + + +static int si476x_codec_set_daudio_params(struct snd_soc_codec *codec, + int width, int rate) +{ + int err; + u16 digital_io_output_format = \ + snd_soc_read(codec, +SI476X_DIGITAL_IO_OUTPUT_FORMAT); + + if ((rate < 32000) || (rate > 48000)) { + dev_dbg(codec->dev, "Rate: %d is not supported\n", rate); + return -EINVAL; + } + + err = snd_soc_write(codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE, + rate); + if (err < 0) { + dev_err(codec->dev, "Failed to set sample rate\n"); + return err; + } + + digital_io_output_format &= SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK; + digital_io_output_format |= (width << 11) | (width << 8); + + return snd_soc_write(codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, +digital_io_output_format); +} + +static int si476x_codec_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = + snd_soc_read(codec, SI476X_AUDIO_VOLUME); + return 0; +} + +static int si476x_codec_volume_put(struct snd_kcontrol *kcontrol, + struc