summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/media/radio
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/drivers/media/radio')
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/Kconfig435
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/Makefile32
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/dsbr100.c632
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-aimslab.c210
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-aztech.c186
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-cadet.c714
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-gemtek.c318
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-isa.c340
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-isa.h105
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-keene.c427
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-maxiradio.c213
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-miropcm20.c272
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-mr800.c662
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-rtrack2.c139
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-sf16fmi.c409
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-sf16fmr2.c266
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-si4713.c358
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-tea5764.c588
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-terratec.c170
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-timb.c235
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-trust.c243
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-typhoon.c180
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-wl1273.c2165
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/radio-zoltrix.c248
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/saa7706h.c441
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si470x/Kconfig37
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si470x/Makefile9
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-common.c931
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-i2c.c547
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-usb.c869
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x.h225
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si4713-i2c.c2109
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/si4713-i2c.h240
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/tef6862.c222
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/Kconfig17
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/Makefile6
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv.h239
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.c1685
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.h402
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.c849
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.h59
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.c426
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.h37
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.c584
-rw-r--r--ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.h33
45 files changed, 0 insertions, 19514 deletions
diff --git a/ANDROID_3.4.5/drivers/media/radio/Kconfig b/ANDROID_3.4.5/drivers/media/radio/Kconfig
deleted file mode 100644
index 8db2d7f4..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/Kconfig
+++ /dev/null
@@ -1,435 +0,0 @@
-#
-# Multimedia Video device configuration
-#
-
-menuconfig RADIO_ADAPTERS
- bool "Radio Adapters"
- depends on VIDEO_V4L2
- default y
- ---help---
- Say Y here to enable selecting AM/FM radio adapters.
-
-if RADIO_ADAPTERS && VIDEO_V4L2
-
-config RADIO_SI470X
- bool "Silicon Labs Si470x FM Radio Receiver support"
- depends on VIDEO_V4L2
-
-source "drivers/media/radio/si470x/Kconfig"
-
-config USB_MR800
- tristate "AverMedia MR 800 USB FM radio support"
- depends on USB && VIDEO_V4L2
- ---help---
- Say Y here if you want to connect this type of radio to your
- computer's USB port. Note that the audio is not digital, and
- you must connect the line out connector to a sound card or a
- set of speakers.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-mr800.
-
-config USB_DSBR
- tristate "D-Link/GemTek USB FM radio support"
- depends on USB && VIDEO_V4L2
- ---help---
- Say Y here if you want to connect this type of radio to your
- computer's USB port. Note that the audio is not digital, and
- you must connect the line out connector to a sound card or a
- set of speakers.
-
- To compile this driver as a module, choose M here: the
- module will be called dsbr100.
-
-config RADIO_MAXIRADIO
- tristate "Guillemot MAXI Radio FM 2000 radio"
- depends on VIDEO_V4L2 && PCI && SND
- ---help---
- Choose Y here if you have this radio card. This card may also be
- found as Gemtek PCI FM.
-
- In order to control your radio card, you will need to use programs
- that are compatible with the Video For Linux API. Information on
- this API and pointers to "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-maxiradio.
-
-
-config I2C_SI4713
- tristate "I2C driver for Silicon Labs Si4713 device"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want support to Si4713 I2C device.
- This device driver supports only i2c bus.
-
- To compile this driver as a module, choose M here: the
- module will be called si4713.
-
-config RADIO_SI4713
- tristate "Silicon Labs Si4713 FM Radio Transmitter support"
- depends on I2C && VIDEO_V4L2
- select I2C_SI4713
- ---help---
- Say Y here if you want support to Si4713 FM Radio Transmitter.
- This device can transmit audio through FM. It can transmit
- RDS and RBDS signals as well. This module is the v4l2 radio
- interface for the i2c driver of this device.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-si4713.
-
-config USB_KEENE
- tristate "Keene FM Transmitter USB support"
- depends on USB && VIDEO_V4L2
- ---help---
- Say Y here if you want to connect this type of FM transmitter
- to your computer's USB port.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-keene.
-
-config RADIO_TEA5764
- tristate "TEA5764 I2C FM radio support"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want to use the TEA5764 FM chip found in
- EZX phones. This FM chip is present in EZX phones from Motorola,
- connected to internal pxa I2C bus.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-tea5764.
-
-config RADIO_TEA5764_XTAL
- bool "TEA5764 crystal reference"
- depends on RADIO_TEA5764=y
- default y
- help
- Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
- here if TEA5764 reference frequency is connected in FREQIN.
-
-config RADIO_SAA7706H
- tristate "SAA7706H Car Radio DSP"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want to use the SAA7706H Car radio Digital
- Signal Processor, found for instance on the Russellville development
- board. On the russellville the device is connected to internal
- timberdale I2C bus.
-
- To compile this driver as a module, choose M here: the
- module will be called SAA7706H.
-
-config RADIO_TEF6862
- tristate "TEF6862 Car Radio Enhanced Selectivity Tuner"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want to use the TEF6862 Car Radio Enhanced
- Selectivity Tuner, found for instance on the Russellville development
- board. On the russellville the device is connected to internal
- timberdale I2C bus.
-
- To compile this driver as a module, choose M here: the
- module will be called TEF6862.
-
-config RADIO_TIMBERDALE
- tristate "Enable the Timberdale radio driver"
- depends on MFD_TIMBERDALE && VIDEO_V4L2
- depends on I2C # for RADIO_SAA7706H
- select RADIO_TEF6862
- select RADIO_SAA7706H
- ---help---
- This is a kind of umbrella driver for the Radio Tuner and DSP
- found behind the Timberdale FPGA on the Russellville board.
- Enabling this driver will automatically select the DSP and tuner.
-
-config RADIO_WL1273
- tristate "Texas Instruments WL1273 I2C FM Radio"
- depends on I2C && VIDEO_V4L2
- select MFD_CORE
- select MFD_WL1273_CORE
- select FW_LOADER
- ---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
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-wl1273.
-
-# TI's ST based wl128x FM radio
-source "drivers/media/radio/wl128x/Kconfig"
-
-#
-# ISA drivers configuration
-#
-
-menuconfig V4L_RADIO_ISA_DRIVERS
- bool "ISA radio devices"
- depends on ISA
- default n
- ---help---
- Say Y here to enable support for these ISA drivers.
-
-if V4L_RADIO_ISA_DRIVERS
-
-config RADIO_ISA
- depends on ISA
- tristate
-
-config RADIO_CADET
- tristate "ADS Cadet AM/FM Tuner"
- depends on ISA && VIDEO_V4L2
- ---help---
- Choose Y here if you have one of these AM/FM radio cards, and then
- fill in the port address below.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-cadet.
-
-config RADIO_RTRACK
- tristate "AIMSlab RadioTrack (aka RadioReveal) support"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- ---help---
- Choose Y here if you have one of these FM radio cards, and then fill
- in the port address below.
-
- Note that newer AIMSlab RadioTrack cards have a different chipset
- and are not supported by this driver. For these cards, use the
- RadioTrack II driver below.
-
- If you have a GemTeks combined (PnP) sound- and radio card you must
- use this driver as a module and setup the card with isapnptools.
- You must also pass the module a suitable io parameter, 0x248 has
- been reported to be used by these cards.
-
- More information is contained in the file
- <file:Documentation/video4linux/radiotrack.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-aimslab.
-
-config RADIO_RTRACK_PORT
- hex "RadioTrack i/o port (0x20f or 0x30f)"
- depends on RADIO_RTRACK=y
- default "30f"
- help
- Enter either 0x30f or 0x20f here. The card default is 0x30f, if you
- haven't changed the jumper setting on the card.
-
-config RADIO_RTRACK2
- tristate "AIMSlab RadioTrack II support"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- ---help---
- Choose Y here if you have this FM radio card, and then fill in the
- port address below.
-
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-rtrack2.
-
-config RADIO_RTRACK2_PORT
- hex "RadioTrack II i/o port (0x20c or 0x30c)"
- depends on RADIO_RTRACK2=y
- default "30c"
- help
- Enter either 0x30c or 0x20c here. The card default is 0x30c, if you
- haven't changed the jumper setting on the card.
-
-config RADIO_AZTECH
- tristate "Aztech/Packard Bell Radio"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- ---help---
- Choose Y here if you have one of these FM radio cards, and then fill
- in the port address below.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-aztech.
-
-config RADIO_AZTECH_PORT
- hex "Aztech/Packard Bell I/O port (0x350 or 0x358)"
- depends on RADIO_AZTECH=y
- default "350"
- help
- Enter either 0x350 or 0x358 here. The card default is 0x350, if you
- haven't changed the setting of jumper JP3 on the card. Removing the
- jumper sets the card to 0x358.
-
-config RADIO_GEMTEK
- tristate "GemTek Radio card (or compatible) support"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- ---help---
- Choose Y here if you have this FM radio card, and then fill in the
- I/O port address and settings below. The following cards either have
- GemTek Radio tuner or are rebranded GemTek Radio cards:
-
- - Sound Vision 16 Gold with FM Radio
- - Typhoon Radio card (some models)
- - Hama Radio card
-
- To compile this driver as a module, choose M here: the
- module will be called radio-gemtek.
-
-config RADIO_GEMTEK_PORT
- hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c)"
- depends on RADIO_GEMTEK=y
- default "34c"
- help
- Enter either 0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c here. The
- card default is 0x34c, if you haven't changed the jumper setting
- on the card.
-
- On Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O
- port is 0x20c, 0x248 or 0x28c.
-
- If automatic I/O port probing is enabled this port will be used only
- in case of automatic probing failure, ie. as a fallback.
-
-config RADIO_GEMTEK_PROBE
- bool "Automatic I/O port probing"
- depends on RADIO_GEMTEK=y
- default y
- help
- Say Y here to enable automatic probing for GemTek Radio card. The
- following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and
- 0x28c.
-
-config RADIO_MIROPCM20
- tristate "miroSOUND PCM20 radio"
- depends on ISA && ISA_DMA_API && VIDEO_V4L2 && SND
- select SND_ISA
- select SND_MIRO
- ---help---
- Choose Y here if you have this FM radio card. You also need to enable
- the ALSA sound system. This choice automatically selects the ALSA
- sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this
- is required for the radio-miropcm20.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-miropcm20.
-
-config RADIO_SF16FMI
- tristate "SF16-FMI/SF16-FMP Radio"
- depends on ISA && VIDEO_V4L2
- ---help---
- Choose Y here if you have one of these FM radio cards.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-sf16fmi.
-
-config RADIO_SF16FMR2
- tristate "SF16FMR2 Radio"
- depends on ISA && VIDEO_V4L2 && SND
- ---help---
- Choose Y here if you have one of these FM radio cards.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-sf16fmr2.
-
-config RADIO_TERRATEC
- tristate "TerraTec ActiveRadio ISA Standalone"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- ---help---
- Choose Y here if you have this FM radio card.
-
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-terratec.
-
-config RADIO_TRUST
- tristate "Trust FM radio card"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- help
- This is a driver for the Trust FM radio cards. Say Y if you have
- such a card and want to use it under Linux.
-
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-trust.
-
-config RADIO_TRUST_PORT
- hex "Trust i/o port (usually 0x350 or 0x358)"
- depends on RADIO_TRUST=y
- default "350"
- help
- Enter the I/O port of your Trust FM radio card. If unsure, try the
- values "0x350" or "0x358".
-
-config RADIO_TYPHOON
- tristate "Typhoon Radio (a.k.a. EcoRadio)"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- ---help---
- Choose Y here if you have one of these FM radio cards, and then fill
- in the port address and the frequency used for muting below.
-
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-typhoon.
-
-config RADIO_TYPHOON_PORT
- hex "Typhoon I/O port (0x316 or 0x336)"
- depends on RADIO_TYPHOON=y
- default "316"
- help
- Enter the I/O port of your Typhoon or EcoRadio radio card.
-
-config RADIO_TYPHOON_MUTEFREQ
- int "Typhoon frequency set when muting the device (kHz)"
- depends on RADIO_TYPHOON=y
- default "87500"
- help
- Enter the frequency used for muting the radio. The device is never
- completely silent. If the volume is just turned down, you can still
- hear silent voices and music. For that reason, the frequency of the
- radio device is set to the frequency you can enter here whenever
- the device is muted. There should be no local radio station at that
- frequency.
-
-config RADIO_ZOLTRIX
- tristate "Zoltrix Radio"
- depends on ISA && VIDEO_V4L2
- select RADIO_ISA
- ---help---
- Choose Y here if you have one of these FM radio cards, and then fill
- in the port address below.
-
- Note: this driver hasn't been tested since a long time due to lack
- of hardware. If you have this hardware, then please contact the
- linux-media mailinglist.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-zoltrix.
-
-config RADIO_ZOLTRIX_PORT
- hex "ZOLTRIX I/O port (0x20c or 0x30c)"
- depends on RADIO_ZOLTRIX=y
- default "20c"
- help
- Enter the I/O port of your Zoltrix radio card.
-
-endif # V4L_RADIO_ISA_DRIVERS
-
-endif # RADIO_ADAPTERS
diff --git a/ANDROID_3.4.5/drivers/media/radio/Makefile b/ANDROID_3.4.5/drivers/media/radio/Makefile
deleted file mode 100644
index ca8c7d13..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Makefile for the kernel character device drivers.
-#
-
-obj-$(CONFIG_RADIO_ISA) += radio-isa.o
-obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
-obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
-obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o
-obj-$(CONFIG_RADIO_SF16FMR2) += radio-sf16fmr2.o
-obj-$(CONFIG_RADIO_CADET) += radio-cadet.o
-obj-$(CONFIG_RADIO_TYPHOON) += radio-typhoon.o
-obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o
-obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o
-obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
-obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
-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_MIROPCM20) += radio-miropcm20.o
-obj-$(CONFIG_USB_DSBR) += dsbr100.o
-obj-$(CONFIG_RADIO_SI470X) += si470x/
-obj-$(CONFIG_USB_MR800) += radio-mr800.o
-obj-$(CONFIG_USB_KEENE) += radio-keene.o
-obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
-obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
-obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
-obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
-obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
-obj-$(CONFIG_RADIO_WL128X) += wl128x/
-
-ccflags-y += -Isound
diff --git a/ANDROID_3.4.5/drivers/media/radio/dsbr100.c b/ANDROID_3.4.5/drivers/media/radio/dsbr100.c
deleted file mode 100644
index f36905b6..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/dsbr100.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/* A driver for the D-Link DSB-R100 USB radio and Gemtek USB Radio 21.
- The device plugs into both the USB and an analog audio input, so this thing
- only deals with initialisation and frequency setting, the
- audio data has to be handled by a sound driver.
-
- Major issue: I can't find out where the device reports the signal
- strength, and indeed the windows software appearantly just looks
- at the stereo indicator as well. So, scanning will only find
- stereo stations. Sad, but I can't help it.
-
- Also, the windows program sends oodles of messages over to the
- device, and I couldn't figure out their meaning. My suspicion
- is that they don't have any:-)
-
- You might find some interesting stuff about this module at
- http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
-
- Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- History:
-
- Version 0.46:
- Removed usb_dsbr100_open/close calls and radio->users counter. Also,
- radio->muted changed to radio->status and suspend/resume calls updated.
-
- Version 0.45:
- Converted to v4l2_device.
-
- Version 0.44:
- Add suspend/resume functions, fix unplug of device,
- a lot of cleanups and fixes by Alexey Klimov <klimov.linux@gmail.com>
-
- Version 0.43:
- Oliver Neukum: avoided DMA coherency issue
-
- Version 0.42:
- Converted dsbr100 to use video_ioctl2
- by Douglas Landgraf <dougsland@gmail.com>
-
- Version 0.41-ac1:
- Alan Cox: Some cleanups and fixes
-
- Version 0.41:
- Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
-
- Version 0.40:
- Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
-
- Version 0.30:
- Markus: Updates for 2.5.x kernel and more ISO compliant source
-
- Version 0.25:
- PSL and Markus: Cleanup, radio now doesn't stop on device close
-
- Version 0.24:
- Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
- right. Some minor cleanup, improved standalone compilation
-
- Version 0.23:
- Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
-
- Version 0.22:
- Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
- thanks to Mike Cox for pointing the problem out.
-
- Version 0.21:
- Markus: Minor cleanup, warnings if something goes wrong, lame attempt
- to adhere to Documentation/CodingStyle
-
- Version 0.2:
- Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
- Markus: Copyright clarification
-
- Version 0.01: Markus: initial release
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "0.4.7"
-
-#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
-#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
-
-#define DSB100_VENDOR 0x04b4
-#define DSB100_PRODUCT 0x1002
-
-/* Commands the device appears to understand */
-#define DSB100_TUNE 1
-#define DSB100_ONOFF 2
-
-#define TB_LEN 16
-
-/* Frequency limits in MHz -- these are European values. For Japanese
-devices, that would be 76 and 91. */
-#define FREQ_MIN 87.5
-#define FREQ_MAX 108.0
-#define FREQ_MUL 16000
-
-/* defines for radio->status */
-#define STARTED 0
-#define STOPPED 1
-
-#define v4l2_dev_to_radio(d) container_of(d, struct dsbr100_device, v4l2_dev)
-
-static int usb_dsbr100_probe(struct usb_interface *intf,
- const struct usb_device_id *id);
-static void usb_dsbr100_disconnect(struct usb_interface *intf);
-static int usb_dsbr100_suspend(struct usb_interface *intf,
- pm_message_t message);
-static int usb_dsbr100_resume(struct usb_interface *intf);
-
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-
-/* Data for one (physical) device */
-struct dsbr100_device {
- struct usb_device *usbdev;
- struct video_device videodev;
- struct v4l2_device v4l2_dev;
-
- u8 *transfer_buffer;
- struct mutex v4l2_lock;
- int curfreq;
- int stereo;
- int status;
-};
-
-static struct usb_device_id usb_dsbr100_device_table [] = {
- { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
-
-/* USB subsystem interface */
-static struct usb_driver usb_dsbr100_driver = {
- .name = "dsbr100",
- .probe = usb_dsbr100_probe,
- .disconnect = usb_dsbr100_disconnect,
- .id_table = usb_dsbr100_device_table,
- .suspend = usb_dsbr100_suspend,
- .resume = usb_dsbr100_resume,
- .reset_resume = usb_dsbr100_resume,
- .supports_autosuspend = 0,
-};
-
-/* Low-level device interface begins here */
-
-/* switch on radio */
-static int dsbr100_start(struct dsbr100_device *radio)
-{
- int retval;
- int request;
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0xC7, radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- request = USB_REQ_GET_STATUS;
- goto usb_control_msg_failed;
- }
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- DSB100_ONOFF,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x01, 0x00, radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- request = DSB100_ONOFF;
- goto usb_control_msg_failed;
- }
-
- radio->status = STARTED;
- return (radio->transfer_buffer)[0];
-
-usb_control_msg_failed:
- dev_err(&radio->usbdev->dev,
- "%s - usb_control_msg returned %i, request %i\n",
- __func__, retval, request);
- return retval;
-
-}
-
-/* switch off radio */
-static int dsbr100_stop(struct dsbr100_device *radio)
-{
- int retval;
- int request;
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x16, 0x1C, radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- request = USB_REQ_GET_STATUS;
- goto usb_control_msg_failed;
- }
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- DSB100_ONOFF,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0x00, radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- request = DSB100_ONOFF;
- goto usb_control_msg_failed;
- }
-
- radio->status = STOPPED;
- return (radio->transfer_buffer)[0];
-
-usb_control_msg_failed:
- dev_err(&radio->usbdev->dev,
- "%s - usb_control_msg returned %i, request %i\n",
- __func__, retval, request);
- return retval;
-
-}
-
-/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
-static int dsbr100_setfreq(struct dsbr100_device *radio)
-{
- int retval;
- int request;
- int freq = (radio->curfreq / 16 * 80) / 1000 + 856;
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- DSB100_TUNE,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- (freq >> 8) & 0x00ff, freq & 0xff,
- radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- request = DSB100_TUNE;
- goto usb_control_msg_failed;
- }
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x96, 0xB7, radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- request = USB_REQ_GET_STATUS;
- goto usb_control_msg_failed;
- }
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0x24, radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- request = USB_REQ_GET_STATUS;
- goto usb_control_msg_failed;
- }
-
- radio->stereo = !((radio->transfer_buffer)[0] & 0x01);
- return (radio->transfer_buffer)[0];
-
-usb_control_msg_failed:
- radio->stereo = -1;
- dev_err(&radio->usbdev->dev,
- "%s - usb_control_msg returned %i, request %i\n",
- __func__, retval, request);
- return retval;
-}
-
-/* return the device status. This is, in effect, just whether it
-sees a stereo signal or not. Pity. */
-static void dsbr100_getstat(struct dsbr100_device *radio)
-{
- int retval;
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00 , 0x24, radio->transfer_buffer, 8, 300);
-
- if (retval < 0) {
- radio->stereo = -1;
- dev_err(&radio->usbdev->dev,
- "%s - usb_control_msg returned %i, request %i\n",
- __func__, retval, USB_REQ_GET_STATUS);
- } else {
- radio->stereo = !(radio->transfer_buffer[0] & 0x01);
- }
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- struct dsbr100_device *radio = video_drvdata(file);
-
- strlcpy(v->driver, "dsbr100", sizeof(v->driver));
- strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
- usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
- v->capabilities = V4L2_CAP_TUNER;
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct dsbr100_device *radio = video_drvdata(file);
-
- if (v->index > 0)
- return -EINVAL;
-
- dsbr100_getstat(radio);
- strcpy(v->name, "FM");
- v->type = V4L2_TUNER_RADIO;
- v->rangelow = FREQ_MIN * FREQ_MUL;
- v->rangehigh = FREQ_MAX * FREQ_MUL;
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- v->capability = V4L2_TUNER_CAP_LOW;
- if(radio->stereo)
- v->audmode = V4L2_TUNER_MODE_STEREO;
- else
- v->audmode = V4L2_TUNER_MODE_MONO;
- v->signal = 0xffff; /* We can't get the signal strength */
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- return v->index ? -EINVAL : 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct dsbr100_device *radio = video_drvdata(file);
- int retval;
-
- radio->curfreq = f->frequency;
-
- retval = dsbr100_setfreq(radio);
- if (retval < 0)
- dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
- return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct dsbr100_device *radio = video_drvdata(file);
-
- f->type = V4L2_TUNER_RADIO;
- f->frequency = radio->curfreq;
- return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
-
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct dsbr100_device *radio = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = radio->status;
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct dsbr100_device *radio = video_drvdata(file);
- int retval;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value) {
- retval = dsbr100_stop(radio);
- if (retval < 0) {
- dev_warn(&radio->usbdev->dev,
- "Radio did not respond properly\n");
- return -EBUSY;
- }
- } else {
- retval = dsbr100_start(radio);
- if (retval < 0) {
- dev_warn(&radio->usbdev->dev,
- "Radio did not respond properly\n");
- return -EBUSY;
- }
- }
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- if (a->index > 1)
- return -EINVAL;
-
- strcpy(a->name, "Radio");
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- return i ? -EINVAL : 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- return a->index ? -EINVAL : 0;
-}
-
-/* USB subsystem interface begins here */
-
-/*
- * Handle unplugging of the device.
- * We call video_unregister_device in any case.
- * The last function called in this procedure is
- * usb_dsbr100_video_device_release
- */
-static void usb_dsbr100_disconnect(struct usb_interface *intf)
-{
- struct dsbr100_device *radio = usb_get_intfdata(intf);
-
- v4l2_device_get(&radio->v4l2_dev);
- mutex_lock(&radio->v4l2_lock);
- usb_set_intfdata(intf, NULL);
- video_unregister_device(&radio->videodev);
- v4l2_device_disconnect(&radio->v4l2_dev);
- mutex_unlock(&radio->v4l2_lock);
- v4l2_device_put(&radio->v4l2_dev);
-}
-
-
-/* Suspend device - stop device. */
-static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct dsbr100_device *radio = usb_get_intfdata(intf);
- int retval;
-
- mutex_lock(&radio->v4l2_lock);
- if (radio->status == STARTED) {
- retval = dsbr100_stop(radio);
- if (retval < 0)
- dev_warn(&intf->dev, "dsbr100_stop failed\n");
-
- /* After dsbr100_stop() status set to STOPPED.
- * If we want driver to start radio on resume
- * we set status equal to STARTED.
- * On resume we will check status and run radio if needed.
- */
- radio->status = STARTED;
- }
- mutex_unlock(&radio->v4l2_lock);
-
- dev_info(&intf->dev, "going into suspend..\n");
-
- return 0;
-}
-
-/* Resume device - start device. */
-static int usb_dsbr100_resume(struct usb_interface *intf)
-{
- struct dsbr100_device *radio = usb_get_intfdata(intf);
- int retval;
-
- mutex_lock(&radio->v4l2_lock);
- if (radio->status == STARTED) {
- retval = dsbr100_start(radio);
- if (retval < 0)
- dev_warn(&intf->dev, "dsbr100_start failed\n");
- }
- mutex_unlock(&radio->v4l2_lock);
-
- dev_info(&intf->dev, "coming out of suspend..\n");
-
- return 0;
-}
-
-/* free data structures */
-static void usb_dsbr100_release(struct v4l2_device *v4l2_dev)
-{
- struct dsbr100_device *radio = v4l2_dev_to_radio(v4l2_dev);
-
- v4l2_device_unregister(&radio->v4l2_dev);
- kfree(radio->transfer_buffer);
- kfree(radio);
-}
-
-/* File system interface */
-static const struct v4l2_file_operations usb_dsbr100_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
-};
-
-/* check if the device is present and register with v4l and usb if it is */
-static int usb_dsbr100_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct dsbr100_device *radio;
- struct v4l2_device *v4l2_dev;
- int retval;
-
- radio = kzalloc(sizeof(struct dsbr100_device), GFP_KERNEL);
-
- if (!radio)
- return -ENOMEM;
-
- radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
-
- if (!(radio->transfer_buffer)) {
- kfree(radio);
- return -ENOMEM;
- }
-
- v4l2_dev = &radio->v4l2_dev;
- v4l2_dev->release = usb_dsbr100_release;
-
- retval = v4l2_device_register(&intf->dev, v4l2_dev);
- if (retval < 0) {
- v4l2_err(v4l2_dev, "couldn't register v4l2_device\n");
- kfree(radio->transfer_buffer);
- kfree(radio);
- return retval;
- }
-
- mutex_init(&radio->v4l2_lock);
- strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name));
- radio->videodev.v4l2_dev = v4l2_dev;
- radio->videodev.fops = &usb_dsbr100_fops;
- radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops;
- radio->videodev.release = video_device_release_empty;
- radio->videodev.lock = &radio->v4l2_lock;
-
- radio->usbdev = interface_to_usbdev(intf);
- radio->curfreq = FREQ_MIN * FREQ_MUL;
- radio->status = STOPPED;
-
- video_set_drvdata(&radio->videodev, radio);
-
- retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr);
- if (retval < 0) {
- v4l2_err(v4l2_dev, "couldn't register video device\n");
- v4l2_device_unregister(v4l2_dev);
- kfree(radio->transfer_buffer);
- kfree(radio);
- return -EIO;
- }
- usb_set_intfdata(intf, radio);
- return 0;
-}
-
-module_usb_driver(usb_dsbr100_driver);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-aimslab.c b/ANDROID_3.4.5/drivers/media/radio/radio-aimslab.c
deleted file mode 100644
index 98e0c8c2..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-aimslab.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * AimsLab RadioTrack (aka RadioVeveal) driver
- *
- * Copyright 1997 M. Kirkwood
- *
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
- *
- * Notes on the hardware (reverse engineered from other peoples'
- * reverse engineering of AIMS' code :-)
- *
- * Frequency control is done digitally -- ie out(port,encodefreq(95.8));
- *
- * The signal strength query is unsurprisingly inaccurate. And it seems
- * to indicate that (on my card, at least) the frequency setting isn't
- * too great. (I have to tune up .025MHz from what the freq should be
- * to get a report that the thing is tuned.)
- *
- * Volume control is (ugh) analogue:
- * out(port, start_increasing_volume);
- * wait(a_wee_while);
- * out(port, stop_changing_the_volume);
- *
- * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
- */
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/delay.h> /* msleep */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/io.h> /* outb, outb_p */
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include "radio-isa.h"
-
-MODULE_AUTHOR("M. Kirkwood");
-MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
-
-#ifndef CONFIG_RADIO_RTRACK_PORT
-#define CONFIG_RADIO_RTRACK_PORT -1
-#endif
-
-#define RTRACK_MAX 2
-
-static int io[RTRACK_MAX] = { [0] = CONFIG_RADIO_RTRACK_PORT,
- [1 ... (RTRACK_MAX - 1)] = -1 };
-static int radio_nr[RTRACK_MAX] = { [0 ... (RTRACK_MAX - 1)] = -1 };
-
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-struct rtrack {
- struct radio_isa_card isa;
- int curvol;
-};
-
-static struct radio_isa_card *rtrack_alloc(void)
-{
- struct rtrack *rt = kzalloc(sizeof(struct rtrack), GFP_KERNEL);
-
- if (rt)
- rt->curvol = 0xff;
- return rt ? &rt->isa : NULL;
-}
-
-/* The 128+64 on these outb's is to keep the volume stable while tuning.
- * Without them, the volume _will_ creep up with each frequency change
- * and bit 4 (+16) is to keep the signal strength meter enabled.
- */
-
-static void send_0_byte(struct radio_isa_card *isa, int on)
-{
- outb_p(128+64+16+on+1, isa->io); /* wr-enable + data low */
- outb_p(128+64+16+on+2+1, isa->io); /* clock */
- msleep(1);
-}
-
-static void send_1_byte(struct radio_isa_card *isa, int on)
-{
- outb_p(128+64+16+on+4+1, isa->io); /* wr-enable+data high */
- outb_p(128+64+16+on+4+2+1, isa->io); /* clock */
- msleep(1);
-}
-
-static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8;
- int i;
-
- freq += 171200; /* Add 10.7 MHz IF */
- freq /= 800; /* Convert to 50 kHz units */
-
- send_0_byte(isa, on); /* 0: LSB of frequency */
-
- for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
- if (freq & (1 << i))
- send_1_byte(isa, on);
- else
- send_0_byte(isa, on);
-
- send_0_byte(isa, on); /* 14: test bit - always 0 */
- send_0_byte(isa, on); /* 15: test bit - always 0 */
-
- send_0_byte(isa, on); /* 16: band data 0 - always 0 */
- send_0_byte(isa, on); /* 17: band data 1 - always 0 */
- send_0_byte(isa, on); /* 18: band data 2 - always 0 */
- send_0_byte(isa, on); /* 19: time base - always 0 */
-
- send_0_byte(isa, on); /* 20: spacing (0 = 25 kHz) */
- send_1_byte(isa, on); /* 21: spacing (1 = 25 kHz) */
- send_0_byte(isa, on); /* 22: spacing (0 = 25 kHz) */
- send_1_byte(isa, on); /* 23: AM/FM (FM = 1, always) */
-
- outb(0xd0 + on, isa->io); /* volume steady + sigstr */
- return 0;
-}
-
-static u32 rtrack_g_signal(struct radio_isa_card *isa)
-{
- /* bit set = no signal present */
- return 0xffff * !(inb(isa->io) & 2);
-}
-
-static int rtrack_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- struct rtrack *rt = container_of(isa, struct rtrack, isa);
- int curvol = rt->curvol;
-
- if (mute) {
- outb(0xd0, isa->io); /* volume steady + sigstr + off */
- return 0;
- }
- if (vol == 0) { /* volume = 0 means mute the card */
- outb(0x48, isa->io); /* volume down but still "on" */
- msleep(curvol * 3); /* make sure it's totally down */
- } else if (curvol < vol) {
- outb(0x98, isa->io); /* volume up + sigstr + on */
- for (; curvol < vol; curvol++)
- udelay(3000);
- } else if (curvol > vol) {
- outb(0x58, isa->io); /* volume down + sigstr + on */
- for (; curvol > vol; curvol--)
- udelay(3000);
- }
- outb(0xd8, isa->io); /* volume steady + sigstr + on */
- rt->curvol = vol;
- return 0;
-}
-
-/* Mute card - prevents noisy bootups */
-static int rtrack_initialize(struct radio_isa_card *isa)
-{
- /* this ensures that the volume is all the way up */
- outb(0x90, isa->io); /* volume up but still "on" */
- msleep(3000); /* make sure it's totally up */
- outb(0xc0, isa->io); /* steady volume, mute card */
- return 0;
-}
-
-static const struct radio_isa_ops rtrack_ops = {
- .alloc = rtrack_alloc,
- .init = rtrack_initialize,
- .s_mute_volume = rtrack_s_mute_volume,
- .s_frequency = rtrack_s_frequency,
- .g_signal = rtrack_g_signal,
-};
-
-static const int rtrack_ioports[] = { 0x20f, 0x30f };
-
-static struct radio_isa_driver rtrack_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-aimslab",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = rtrack_ioports,
- .num_of_io_ports = ARRAY_SIZE(rtrack_ioports),
- .region_size = 2,
- .card = "AIMSlab RadioTrack/RadioReveal",
- .ops = &rtrack_ops,
- .has_stereo = true,
- .max_volume = 0xff,
-};
-
-static int __init rtrack_init(void)
-{
- return isa_register_driver(&rtrack_driver.driver, RTRACK_MAX);
-}
-
-static void __exit rtrack_exit(void)
-{
- isa_unregister_driver(&rtrack_driver.driver);
-}
-
-module_init(rtrack_init);
-module_exit(rtrack_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-aztech.c b/ANDROID_3.4.5/drivers/media/radio/radio-aztech.c
deleted file mode 100644
index 177bcbd7..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-aztech.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * radio-aztech.c - Aztech radio card driver
- *
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@xs4all.nl>
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- * Adapted to support the Video for Linux API by
- * Russell Kroll <rkroll@exploits.org>. Based on original tuner code by:
- *
- * Quay Ly
- * Donald Song
- * Jason Lewis (jlewis@twilight.vtc.vsc.edu)
- * Scott McGrath (smcgrath@twilight.vtc.vsc.edu)
- * William McGrath (wmcgrath@twilight.vtc.vsc.edu)
- *
- * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
-*/
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/delay.h> /* udelay */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/io.h> /* outb, outb_p */
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include "radio-isa.h"
-
-MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
-MODULE_DESCRIPTION("A driver for the Aztech radio card.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
-
-/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
-#ifndef CONFIG_RADIO_AZTECH_PORT
-#define CONFIG_RADIO_AZTECH_PORT -1
-#endif
-
-#define AZTECH_MAX 2
-
-static int io[AZTECH_MAX] = { [0] = CONFIG_RADIO_AZTECH_PORT,
- [1 ... (AZTECH_MAX - 1)] = -1 };
-static int radio_nr[AZTECH_MAX] = { [0 ... (AZTECH_MAX - 1)] = -1 };
-static const int radio_wait_time = 1000;
-
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the Aztech card (0x350 or 0x358)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-struct aztech {
- struct radio_isa_card isa;
- int curvol;
-};
-
-static void send_0_byte(struct aztech *az)
-{
- udelay(radio_wait_time);
- outb_p(2 + az->curvol, az->isa.io);
- outb_p(64 + 2 + az->curvol, az->isa.io);
-}
-
-static void send_1_byte(struct aztech *az)
-{
- udelay(radio_wait_time);
- outb_p(128 + 2 + az->curvol, az->isa.io);
- outb_p(128 + 64 + 2 + az->curvol, az->isa.io);
-}
-
-static struct radio_isa_card *aztech_alloc(void)
-{
- struct aztech *az = kzalloc(sizeof(*az), GFP_KERNEL);
-
- return az ? &az->isa : NULL;
-}
-
-static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- struct aztech *az = container_of(isa, struct aztech, isa);
- int i;
-
- freq += 171200; /* Add 10.7 MHz IF */
- freq /= 800; /* Convert to 50 kHz units */
-
- send_0_byte(az); /* 0: LSB of frequency */
-
- for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
- if (freq & (1 << i))
- send_1_byte(az);
- else
- send_0_byte(az);
-
- send_0_byte(az); /* 14: test bit - always 0 */
- send_0_byte(az); /* 15: test bit - always 0 */
- send_0_byte(az); /* 16: band data 0 - always 0 */
- if (isa->stereo) /* 17: stereo (1 to enable) */
- send_1_byte(az);
- else
- send_0_byte(az);
-
- send_1_byte(az); /* 18: band data 1 - unknown */
- send_0_byte(az); /* 19: time base - always 0 */
- send_0_byte(az); /* 20: spacing (0 = 25 kHz) */
- send_1_byte(az); /* 21: spacing (1 = 25 kHz) */
- send_0_byte(az); /* 22: spacing (0 = 25 kHz) */
- send_1_byte(az); /* 23: AM/FM (FM = 1, always) */
-
- /* latch frequency */
-
- udelay(radio_wait_time);
- outb_p(128 + 64 + az->curvol, az->isa.io);
-
- return 0;
-}
-
-/* thanks to Michael Dwyer for giving me a dose of clues in
- * the signal strength department..
- *
- * This card has a stereo bit - bit 0 set = mono, not set = stereo
- */
-static u32 aztech_g_rxsubchans(struct radio_isa_card *isa)
-{
- if (inb(isa->io) & 1)
- return V4L2_TUNER_SUB_MONO;
- return V4L2_TUNER_SUB_STEREO;
-}
-
-static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo)
-{
- return aztech_s_frequency(isa, isa->freq);
-}
-
-static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- struct aztech *az = container_of(isa, struct aztech, isa);
-
- if (mute)
- vol = 0;
- az->curvol = (vol & 1) + ((vol & 2) << 1);
- outb(az->curvol, isa->io);
- return 0;
-}
-
-static const struct radio_isa_ops aztech_ops = {
- .alloc = aztech_alloc,
- .s_mute_volume = aztech_s_mute_volume,
- .s_frequency = aztech_s_frequency,
- .s_stereo = aztech_s_stereo,
- .g_rxsubchans = aztech_g_rxsubchans,
-};
-
-static const int aztech_ioports[] = { 0x350, 0x358 };
-
-static struct radio_isa_driver aztech_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-aztech",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = aztech_ioports,
- .num_of_io_ports = ARRAY_SIZE(aztech_ioports),
- .region_size = 2,
- .card = "Aztech Radio",
- .ops = &aztech_ops,
- .has_stereo = true,
- .max_volume = 3,
-};
-
-static int __init aztech_init(void)
-{
- return isa_register_driver(&aztech_driver.driver, AZTECH_MAX);
-}
-
-static void __exit aztech_exit(void)
-{
- isa_unregister_driver(&aztech_driver.driver);
-}
-
-module_init(aztech_init);
-module_exit(aztech_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-cadet.c b/ANDROID_3.4.5/drivers/media/radio/radio-cadet.c
deleted file mode 100644
index 16a089fa..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-cadet.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/* radio-cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card
- *
- * by Fred Gleason <fredg@wava.com>
- * Version 0.3.3
- *
- * (Loosely) based on code for the Aztech radio card by
- *
- * Russell Kroll (rkroll@exploits.org)
- * Quay Ly
- * Donald Song
- * Jason Lewis (jlewis@twilight.vtc.vsc.edu)
- * Scott McGrath (smcgrath@twilight.vtc.vsc.edu)
- * William McGrath (wmcgrath@twilight.vtc.vsc.edu)
- *
- * History:
- * 2000-04-29 Russell Kroll <rkroll@exploits.org>
- * Added ISAPnP detection for Linux 2.3/2.4
- *
- * 2001-01-10 Russell Kroll <rkroll@exploits.org>
- * Removed dead CONFIG_RADIO_CADET_PORT code
- * PnP detection on load is now default (no args necessary)
- *
- * 2002-01-17 Adam Belay <ambx1@neo.rr.com>
- * Updated to latest pnp code
- *
- * 2003-01-31 Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Cleaned up locking, delay code, general odds and ends
- *
- * 2006-07-30 Hans J. Koch <koch@hjk-az.de>
- * Changed API to V4L2
- */
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/delay.h> /* udelay */
-#include <linux/videodev2.h> /* V4L2 API defs */
-#include <linux/param.h>
-#include <linux/pnp.h>
-#include <linux/sched.h>
-#include <linux/io.h> /* outb, outb_p */
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-
-MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
-MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.3.4");
-
-static int io = -1; /* default to isapnp activation */
-static int radio_nr = -1;
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
-module_param(radio_nr, int, 0);
-
-#define RDS_BUFFER 256
-#define RDS_RX_FLAG 1
-#define MBS_RX_FLAG 2
-
-struct cadet {
- struct v4l2_device v4l2_dev;
- struct video_device vdev;
- int io;
- int users;
- int curtuner;
- int tunestat;
- int sigstrength;
- wait_queue_head_t read_queue;
- struct timer_list readtimer;
- __u8 rdsin, rdsout, rdsstat;
- unsigned char rdsbuf[RDS_BUFFER];
- struct mutex lock;
- int reading;
-};
-
-static struct cadet cadet_card;
-
-/*
- * Signal Strength Threshold Values
- * The V4L API spec does not define any particular unit for the signal
- * strength value. These values are in microvolts of RF at the tuner's input.
- */
-static __u16 sigtable[2][4] = {
- { 5, 10, 30, 150 },
- { 28, 40, 63, 1000 }
-};
-
-
-static int cadet_getstereo(struct cadet *dev)
-{
- int ret = V4L2_TUNER_SUB_MONO;
-
- if (dev->curtuner != 0) /* Only FM has stereo capability! */
- return V4L2_TUNER_SUB_MONO;
-
- mutex_lock(&dev->lock);
- outb(7, dev->io); /* Select tuner control */
- if ((inb(dev->io + 1) & 0x40) == 0)
- ret = V4L2_TUNER_SUB_STEREO;
- mutex_unlock(&dev->lock);
- return ret;
-}
-
-static unsigned cadet_gettune(struct cadet *dev)
-{
- int curvol, i;
- unsigned fifo = 0;
-
- /*
- * Prepare for read
- */
-
- mutex_lock(&dev->lock);
-
- outb(7, dev->io); /* Select tuner control */
- curvol = inb(dev->io + 1); /* Save current volume/mute setting */
- outb(0x00, dev->io + 1); /* Ensure WRITE-ENABLE is LOW */
- dev->tunestat = 0xffff;
-
- /*
- * Read the shift register
- */
- for (i = 0; i < 25; i++) {
- fifo = (fifo << 1) | ((inb(dev->io + 1) >> 7) & 0x01);
- if (i < 24) {
- outb(0x01, dev->io + 1);
- dev->tunestat &= inb(dev->io + 1);
- outb(0x00, dev->io + 1);
- }
- }
-
- /*
- * Restore volume/mute setting
- */
- outb(curvol, dev->io + 1);
- mutex_unlock(&dev->lock);
-
- return fifo;
-}
-
-static unsigned cadet_getfreq(struct cadet *dev)
-{
- int i;
- unsigned freq = 0, test, fifo = 0;
-
- /*
- * Read current tuning
- */
- fifo = cadet_gettune(dev);
-
- /*
- * Convert to actual frequency
- */
- if (dev->curtuner == 0) { /* FM */
- test = 12500;
- for (i = 0; i < 14; i++) {
- if ((fifo & 0x01) != 0)
- freq += test;
- test = test << 1;
- fifo = fifo >> 1;
- }
- freq -= 10700000; /* IF frequency is 10.7 MHz */
- freq = (freq * 16) / 1000000; /* Make it 1/16 MHz */
- }
- if (dev->curtuner == 1) /* AM */
- freq = ((fifo & 0x7fff) - 2010) * 16;
-
- return freq;
-}
-
-static void cadet_settune(struct cadet *dev, unsigned fifo)
-{
- int i;
- unsigned test;
-
- mutex_lock(&dev->lock);
-
- outb(7, dev->io); /* Select tuner control */
- /*
- * Write the shift register
- */
- test = 0;
- test = (fifo >> 23) & 0x02; /* Align data for SDO */
- test |= 0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */
- outb(7, dev->io); /* Select tuner control */
- outb(test, dev->io + 1); /* Initialize for write */
- for (i = 0; i < 25; i++) {
- test |= 0x01; /* Toggle SCK High */
- outb(test, dev->io + 1);
- test &= 0xfe; /* Toggle SCK Low */
- outb(test, dev->io + 1);
- fifo = fifo << 1; /* Prepare the next bit */
- test = 0x1c | ((fifo >> 23) & 0x02);
- outb(test, dev->io + 1);
- }
- mutex_unlock(&dev->lock);
-}
-
-static void cadet_setfreq(struct cadet *dev, unsigned freq)
-{
- unsigned fifo;
- int i, j, test;
- int curvol;
-
- /*
- * Formulate a fifo command
- */
- fifo = 0;
- if (dev->curtuner == 0) { /* FM */
- test = 102400;
- freq = (freq * 1000) / 16; /* Make it kHz */
- freq += 10700; /* IF is 10700 kHz */
- for (i = 0; i < 14; i++) {
- fifo = fifo << 1;
- if (freq >= test) {
- fifo |= 0x01;
- freq -= test;
- }
- test = test >> 1;
- }
- }
- if (dev->curtuner == 1) { /* AM */
- fifo = (freq / 16) + 2010; /* Make it kHz */
- fifo |= 0x100000; /* Select AM Band */
- }
-
- /*
- * Save current volume/mute setting
- */
-
- mutex_lock(&dev->lock);
- outb(7, dev->io); /* Select tuner control */
- curvol = inb(dev->io + 1);
- mutex_unlock(&dev->lock);
-
- /*
- * Tune the card
- */
- for (j = 3; j > -1; j--) {
- cadet_settune(dev, fifo | (j << 16));
-
- mutex_lock(&dev->lock);
- outb(7, dev->io); /* Select tuner control */
- outb(curvol, dev->io + 1);
- mutex_unlock(&dev->lock);
-
- msleep(100);
-
- cadet_gettune(dev);
- if ((dev->tunestat & 0x40) == 0) { /* Tuned */
- dev->sigstrength = sigtable[dev->curtuner][j];
- return;
- }
- }
- dev->sigstrength = 0;
-}
-
-
-static int cadet_getvol(struct cadet *dev)
-{
- int ret = 0;
-
- mutex_lock(&dev->lock);
-
- outb(7, dev->io); /* Select tuner control */
- if ((inb(dev->io + 1) & 0x20) != 0)
- ret = 0xffff;
-
- mutex_unlock(&dev->lock);
- return ret;
-}
-
-
-static void cadet_setvol(struct cadet *dev, int vol)
-{
- mutex_lock(&dev->lock);
- outb(7, dev->io); /* Select tuner control */
- if (vol > 0)
- outb(0x20, dev->io + 1);
- else
- outb(0x00, dev->io + 1);
- mutex_unlock(&dev->lock);
-}
-
-static void cadet_handler(unsigned long data)
-{
- struct cadet *dev = (void *)data;
-
- /* Service the RDS fifo */
- if (mutex_trylock(&dev->lock)) {
- outb(0x3, dev->io); /* Select RDS Decoder Control */
- if ((inb(dev->io + 1) & 0x20) != 0)
- printk(KERN_CRIT "cadet: RDS fifo overflow\n");
- outb(0x80, dev->io); /* Select RDS fifo */
- while ((inb(dev->io) & 0x80) != 0) {
- dev->rdsbuf[dev->rdsin] = inb(dev->io + 1);
- if (dev->rdsin == dev->rdsout)
- printk(KERN_WARNING "cadet: RDS buffer overflow\n");
- else
- dev->rdsin++;
- }
- mutex_unlock(&dev->lock);
- }
-
- /*
- * Service pending read
- */
- if (dev->rdsin != dev->rdsout)
- wake_up_interruptible(&dev->read_queue);
-
- /*
- * Clean up and exit
- */
- init_timer(&dev->readtimer);
- dev->readtimer.function = cadet_handler;
- dev->readtimer.data = (unsigned long)0;
- dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
- add_timer(&dev->readtimer);
-}
-
-
-static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
- struct cadet *dev = video_drvdata(file);
- unsigned char readbuf[RDS_BUFFER];
- int i = 0;
-
- mutex_lock(&dev->lock);
- if (dev->rdsstat == 0) {
- dev->rdsstat = 1;
- outb(0x80, dev->io); /* Select RDS fifo */
- init_timer(&dev->readtimer);
- dev->readtimer.function = cadet_handler;
- dev->readtimer.data = (unsigned long)dev;
- dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
- add_timer(&dev->readtimer);
- }
- if (dev->rdsin == dev->rdsout) {
- mutex_unlock(&dev->lock);
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
- interruptible_sleep_on(&dev->read_queue);
- mutex_lock(&dev->lock);
- }
- while (i < count && dev->rdsin != dev->rdsout)
- readbuf[i++] = dev->rdsbuf[dev->rdsout++];
- mutex_unlock(&dev->lock);
-
- if (copy_to_user(data, readbuf, i))
- return -EFAULT;
- return i;
-}
-
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- strlcpy(v->driver, "ADS Cadet", sizeof(v->driver));
- strlcpy(v->card, "ADS Cadet", sizeof(v->card));
- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
- V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE;
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct cadet *dev = video_drvdata(file);
-
- v->type = V4L2_TUNER_RADIO;
- switch (v->index) {
- case 0:
- strlcpy(v->name, "FM", sizeof(v->name));
- v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
- V4L2_TUNER_CAP_RDS_BLOCK_IO;
- v->rangelow = 1400; /* 87.5 MHz */
- v->rangehigh = 1728; /* 108.0 MHz */
- v->rxsubchans = cadet_getstereo(dev);
- switch (v->rxsubchans) {
- case V4L2_TUNER_SUB_MONO:
- v->audmode = V4L2_TUNER_MODE_MONO;
- break;
- case V4L2_TUNER_SUB_STEREO:
- v->audmode = V4L2_TUNER_MODE_STEREO;
- break;
- default:
- break;
- }
- v->rxsubchans |= V4L2_TUNER_SUB_RDS;
- break;
- case 1:
- strlcpy(v->name, "AM", sizeof(v->name));
- v->capability = V4L2_TUNER_CAP_LOW;
- v->rangelow = 8320; /* 520 kHz */
- v->rangehigh = 26400; /* 1650 kHz */
- v->rxsubchans = V4L2_TUNER_SUB_MONO;
- v->audmode = V4L2_TUNER_MODE_MONO;
- break;
- default:
- return -EINVAL;
- }
- v->signal = dev->sigstrength; /* We might need to modify scaling of this */
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct cadet *dev = video_drvdata(file);
-
- if (v->index != 0 && v->index != 1)
- return -EINVAL;
- dev->curtuner = v->index;
- return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct cadet *dev = video_drvdata(file);
-
- f->tuner = dev->curtuner;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = cadet_getfreq(dev);
- return 0;
-}
-
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct cadet *dev = video_drvdata(file);
-
- if (f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- if (dev->curtuner == 0 && (f->frequency < 1400 || f->frequency > 1728))
- return -EINVAL;
- if (dev->curtuner == 1 && (f->frequency < 8320 || f->frequency > 26400))
- return -EINVAL;
- cadet_setfreq(dev, f->frequency);
- return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- case V4L2_CID_AUDIO_VOLUME:
- return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff);
- }
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct cadet *dev = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
- ctrl->value = (cadet_getvol(dev) == 0);
- break;
- case V4L2_CID_AUDIO_VOLUME:
- ctrl->value = cadet_getvol(dev);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct cadet *dev = video_drvdata(file);
-
- switch (ctrl->id){
- case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
- if (ctrl->value)
- cadet_setvol(dev, 0);
- else
- cadet_setvol(dev, 0xffff);
- break;
- case V4L2_CID_AUDIO_VOLUME:
- cadet_setvol(dev, ctrl->value);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- return i ? -EINVAL : 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- a->index = 0;
- strlcpy(a->name, "Radio", sizeof(a->name));
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- return a->index ? -EINVAL : 0;
-}
-
-static int cadet_open(struct file *file)
-{
- struct cadet *dev = video_drvdata(file);
-
- mutex_lock(&dev->lock);
- dev->users++;
- if (1 == dev->users)
- init_waitqueue_head(&dev->read_queue);
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int cadet_release(struct file *file)
-{
- struct cadet *dev = video_drvdata(file);
-
- mutex_lock(&dev->lock);
- dev->users--;
- if (0 == dev->users) {
- del_timer_sync(&dev->readtimer);
- dev->rdsstat = 0;
- }
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct cadet *dev = video_drvdata(file);
-
- poll_wait(file, &dev->read_queue, wait);
- if (dev->rdsin != dev->rdsout)
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-
-static const struct v4l2_file_operations cadet_fops = {
- .owner = THIS_MODULE,
- .open = cadet_open,
- .release = cadet_release,
- .read = cadet_read,
- .unlocked_ioctl = video_ioctl2,
- .poll = cadet_poll,
-};
-
-static const struct v4l2_ioctl_ops cadet_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
-};
-
-#ifdef CONFIG_PNP
-
-static struct pnp_device_id cadet_pnp_devices[] = {
- /* ADS Cadet AM/FM Radio Card */
- {.id = "MSM0c24", .driver_data = 0},
- {.id = ""}
-};
-
-MODULE_DEVICE_TABLE(pnp, cadet_pnp_devices);
-
-static int cadet_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
- if (!dev)
- return -ENODEV;
- /* only support one device */
- if (io > 0)
- return -EBUSY;
-
- if (!pnp_port_valid(dev, 0))
- return -ENODEV;
-
- io = pnp_port_start(dev, 0);
-
- printk(KERN_INFO "radio-cadet: PnP reports device at %#x\n", io);
-
- return io;
-}
-
-static struct pnp_driver cadet_pnp_driver = {
- .name = "radio-cadet",
- .id_table = cadet_pnp_devices,
- .probe = cadet_pnp_probe,
- .remove = NULL,
-};
-
-#else
-static struct pnp_driver cadet_pnp_driver;
-#endif
-
-static void cadet_probe(struct cadet *dev)
-{
- static int iovals[8] = { 0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e };
- int i;
-
- for (i = 0; i < 8; i++) {
- dev->io = iovals[i];
- if (request_region(dev->io, 2, "cadet-probe")) {
- cadet_setfreq(dev, 1410);
- if (cadet_getfreq(dev) == 1410) {
- release_region(dev->io, 2);
- return;
- }
- release_region(dev->io, 2);
- }
- }
- dev->io = -1;
-}
-
-/*
- * io should only be set if the user has used something like
- * isapnp (the userspace program) to initialize this card for us
- */
-
-static int __init cadet_init(void)
-{
- struct cadet *dev = &cadet_card;
- struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
- int res;
-
- strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name));
- mutex_init(&dev->lock);
-
- /* If a probe was requested then probe ISAPnP first (safest) */
- if (io < 0)
- pnp_register_driver(&cadet_pnp_driver);
- dev->io = io;
-
- /* If that fails then probe unsafely if probe is requested */
- if (dev->io < 0)
- cadet_probe(dev);
-
- /* Else we bail out */
- if (dev->io < 0) {
-#ifdef MODULE
- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x330, 0x332, 0x334,\n");
- v4l2_err(v4l2_dev, "0x336, 0x338, 0x33a, 0x33c or 0x33e\n");
-#endif
- goto fail;
- }
- if (!request_region(dev->io, 2, "cadet"))
- goto fail;
-
- res = v4l2_device_register(NULL, v4l2_dev);
- if (res < 0) {
- release_region(dev->io, 2);
- v4l2_err(v4l2_dev, "could not register v4l2_device\n");
- goto fail;
- }
-
- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
- dev->vdev.v4l2_dev = v4l2_dev;
- dev->vdev.fops = &cadet_fops;
- dev->vdev.ioctl_ops = &cadet_ioctl_ops;
- dev->vdev.release = video_device_release_empty;
- video_set_drvdata(&dev->vdev, dev);
-
- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
- v4l2_device_unregister(v4l2_dev);
- release_region(dev->io, 2);
- goto fail;
- }
- v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io);
- return 0;
-fail:
- pnp_unregister_driver(&cadet_pnp_driver);
- return -ENODEV;
-}
-
-static void __exit cadet_exit(void)
-{
- struct cadet *dev = &cadet_card;
-
- video_unregister_device(&dev->vdev);
- v4l2_device_unregister(&dev->v4l2_dev);
- release_region(dev->io, 2);
- pnp_unregister_driver(&cadet_pnp_driver);
-}
-
-module_init(cadet_init);
-module_exit(cadet_exit);
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-gemtek.c b/ANDROID_3.4.5/drivers/media/radio/radio-gemtek.c
deleted file mode 100644
index 2e639ce6..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-gemtek.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * GemTek radio card driver
- *
- * Copyright 1998 Jonas Munsin <jmunsin@iki.fi>
- *
- * GemTek hasn't released any specs on the card, so the protocol had to
- * be reverse engineered with dosemu.
- *
- * Besides the protocol changes, this is mostly a copy of:
- *
- * RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
- *
- * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
- * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
- *
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- * Note: this card seems to swap the left and right audio channels!
- *
- * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
- */
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/delay.h> /* udelay */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/mutex.h>
-#include <linux/io.h> /* outb, outb_p */
-#include <linux/slab.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include "radio-isa.h"
-
-/*
- * Module info.
- */
-
-MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>");
-MODULE_DESCRIPTION("A driver for the GemTek Radio card.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
-
-/*
- * Module params.
- */
-
-#ifndef CONFIG_RADIO_GEMTEK_PORT
-#define CONFIG_RADIO_GEMTEK_PORT -1
-#endif
-#ifndef CONFIG_RADIO_GEMTEK_PROBE
-#define CONFIG_RADIO_GEMTEK_PROBE 1
-#endif
-
-#define GEMTEK_MAX 4
-
-static bool probe = CONFIG_RADIO_GEMTEK_PROBE;
-static bool hardmute;
-static int io[GEMTEK_MAX] = { [0] = CONFIG_RADIO_GEMTEK_PORT,
- [1 ... (GEMTEK_MAX - 1)] = -1 };
-static int radio_nr[GEMTEK_MAX] = { [0 ... (GEMTEK_MAX - 1)] = -1 };
-
-module_param(probe, bool, 0444);
-MODULE_PARM_DESC(probe, "Enable automatic device probing.");
-
-module_param(hardmute, bool, 0644);
-MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may "
- "reduce static noise.");
-
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic "
- "probing is disabled or fails. The most common I/O ports are: 0x20c "
- "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
- "work for the combined sound/radiocard).");
-
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-/*
- * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal
- * value 10.7 MHz), reference divisor 6.39 kHz (nominal 6.25 kHz).
- */
-#define FSCALE 8
-#define IF_OFFSET ((unsigned int)(10.52 * 16000 * (1<<FSCALE)))
-#define REF_FREQ ((unsigned int)(6.39 * 16 * (1<<FSCALE)))
-
-#define GEMTEK_CK 0x01 /* Clock signal */
-#define GEMTEK_DA 0x02 /* Serial data */
-#define GEMTEK_CE 0x04 /* Chip enable */
-#define GEMTEK_NS 0x08 /* No signal */
-#define GEMTEK_MT 0x10 /* Line mute */
-#define GEMTEK_STDF_3_125_KHZ 0x01 /* Standard frequency 3.125 kHz */
-#define GEMTEK_PLL_OFF 0x07 /* PLL off */
-
-#define BU2614_BUS_SIZE 32 /* BU2614 / BU2614FS bus size */
-
-#define SHORT_DELAY 5 /* usec */
-#define LONG_DELAY 75 /* usec */
-
-struct gemtek {
- struct radio_isa_card isa;
- bool muted;
- u32 bu2614data;
-};
-
-#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */
-#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */
-#define BU2614_VOID_BITS 4 /* unused */
-#define BU2614_FMES_BITS 1 /* CT, Frequency measurement beginning data */
-#define BU2614_STDF_BITS 3 /* R0..R2, Standard frequency data */
-#define BU2614_SWIN_BITS 1 /* S, Switch between FMIN / AMIN */
-#define BU2614_SWAL_BITS 1 /* PS, Swallow counter division (AMIN only)*/
-#define BU2614_VOID2_BITS 1 /* unused */
-#define BU2614_FMUN_BITS 1 /* GT, Frequency measurement time & unlock */
-#define BU2614_TEST_BITS 1 /* TS, Test data is input */
-
-#define BU2614_FREQ_SHIFT 0
-#define BU2614_PORT_SHIFT (BU2614_FREQ_BITS + BU2614_FREQ_SHIFT)
-#define BU2614_VOID_SHIFT (BU2614_PORT_BITS + BU2614_PORT_SHIFT)
-#define BU2614_FMES_SHIFT (BU2614_VOID_BITS + BU2614_VOID_SHIFT)
-#define BU2614_STDF_SHIFT (BU2614_FMES_BITS + BU2614_FMES_SHIFT)
-#define BU2614_SWIN_SHIFT (BU2614_STDF_BITS + BU2614_STDF_SHIFT)
-#define BU2614_SWAL_SHIFT (BU2614_SWIN_BITS + BU2614_SWIN_SHIFT)
-#define BU2614_VOID2_SHIFT (BU2614_SWAL_BITS + BU2614_SWAL_SHIFT)
-#define BU2614_FMUN_SHIFT (BU2614_VOID2_BITS + BU2614_VOID2_SHIFT)
-#define BU2614_TEST_SHIFT (BU2614_FMUN_BITS + BU2614_FMUN_SHIFT)
-
-#define MKMASK(field) (((1<<BU2614_##field##_BITS) - 1) << \
- BU2614_##field##_SHIFT)
-#define BU2614_PORT_MASK MKMASK(PORT)
-#define BU2614_FREQ_MASK MKMASK(FREQ)
-#define BU2614_VOID_MASK MKMASK(VOID)
-#define BU2614_FMES_MASK MKMASK(FMES)
-#define BU2614_STDF_MASK MKMASK(STDF)
-#define BU2614_SWIN_MASK MKMASK(SWIN)
-#define BU2614_SWAL_MASK MKMASK(SWAL)
-#define BU2614_VOID2_MASK MKMASK(VOID2)
-#define BU2614_FMUN_MASK MKMASK(FMUN)
-#define BU2614_TEST_MASK MKMASK(TEST)
-
-/*
- * Set data which will be sent to BU2614FS.
- */
-#define gemtek_bu2614_set(dev, field, data) ((dev)->bu2614data = \
- ((dev)->bu2614data & ~field##_MASK) | ((data) << field##_SHIFT))
-
-/*
- * Transmit settings to BU2614FS over GemTek IC.
- */
-static void gemtek_bu2614_transmit(struct gemtek *gt)
-{
- struct radio_isa_card *isa = &gt->isa;
- int i, bit, q, mute;
-
- mute = gt->muted ? GEMTEK_MT : 0x00;
-
- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, isa->io);
- udelay(LONG_DELAY);
-
- for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) {
- bit = (q & 1) ? GEMTEK_DA : 0;
- outb_p(mute | GEMTEK_CE | bit, isa->io);
- udelay(SHORT_DELAY);
- outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, isa->io);
- udelay(SHORT_DELAY);
- }
-
- outb_p(mute | GEMTEK_DA | GEMTEK_CK, isa->io);
- udelay(SHORT_DELAY);
-}
-
-/*
- * Calculate divisor from FM-frequency for BU2614FS (3.125 KHz STDF expected).
- */
-static unsigned long gemtek_convfreq(unsigned long freq)
-{
- return ((freq << FSCALE) + IF_OFFSET + REF_FREQ / 2) / REF_FREQ;
-}
-
-static struct radio_isa_card *gemtek_alloc(void)
-{
- struct gemtek *gt = kzalloc(sizeof(*gt), GFP_KERNEL);
-
- if (gt)
- gt->muted = true;
- return gt ? &gt->isa : NULL;
-}
-
-/*
- * Set FM-frequency.
- */
-static int gemtek_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- struct gemtek *gt = container_of(isa, struct gemtek, isa);
-
- if (hardmute && gt->muted)
- return 0;
-
- gemtek_bu2614_set(gt, BU2614_PORT, 0);
- gemtek_bu2614_set(gt, BU2614_FMES, 0);
- gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */
- gemtek_bu2614_set(gt, BU2614_SWAL, 0);
- gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */
- gemtek_bu2614_set(gt, BU2614_TEST, 0);
- gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
- gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq));
- gemtek_bu2614_transmit(gt);
- return 0;
-}
-
-/*
- * Set mute flag.
- */
-static int gemtek_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- struct gemtek *gt = container_of(isa, struct gemtek, isa);
- int i;
-
- gt->muted = mute;
- if (hardmute) {
- if (!mute)
- return gemtek_s_frequency(isa, isa->freq);
-
- /* Turn off PLL, disable data output */
- gemtek_bu2614_set(gt, BU2614_PORT, 0);
- gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */
- gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */
- gemtek_bu2614_set(gt, BU2614_SWAL, 0);
- gemtek_bu2614_set(gt, BU2614_FMUN, 0); /* GT bit off */
- gemtek_bu2614_set(gt, BU2614_TEST, 0);
- gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF);
- gemtek_bu2614_set(gt, BU2614_FREQ, 0);
- gemtek_bu2614_transmit(gt);
- return 0;
- }
-
- /* Read bus contents (CE, CK and DA). */
- i = inb_p(isa->io);
- /* Write it back with mute flag set. */
- outb_p((i >> 5) | (mute ? GEMTEK_MT : 0), isa->io);
- udelay(SHORT_DELAY);
- return 0;
-}
-
-static u32 gemtek_g_rxsubchans(struct radio_isa_card *isa)
-{
- if (inb_p(isa->io) & GEMTEK_NS)
- return V4L2_TUNER_SUB_MONO;
- return V4L2_TUNER_SUB_STEREO;
-}
-
-/*
- * Check if requested card acts like GemTek Radio card.
- */
-static bool gemtek_probe(struct radio_isa_card *isa, int io)
-{
- int i, q;
-
- q = inb_p(io); /* Read bus contents before probing. */
- /* Try to turn on CE, CK and DA respectively and check if card responds
- properly. */
- for (i = 0; i < 3; ++i) {
- outb_p(1 << i, io);
- udelay(SHORT_DELAY);
-
- if ((inb_p(io) & ~GEMTEK_NS) != (0x17 | (1 << (i + 5))))
- return false;
- }
- outb_p(q >> 5, io); /* Write bus contents back. */
- udelay(SHORT_DELAY);
- return true;
-}
-
-static const struct radio_isa_ops gemtek_ops = {
- .alloc = gemtek_alloc,
- .probe = gemtek_probe,
- .s_mute_volume = gemtek_s_mute_volume,
- .s_frequency = gemtek_s_frequency,
- .g_rxsubchans = gemtek_g_rxsubchans,
-};
-
-static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
-
-static struct radio_isa_driver gemtek_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-gemtek",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = gemtek_ioports,
- .num_of_io_ports = ARRAY_SIZE(gemtek_ioports),
- .region_size = 1,
- .card = "GemTek Radio",
- .ops = &gemtek_ops,
- .has_stereo = true,
-};
-
-static int __init gemtek_init(void)
-{
- gemtek_driver.probe = probe;
- return isa_register_driver(&gemtek_driver.driver, GEMTEK_MAX);
-}
-
-static void __exit gemtek_exit(void)
-{
- hardmute = 1; /* Turn off PLL */
- isa_unregister_driver(&gemtek_driver.driver);
-}
-
-module_init(gemtek_init);
-module_exit(gemtek_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-isa.c b/ANDROID_3.4.5/drivers/media/radio/radio-isa.c
deleted file mode 100644
index 06f90635..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-isa.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Framework for ISA radio drivers.
- * This takes care of all the V4L2 scaffolding, allowing the ISA drivers
- * to concentrate on the actual hardware operation.
- *
- * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-
-#include "radio-isa.h"
-
-MODULE_AUTHOR("Hans Verkuil");
-MODULE_DESCRIPTION("A framework for ISA radio drivers.");
-MODULE_LICENSE("GPL");
-
-#define FREQ_LOW (87U * 16000U)
-#define FREQ_HIGH (108U * 16000U)
-
-static int radio_isa_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- struct radio_isa_card *isa = video_drvdata(file);
-
- strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
- strlcpy(v->card, isa->drv->card, sizeof(v->card));
- snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
-
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS;
- return 0;
-}
-
-static int radio_isa_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct radio_isa_card *isa = video_drvdata(file);
- const struct radio_isa_ops *ops = isa->drv->ops;
-
- if (v->index > 0)
- return -EINVAL;
-
- strlcpy(v->name, "FM", sizeof(v->name));
- v->type = V4L2_TUNER_RADIO;
- v->rangelow = FREQ_LOW;
- v->rangehigh = FREQ_HIGH;
- v->capability = V4L2_TUNER_CAP_LOW;
- if (isa->drv->has_stereo)
- v->capability |= V4L2_TUNER_CAP_STEREO;
-
- if (ops->g_rxsubchans)
- v->rxsubchans = ops->g_rxsubchans(isa);
- else
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- v->audmode = isa->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
- if (ops->g_signal)
- v->signal = ops->g_signal(isa);
- else
- v->signal = (v->rxsubchans & V4L2_TUNER_SUB_STEREO) ?
- 0xffff : 0;
- return 0;
-}
-
-static int radio_isa_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct radio_isa_card *isa = video_drvdata(file);
- const struct radio_isa_ops *ops = isa->drv->ops;
-
- if (v->index)
- return -EINVAL;
- if (ops->s_stereo) {
- isa->stereo = (v->audmode == V4L2_TUNER_MODE_STEREO);
- return ops->s_stereo(isa, isa->stereo);
- }
- return 0;
-}
-
-static int radio_isa_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct radio_isa_card *isa = video_drvdata(file);
- int res;
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH);
- res = isa->drv->ops->s_frequency(isa, f->frequency);
- if (res == 0)
- isa->freq = f->frequency;
- return res;
-}
-
-static int radio_isa_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct radio_isa_card *isa = video_drvdata(file);
-
- if (f->tuner != 0)
- return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = isa->freq;
- return 0;
-}
-
-static int radio_isa_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct radio_isa_card *isa =
- container_of(ctrl->handler, struct radio_isa_card, hdl);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- return isa->drv->ops->s_mute_volume(isa, ctrl->val,
- isa->volume ? isa->volume->val : 0);
- }
- return -EINVAL;
-}
-
-static int radio_isa_log_status(struct file *file, void *priv)
-{
- struct radio_isa_card *isa = video_drvdata(file);
-
- v4l2_info(&isa->v4l2_dev, "I/O Port = 0x%03x\n", isa->io);
- v4l2_ctrl_handler_log_status(&isa->hdl, isa->v4l2_dev.name);
- return 0;
-}
-
-static int radio_isa_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- if (sub->type == V4L2_EVENT_CTRL)
- return v4l2_event_subscribe(fh, sub, 0);
- return -EINVAL;
-}
-
-static const struct v4l2_ctrl_ops radio_isa_ctrl_ops = {
- .s_ctrl = radio_isa_s_ctrl,
-};
-
-static const struct v4l2_file_operations radio_isa_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = v4l2_fh_release,
- .poll = v4l2_ctrl_poll,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops radio_isa_ioctl_ops = {
- .vidioc_querycap = radio_isa_querycap,
- .vidioc_g_tuner = radio_isa_g_tuner,
- .vidioc_s_tuner = radio_isa_s_tuner,
- .vidioc_g_frequency = radio_isa_g_frequency,
- .vidioc_s_frequency = radio_isa_s_frequency,
- .vidioc_log_status = radio_isa_log_status,
- .vidioc_subscribe_event = radio_isa_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-int radio_isa_match(struct device *pdev, unsigned int dev)
-{
- struct radio_isa_driver *drv = pdev->platform_data;
-
- return drv->probe || drv->io_params[dev] >= 0;
-}
-EXPORT_SYMBOL_GPL(radio_isa_match);
-
-static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io)
-{
- int i;
-
- for (i = 0; i < drv->num_of_io_ports; i++)
- if (drv->io_ports[i] == io)
- return true;
- return false;
-}
-
-int radio_isa_probe(struct device *pdev, unsigned int dev)
-{
- struct radio_isa_driver *drv = pdev->platform_data;
- const struct radio_isa_ops *ops = drv->ops;
- struct v4l2_device *v4l2_dev;
- struct radio_isa_card *isa;
- int res;
-
- isa = drv->ops->alloc();
- if (isa == NULL)
- return -ENOMEM;
- dev_set_drvdata(pdev, isa);
- isa->drv = drv;
- isa->io = drv->io_params[dev];
- v4l2_dev = &isa->v4l2_dev;
- strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name));
-
- if (drv->probe && ops->probe) {
- int i;
-
- for (i = 0; i < drv->num_of_io_ports; ++i) {
- int io = drv->io_ports[i];
-
- if (request_region(io, drv->region_size, v4l2_dev->name)) {
- bool found = ops->probe(isa, io);
-
- release_region(io, drv->region_size);
- if (found) {
- isa->io = io;
- break;
- }
- }
- }
- }
-
- if (!radio_isa_valid_io(drv, isa->io)) {
- int i;
-
- if (isa->io < 0)
- return -ENODEV;
- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x",
- drv->io_ports[0]);
- for (i = 1; i < drv->num_of_io_ports; i++)
- printk(KERN_CONT "/0x%03x", drv->io_ports[i]);
- printk(KERN_CONT ".\n");
- kfree(isa);
- return -EINVAL;
- }
-
- if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) {
- v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io);
- kfree(isa);
- return -EBUSY;
- }
-
- res = v4l2_device_register(pdev, v4l2_dev);
- if (res < 0) {
- v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
- goto err_dev_reg;
- }
-
- v4l2_ctrl_handler_init(&isa->hdl, 1);
- isa->mute = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops,
- V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
- if (drv->max_volume)
- isa->volume = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops,
- V4L2_CID_AUDIO_VOLUME, 0, drv->max_volume, 1,
- drv->max_volume);
- v4l2_dev->ctrl_handler = &isa->hdl;
- if (isa->hdl.error) {
- res = isa->hdl.error;
- v4l2_err(v4l2_dev, "Could not register controls\n");
- goto err_hdl;
- }
- if (drv->max_volume)
- v4l2_ctrl_cluster(2, &isa->mute);
- v4l2_dev->ctrl_handler = &isa->hdl;
-
- mutex_init(&isa->lock);
- isa->vdev.lock = &isa->lock;
- strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name));
- isa->vdev.v4l2_dev = v4l2_dev;
- isa->vdev.fops = &radio_isa_fops;
- isa->vdev.ioctl_ops = &radio_isa_ioctl_ops;
- isa->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags);
- video_set_drvdata(&isa->vdev, isa);
- isa->freq = FREQ_LOW;
- isa->stereo = drv->has_stereo;
-
- if (ops->init)
- res = ops->init(isa);
- if (!res)
- res = v4l2_ctrl_handler_setup(&isa->hdl);
- if (!res)
- res = ops->s_frequency(isa, isa->freq);
- if (!res && ops->s_stereo)
- res = ops->s_stereo(isa, isa->stereo);
- if (res < 0) {
- v4l2_err(v4l2_dev, "Could not setup card\n");
- goto err_node_reg;
- }
- res = video_register_device(&isa->vdev, VFL_TYPE_RADIO,
- drv->radio_nr_params[dev]);
- if (res < 0) {
- v4l2_err(v4l2_dev, "Could not register device node\n");
- goto err_node_reg;
- }
-
- v4l2_info(v4l2_dev, "Initialized radio card %s on port 0x%03x\n",
- drv->card, isa->io);
- return 0;
-
-err_node_reg:
- v4l2_ctrl_handler_free(&isa->hdl);
-err_hdl:
- v4l2_device_unregister(&isa->v4l2_dev);
-err_dev_reg:
- release_region(isa->io, drv->region_size);
- kfree(isa);
- return res;
-}
-EXPORT_SYMBOL_GPL(radio_isa_probe);
-
-int radio_isa_remove(struct device *pdev, unsigned int dev)
-{
- struct radio_isa_card *isa = dev_get_drvdata(pdev);
- const struct radio_isa_ops *ops = isa->drv->ops;
-
- ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0);
- video_unregister_device(&isa->vdev);
- v4l2_ctrl_handler_free(&isa->hdl);
- v4l2_device_unregister(&isa->v4l2_dev);
- release_region(isa->io, isa->drv->region_size);
- v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card);
- kfree(isa);
- return 0;
-}
-EXPORT_SYMBOL_GPL(radio_isa_remove);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-isa.h b/ANDROID_3.4.5/drivers/media/radio/radio-isa.h
deleted file mode 100644
index 8a0ea84d..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-isa.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Framework for ISA radio drivers.
- * This takes care of all the V4L2 scaffolding, allowing the ISA drivers
- * to concentrate on the actual hardware operation.
- *
- * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#ifndef _RADIO_ISA_H_
-#define _RADIO_ISA_H_
-
-#include <linux/isa.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-struct radio_isa_driver;
-struct radio_isa_ops;
-
-/* Core structure for radio ISA cards */
-struct radio_isa_card {
- const struct radio_isa_driver *drv;
- struct v4l2_device v4l2_dev;
- struct v4l2_ctrl_handler hdl;
- struct video_device vdev;
- struct mutex lock;
- const struct radio_isa_ops *ops;
- struct { /* mute/volume cluster */
- struct v4l2_ctrl *mute;
- struct v4l2_ctrl *volume;
- };
- /* I/O port */
- int io;
-
- /* Card is in stereo audio mode */
- bool stereo;
- /* Current frequency */
- u32 freq;
-};
-
-struct radio_isa_ops {
- /* Allocate and initialize a radio_isa_card struct */
- struct radio_isa_card *(*alloc)(void);
- /* Probe whether a card is present at the given port */
- bool (*probe)(struct radio_isa_card *isa, int io);
- /* Special card initialization can be done here, this is called after
- * the standard controls are registered, but before they are setup,
- * thus allowing drivers to add their own controls here. */
- int (*init)(struct radio_isa_card *isa);
- /* Set mute and volume. */
- int (*s_mute_volume)(struct radio_isa_card *isa, bool mute, int volume);
- /* Set frequency */
- int (*s_frequency)(struct radio_isa_card *isa, u32 freq);
- /* Set stereo/mono audio mode */
- int (*s_stereo)(struct radio_isa_card *isa, bool stereo);
- /* Get rxsubchans value for VIDIOC_G_TUNER */
- u32 (*g_rxsubchans)(struct radio_isa_card *isa);
- /* Get the signal strength for VIDIOC_G_TUNER */
- u32 (*g_signal)(struct radio_isa_card *isa);
-};
-
-/* Top level structure needed to instantiate the cards */
-struct radio_isa_driver {
- struct isa_driver driver;
- const struct radio_isa_ops *ops;
- /* The module_param_array with the specified I/O ports */
- int *io_params;
- /* The module_param_array with the radio_nr values */
- int *radio_nr_params;
- /* Whether we should probe for possible cards */
- bool probe;
- /* The list of possible I/O ports */
- const int *io_ports;
- /* The size of that list */
- int num_of_io_ports;
- /* The region size to request */
- unsigned region_size;
- /* The name of the card */
- const char *card;
- /* Card can capture stereo audio */
- bool has_stereo;
- /* The maximum volume for the volume control. If 0, then there
- is no volume control possible. */
- int max_volume;
-};
-
-int radio_isa_match(struct device *pdev, unsigned int dev);
-int radio_isa_probe(struct device *pdev, unsigned int dev);
-int radio_isa_remove(struct device *pdev, unsigned int dev);
-
-#endif
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-keene.c b/ANDROID_3.4.5/drivers/media/radio/radio-keene.c
deleted file mode 100644
index 55bd1d29..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-keene.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (c) 2012 Hans Verkuil <hverkuil@xs4all.nl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* kernel includes */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <linux/usb.h>
-#include <linux/version.h>
-#include <linux/mutex.h>
-
-/* driver and module definitions */
-MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
-MODULE_DESCRIPTION("Keene FM Transmitter driver");
-MODULE_LICENSE("GPL");
-
-/* Actually, it advertises itself as a Logitech */
-#define USB_KEENE_VENDOR 0x046d
-#define USB_KEENE_PRODUCT 0x0a0e
-
-/* Probably USB_TIMEOUT should be modified in module parameter */
-#define BUFFER_LENGTH 8
-#define USB_TIMEOUT 500
-
-/* Frequency limits in MHz */
-#define FREQ_MIN 76U
-#define FREQ_MAX 108U
-#define FREQ_MUL 16000U
-
-/* USB Device ID List */
-static struct usb_device_id usb_keene_device_table[] = {
- {USB_DEVICE_AND_INTERFACE_INFO(USB_KEENE_VENDOR, USB_KEENE_PRODUCT,
- USB_CLASS_HID, 0, 0) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, usb_keene_device_table);
-
-struct keene_device {
- struct usb_device *usbdev;
- struct usb_interface *intf;
- struct video_device vdev;
- struct v4l2_device v4l2_dev;
- struct v4l2_ctrl_handler hdl;
- struct mutex lock;
-
- u8 *buffer;
- unsigned curfreq;
- u8 tx;
- u8 pa;
- bool stereo;
- bool muted;
- bool preemph_75_us;
-};
-
-static inline struct keene_device *to_keene_dev(struct v4l2_device *v4l2_dev)
-{
- return container_of(v4l2_dev, struct keene_device, v4l2_dev);
-}
-
-/* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */
-static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play)
-{
- unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0;
- int ret;
-
- radio->buffer[0] = 0x00;
- radio->buffer[1] = 0x50;
- radio->buffer[2] = (freq_send >> 8) & 0xff;
- radio->buffer[3] = freq_send & 0xff;
- radio->buffer[4] = radio->pa;
- /* If bit 4 is set, then tune to the frequency.
- If bit 3 is set, then unmute; if bit 2 is set, then mute.
- If bit 1 is set, then enter idle mode; if bit 0 is set,
- then enter transit mode.
- */
- radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) |
- (freq ? 0x10 : 0);
- radio->buffer[6] = 0x00;
- radio->buffer[7] = 0x00;
-
- ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
- 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
-
- if (ret < 0) {
- dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret);
- return ret;
- }
- if (freq)
- radio->curfreq = freq;
- return 0;
-}
-
-/* Set TX, stereo and preemphasis mode (50 us vs 75 us). */
-static int keene_cmd_set(struct keene_device *radio)
-{
- int ret;
-
- radio->buffer[0] = 0x00;
- radio->buffer[1] = 0x51;
- radio->buffer[2] = radio->tx;
- /* If bit 0 is set, then transmit mono, otherwise stereo.
- If bit 2 is set, then enable 75 us preemphasis, otherwise
- it is 50 us. */
- radio->buffer[3] = (!radio->stereo) | (radio->preemph_75_us ? 4 : 0);
- radio->buffer[4] = 0x00;
- radio->buffer[5] = 0x00;
- radio->buffer[6] = 0x00;
- radio->buffer[7] = 0x00;
-
- ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
- 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
-
- if (ret < 0) {
- dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret);
- return ret;
- }
- return 0;
-}
-
-/* Handle unplugging the device.
- * We call video_unregister_device in any case.
- * The last function called in this procedure is
- * usb_keene_device_release.
- */
-static void usb_keene_disconnect(struct usb_interface *intf)
-{
- struct keene_device *radio = to_keene_dev(usb_get_intfdata(intf));
-
- v4l2_device_get(&radio->v4l2_dev);
- mutex_lock(&radio->lock);
- usb_set_intfdata(intf, NULL);
- video_unregister_device(&radio->vdev);
- v4l2_device_disconnect(&radio->v4l2_dev);
- mutex_unlock(&radio->lock);
- v4l2_device_put(&radio->v4l2_dev);
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- struct keene_device *radio = video_drvdata(file);
-
- strlcpy(v->driver, "radio-keene", sizeof(v->driver));
- strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card));
- usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
- v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR;
- v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
- return 0;
-}
-
-static int vidioc_g_modulator(struct file *file, void *priv,
- struct v4l2_modulator *v)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (v->index > 0)
- return -EINVAL;
-
- strlcpy(v->name, "FM", sizeof(v->name));
- v->rangelow = FREQ_MIN * FREQ_MUL;
- v->rangehigh = FREQ_MAX * FREQ_MUL;
- v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_modulator(struct file *file, void *priv,
- struct v4l2_modulator *v)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (v->index > 0)
- return -EINVAL;
-
- radio->stereo = (v->txsubchans == V4L2_TUNER_SUB_STEREO);
- return keene_cmd_set(radio);
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- f->frequency = clamp(f->frequency,
- FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
- return keene_cmd_main(radio, f->frequency, true);
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct keene_device *radio = video_drvdata(file);
-
- if (f->tuner != 0)
- return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = radio->curfreq;
- return 0;
-}
-
-static int keene_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- static const u8 db2tx[] = {
- /* -15, -12, -9, -6, -3, 0 dB */
- 0x03, 0x13, 0x02, 0x12, 0x22, 0x32,
- /* 3, 6, 9, 12, 15, 18 dB */
- 0x21, 0x31, 0x20, 0x30, 0x40, 0x50
- };
- struct keene_device *radio =
- container_of(ctrl->handler, struct keene_device, hdl);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- radio->muted = ctrl->val;
- return keene_cmd_main(radio, 0, true);
-
- case V4L2_CID_TUNE_POWER_LEVEL:
- /* To go from dBuV to the register value we apply the
- following formula: */
- radio->pa = (ctrl->val - 71) * 100 / 62;
- return keene_cmd_main(radio, 0, true);
-
- case V4L2_CID_TUNE_PREEMPHASIS:
- radio->preemph_75_us = ctrl->val == V4L2_PREEMPHASIS_75_uS;
- return keene_cmd_set(radio);
-
- case V4L2_CID_AUDIO_COMPRESSION_GAIN:
- radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step];
- return keene_cmd_set(radio);
- }
- return -EINVAL;
-}
-
-static int vidioc_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- switch (sub->type) {
- case V4L2_EVENT_CTRL:
- return v4l2_event_subscribe(fh, sub, 0);
- default:
- return -EINVAL;
- }
-}
-
-
-/* File system interface */
-static const struct v4l2_file_operations usb_keene_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = v4l2_fh_release,
- .poll = v4l2_ctrl_poll,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ctrl_ops keene_ctrl_ops = {
- .s_ctrl = keene_s_ctrl,
-};
-
-static const struct v4l2_ioctl_ops usb_keene_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_modulator = vidioc_g_modulator,
- .vidioc_s_modulator = vidioc_s_modulator,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = vidioc_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static void usb_keene_video_device_release(struct v4l2_device *v4l2_dev)
-{
- struct keene_device *radio = to_keene_dev(v4l2_dev);
-
- /* free rest memory */
- v4l2_ctrl_handler_free(&radio->hdl);
- kfree(radio->buffer);
- kfree(radio);
-}
-
-/* check if the device is present and register with v4l and usb if it is */
-static int usb_keene_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct keene_device *radio;
- struct v4l2_ctrl_handler *hdl;
- int retval = 0;
-
- /*
- * The Keene FM transmitter USB device has the same USB ID as
- * the Logitech AudioHub Speaker, but it should ignore the hid.
- * Check if the name is that of the Keene device.
- * If not, then someone connected the AudioHub and we shouldn't
- * attempt to handle this driver.
- * For reference: the product name of the AudioHub is
- * "AudioHub Speaker".
- */
- if (dev->product && strcmp(dev->product, "B-LINK USB Audio "))
- return -ENODEV;
-
- radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL);
- if (radio)
- radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
-
- if (!radio || !radio->buffer) {
- dev_err(&intf->dev, "kmalloc for keene_device failed\n");
- kfree(radio);
- retval = -ENOMEM;
- goto err;
- }
-
- hdl = &radio->hdl;
- v4l2_ctrl_handler_init(hdl, 4);
- v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_MUTE,
- 0, 1, 1, 0);
- v4l2_ctrl_new_std_menu(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS,
- V4L2_PREEMPHASIS_75_uS, 1, V4L2_PREEMPHASIS_50_uS);
- v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL,
- 84, 118, 1, 118);
- v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN,
- -15, 18, 3, 0);
- radio->pa = 118;
- radio->tx = 0x32;
- radio->stereo = true;
- radio->curfreq = 95.16 * FREQ_MUL;
- if (hdl->error) {
- retval = hdl->error;
-
- v4l2_ctrl_handler_free(hdl);
- goto err_v4l2;
- }
- retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
- if (retval < 0) {
- dev_err(&intf->dev, "couldn't register v4l2_device\n");
- goto err_v4l2;
- }
-
- mutex_init(&radio->lock);
-
- radio->v4l2_dev.ctrl_handler = hdl;
- radio->v4l2_dev.release = usb_keene_video_device_release;
- strlcpy(radio->vdev.name, radio->v4l2_dev.name,
- sizeof(radio->vdev.name));
- radio->vdev.v4l2_dev = &radio->v4l2_dev;
- radio->vdev.fops = &usb_keene_fops;
- radio->vdev.ioctl_ops = &usb_keene_ioctl_ops;
- radio->vdev.lock = &radio->lock;
- radio->vdev.release = video_device_release_empty;
-
- radio->usbdev = interface_to_usbdev(intf);
- radio->intf = intf;
- usb_set_intfdata(intf, &radio->v4l2_dev);
-
- video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
-
- retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1);
- if (retval < 0) {
- dev_err(&intf->dev, "could not register video device\n");
- goto err_vdev;
- }
- v4l2_ctrl_handler_setup(hdl);
- dev_info(&intf->dev, "V4L2 device registered as %s\n",
- video_device_node_name(&radio->vdev));
- return 0;
-
-err_vdev:
- v4l2_device_unregister(&radio->v4l2_dev);
-err_v4l2:
- kfree(radio->buffer);
- kfree(radio);
-err:
- return retval;
-}
-
-/* USB subsystem interface */
-static struct usb_driver usb_keene_driver = {
- .name = "radio-keene",
- .probe = usb_keene_probe,
- .disconnect = usb_keene_disconnect,
- .id_table = usb_keene_device_table,
-};
-
-static int __init keene_init(void)
-{
- int retval = usb_register(&usb_keene_driver);
-
- if (retval)
- pr_err(KBUILD_MODNAME
- ": usb_register failed. Error number %d\n", retval);
-
- return retval;
-}
-
-static void __exit keene_exit(void)
-{
- usb_deregister(&usb_keene_driver);
-}
-
-module_init(keene_init);
-module_exit(keene_exit);
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-maxiradio.c b/ANDROID_3.4.5/drivers/media/radio/radio-maxiradio.c
deleted file mode 100644
index 740a3d55..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-maxiradio.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux
- * (C) 2001 Dimitromanolakis Apostolos <apdim@grecian.net>
- *
- * Based in the radio Maestro PCI driver. Actually it uses the same chip
- * for radio but different pci controller.
- *
- * I didn't have any specs I reversed engineered the protocol from
- * the windows driver (radio.dll).
- *
- * The card uses the TEA5757 chip that includes a search function but it
- * is useless as I haven't found any way to read back the frequency. If
- * anybody does please mail me.
- *
- * For the pdf file see:
- * http://www.nxp.com/acrobat_download2/expired_datasheets/TEA5757_5759_3.pdf
- *
- *
- * CHANGES:
- * 0.75b
- * - better pci interface thanks to Francois Romieu <romieu@cogenit.fr>
- *
- * 0.75 Sun Feb 4 22:51:27 EET 2001
- * - tiding up
- * - removed support for multiple devices as it didn't work anyway
- *
- * BUGS:
- * - card unmutes if you change frequency
- *
- * (c) 2006, 2007 by Mauro Carvalho Chehab <mchehab@infradead.org>:
- * - Conversion to V4L2 API
- * - Uses video_ioctl2 for parsing and to add debug support
- */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/pci.h>
-#include <linux/videodev2.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <sound/tea575x-tuner.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-
-MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
-MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
-
-static int radio_nr = -1;
-module_param(radio_nr, int, 0644);
-MODULE_PARM_DESC(radio_nr, "Radio device number");
-
-/* TEA5757 pin mappings */
-static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16;
-
-static atomic_t maxiradio_instance = ATOMIC_INIT(0);
-
-#define PCI_VENDOR_ID_GUILLEMOT 0x5046
-#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001
-
-struct maxiradio
-{
- struct snd_tea575x tea;
- struct v4l2_device v4l2_dev;
- struct pci_dev *pdev;
-
- u16 io; /* base of radio io */
-};
-
-static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev)
-{
- return container_of(v4l2_dev, struct maxiradio, v4l2_dev);
-}
-
-static void maxiradio_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
-{
- struct maxiradio *dev = tea->private_data;
- u8 bits = 0;
-
- bits |= (pins & TEA575X_DATA) ? data : 0;
- bits |= (pins & TEA575X_CLK) ? clk : 0;
- bits |= (pins & TEA575X_WREN) ? wren : 0;
- bits |= power;
-
- outb(bits, dev->io);
-}
-
-/* Note: this card cannot read out the data of the shift registers,
- only the mono/stereo pin works. */
-static u8 maxiradio_tea575x_get_pins(struct snd_tea575x *tea)
-{
- struct maxiradio *dev = tea->private_data;
- u8 bits = inb(dev->io);
-
- return ((bits & data) ? TEA575X_DATA : 0) |
- ((bits & mo_st) ? TEA575X_MOST : 0);
-}
-
-static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output)
-{
-}
-
-static struct snd_tea575x_ops maxiradio_tea_ops = {
- .set_pins = maxiradio_tea575x_set_pins,
- .get_pins = maxiradio_tea575x_get_pins,
- .set_direction = maxiradio_tea575x_set_direction,
-};
-
-static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- struct maxiradio *dev;
- struct v4l2_device *v4l2_dev;
- int retval = -ENOMEM;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&pdev->dev, "not enough memory\n");
- return -ENOMEM;
- }
-
- v4l2_dev = &dev->v4l2_dev;
- v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance);
-
- retval = v4l2_device_register(&pdev->dev, v4l2_dev);
- if (retval < 0) {
- v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
- goto errfr;
- }
- dev->tea.private_data = dev;
- dev->tea.ops = &maxiradio_tea_ops;
- /* The data pin cannot be read. This may be a hardware limitation, or
- we just don't know how to read it. */
- dev->tea.cannot_read_data = true;
- dev->tea.v4l2_dev = v4l2_dev;
- dev->tea.radio_nr = radio_nr;
- strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card));
- snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info),
- "PCI:%s", pci_name(pdev));
-
- retval = -ENODEV;
-
- if (!request_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), v4l2_dev->name)) {
- dev_err(&pdev->dev, "can't reserve I/O ports\n");
- goto err_hdl;
- }
-
- if (pci_enable_device(pdev))
- goto err_out_free_region;
-
- dev->io = pci_resource_start(pdev, 0);
- if (snd_tea575x_init(&dev->tea)) {
- printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n");
- goto err_out_free_region;
- }
- return 0;
-
-err_out_free_region:
- release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_hdl:
- v4l2_device_unregister(v4l2_dev);
-errfr:
- kfree(dev);
- return retval;
-}
-
-static void __devexit maxiradio_remove(struct pci_dev *pdev)
-{
- struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
- struct maxiradio *dev = to_maxiradio(v4l2_dev);
-
- snd_tea575x_exit(&dev->tea);
- /* Turn off power */
- outb(0, dev->io);
- v4l2_device_unregister(v4l2_dev);
- release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-}
-
-static struct pci_device_id maxiradio_pci_tbl[] = {
- { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO,
- PCI_ANY_ID, PCI_ANY_ID, },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl);
-
-static struct pci_driver maxiradio_driver = {
- .name = "radio-maxiradio",
- .id_table = maxiradio_pci_tbl,
- .probe = maxiradio_probe,
- .remove = __devexit_p(maxiradio_remove),
-};
-
-static int __init maxiradio_init(void)
-{
- return pci_register_driver(&maxiradio_driver);
-}
-
-static void __exit maxiradio_exit(void)
-{
- pci_unregister_driver(&maxiradio_driver);
-}
-
-module_init(maxiradio_init);
-module_exit(maxiradio_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-miropcm20.c b/ANDROID_3.4.5/drivers/media/radio/radio-miropcm20.c
deleted file mode 100644
index 87c1ee13..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-miropcm20.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/* Miro PCM20 radio driver for Linux radio support
- * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- * Thanks to Norberto Pellici for the ACI device interface specification
- * The API part is based on the radiotrack driver by M. Kirkwood
- * This driver relies on the aci mixer provided by the snd-miro
- * ALSA driver.
- * Look there for further info...
- */
-
-/* What ever you think about the ACI, version 0x07 is not very well!
- * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions... Robert
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <sound/aci.h>
-
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)");
-
-static bool mono;
-module_param(mono, bool, 0);
-MODULE_PARM_DESC(mono, "Force tuner into mono mode.");
-
-struct pcm20 {
- struct v4l2_device v4l2_dev;
- struct video_device vdev;
- unsigned long freq;
- int muted;
- struct snd_miro_aci *aci;
- struct mutex lock;
-};
-
-static struct pcm20 pcm20_card = {
- .freq = 87*16000,
- .muted = 1,
-};
-
-static int pcm20_mute(struct pcm20 *dev, unsigned char mute)
-{
- dev->muted = mute;
- return snd_aci_cmd(dev->aci, ACI_SET_TUNERMUTE, mute, -1);
-}
-
-static int pcm20_stereo(struct pcm20 *dev, unsigned char stereo)
-{
- return snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO, !stereo, -1);
-}
-
-static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
-{
- unsigned char freql;
- unsigned char freqh;
- struct snd_miro_aci *aci = dev->aci;
-
- dev->freq = freq;
-
- freq /= 160;
- if (!(aci->aci_version == 0x07 || aci->aci_version >= 0xb0))
- freq /= 10; /* I don't know exactly which version
- * needs this hack */
- freql = freq & 0xff;
- freqh = freq >> 8;
-
- pcm20_stereo(dev, !mono);
- return snd_aci_cmd(aci, ACI_WRITE_TUNE, freql, freqh);
-}
-
-static const struct v4l2_file_operations pcm20_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- strlcpy(v->driver, "Miro PCM20", sizeof(v->driver));
- strlcpy(v->card, "Miro PCM20", sizeof(v->card));
- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
- v->version = 0x1;
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- if (v->index) /* Only 1 tuner */
- return -EINVAL;
- strlcpy(v->name, "FM", sizeof(v->name));
- v->type = V4L2_TUNER_RADIO;
- v->rangelow = 87*16000;
- v->rangehigh = 108*16000;
- v->signal = 0xffff;
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- v->capability = V4L2_TUNER_CAP_LOW;
- v->audmode = V4L2_TUNER_MODE_MONO;
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- return v->index ? -EINVAL : 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct pcm20 *dev = video_drvdata(file);
-
- if (f->tuner != 0)
- return -EINVAL;
-
- f->type = V4L2_TUNER_RADIO;
- f->frequency = dev->freq;
- return 0;
-}
-
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct pcm20 *dev = video_drvdata(file);
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
-
- dev->freq = f->frequency;
- pcm20_setfreq(dev, f->frequency);
- return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct pcm20 *dev = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = dev->muted;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct pcm20 *dev = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- pcm20_mute(dev, ctrl->value);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- return i ? -EINVAL : 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- a->index = 0;
- strlcpy(a->name, "Radio", sizeof(a->name));
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- return a->index ? -EINVAL : 0;
-}
-
-static const struct v4l2_ioctl_ops pcm20_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
-};
-
-static int __init pcm20_init(void)
-{
- struct pcm20 *dev = &pcm20_card;
- struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
- int res;
-
- dev->aci = snd_aci_get_aci();
- if (dev->aci == NULL) {
- v4l2_err(v4l2_dev,
- "you must load the snd-miro driver first!\n");
- return -ENODEV;
- }
- strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name));
- mutex_init(&dev->lock);
-
- res = v4l2_device_register(NULL, v4l2_dev);
- if (res < 0) {
- v4l2_err(v4l2_dev, "could not register v4l2_device\n");
- return -EINVAL;
- }
-
- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
- dev->vdev.v4l2_dev = v4l2_dev;
- dev->vdev.fops = &pcm20_fops;
- dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
- dev->vdev.release = video_device_release_empty;
- dev->vdev.lock = &dev->lock;
- video_set_drvdata(&dev->vdev, dev);
-
- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
- goto fail;
-
- v4l2_info(v4l2_dev, "Mirosound PCM20 Radio tuner\n");
- return 0;
-fail:
- v4l2_device_unregister(v4l2_dev);
- return -EINVAL;
-}
-
-MODULE_AUTHOR("Ruurd Reitsma, Krzysztof Helt");
-MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
-MODULE_LICENSE("GPL");
-
-static void __exit pcm20_cleanup(void)
-{
- struct pcm20 *dev = &pcm20_card;
-
- video_unregister_device(&dev->vdev);
- v4l2_device_unregister(&dev->v4l2_dev);
-}
-
-module_init(pcm20_init);
-module_exit(pcm20_cleanup);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-mr800.c b/ANDROID_3.4.5/drivers/media/radio/radio-mr800.c
deleted file mode 100644
index a860a72a..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-mr800.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * A driver for the AverMedia MR 800 USB FM radio. This device plugs
- * into both the USB and an analog audio input, so this thing
- * only deals with initialization and frequency setting, the
- * audio data has to be handled by a sound driver.
- *
- * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Big thanks to authors and contributors of dsbr100.c and radio-si470x.c
- *
- * When work was looked pretty good, i discover this:
- * http://av-usbradio.sourceforge.net/index.php
- * http://sourceforge.net/projects/av-usbradio/
- * Latest release of theirs project was in 2005.
- * Probably, this driver could be improved through using their
- * achievements (specifications given).
- * Also, Faidon Liambotis <paravoid@debian.org> wrote nice driver for this radio
- * in 2007. He allowed to use his driver to improve current mr800 radio driver.
- * http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/11/342492
- *
- * Version 0.01: First working version.
- * It's required to blacklist AverMedia USB Radio
- * in usbhid/hid-quirks.c
- * Version 0.10: A lot of cleanups and fixes: unpluging the device,
- * few mutex locks were added, codinstyle issues, etc.
- * Added stereo support. Thanks to
- * Douglas Schilling Landgraf <dougsland@gmail.com> and
- * David Ellingsworth <david@identd.dyndns.org>
- * for discussion, help and support.
- * Version 0.11: Converted to v4l2_device.
- *
- * Many things to do:
- * - Correct power management of device (suspend & resume)
- * - Add code for scanning and smooth tuning
- * - Add code for sensitivity value
- * - Correct mistakes
- * - In Japan another FREQ_MIN and FREQ_MAX
- */
-
-/* kernel includes */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-
-/* driver and module definitions */
-#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
-#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
-#define DRIVER_VERSION "0.1.2"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
-
-#define USB_AMRADIO_VENDOR 0x07ca
-#define USB_AMRADIO_PRODUCT 0xb800
-
-/* dev_warn macro with driver name */
-#define MR800_DRIVER_NAME "radio-mr800"
-#define amradio_dev_warn(dev, fmt, arg...) \
- dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
-
-#define amradio_dev_err(dev, fmt, arg...) \
- dev_err(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
-
-/* Probably USB_TIMEOUT should be modified in module parameter */
-#define BUFFER_LENGTH 8
-#define USB_TIMEOUT 500
-
-/* Frequency limits in MHz -- these are European values. For Japanese
-devices, that would be 76 and 91. */
-#define FREQ_MIN 87.5
-#define FREQ_MAX 108.0
-#define FREQ_MUL 16000
-
-/*
- * Commands that device should understand
- * List isn't full and will be updated with implementation of new functions
- */
-#define AMRADIO_SET_FREQ 0xa4
-#define AMRADIO_SET_MUTE 0xab
-#define AMRADIO_SET_MONO 0xae
-
-/* Comfortable defines for amradio_set_mute */
-#define AMRADIO_START 0x00
-#define AMRADIO_STOP 0x01
-
-/* Comfortable defines for amradio_set_stereo */
-#define WANT_STEREO 0x00
-#define WANT_MONO 0x01
-
-/* module parameter */
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-MODULE_PARM_DESC(radio_nr, "Radio Nr");
-
-static int usb_amradio_probe(struct usb_interface *intf,
- const struct usb_device_id *id);
-static void usb_amradio_disconnect(struct usb_interface *intf);
-static int usb_amradio_open(struct file *file);
-static int usb_amradio_close(struct file *file);
-static int usb_amradio_suspend(struct usb_interface *intf,
- pm_message_t message);
-static int usb_amradio_resume(struct usb_interface *intf);
-
-/* Data for one (physical) device */
-struct amradio_device {
- /* reference to USB and video device */
- struct usb_device *usbdev;
- struct usb_interface *intf;
- struct video_device videodev;
- struct v4l2_device v4l2_dev;
-
- unsigned char *buffer;
- struct mutex lock; /* buffer locking */
- int curfreq;
- int stereo;
- int muted;
- int initialized;
-};
-
-static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev)
-{
- return container_of(v4l2_dev, struct amradio_device, v4l2_dev);
-}
-
-/* USB Device ID List */
-static struct usb_device_id usb_amradio_device_table[] = {
- {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
- USB_CLASS_HID, 0, 0) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
-
-/* USB subsystem interface */
-static struct usb_driver usb_amradio_driver = {
- .name = MR800_DRIVER_NAME,
- .probe = usb_amradio_probe,
- .disconnect = usb_amradio_disconnect,
- .suspend = usb_amradio_suspend,
- .resume = usb_amradio_resume,
- .reset_resume = usb_amradio_resume,
- .id_table = usb_amradio_device_table,
- .supports_autosuspend = 1,
-};
-
-/* switch on/off the radio. Send 8 bytes to device */
-static int amradio_set_mute(struct amradio_device *radio, char argument)
-{
- int retval;
- int size;
-
- radio->buffer[0] = 0x00;
- radio->buffer[1] = 0x55;
- radio->buffer[2] = 0xaa;
- radio->buffer[3] = 0x00;
- radio->buffer[4] = AMRADIO_SET_MUTE;
- radio->buffer[5] = argument;
- radio->buffer[6] = 0x00;
- radio->buffer[7] = 0x00;
-
- retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
- (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
-
- if (retval < 0 || size != BUFFER_LENGTH) {
- amradio_dev_warn(&radio->videodev.dev, "set mute failed\n");
- return retval;
- }
-
- radio->muted = argument;
-
- return retval;
-}
-
-/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
-static int amradio_setfreq(struct amradio_device *radio, int freq)
-{
- int retval;
- int size;
- unsigned short freq_send = 0x10 + (freq >> 3) / 25;
-
- radio->buffer[0] = 0x00;
- radio->buffer[1] = 0x55;
- radio->buffer[2] = 0xaa;
- radio->buffer[3] = 0x03;
- radio->buffer[4] = AMRADIO_SET_FREQ;
- radio->buffer[5] = 0x00;
- radio->buffer[6] = 0x00;
- radio->buffer[7] = 0x08;
-
- retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
- (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
-
- if (retval < 0 || size != BUFFER_LENGTH)
- goto out_err;
-
- /* frequency is calculated from freq_send and placed in first 2 bytes */
- radio->buffer[0] = (freq_send >> 8) & 0xff;
- radio->buffer[1] = freq_send & 0xff;
- radio->buffer[2] = 0x01;
- radio->buffer[3] = 0x00;
- radio->buffer[4] = 0x00;
- /* 5 and 6 bytes of buffer already = 0x00 */
- radio->buffer[7] = 0x00;
-
- retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
- (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
-
- if (retval < 0 || size != BUFFER_LENGTH)
- goto out_err;
-
- radio->curfreq = freq;
- goto out;
-
-out_err:
- amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n");
-out:
- return retval;
-}
-
-static int amradio_set_stereo(struct amradio_device *radio, char argument)
-{
- int retval;
- int size;
-
- radio->buffer[0] = 0x00;
- radio->buffer[1] = 0x55;
- radio->buffer[2] = 0xaa;
- radio->buffer[3] = 0x00;
- radio->buffer[4] = AMRADIO_SET_MONO;
- radio->buffer[5] = argument;
- radio->buffer[6] = 0x00;
- radio->buffer[7] = 0x00;
-
- retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
- (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
-
- if (retval < 0 || size != BUFFER_LENGTH) {
- amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n");
- return retval;
- }
-
- if (argument == WANT_STEREO)
- radio->stereo = 1;
- else
- radio->stereo = 0;
-
- return retval;
-}
-
-/* Handle unplugging the device.
- * We call video_unregister_device in any case.
- * The last function called in this procedure is
- * usb_amradio_device_release.
- */
-static void usb_amradio_disconnect(struct usb_interface *intf)
-{
- struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
-
- mutex_lock(&radio->lock);
- /* increase the device node's refcount */
- get_device(&radio->videodev.dev);
- v4l2_device_disconnect(&radio->v4l2_dev);
- video_unregister_device(&radio->videodev);
- mutex_unlock(&radio->lock);
- /* decrease the device node's refcount, allowing it to be released */
- put_device(&radio->videodev.dev);
-}
-
-/* vidioc_querycap - query device capabilities */
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- struct amradio_device *radio = file->private_data;
-
- strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
- strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
- usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
- v->capabilities = V4L2_CAP_TUNER;
- return 0;
-}
-
-/* vidioc_g_tuner - get tuner attributes */
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct amradio_device *radio = file->private_data;
- int retval;
-
- if (v->index > 0)
- return -EINVAL;
-
-/* TODO: Add function which look is signal stereo or not
- * amradio_getstat(radio);
- */
-
-/* we call amradio_set_stereo to set radio->stereo
- * Honestly, amradio_getstat should cover this in future and
- * amradio_set_stereo shouldn't be here
- */
- retval = amradio_set_stereo(radio, WANT_STEREO);
-
- strcpy(v->name, "FM");
- v->type = V4L2_TUNER_RADIO;
- v->rangelow = FREQ_MIN * FREQ_MUL;
- v->rangehigh = FREQ_MAX * FREQ_MUL;
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- v->capability = V4L2_TUNER_CAP_LOW;
- if (radio->stereo)
- v->audmode = V4L2_TUNER_MODE_STEREO;
- else
- v->audmode = V4L2_TUNER_MODE_MONO;
- v->signal = 0xffff; /* Can't get the signal strength, sad.. */
- v->afc = 0; /* Don't know what is this */
-
- return retval;
-}
-
-/* vidioc_s_tuner - set tuner attributes */
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct amradio_device *radio = file->private_data;
- int retval = -EINVAL;
-
- if (v->index > 0)
- return -EINVAL;
-
- /* mono/stereo selector */
- switch (v->audmode) {
- case V4L2_TUNER_MODE_MONO:
- retval = amradio_set_stereo(radio, WANT_MONO);
- break;
- case V4L2_TUNER_MODE_STEREO:
- retval = amradio_set_stereo(radio, WANT_STEREO);
- break;
- }
-
- return retval;
-}
-
-/* vidioc_s_frequency - set tuner radio frequency */
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct amradio_device *radio = file->private_data;
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- return amradio_setfreq(radio, f->frequency);
-}
-
-/* vidioc_g_frequency - get tuner radio frequency */
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct amradio_device *radio = file->private_data;
-
- if (f->tuner != 0)
- return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = radio->curfreq;
-
- return 0;
-}
-
-/* vidioc_queryctrl - enumerate control items */
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
-
- return -EINVAL;
-}
-
-/* vidioc_g_ctrl - get the value of a control */
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct amradio_device *radio = file->private_data;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = radio->muted;
- return 0;
- }
-
- return -EINVAL;
-}
-
-/* vidioc_s_ctrl - set the value of a control */
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct amradio_device *radio = file->private_data;
- int retval = -EINVAL;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value)
- retval = amradio_set_mute(radio, AMRADIO_STOP);
- else
- retval = amradio_set_mute(radio, AMRADIO_START);
-
- break;
- }
-
- return retval;
-}
-
-/* vidioc_g_audio - get audio attributes */
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- if (a->index > 1)
- return -EINVAL;
-
- strcpy(a->name, "Radio");
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-/* vidioc_s_audio - set audio attributes */
-static int vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- if (a->index != 0)
- return -EINVAL;
- return 0;
-}
-
-/* vidioc_g_input - get input */
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-/* vidioc_s_input - set input */
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- if (i != 0)
- return -EINVAL;
- return 0;
-}
-
-static int usb_amradio_init(struct amradio_device *radio)
-{
- int retval;
-
- retval = amradio_set_mute(radio, AMRADIO_STOP);
- if (retval)
- goto out_err;
-
- retval = amradio_set_stereo(radio, WANT_STEREO);
- if (retval)
- goto out_err;
-
- radio->initialized = 1;
- goto out;
-
-out_err:
- amradio_dev_err(&radio->videodev.dev, "initialization failed\n");
-out:
- return retval;
-}
-
-/* open device - amradio_start() and amradio_setfreq() */
-static int usb_amradio_open(struct file *file)
-{
- struct amradio_device *radio = video_drvdata(file);
- int retval;
-
- file->private_data = radio;
- retval = usb_autopm_get_interface(radio->intf);
- if (retval)
- return retval;
-
- if (unlikely(!radio->initialized)) {
- retval = usb_amradio_init(radio);
- if (retval)
- usb_autopm_put_interface(radio->intf);
- }
- return retval;
-}
-
-/*close device */
-static int usb_amradio_close(struct file *file)
-{
- struct amradio_device *radio = file->private_data;
-
- if (video_is_registered(&radio->videodev))
- usb_autopm_put_interface(radio->intf);
- return 0;
-}
-
-/* Suspend device - stop device. Need to be checked and fixed */
-static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
-
- mutex_lock(&radio->lock);
- if (!radio->muted && radio->initialized) {
- amradio_set_mute(radio, AMRADIO_STOP);
- radio->muted = 0;
- }
- mutex_unlock(&radio->lock);
-
- dev_info(&intf->dev, "going into suspend..\n");
- return 0;
-}
-
-/* Resume device - start device. Need to be checked and fixed */
-static int usb_amradio_resume(struct usb_interface *intf)
-{
- struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
-
- mutex_lock(&radio->lock);
- if (unlikely(!radio->initialized))
- goto unlock;
-
- if (radio->stereo)
- amradio_set_stereo(radio, WANT_STEREO);
- else
- amradio_set_stereo(radio, WANT_MONO);
-
- amradio_setfreq(radio, radio->curfreq);
-
- if (!radio->muted)
- amradio_set_mute(radio, AMRADIO_START);
-
-unlock:
- mutex_unlock(&radio->lock);
-
- dev_info(&intf->dev, "coming out of suspend..\n");
- return 0;
-}
-
-/* File system interface */
-static const struct v4l2_file_operations usb_amradio_fops = {
- .owner = THIS_MODULE,
- .open = usb_amradio_open,
- .release = usb_amradio_close,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
-};
-
-static void usb_amradio_video_device_release(struct video_device *videodev)
-{
- struct amradio_device *radio = video_get_drvdata(videodev);
-
- /* free rest memory */
- kfree(radio->buffer);
- kfree(radio);
-}
-
-/* check if the device is present and register with v4l and usb if it is */
-static int usb_amradio_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct amradio_device *radio;
- int retval = 0;
-
- radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL);
-
- if (!radio) {
- dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
- retval = -ENOMEM;
- goto err;
- }
-
- radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
-
- if (!radio->buffer) {
- dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
- retval = -ENOMEM;
- goto err_nobuf;
- }
-
- retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
- if (retval < 0) {
- dev_err(&intf->dev, "couldn't register v4l2_device\n");
- goto err_v4l2;
- }
-
- mutex_init(&radio->lock);
-
- strlcpy(radio->videodev.name, radio->v4l2_dev.name,
- sizeof(radio->videodev.name));
- radio->videodev.v4l2_dev = &radio->v4l2_dev;
- radio->videodev.fops = &usb_amradio_fops;
- radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops;
- radio->videodev.release = usb_amradio_video_device_release;
- radio->videodev.lock = &radio->lock;
-
- radio->usbdev = interface_to_usbdev(intf);
- radio->intf = intf;
- radio->curfreq = 95.16 * FREQ_MUL;
-
- video_set_drvdata(&radio->videodev, radio);
-
- retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
- radio_nr);
- if (retval < 0) {
- dev_err(&intf->dev, "could not register video device\n");
- goto err_vdev;
- }
-
- return 0;
-
-err_vdev:
- v4l2_device_unregister(&radio->v4l2_dev);
-err_v4l2:
- kfree(radio->buffer);
-err_nobuf:
- kfree(radio);
-err:
- return retval;
-}
-
-module_usb_driver(usb_amradio_driver);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-rtrack2.c b/ANDROID_3.4.5/drivers/media/radio/radio-rtrack2.c
deleted file mode 100644
index b275c5d0..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-rtrack2.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * RadioTrack II driver
- * Copyright 1998 Ben Pfaff
- *
- * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
- * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
- *
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/delay.h> /* udelay */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/mutex.h>
-#include <linux/io.h> /* outb, outb_p */
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include "radio-isa.h"
-
-MODULE_AUTHOR("Ben Pfaff");
-MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1.99");
-
-#ifndef CONFIG_RADIO_RTRACK2_PORT
-#define CONFIG_RADIO_RTRACK2_PORT -1
-#endif
-
-#define RTRACK2_MAX 2
-
-static int io[RTRACK2_MAX] = { [0] = CONFIG_RADIO_RTRACK2_PORT,
- [1 ... (RTRACK2_MAX - 1)] = -1 };
-static int radio_nr[RTRACK2_MAX] = { [0 ... (RTRACK2_MAX - 1)] = -1 };
-
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-static struct radio_isa_card *rtrack2_alloc(void)
-{
- return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL);
-}
-
-static void zero(struct radio_isa_card *isa)
-{
- outb_p(1, isa->io);
- outb_p(3, isa->io);
- outb_p(1, isa->io);
-}
-
-static void one(struct radio_isa_card *isa)
-{
- outb_p(5, isa->io);
- outb_p(7, isa->io);
- outb_p(5, isa->io);
-}
-
-static int rtrack2_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- int i;
-
- freq = freq / 200 + 856;
-
- outb_p(0xc8, isa->io);
- outb_p(0xc9, isa->io);
- outb_p(0xc9, isa->io);
-
- for (i = 0; i < 10; i++)
- zero(isa);
-
- for (i = 14; i >= 0; i--)
- if (freq & (1 << i))
- one(isa);
- else
- zero(isa);
-
- outb_p(0xc8, isa->io);
- if (!v4l2_ctrl_g_ctrl(isa->mute))
- outb_p(0, isa->io);
- return 0;
-}
-
-static u32 rtrack2_g_signal(struct radio_isa_card *isa)
-{
- /* bit set = no signal present */
- return (inb(isa->io) & 2) ? 0 : 0xffff;
-}
-
-static int rtrack2_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- outb(mute, isa->io);
- return 0;
-}
-
-static const struct radio_isa_ops rtrack2_ops = {
- .alloc = rtrack2_alloc,
- .s_mute_volume = rtrack2_s_mute_volume,
- .s_frequency = rtrack2_s_frequency,
- .g_signal = rtrack2_g_signal,
-};
-
-static const int rtrack2_ioports[] = { 0x20f, 0x30f };
-
-static struct radio_isa_driver rtrack2_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-rtrack2",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = rtrack2_ioports,
- .num_of_io_ports = ARRAY_SIZE(rtrack2_ioports),
- .region_size = 4,
- .card = "AIMSlab RadioTrack II",
- .ops = &rtrack2_ops,
- .has_stereo = true,
-};
-
-static int __init rtrack2_init(void)
-{
- return isa_register_driver(&rtrack2_driver.driver, RTRACK2_MAX);
-}
-
-static void __exit rtrack2_exit(void)
-{
- isa_unregister_driver(&rtrack2_driver.driver);
-}
-
-module_init(rtrack2_init);
-module_exit(rtrack2_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-sf16fmi.c b/ANDROID_3.4.5/drivers/media/radio/radio-sf16fmi.c
deleted file mode 100644
index 22c5743b..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-sf16fmi.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/* SF16-FMI and SF16-FMP radio driver for Linux radio support
- * heavily based on rtrack driver...
- * (c) 1997 M. Kirkwood
- * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz
- *
- * Fitted to new interface by Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Made working and cleaned up functions <mikael.hedin@irf.se>
- * Support for ISAPnP by Ladislav Michl <ladis@psi.cz>
- *
- * Notes on the hardware
- *
- * Frequency control is done digitally -- ie out(port,encodefreq(95.8));
- * No volume control - only mute/unmute - you have to use line volume
- * control on SB-part of SF16-FMI/SF16-FMP
- *
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-#include <linux/kernel.h> /* __setup */
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/delay.h> /* udelay */
-#include <linux/isapnp.h>
-#include <linux/mutex.h>
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/io.h> /* outb, outb_p */
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-
-MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
-MODULE_DESCRIPTION("A driver for the SF16-FMI and SF16-FMP radio.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.3");
-
-static int io = -1;
-static int radio_nr = -1;
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the SF16-FMI or SF16-FMP card (0x284 or 0x384)");
-module_param(radio_nr, int, 0);
-
-struct fmi
-{
- struct v4l2_device v4l2_dev;
- struct video_device vdev;
- int io;
- bool mute;
- unsigned long curfreq; /* freq in kHz */
- struct mutex lock;
-};
-
-static struct fmi fmi_card;
-static struct pnp_dev *dev;
-bool pnp_attached;
-
-/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
-/* It is only useful to give freq in interval of 800 (=0.05Mhz),
- * other bits will be truncated, e.g 92.7400016 -> 92.7, but
- * 92.7400017 -> 92.75
- */
-#define RSF16_ENCODE(x) ((x) / 800 + 214)
-#define RSF16_MINFREQ (87 * 16000)
-#define RSF16_MAXFREQ (108 * 16000)
-
-static void outbits(int bits, unsigned int data, int io)
-{
- while (bits--) {
- if (data & 1) {
- outb(5, io);
- udelay(6);
- outb(7, io);
- udelay(6);
- } else {
- outb(1, io);
- udelay(6);
- outb(3, io);
- udelay(6);
- }
- data >>= 1;
- }
-}
-
-static inline void fmi_mute(struct fmi *fmi)
-{
- mutex_lock(&fmi->lock);
- outb(0x00, fmi->io);
- mutex_unlock(&fmi->lock);
-}
-
-static inline void fmi_unmute(struct fmi *fmi)
-{
- mutex_lock(&fmi->lock);
- outb(0x08, fmi->io);
- mutex_unlock(&fmi->lock);
-}
-
-static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq)
-{
- mutex_lock(&fmi->lock);
- fmi->curfreq = freq;
-
- outbits(16, RSF16_ENCODE(freq), fmi->io);
- outbits(8, 0xC0, fmi->io);
- msleep(143); /* was schedule_timeout(HZ/7) */
- mutex_unlock(&fmi->lock);
- if (!fmi->mute)
- fmi_unmute(fmi);
- return 0;
-}
-
-static inline int fmi_getsigstr(struct fmi *fmi)
-{
- int val;
- int res;
-
- mutex_lock(&fmi->lock);
- val = fmi->mute ? 0x00 : 0x08; /* mute/unmute */
- outb(val, fmi->io);
- outb(val | 0x10, fmi->io);
- msleep(143); /* was schedule_timeout(HZ/7) */
- res = (int)inb(fmi->io + 1);
- outb(val, fmi->io);
-
- mutex_unlock(&fmi->lock);
- return (res & 2) ? 0 : 0xFFFF;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver));
- strlcpy(v->card, "SF16-FMx radio", sizeof(v->card));
- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct fmi *fmi = video_drvdata(file);
-
- if (v->index > 0)
- return -EINVAL;
-
- strlcpy(v->name, "FM", sizeof(v->name));
- v->type = V4L2_TUNER_RADIO;
- v->rangelow = RSF16_MINFREQ;
- v->rangehigh = RSF16_MAXFREQ;
- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
- v->audmode = V4L2_TUNER_MODE_STEREO;
- v->signal = fmi_getsigstr(fmi);
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- return v->index ? -EINVAL : 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct fmi *fmi = video_drvdata(file);
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- if (f->frequency < RSF16_MINFREQ ||
- f->frequency > RSF16_MAXFREQ)
- return -EINVAL;
- /* rounding in steps of 800 to match the freq
- that will be used */
- fmi_setfreq(fmi, (f->frequency / 800) * 800);
- return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct fmi *fmi = video_drvdata(file);
-
- if (f->tuner != 0)
- return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = fmi->curfreq;
- return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct fmi *fmi = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = fmi->mute;
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct fmi *fmi = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value)
- fmi_mute(fmi);
- else
- fmi_unmute(fmi);
- fmi->mute = ctrl->value;
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- return i ? -EINVAL : 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- a->index = 0;
- strlcpy(a->name, "Radio", sizeof(a->name));
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- return a->index ? -EINVAL : 0;
-}
-
-static const struct v4l2_file_operations fmi_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
-};
-
-/* ladis: this is my card. does any other types exist? */
-static struct isapnp_device_id id_table[] __devinitdata = {
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('M','F','R'), ISAPNP_FUNCTION(0xad10), 0},
- { ISAPNP_CARD_END, },
-};
-
-MODULE_DEVICE_TABLE(isapnp, id_table);
-
-static int __init isapnp_fmi_probe(void)
-{
- int i = 0;
-
- while (id_table[i].card_vendor != 0 && dev == NULL) {
- dev = pnp_find_dev(NULL, id_table[i].vendor,
- id_table[i].function, NULL);
- i++;
- }
-
- if (!dev)
- return -ENODEV;
- if (pnp_device_attach(dev) < 0)
- return -EAGAIN;
- if (pnp_activate_dev(dev) < 0) {
- printk(KERN_ERR "radio-sf16fmi: PnP configure failed (out of resources?)\n");
- pnp_device_detach(dev);
- return -ENOMEM;
- }
- if (!pnp_port_valid(dev, 0)) {
- pnp_device_detach(dev);
- return -ENODEV;
- }
-
- i = pnp_port_start(dev, 0);
- printk(KERN_INFO "radio-sf16fmi: PnP reports card at %#x\n", i);
-
- return i;
-}
-
-static int __init fmi_init(void)
-{
- struct fmi *fmi = &fmi_card;
- struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
- int res, i;
- int probe_ports[] = { 0, 0x284, 0x384 };
-
- if (io < 0) {
- for (i = 0; i < ARRAY_SIZE(probe_ports); i++) {
- io = probe_ports[i];
- if (io == 0) {
- io = isapnp_fmi_probe();
- if (io < 0)
- continue;
- pnp_attached = 1;
- }
- if (!request_region(io, 2, "radio-sf16fmi")) {
- if (pnp_attached)
- pnp_device_detach(dev);
- io = -1;
- continue;
- }
- if (pnp_attached ||
- ((inb(io) & 0xf9) == 0xf9 && (inb(io) & 0x4) == 0))
- break;
- release_region(io, 2);
- io = -1;
- }
- } else {
- if (!request_region(io, 2, "radio-sf16fmi")) {
- printk(KERN_ERR "radio-sf16fmi: port %#x already in use\n", io);
- return -EBUSY;
- }
- if (inb(io) == 0xff) {
- printk(KERN_ERR "radio-sf16fmi: card not present at %#x\n", io);
- release_region(io, 2);
- return -ENODEV;
- }
- }
- if (io < 0) {
- printk(KERN_ERR "radio-sf16fmi: no cards found\n");
- return -ENODEV;
- }
-
- strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
- fmi->io = io;
-
- res = v4l2_device_register(NULL, v4l2_dev);
- if (res < 0) {
- release_region(fmi->io, 2);
- if (pnp_attached)
- pnp_device_detach(dev);
- v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
- return res;
- }
-
- strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
- fmi->vdev.v4l2_dev = v4l2_dev;
- fmi->vdev.fops = &fmi_fops;
- fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
- fmi->vdev.release = video_device_release_empty;
- video_set_drvdata(&fmi->vdev, fmi);
-
- mutex_init(&fmi->lock);
-
- /* mute card - prevents noisy bootups */
- fmi_mute(fmi);
-
- if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
- v4l2_device_unregister(v4l2_dev);
- release_region(fmi->io, 2);
- if (pnp_attached)
- pnp_device_detach(dev);
- return -EINVAL;
- }
-
- v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
- return 0;
-}
-
-static void __exit fmi_exit(void)
-{
- struct fmi *fmi = &fmi_card;
-
- video_unregister_device(&fmi->vdev);
- v4l2_device_unregister(&fmi->v4l2_dev);
- release_region(fmi->io, 2);
- if (dev && pnp_attached)
- pnp_device_detach(dev);
-}
-
-module_init(fmi_init);
-module_exit(fmi_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-sf16fmr2.c b/ANDROID_3.4.5/drivers/media/radio/radio-sf16fmr2.c
deleted file mode 100644
index 7c692143..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-sf16fmr2.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/* SF16-FMR2 radio driver for Linux
- * Copyright (c) 2011 Ondrej Zary
- *
- * Original driver was (c) 2000-2002 Ziglio Frediano, freddy77@angelfire.com
- * but almost nothing remained here after conversion to generic TEA575x
- * implementation
- */
-
-#include <linux/delay.h>
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/slab.h>
-#include <linux/ioport.h> /* request_region */
-#include <linux/io.h> /* outb, outb_p */
-#include <linux/isa.h>
-#include <sound/tea575x-tuner.h>
-
-MODULE_AUTHOR("Ondrej Zary");
-MODULE_DESCRIPTION("MediaForte SF16-FMR2 FM radio card driver");
-MODULE_LICENSE("GPL");
-
-static int radio_nr = -1;
-module_param(radio_nr, int, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device number");
-
-struct fmr2 {
- int io;
- struct v4l2_device v4l2_dev;
- struct snd_tea575x tea;
- struct v4l2_ctrl *volume;
- struct v4l2_ctrl *balance;
-};
-
-/* the port is hardwired so no need to support multiple cards */
-#define FMR2_PORT 0x384
-
-/* TEA575x tuner pins */
-#define STR_DATA (1 << 0)
-#define STR_CLK (1 << 1)
-#define STR_WREN (1 << 2)
-#define STR_MOST (1 << 3)
-/* PT2254A/TC9154A volume control pins */
-#define PT_ST (1 << 4)
-#define PT_CK (1 << 5)
-#define PT_DATA (1 << 6)
-/* volume control presence pin */
-#define FMR2_HASVOL (1 << 7)
-
-static void fmr2_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
-{
- struct fmr2 *fmr2 = tea->private_data;
- u8 bits = 0;
-
- bits |= (pins & TEA575X_DATA) ? STR_DATA : 0;
- bits |= (pins & TEA575X_CLK) ? STR_CLK : 0;
- /* WRITE_ENABLE is inverted, DATA must be high during read */
- bits |= (pins & TEA575X_WREN) ? 0 : STR_WREN | STR_DATA;
-
- outb(bits, fmr2->io);
-}
-
-static u8 fmr2_tea575x_get_pins(struct snd_tea575x *tea)
-{
- struct fmr2 *fmr2 = tea->private_data;
- u8 bits = inb(fmr2->io);
-
- return (bits & STR_DATA) ? TEA575X_DATA : 0 |
- (bits & STR_MOST) ? TEA575X_MOST : 0;
-}
-
-static void fmr2_tea575x_set_direction(struct snd_tea575x *tea, bool output)
-{
-}
-
-static struct snd_tea575x_ops fmr2_tea_ops = {
- .set_pins = fmr2_tea575x_set_pins,
- .get_pins = fmr2_tea575x_get_pins,
- .set_direction = fmr2_tea575x_set_direction,
-};
-
-/* TC9154A/PT2254A volume control */
-
-/* 18-bit shift register bit definitions */
-#define TC9154A_ATT_MAJ_0DB (1 << 0)
-#define TC9154A_ATT_MAJ_10DB (1 << 1)
-#define TC9154A_ATT_MAJ_20DB (1 << 2)
-#define TC9154A_ATT_MAJ_30DB (1 << 3)
-#define TC9154A_ATT_MAJ_40DB (1 << 4)
-#define TC9154A_ATT_MAJ_50DB (1 << 5)
-#define TC9154A_ATT_MAJ_60DB (1 << 6)
-
-#define TC9154A_ATT_MIN_0DB (1 << 7)
-#define TC9154A_ATT_MIN_2DB (1 << 8)
-#define TC9154A_ATT_MIN_4DB (1 << 9)
-#define TC9154A_ATT_MIN_6DB (1 << 10)
-#define TC9154A_ATT_MIN_8DB (1 << 11)
-/* bit 12 is ignored */
-#define TC9154A_CHANNEL_LEFT (1 << 13)
-#define TC9154A_CHANNEL_RIGHT (1 << 14)
-/* bits 15, 16, 17 must be 0 */
-
-#define TC9154A_ATT_MAJ(x) (1 << x)
-#define TC9154A_ATT_MIN(x) (1 << (7 + x))
-
-static void tc9154a_set_pins(struct fmr2 *fmr2, u8 pins)
-{
- if (!fmr2->tea.mute)
- pins |= STR_WREN;
-
- outb(pins, fmr2->io);
-}
-
-static void tc9154a_set_attenuation(struct fmr2 *fmr2, int att, u32 channel)
-{
- int i;
- u32 reg;
- u8 bit;
-
- reg = TC9154A_ATT_MAJ(att / 10) | TC9154A_ATT_MIN((att % 10) / 2);
- reg |= channel;
- /* write 18-bit shift register, LSB first */
- for (i = 0; i < 18; i++) {
- bit = reg & (1 << i) ? PT_DATA : 0;
- tc9154a_set_pins(fmr2, bit);
- udelay(5);
- tc9154a_set_pins(fmr2, bit | PT_CK);
- udelay(5);
- tc9154a_set_pins(fmr2, bit);
- }
-
- /* latch register data */
- udelay(5);
- tc9154a_set_pins(fmr2, PT_ST);
- udelay(5);
- tc9154a_set_pins(fmr2, 0);
-}
-
-static int fmr2_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler);
- struct fmr2 *fmr2 = tea->private_data;
- int volume, balance, left, right;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_VOLUME:
- volume = ctrl->val;
- balance = fmr2->balance->cur.val;
- break;
- case V4L2_CID_AUDIO_BALANCE:
- balance = ctrl->val;
- volume = fmr2->volume->cur.val;
- break;
- default:
- return -EINVAL;
- }
-
- left = right = volume;
- if (balance < 0)
- right = max(0, right + balance);
- if (balance > 0)
- left = max(0, left - balance);
-
- tc9154a_set_attenuation(fmr2, abs(left - 68), TC9154A_CHANNEL_LEFT);
- tc9154a_set_attenuation(fmr2, abs(right - 68), TC9154A_CHANNEL_RIGHT);
-
- return 0;
-}
-
-static const struct v4l2_ctrl_ops fmr2_ctrl_ops = {
- .s_ctrl = fmr2_s_ctrl,
-};
-
-static int fmr2_tea_ext_init(struct snd_tea575x *tea)
-{
- struct fmr2 *fmr2 = tea->private_data;
-
- if (inb(fmr2->io) & FMR2_HASVOL) {
- fmr2->volume = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_VOLUME, 0, 68, 2, 56);
- fmr2->balance = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_BALANCE, -68, 68, 2, 0);
- if (tea->ctrl_handler.error) {
- printk(KERN_ERR "radio-sf16fmr2: can't initialize controls\n");
- return tea->ctrl_handler.error;
- }
- }
-
- return 0;
-}
-
-static int __devinit fmr2_probe(struct device *pdev, unsigned int dev)
-{
- struct fmr2 *fmr2;
- int err;
-
- fmr2 = kzalloc(sizeof(*fmr2), GFP_KERNEL);
- if (fmr2 == NULL)
- return -ENOMEM;
-
- strlcpy(fmr2->v4l2_dev.name, dev_name(pdev),
- sizeof(fmr2->v4l2_dev.name));
- fmr2->io = FMR2_PORT;
-
- if (!request_region(fmr2->io, 2, fmr2->v4l2_dev.name)) {
- printk(KERN_ERR "radio-sf16fmr2: I/O port 0x%x already in use\n", fmr2->io);
- kfree(fmr2);
- return -EBUSY;
- }
-
- dev_set_drvdata(pdev, fmr2);
- err = v4l2_device_register(pdev, &fmr2->v4l2_dev);
- if (err < 0) {
- v4l2_err(&fmr2->v4l2_dev, "Could not register v4l2_device\n");
- release_region(fmr2->io, 2);
- kfree(fmr2);
- return err;
- }
- fmr2->tea.v4l2_dev = &fmr2->v4l2_dev;
- fmr2->tea.private_data = fmr2;
- fmr2->tea.radio_nr = radio_nr;
- fmr2->tea.ops = &fmr2_tea_ops;
- fmr2->tea.ext_init = fmr2_tea_ext_init;
- strlcpy(fmr2->tea.card, "SF16-FMR2", sizeof(fmr2->tea.card));
- snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "ISA:%s",
- fmr2->v4l2_dev.name);
-
- if (snd_tea575x_init(&fmr2->tea)) {
- printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n");
- release_region(fmr2->io, 2);
- kfree(fmr2);
- return -ENODEV;
- }
-
- printk(KERN_INFO "radio-sf16fmr2: SF16-FMR2 radio card at 0x%x.\n", fmr2->io);
- return 0;
-}
-
-static int __exit fmr2_remove(struct device *pdev, unsigned int dev)
-{
- struct fmr2 *fmr2 = dev_get_drvdata(pdev);
-
- snd_tea575x_exit(&fmr2->tea);
- release_region(fmr2->io, 2);
- v4l2_device_unregister(&fmr2->v4l2_dev);
- kfree(fmr2);
- return 0;
-}
-
-struct isa_driver fmr2_driver = {
- .probe = fmr2_probe,
- .remove = fmr2_remove,
- .driver = {
- .name = "radio-sf16fmr2",
- },
-};
-
-static int __init fmr2_init(void)
-{
- return isa_register_driver(&fmr2_driver, 1);
-}
-
-static void __exit fmr2_exit(void)
-{
- isa_unregister_driver(&fmr2_driver);
-}
-
-module_init(fmr2_init);
-module_exit(fmr2_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-si4713.c b/ANDROID_3.4.5/drivers/media/radio/radio-si4713.c
deleted file mode 100644
index c54210c7..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-si4713.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * drivers/media/radio/radio-si4713.c
- *
- * Platform Driver for Silicon Labs Si4713 FM Radio Transmitter:
- *
- * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
- * Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/radio-si4713.h>
-
-/* module parameters */
-static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */
-module_param(radio_nr, int, 0);
-MODULE_PARM_DESC(radio_nr,
- "Minor number for radio device (-1 ==> auto assign)");
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>");
-MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter");
-MODULE_VERSION("0.0.1");
-
-/* Driver state struct */
-struct radio_si4713_device {
- struct v4l2_device v4l2_dev;
- struct video_device *radio_dev;
-};
-
-/* radio_si4713_fops - file operations interface */
-static const struct v4l2_file_operations radio_si4713_fops = {
- .owner = THIS_MODULE,
- /* Note: locking is done at the subdev level in the i2c driver. */
- .unlocked_ioctl = video_ioctl2,
-};
-
-/* Video4Linux Interface */
-static int radio_si4713_fill_audout(struct v4l2_audioout *vao)
-{
- /* TODO: check presence of audio output */
- strlcpy(vao->name, "FM Modulator Audio Out", 32);
-
- return 0;
-}
-
-static int radio_si4713_enumaudout(struct file *file, void *priv,
- struct v4l2_audioout *vao)
-{
- return radio_si4713_fill_audout(vao);
-}
-
-static int radio_si4713_g_audout(struct file *file, void *priv,
- struct v4l2_audioout *vao)
-{
- int rval = radio_si4713_fill_audout(vao);
-
- vao->index = 0;
-
- return rval;
-}
-
-static int radio_si4713_s_audout(struct file *file, void *priv,
- struct v4l2_audioout *vao)
-{
- return vao->index ? -EINVAL : 0;
-}
-
-/* radio_si4713_querycap - query device capabilities */
-static int radio_si4713_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability)
-{
- strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
- strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
- sizeof(capability->card));
- capability->capabilities = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
-
- return 0;
-}
-
-/* radio_si4713_queryctrl - enumerate control items */
-static int radio_si4713_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- /* Must be sorted from low to high control ID! */
- static const u32 user_ctrls[] = {
- V4L2_CID_USER_CLASS,
- V4L2_CID_AUDIO_MUTE,
- 0
- };
-
- /* Must be sorted from low to high control ID! */
- static const u32 fmtx_ctrls[] = {
- V4L2_CID_FM_TX_CLASS,
- V4L2_CID_RDS_TX_DEVIATION,
- V4L2_CID_RDS_TX_PI,
- V4L2_CID_RDS_TX_PTY,
- V4L2_CID_RDS_TX_PS_NAME,
- V4L2_CID_RDS_TX_RADIO_TEXT,
- V4L2_CID_AUDIO_LIMITER_ENABLED,
- V4L2_CID_AUDIO_LIMITER_RELEASE_TIME,
- V4L2_CID_AUDIO_LIMITER_DEVIATION,
- V4L2_CID_AUDIO_COMPRESSION_ENABLED,
- V4L2_CID_AUDIO_COMPRESSION_GAIN,
- V4L2_CID_AUDIO_COMPRESSION_THRESHOLD,
- V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME,
- V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME,
- V4L2_CID_PILOT_TONE_ENABLED,
- V4L2_CID_PILOT_TONE_DEVIATION,
- V4L2_CID_PILOT_TONE_FREQUENCY,
- V4L2_CID_TUNE_PREEMPHASIS,
- V4L2_CID_TUNE_POWER_LEVEL,
- V4L2_CID_TUNE_ANTENNA_CAPACITOR,
- 0
- };
- static const u32 *ctrl_classes[] = {
- user_ctrls,
- fmtx_ctrls,
- NULL
- };
- struct radio_si4713_device *rsdev;
-
- rsdev = video_get_drvdata(video_devdata(file));
-
- qc->id = v4l2_ctrl_next(ctrl_classes, qc->id);
- if (qc->id == 0)
- return -EINVAL;
-
- if (qc->id == V4L2_CID_USER_CLASS || qc->id == V4L2_CID_FM_TX_CLASS)
- return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0);
-
- return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core,
- queryctrl, qc);
-}
-
-/*
- * v4l2 ioctl call backs.
- * we are just a wrapper for v4l2_sub_devs.
- */
-static inline struct v4l2_device *get_v4l2_dev(struct file *file)
-{
- return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev;
-}
-
-static int radio_si4713_g_ext_ctrls(struct file *file, void *p,
- struct v4l2_ext_controls *vecs)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
- g_ext_ctrls, vecs);
-}
-
-static int radio_si4713_s_ext_ctrls(struct file *file, void *p,
- struct v4l2_ext_controls *vecs)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
- s_ext_ctrls, vecs);
-}
-
-static int radio_si4713_g_ctrl(struct file *file, void *p,
- struct v4l2_control *vc)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
- g_ctrl, vc);
-}
-
-static int radio_si4713_s_ctrl(struct file *file, void *p,
- struct v4l2_control *vc)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
- s_ctrl, vc);
-}
-
-static int radio_si4713_g_modulator(struct file *file, void *p,
- struct v4l2_modulator *vm)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
- g_modulator, vm);
-}
-
-static int radio_si4713_s_modulator(struct file *file, void *p,
- struct v4l2_modulator *vm)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
- s_modulator, vm);
-}
-
-static int radio_si4713_g_frequency(struct file *file, void *p,
- struct v4l2_frequency *vf)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
- g_frequency, vf);
-}
-
-static int radio_si4713_s_frequency(struct file *file, void *p,
- struct v4l2_frequency *vf)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
- s_frequency, vf);
-}
-
-static long radio_si4713_default(struct file *file, void *p,
- bool valid_prio, int cmd, void *arg)
-{
- return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
- ioctl, cmd, arg);
-}
-
-static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
- .vidioc_enumaudout = radio_si4713_enumaudout,
- .vidioc_g_audout = radio_si4713_g_audout,
- .vidioc_s_audout = radio_si4713_s_audout,
- .vidioc_querycap = radio_si4713_querycap,
- .vidioc_queryctrl = radio_si4713_queryctrl,
- .vidioc_g_ext_ctrls = radio_si4713_g_ext_ctrls,
- .vidioc_s_ext_ctrls = radio_si4713_s_ext_ctrls,
- .vidioc_g_ctrl = radio_si4713_g_ctrl,
- .vidioc_s_ctrl = radio_si4713_s_ctrl,
- .vidioc_g_modulator = radio_si4713_g_modulator,
- .vidioc_s_modulator = radio_si4713_s_modulator,
- .vidioc_g_frequency = radio_si4713_g_frequency,
- .vidioc_s_frequency = radio_si4713_s_frequency,
- .vidioc_default = radio_si4713_default,
-};
-
-/* radio_si4713_vdev_template - video device interface */
-static struct video_device radio_si4713_vdev_template = {
- .fops = &radio_si4713_fops,
- .name = "radio-si4713",
- .release = video_device_release,
- .ioctl_ops = &radio_si4713_ioctl_ops,
-};
-
-/* Platform driver interface */
-/* radio_si4713_pdriver_probe - probe for the device */
-static int radio_si4713_pdriver_probe(struct platform_device *pdev)
-{
- struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
- struct radio_si4713_device *rsdev;
- struct i2c_adapter *adapter;
- struct v4l2_subdev *sd;
- int rval = 0;
-
- if (!pdata) {
- dev_err(&pdev->dev, "Cannot proceed without platform data.\n");
- rval = -EINVAL;
- goto exit;
- }
-
- rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL);
- if (!rsdev) {
- dev_err(&pdev->dev, "Failed to alloc video device.\n");
- rval = -ENOMEM;
- goto exit;
- }
-
- rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev);
- if (rval) {
- dev_err(&pdev->dev, "Failed to register v4l2 device.\n");
- goto free_rsdev;
- }
-
- adapter = i2c_get_adapter(pdata->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
- pdata->i2c_bus);
- rval = -ENODEV;
- goto unregister_v4l2_dev;
- }
-
- sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
- pdata->subdev_board_info, NULL);
- if (!sd) {
- dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
- rval = -ENODEV;
- goto put_adapter;
- }
-
- rsdev->radio_dev = video_device_alloc();
- if (!rsdev->radio_dev) {
- dev_err(&pdev->dev, "Failed to alloc video device.\n");
- rval = -ENOMEM;
- goto put_adapter;
- }
-
- memcpy(rsdev->radio_dev, &radio_si4713_vdev_template,
- sizeof(radio_si4713_vdev_template));
- video_set_drvdata(rsdev->radio_dev, rsdev);
- if (video_register_device(rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
- dev_err(&pdev->dev, "Could not register video device.\n");
- rval = -EIO;
- goto free_vdev;
- }
- dev_info(&pdev->dev, "New device successfully probed\n");
-
- goto exit;
-
-free_vdev:
- video_device_release(rsdev->radio_dev);
-put_adapter:
- i2c_put_adapter(adapter);
-unregister_v4l2_dev:
- v4l2_device_unregister(&rsdev->v4l2_dev);
-free_rsdev:
- kfree(rsdev);
-exit:
- return rval;
-}
-
-/* radio_si4713_pdriver_remove - remove the device */
-static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev)
-{
- struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
- struct radio_si4713_device *rsdev = container_of(v4l2_dev,
- struct radio_si4713_device,
- v4l2_dev);
- struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
- struct v4l2_subdev, list);
- struct i2c_client *client = v4l2_get_subdevdata(sd);
-
- video_unregister_device(rsdev->radio_dev);
- i2c_put_adapter(client->adapter);
- v4l2_device_unregister(&rsdev->v4l2_dev);
- kfree(rsdev);
-
- return 0;
-}
-
-static struct platform_driver radio_si4713_pdriver = {
- .driver = {
- .name = "radio-si4713",
- },
- .probe = radio_si4713_pdriver_probe,
- .remove = __exit_p(radio_si4713_pdriver_remove),
-};
-
-module_platform_driver(radio_si4713_pdriver);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-tea5764.c b/ANDROID_3.4.5/drivers/media/radio/radio-tea5764.c
deleted file mode 100644
index 6b1fae32..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-tea5764.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * driver/media/radio/radio-tea5764.c
- *
- * Driver for TEA5764 radio chip for linux 2.6.
- * This driver is for TEA5764 chip from NXP, used in EZX phones from Motorola.
- * The I2C protocol is used for communicate with chip.
- *
- * Based in radio-tea5761.c Copyright (C) 2005 Nokia Corporation
- *
- * Copyright (c) 2008 Fabio Belavenuto <belavenuto@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * History:
- * 2008-12-06 Fabio Belavenuto <belavenuto@gmail.com>
- * initial code
- *
- * TODO:
- * add platform_data support for IRQs platform dependencies
- * add RDS support
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h> /* Initdata */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/i2c.h> /* I2C */
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-#define DRIVER_VERSION "0.0.2"
-
-#define DRIVER_AUTHOR "Fabio Belavenuto <belavenuto@gmail.com>"
-#define DRIVER_DESC "A driver for the TEA5764 radio chip for EZX Phones."
-
-#define PINFO(format, ...)\
- printk(KERN_INFO KBUILD_MODNAME ": "\
- DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
-#define PWARN(format, ...)\
- printk(KERN_WARNING KBUILD_MODNAME ": "\
- DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
-# define PDEBUG(format, ...)\
- printk(KERN_DEBUG KBUILD_MODNAME ": "\
- DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
-
-/* Frequency limits in MHz -- these are European values. For Japanese
-devices, that would be 76000 and 91000. */
-#define FREQ_MIN 87500
-#define FREQ_MAX 108000
-#define FREQ_MUL 16
-
-/* TEA5764 registers */
-#define TEA5764_MANID 0x002b
-#define TEA5764_CHIPID 0x5764
-
-#define TEA5764_INTREG_BLMSK 0x0001
-#define TEA5764_INTREG_FRRMSK 0x0002
-#define TEA5764_INTREG_LEVMSK 0x0008
-#define TEA5764_INTREG_IFMSK 0x0010
-#define TEA5764_INTREG_BLMFLAG 0x0100
-#define TEA5764_INTREG_FRRFLAG 0x0200
-#define TEA5764_INTREG_LEVFLAG 0x0800
-#define TEA5764_INTREG_IFFLAG 0x1000
-
-#define TEA5764_FRQSET_SUD 0x8000
-#define TEA5764_FRQSET_SM 0x4000
-
-#define TEA5764_TNCTRL_PUPD1 0x8000
-#define TEA5764_TNCTRL_PUPD0 0x4000
-#define TEA5764_TNCTRL_BLIM 0x2000
-#define TEA5764_TNCTRL_SWPM 0x1000
-#define TEA5764_TNCTRL_IFCTC 0x0800
-#define TEA5764_TNCTRL_AFM 0x0400
-#define TEA5764_TNCTRL_SMUTE 0x0200
-#define TEA5764_TNCTRL_SNC 0x0100
-#define TEA5764_TNCTRL_MU 0x0080
-#define TEA5764_TNCTRL_SSL1 0x0040
-#define TEA5764_TNCTRL_SSL0 0x0020
-#define TEA5764_TNCTRL_HLSI 0x0010
-#define TEA5764_TNCTRL_MST 0x0008
-#define TEA5764_TNCTRL_SWP 0x0004
-#define TEA5764_TNCTRL_DTC 0x0002
-#define TEA5764_TNCTRL_AHLSI 0x0001
-
-#define TEA5764_TUNCHK_LEVEL(x) (((x) & 0x00F0) >> 4)
-#define TEA5764_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
-#define TEA5764_TUNCHK_TUNTO 0x0100
-#define TEA5764_TUNCHK_LD 0x0008
-#define TEA5764_TUNCHK_STEREO 0x0004
-
-#define TEA5764_TESTREG_TRIGFR 0x0800
-
-struct tea5764_regs {
- u16 intreg; /* INTFLAG & INTMSK */
- u16 frqset; /* FRQSETMSB & FRQSETLSB */
- u16 tnctrl; /* TNCTRL1 & TNCTRL2 */
- u16 frqchk; /* FRQCHKMSB & FRQCHKLSB */
- u16 tunchk; /* IFCHK & LEVCHK */
- u16 testreg; /* TESTBITS & TESTMODE */
- u16 rdsstat; /* RDSSTAT1 & RDSSTAT2 */
- u16 rdslb; /* RDSLBMSB & RDSLBLSB */
- u16 rdspb; /* RDSPBMSB & RDSPBLSB */
- u16 rdsbc; /* RDSBBC & RDSGBC */
- u16 rdsctrl; /* RDSCTRL1 & RDSCTRL2 */
- u16 rdsbbl; /* PAUSEDET & RDSBBL */
- u16 manid; /* MANID1 & MANID2 */
- u16 chipid; /* CHIPID1 & CHIPID2 */
-} __attribute__ ((packed));
-
-struct tea5764_write_regs {
- u8 intreg; /* INTMSK */
- u16 frqset; /* FRQSETMSB & FRQSETLSB */
- u16 tnctrl; /* TNCTRL1 & TNCTRL2 */
- u16 testreg; /* TESTBITS & TESTMODE */
- u16 rdsctrl; /* RDSCTRL1 & RDSCTRL2 */
- u16 rdsbbl; /* PAUSEDET & RDSBBL */
-} __attribute__ ((packed));
-
-#ifdef CONFIG_RADIO_TEA5764_XTAL
-#define RADIO_TEA5764_XTAL 1
-#else
-#define RADIO_TEA5764_XTAL 0
-#endif
-
-static int radio_nr = -1;
-static int use_xtal = RADIO_TEA5764_XTAL;
-
-struct tea5764_device {
- struct i2c_client *i2c_client;
- struct video_device *videodev;
- struct tea5764_regs regs;
- struct mutex mutex;
-};
-
-/* I2C code related */
-int tea5764_i2c_read(struct tea5764_device *radio)
-{
- int i;
- u16 *p = (u16 *) &radio->regs;
-
- struct i2c_msg msgs[1] = {
- { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs),
- (void *)&radio->regs },
- };
- if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
- return -EIO;
- for (i = 0; i < sizeof(struct tea5764_regs) / sizeof(u16); i++)
- p[i] = __be16_to_cpu(p[i]);
-
- return 0;
-}
-
-int tea5764_i2c_write(struct tea5764_device *radio)
-{
- struct tea5764_write_regs wr;
- struct tea5764_regs *r = &radio->regs;
- struct i2c_msg msgs[1] = {
- { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr },
- };
- wr.intreg = r->intreg & 0xff;
- wr.frqset = __cpu_to_be16(r->frqset);
- wr.tnctrl = __cpu_to_be16(r->tnctrl);
- wr.testreg = __cpu_to_be16(r->testreg);
- wr.rdsctrl = __cpu_to_be16(r->rdsctrl);
- wr.rdsbbl = __cpu_to_be16(r->rdsbbl);
- if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
- return -EIO;
- return 0;
-}
-
-/* V4L2 code related */
-static struct v4l2_queryctrl radio_qctrl[] = {
- {
- .id = V4L2_CID_AUDIO_MUTE,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .default_value = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- }
-};
-
-static void tea5764_power_up(struct tea5764_device *radio)
-{
- struct tea5764_regs *r = &radio->regs;
-
- if (!(r->tnctrl & TEA5764_TNCTRL_PUPD0)) {
- r->tnctrl &= ~(TEA5764_TNCTRL_AFM | TEA5764_TNCTRL_MU |
- TEA5764_TNCTRL_HLSI);
- if (!use_xtal)
- r->testreg |= TEA5764_TESTREG_TRIGFR;
- else
- r->testreg &= ~TEA5764_TESTREG_TRIGFR;
-
- r->tnctrl |= TEA5764_TNCTRL_PUPD0;
- tea5764_i2c_write(radio);
- }
-}
-
-static void tea5764_power_down(struct tea5764_device *radio)
-{
- struct tea5764_regs *r = &radio->regs;
-
- if (r->tnctrl & TEA5764_TNCTRL_PUPD0) {
- r->tnctrl &= ~TEA5764_TNCTRL_PUPD0;
- tea5764_i2c_write(radio);
- }
-}
-
-static void tea5764_set_freq(struct tea5764_device *radio, int freq)
-{
- struct tea5764_regs *r = &radio->regs;
-
- /* formula: (freq [+ or -] 225000) / 8192 */
- if (r->tnctrl & TEA5764_TNCTRL_HLSI)
- r->frqset = (freq + 225000) / 8192;
- else
- r->frqset = (freq - 225000) / 8192;
-}
-
-static int tea5764_get_freq(struct tea5764_device *radio)
-{
- struct tea5764_regs *r = &radio->regs;
-
- if (r->tnctrl & TEA5764_TNCTRL_HLSI)
- return (r->frqchk * 8192) - 225000;
- else
- return (r->frqchk * 8192) + 225000;
-}
-
-/* tune an frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
-static void tea5764_tune(struct tea5764_device *radio, int freq)
-{
- tea5764_set_freq(radio, freq);
- if (tea5764_i2c_write(radio))
- PWARN("Could not set frequency!");
-}
-
-static void tea5764_set_audout_mode(struct tea5764_device *radio, int audmode)
-{
- struct tea5764_regs *r = &radio->regs;
- int tnctrl = r->tnctrl;
-
- if (audmode == V4L2_TUNER_MODE_MONO)
- r->tnctrl |= TEA5764_TNCTRL_MST;
- else
- r->tnctrl &= ~TEA5764_TNCTRL_MST;
- if (tnctrl != r->tnctrl)
- tea5764_i2c_write(radio);
-}
-
-static int tea5764_get_audout_mode(struct tea5764_device *radio)
-{
- struct tea5764_regs *r = &radio->regs;
-
- if (r->tnctrl & TEA5764_TNCTRL_MST)
- return V4L2_TUNER_MODE_MONO;
- else
- return V4L2_TUNER_MODE_STEREO;
-}
-
-static void tea5764_mute(struct tea5764_device *radio, int on)
-{
- struct tea5764_regs *r = &radio->regs;
- int tnctrl = r->tnctrl;
-
- if (on)
- r->tnctrl |= TEA5764_TNCTRL_MU;
- else
- r->tnctrl &= ~TEA5764_TNCTRL_MU;
- if (tnctrl != r->tnctrl)
- tea5764_i2c_write(radio);
-}
-
-static int tea5764_is_muted(struct tea5764_device *radio)
-{
- return radio->regs.tnctrl & TEA5764_TNCTRL_MU;
-}
-
-/* V4L2 vidioc */
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- struct tea5764_device *radio = video_drvdata(file);
- struct video_device *dev = radio->videodev;
-
- strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
- strlcpy(v->card, dev->name, sizeof(v->card));
- snprintf(v->bus_info, sizeof(v->bus_info),
- "I2C:%s", dev_name(&dev->dev));
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct tea5764_device *radio = video_drvdata(file);
- struct tea5764_regs *r = &radio->regs;
-
- if (v->index > 0)
- return -EINVAL;
-
- memset(v, 0, sizeof(*v));
- strcpy(v->name, "FM");
- v->type = V4L2_TUNER_RADIO;
- tea5764_i2c_read(radio);
- v->rangelow = FREQ_MIN * FREQ_MUL;
- v->rangehigh = FREQ_MAX * FREQ_MUL;
- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
- if (r->tunchk & TEA5764_TUNCHK_STEREO)
- v->rxsubchans = V4L2_TUNER_SUB_STEREO;
- else
- v->rxsubchans = V4L2_TUNER_SUB_MONO;
- v->audmode = tea5764_get_audout_mode(radio);
- v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
- v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk);
-
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct tea5764_device *radio = video_drvdata(file);
-
- if (v->index > 0)
- return -EINVAL;
-
- tea5764_set_audout_mode(radio, v->audmode);
- return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct tea5764_device *radio = video_drvdata(file);
-
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
- return -EINVAL;
- if (f->frequency == 0) {
- /* We special case this as a power down control. */
- tea5764_power_down(radio);
- }
- if (f->frequency < (FREQ_MIN * FREQ_MUL))
- return -EINVAL;
- if (f->frequency > (FREQ_MAX * FREQ_MUL))
- return -EINVAL;
- tea5764_power_up(radio);
- tea5764_tune(radio, (f->frequency * 125) / 2);
- return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct tea5764_device *radio = video_drvdata(file);
- struct tea5764_regs *r = &radio->regs;
-
- if (f->tuner != 0)
- return -EINVAL;
- tea5764_i2c_read(radio);
- memset(f, 0, sizeof(*f));
- f->type = V4L2_TUNER_RADIO;
- if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
- f->frequency = (tea5764_get_freq(radio) * 2) / 125;
- else
- f->frequency = 0;
-
- return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
- if (qc->id && qc->id == radio_qctrl[i].id) {
- memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
- return 0;
- }
- }
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct tea5764_device *radio = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- tea5764_i2c_read(radio);
- ctrl->value = tea5764_is_muted(radio) ? 1 : 0;
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct tea5764_device *radio = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- tea5764_mute(radio, ctrl->value);
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- if (i != 0)
- return -EINVAL;
- return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- if (a->index > 1)
- return -EINVAL;
-
- strcpy(a->name, "Radio");
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- if (a->index != 0)
- return -EINVAL;
-
- return 0;
-}
-
-/* File system interface */
-static const struct v4l2_file_operations tea5764_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
-};
-
-/* V4L2 interface */
-static struct video_device tea5764_radio_template = {
- .name = "TEA5764 FM-Radio",
- .fops = &tea5764_fops,
- .ioctl_ops = &tea5764_ioctl_ops,
- .release = video_device_release,
-};
-
-/* I2C probe: check if the device exists and register with v4l if it is */
-static int __devinit tea5764_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct tea5764_device *radio;
- struct tea5764_regs *r;
- int ret;
-
- PDEBUG("probe");
- radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);
- if (!radio)
- return -ENOMEM;
-
- mutex_init(&radio->mutex);
- radio->i2c_client = client;
- ret = tea5764_i2c_read(radio);
- if (ret)
- goto errfr;
- r = &radio->regs;
- PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid);
- if (r->chipid != TEA5764_CHIPID ||
- (r->manid & 0x0fff) != TEA5764_MANID) {
- PWARN("This chip is not a TEA5764!");
- ret = -EINVAL;
- goto errfr;
- }
-
- radio->videodev = video_device_alloc();
- if (!(radio->videodev)) {
- ret = -ENOMEM;
- goto errfr;
- }
- memcpy(radio->videodev, &tea5764_radio_template,
- sizeof(tea5764_radio_template));
-
- i2c_set_clientdata(client, radio);
- video_set_drvdata(radio->videodev, radio);
- radio->videodev->lock = &radio->mutex;
-
- /* initialize and power off the chip */
- tea5764_i2c_read(radio);
- tea5764_set_audout_mode(radio, V4L2_TUNER_MODE_STEREO);
- tea5764_mute(radio, 1);
- tea5764_power_down(radio);
-
- ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
- if (ret < 0) {
- PWARN("Could not register video device!");
- goto errrel;
- }
-
- PINFO("registered.");
- return 0;
-errrel:
- video_device_release(radio->videodev);
-errfr:
- kfree(radio);
- return ret;
-}
-
-static int __devexit tea5764_i2c_remove(struct i2c_client *client)
-{
- struct tea5764_device *radio = i2c_get_clientdata(client);
-
- PDEBUG("remove");
- if (radio) {
- tea5764_power_down(radio);
- video_unregister_device(radio->videodev);
- kfree(radio);
- }
- return 0;
-}
-
-/* I2C subsystem interface */
-static const struct i2c_device_id tea5764_id[] = {
- { "radio-tea5764", 0 },
- { } /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(i2c, tea5764_id);
-
-static struct i2c_driver tea5764_i2c_driver = {
- .driver = {
- .name = "radio-tea5764",
- .owner = THIS_MODULE,
- },
- .probe = tea5764_i2c_probe,
- .remove = __devexit_p(tea5764_i2c_remove),
- .id_table = tea5764_id,
-};
-
-module_i2c_driver(tea5764_i2c_driver);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
-
-module_param(use_xtal, int, 0);
-MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board");
-module_param(radio_nr, int, 0);
-MODULE_PARM_DESC(radio_nr, "video4linux device number to use");
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-terratec.c b/ANDROID_3.4.5/drivers/media/radio/radio-terratec.c
deleted file mode 100644
index be10a802..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-terratec.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* Terratec ActiveRadio ISA Standalone card driver for Linux radio support
- * (c) 1999 R. Offermanns (rolf@offermanns.de)
- * based on the aimslab radio driver from M. Kirkwood
- * many thanks to Michael Becker and Friedhelm Birth (from TerraTec)
- *
- *
- * History:
- * 1999-05-21 First preview release
- *
- * Notes on the hardware:
- * There are two "main" chips on the card:
- * - Philips OM5610 (http://www-us.semiconductors.philips.com/acrobat/datasheets/OM5610_2.pdf)
- * - Philips SAA6588 (http://www-us.semiconductors.philips.com/acrobat/datasheets/SAA6588_1.pdf)
- * (you can get the datasheet at the above links)
- *
- * Frequency control is done digitally -- ie out(port,encodefreq(95.8));
- * Volume Control is done digitally
- *
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/mutex.h>
-#include <linux/io.h> /* outb, outb_p */
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include "radio-isa.h"
-
-MODULE_AUTHOR("R. Offermans & others");
-MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1.99");
-
-/* Note: there seems to be only one possible port (0x590), but without
- hardware this is hard to verify. For now, this is the only one we will
- support. */
-static int io = 0x590;
-static int radio_nr = -1;
-
-module_param(radio_nr, int, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device number");
-
-#define WRT_DIS 0x00
-#define CLK_OFF 0x00
-#define IIC_DATA 0x01
-#define IIC_CLK 0x02
-#define DATA 0x04
-#define CLK_ON 0x08
-#define WRT_EN 0x10
-
-static struct radio_isa_card *terratec_alloc(void)
-{
- return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL);
-}
-
-static int terratec_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- int i;
-
- if (mute)
- vol = 0;
- vol = vol + (vol * 32); /* change both channels */
- for (i = 0; i < 8; i++) {
- if (vol & (0x80 >> i))
- outb(0x80, isa->io + 1);
- else
- outb(0x00, isa->io + 1);
- }
- return 0;
-}
-
-
-/* this is the worst part in this driver */
-/* many more or less strange things are going on here, but hey, it works :) */
-
-static int terratec_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- int i;
- int p;
- int temp;
- long rest;
- unsigned char buffer[25]; /* we have to bit shift 25 registers */
-
- freq = freq / 160; /* convert the freq. to a nice to handle value */
- memset(buffer, 0, sizeof(buffer));
-
- rest = freq * 10 + 10700; /* I once had understood what is going on here */
- /* maybe some wise guy (friedhelm?) can comment this stuff */
- i = 13;
- p = 10;
- temp = 102400;
- while (rest != 0) {
- if (rest % temp == rest)
- buffer[i] = 0;
- else {
- buffer[i] = 1;
- rest = rest - temp;
- }
- i--;
- p--;
- temp = temp / 2;
- }
-
- for (i = 24; i > -1; i--) { /* bit shift the values to the radiocard */
- if (buffer[i] == 1) {
- outb(WRT_EN | DATA, isa->io);
- outb(WRT_EN | DATA | CLK_ON, isa->io);
- outb(WRT_EN | DATA, isa->io);
- } else {
- outb(WRT_EN | 0x00, isa->io);
- outb(WRT_EN | 0x00 | CLK_ON, isa->io);
- }
- }
- outb(0x00, isa->io);
- return 0;
-}
-
-static u32 terratec_g_signal(struct radio_isa_card *isa)
-{
- /* bit set = no signal present */
- return (inb(isa->io) & 2) ? 0 : 0xffff;
-}
-
-static const struct radio_isa_ops terratec_ops = {
- .alloc = terratec_alloc,
- .s_mute_volume = terratec_s_mute_volume,
- .s_frequency = terratec_s_frequency,
- .g_signal = terratec_g_signal,
-};
-
-static const int terratec_ioports[] = { 0x590 };
-
-static struct radio_isa_driver terratec_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-terratec",
- },
- },
- .io_params = &io,
- .radio_nr_params = &radio_nr,
- .io_ports = terratec_ioports,
- .num_of_io_ports = ARRAY_SIZE(terratec_ioports),
- .region_size = 2,
- .card = "TerraTec ActiveRadio",
- .ops = &terratec_ops,
- .has_stereo = true,
- .max_volume = 10,
-};
-
-static int __init terratec_init(void)
-{
- return isa_register_driver(&terratec_driver.driver, 1);
-}
-
-static void __exit terratec_exit(void)
-{
- isa_unregister_driver(&terratec_driver.driver);
-}
-
-module_init(terratec_init);
-module_exit(terratec_exit);
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-timb.c b/ANDROID_3.4.5/drivers/media/radio/radio-timb.c
deleted file mode 100644
index 5d9a90ac..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-timb.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * radio-timb.c Timberdale FPGA Radio driver
- * Copyright (c) 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/io.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <media/timb_radio.h>
-
-#define DRIVER_NAME "timb-radio"
-
-struct timbradio {
- struct timb_radio_platform_data pdata;
- struct v4l2_subdev *sd_tuner;
- struct v4l2_subdev *sd_dsp;
- struct video_device video_dev;
- struct v4l2_device v4l2_dev;
- struct mutex lock;
-};
-
-
-static int timbradio_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
-{
- strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver));
- strlcpy(v->card, "Timberdale Radio", sizeof(v->card));
- snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME);
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- return 0;
-}
-
-static int timbradio_vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_tuner, tuner, g_tuner, v);
-}
-
-static int timbradio_vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v);
-}
-
-static int timbradio_vidioc_g_input(struct file *filp, void *priv,
- unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int timbradio_vidioc_s_input(struct file *filp, void *priv,
- unsigned int i)
-{
- return i ? -EINVAL : 0;
-}
-
-static int timbradio_vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- a->index = 0;
- strlcpy(a->name, "Radio", sizeof(a->name));
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int timbradio_vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- return a->index ? -EINVAL : 0;
-}
-
-static int timbradio_vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_tuner, tuner, s_frequency, f);
-}
-
-static int timbradio_vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_tuner, tuner, g_frequency, f);
-}
-
-static int timbradio_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_dsp, core, queryctrl, qc);
-}
-
-static int timbradio_vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_dsp, core, g_ctrl, ctrl);
-}
-
-static int timbradio_vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_dsp, core, s_ctrl, ctrl);
-}
-
-static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
- .vidioc_querycap = timbradio_vidioc_querycap,
- .vidioc_g_tuner = timbradio_vidioc_g_tuner,
- .vidioc_s_tuner = timbradio_vidioc_s_tuner,
- .vidioc_g_frequency = timbradio_vidioc_g_frequency,
- .vidioc_s_frequency = timbradio_vidioc_s_frequency,
- .vidioc_g_input = timbradio_vidioc_g_input,
- .vidioc_s_input = timbradio_vidioc_s_input,
- .vidioc_g_audio = timbradio_vidioc_g_audio,
- .vidioc_s_audio = timbradio_vidioc_s_audio,
- .vidioc_queryctrl = timbradio_vidioc_queryctrl,
- .vidioc_g_ctrl = timbradio_vidioc_g_ctrl,
- .vidioc_s_ctrl = timbradio_vidioc_s_ctrl
-};
-
-static const struct v4l2_file_operations timbradio_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static int __devinit timbradio_probe(struct platform_device *pdev)
-{
- struct timb_radio_platform_data *pdata = pdev->dev.platform_data;
- struct timbradio *tr;
- int err;
-
- if (!pdata) {
- dev_err(&pdev->dev, "Platform data missing\n");
- err = -EINVAL;
- goto err;
- }
-
- tr = kzalloc(sizeof(*tr), GFP_KERNEL);
- if (!tr) {
- err = -ENOMEM;
- goto err;
- }
-
- tr->pdata = *pdata;
- mutex_init(&tr->lock);
-
- strlcpy(tr->video_dev.name, "Timberdale Radio",
- sizeof(tr->video_dev.name));
- tr->video_dev.fops = &timbradio_fops;
- tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
- tr->video_dev.release = video_device_release_empty;
- tr->video_dev.minor = -1;
- tr->video_dev.lock = &tr->lock;
-
- strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
- err = v4l2_device_register(NULL, &tr->v4l2_dev);
- if (err)
- goto err_v4l2_dev;
-
- tr->video_dev.v4l2_dev = &tr->v4l2_dev;
-
- err = video_register_device(&tr->video_dev, VFL_TYPE_RADIO, -1);
- if (err) {
- dev_err(&pdev->dev, "Error reg video\n");
- goto err_video_req;
- }
-
- video_set_drvdata(&tr->video_dev, tr);
-
- platform_set_drvdata(pdev, tr);
- return 0;
-
-err_video_req:
- video_device_release_empty(&tr->video_dev);
- v4l2_device_unregister(&tr->v4l2_dev);
-err_v4l2_dev:
- kfree(tr);
-err:
- dev_err(&pdev->dev, "Failed to register: %d\n", err);
-
- return err;
-}
-
-static int __devexit timbradio_remove(struct platform_device *pdev)
-{
- struct timbradio *tr = platform_get_drvdata(pdev);
-
- video_unregister_device(&tr->video_dev);
- video_device_release_empty(&tr->video_dev);
-
- v4l2_device_unregister(&tr->v4l2_dev);
-
- kfree(tr);
-
- return 0;
-}
-
-static struct platform_driver timbradio_platform_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
- .probe = timbradio_probe,
- .remove = timbradio_remove,
-};
-
-module_platform_driver(timbradio_platform_driver);
-
-MODULE_DESCRIPTION("Timberdale Radio driver");
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.0.2");
-MODULE_ALIAS("platform:"DRIVER_NAME);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-trust.c b/ANDROID_3.4.5/drivers/media/radio/radio-trust.c
deleted file mode 100644
index 26a8c600..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-trust.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/* radio-trust.c - Trust FM Radio card driver for Linux 2.2
- * by Eric Lammerts <eric@scintilla.utwente.nl>
- *
- * Based on radio-aztech.c. Original notes:
- *
- * Adapted to support the Video for Linux API by
- * Russell Kroll <rkroll@exploits.org>. Based on original tuner code by:
- *
- * Quay Ly
- * Donald Song
- * Jason Lewis (jlewis@twilight.vtc.vsc.edu)
- * Scott McGrath (smcgrath@twilight.vtc.vsc.edu)
- * William McGrath (wmcgrath@twilight.vtc.vsc.edu)
- *
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-#include <stdarg.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/videodev2.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include "radio-isa.h"
-
-MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
-MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1.99");
-
-/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
-
-#ifndef CONFIG_RADIO_TRUST_PORT
-#define CONFIG_RADIO_TRUST_PORT -1
-#endif
-
-#define TRUST_MAX 2
-
-static int io[TRUST_MAX] = { [0] = CONFIG_RADIO_TRUST_PORT,
- [1 ... (TRUST_MAX - 1)] = -1 };
-static int radio_nr[TRUST_MAX] = { [0 ... (TRUST_MAX - 1)] = -1 };
-
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the Trust FM Radio card (0x350 or 0x358)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-struct trust {
- struct radio_isa_card isa;
- int ioval;
-};
-
-static struct radio_isa_card *trust_alloc(void)
-{
- struct trust *tr = kzalloc(sizeof(*tr), GFP_KERNEL);
-
- return tr ? &tr->isa : NULL;
-}
-
-/* i2c addresses */
-#define TDA7318_ADDR 0x88
-#define TSA6060T_ADDR 0xc4
-
-#define TR_DELAY do { inb(tr->isa.io); inb(tr->isa.io); inb(tr->isa.io); } while (0)
-#define TR_SET_SCL outb(tr->ioval |= 2, tr->isa.io)
-#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->isa.io)
-#define TR_SET_SDA outb(tr->ioval |= 1, tr->isa.io)
-#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->isa.io)
-
-static void write_i2c(struct trust *tr, int n, ...)
-{
- unsigned char val, mask;
- va_list args;
-
- va_start(args, n);
-
- /* start condition */
- TR_SET_SDA;
- TR_SET_SCL;
- TR_DELAY;
- TR_CLR_SDA;
- TR_CLR_SCL;
- TR_DELAY;
-
- for (; n; n--) {
- val = va_arg(args, unsigned);
- for (mask = 0x80; mask; mask >>= 1) {
- if (val & mask)
- TR_SET_SDA;
- else
- TR_CLR_SDA;
- TR_SET_SCL;
- TR_DELAY;
- TR_CLR_SCL;
- TR_DELAY;
- }
- /* acknowledge bit */
- TR_SET_SDA;
- TR_SET_SCL;
- TR_DELAY;
- TR_CLR_SCL;
- TR_DELAY;
- }
-
- /* stop condition */
- TR_CLR_SDA;
- TR_DELAY;
- TR_SET_SCL;
- TR_DELAY;
- TR_SET_SDA;
- TR_DELAY;
-
- va_end(args);
-}
-
-static int trust_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- struct trust *tr = container_of(isa, struct trust, isa);
-
- tr->ioval = (tr->ioval & 0xf7) | (mute << 3);
- outb(tr->ioval, isa->io);
- write_i2c(tr, 2, TDA7318_ADDR, vol ^ 0x1f);
- return 0;
-}
-
-static int trust_s_stereo(struct radio_isa_card *isa, bool stereo)
-{
- struct trust *tr = container_of(isa, struct trust, isa);
-
- tr->ioval = (tr->ioval & 0xfb) | (!stereo << 2);
- outb(tr->ioval, isa->io);
- return 0;
-}
-
-static u32 trust_g_signal(struct radio_isa_card *isa)
-{
- int i, v;
-
- for (i = 0, v = 0; i < 100; i++)
- v |= inb(isa->io);
- return (v & 1) ? 0 : 0xffff;
-}
-
-static int trust_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- struct trust *tr = container_of(isa, struct trust, isa);
-
- freq /= 160; /* Convert to 10 kHz units */
- freq += 1070; /* Add 10.7 MHz IF */
- write_i2c(tr, 5, TSA6060T_ADDR, (freq << 1) | 1,
- freq >> 7, 0x60 | ((freq >> 15) & 1), 0);
- return 0;
-}
-
-static int basstreble2chip[15] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8
-};
-
-static int trust_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct radio_isa_card *isa =
- container_of(ctrl->handler, struct radio_isa_card, hdl);
- struct trust *tr = container_of(isa, struct trust, isa);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_BASS:
- write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[ctrl->val]);
- return 0;
- case V4L2_CID_AUDIO_TREBLE:
- write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[ctrl->val]);
- return 0;
- }
- return -EINVAL;
-}
-
-static const struct v4l2_ctrl_ops trust_ctrl_ops = {
- .s_ctrl = trust_s_ctrl,
-};
-
-static int trust_initialize(struct radio_isa_card *isa)
-{
- struct trust *tr = container_of(isa, struct trust, isa);
-
- tr->ioval = 0xf;
- write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */
- write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */
- write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */
- write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */
- write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */
-
- v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops,
- V4L2_CID_AUDIO_BASS, 0, 15, 1, 8);
- v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops,
- V4L2_CID_AUDIO_TREBLE, 0, 15, 1, 8);
- return isa->hdl.error;
-}
-
-static const struct radio_isa_ops trust_ops = {
- .init = trust_initialize,
- .alloc = trust_alloc,
- .s_mute_volume = trust_s_mute_volume,
- .s_frequency = trust_s_frequency,
- .s_stereo = trust_s_stereo,
- .g_signal = trust_g_signal,
-};
-
-static const int trust_ioports[] = { 0x350, 0x358 };
-
-static struct radio_isa_driver trust_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-trust",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = trust_ioports,
- .num_of_io_ports = ARRAY_SIZE(trust_ioports),
- .region_size = 2,
- .card = "Trust FM Radio",
- .ops = &trust_ops,
- .has_stereo = true,
- .max_volume = 31,
-};
-
-static int __init trust_init(void)
-{
- return isa_register_driver(&trust_driver.driver, TRUST_MAX);
-}
-
-static void __exit trust_exit(void)
-{
- isa_unregister_driver(&trust_driver.driver);
-}
-
-module_init(trust_init);
-module_exit(trust_exit);
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-typhoon.c b/ANDROID_3.4.5/drivers/media/radio/radio-typhoon.c
deleted file mode 100644
index eb72a4d1..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-typhoon.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Typhoon Radio Card driver for radio support
- * (c) 1999 Dr. Henrik Seidel <Henrik.Seidel@gmx.de>
- *
- * Notes on the hardware
- *
- * This card has two output sockets, one for speakers and one for line.
- * The speaker output has volume control, but only in four discrete
- * steps. The line output has neither volume control nor mute.
- *
- * The card has auto-stereo according to its manual, although it all
- * sounds mono to me (even with the Win/DOS drivers). Maybe it's my
- * antenna - I really don't know for sure.
- *
- * Frequency control is done digitally.
- *
- * Volume control is done digitally, but there are only four different
- * possible values. So you should better always turn the volume up and
- * use line control. I got the best results by connecting line output
- * to the sound card microphone input. For such a configuration the
- * volume control has no effect, since volume control only influences
- * the speaker output.
- *
- * There is no explicit mute/unmute. So I set the radio frequency to a
- * value where I do expect just noise and turn the speaker volume down.
- * The frequency change is necessary since the card never seems to be
- * completely silent.
- *
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/io.h> /* outb, outb_p */
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include "radio-isa.h"
-
-#define DRIVER_VERSION "0.1.2"
-
-MODULE_AUTHOR("Dr. Henrik Seidel");
-MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1.99");
-
-#ifndef CONFIG_RADIO_TYPHOON_PORT
-#define CONFIG_RADIO_TYPHOON_PORT -1
-#endif
-
-#ifndef CONFIG_RADIO_TYPHOON_MUTEFREQ
-#define CONFIG_RADIO_TYPHOON_MUTEFREQ 87000
-#endif
-
-#define TYPHOON_MAX 2
-
-static int io[TYPHOON_MAX] = { [0] = CONFIG_RADIO_TYPHOON_PORT,
- [1 ... (TYPHOON_MAX - 1)] = -1 };
-static int radio_nr[TYPHOON_MAX] = { [0 ... (TYPHOON_MAX - 1)] = -1 };
-static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ;
-
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the Typhoon card (0x316 or 0x336)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-module_param(mutefreq, ulong, 0);
-MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
-
-struct typhoon {
- struct radio_isa_card isa;
- int muted;
-};
-
-static struct radio_isa_card *typhoon_alloc(void)
-{
- struct typhoon *ty = kzalloc(sizeof(*ty), GFP_KERNEL);
-
- return ty ? &ty->isa : NULL;
-}
-
-static int typhoon_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- unsigned long outval;
- unsigned long x;
-
- /*
- * The frequency transfer curve is not linear. The best fit I could
- * get is
- *
- * outval = -155 + exp((f + 15.55) * 0.057))
- *
- * where frequency f is in MHz. Since we don't have exp in the kernel,
- * I approximate this function by a third order polynomial.
- *
- */
-
- x = freq / 160;
- outval = (x * x + 2500) / 5000;
- outval = (outval * x + 5000) / 10000;
- outval -= (10 * x * x + 10433) / 20866;
- outval += 4 * x - 11505;
-
- outb_p((outval >> 8) & 0x01, isa->io + 4);
- outb_p(outval >> 9, isa->io + 6);
- outb_p(outval & 0xff, isa->io + 8);
- return 0;
-}
-
-static int typhoon_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- struct typhoon *ty = container_of(isa, struct typhoon, isa);
-
- if (mute)
- vol = 0;
- vol >>= 14; /* Map 16 bit to 2 bit */
- vol &= 3;
- outb_p(vol / 2, isa->io); /* Set the volume, high bit. */
- outb_p(vol % 2, isa->io + 2); /* Set the volume, low bit. */
-
- if (vol == 0 && !ty->muted) {
- ty->muted = true;
- return typhoon_s_frequency(isa, mutefreq << 4);
- }
- if (vol && ty->muted) {
- ty->muted = false;
- return typhoon_s_frequency(isa, isa->freq);
- }
- return 0;
-}
-
-static const struct radio_isa_ops typhoon_ops = {
- .alloc = typhoon_alloc,
- .s_mute_volume = typhoon_s_mute_volume,
- .s_frequency = typhoon_s_frequency,
-};
-
-static const int typhoon_ioports[] = { 0x316, 0x336 };
-
-static struct radio_isa_driver typhoon_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-typhoon",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = typhoon_ioports,
- .num_of_io_ports = ARRAY_SIZE(typhoon_ioports),
- .region_size = 8,
- .card = "Typhoon Radio",
- .ops = &typhoon_ops,
- .has_stereo = true,
- .max_volume = 3,
-};
-
-static int __init typhoon_init(void)
-{
- if (mutefreq < 87000 || mutefreq > 108000) {
- printk(KERN_ERR "%s: You must set a frequency (in kHz) used when muting the card,\n",
- typhoon_driver.driver.driver.name);
- printk(KERN_ERR "%s: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108000)\n",
- typhoon_driver.driver.driver.name);
- return -ENODEV;
- }
- return isa_register_driver(&typhoon_driver.driver, TYPHOON_MAX);
-}
-
-static void __exit typhoon_exit(void)
-{
- isa_unregister_driver(&typhoon_driver.driver);
-}
-
-
-module_init(typhoon_init);
-module_exit(typhoon_exit);
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-wl1273.c b/ANDROID_3.4.5/drivers/media/radio/radio-wl1273.c
deleted file mode 100644
index f1b60709..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-wl1273.c
+++ /dev/null
@@ -1,2165 +0,0 @@
-/*
- * Driver for the Texas Instruments WL1273 FM radio.
- *
- * Copyright (C) 2011 Nokia Corporation
- * Author: Matti J. Aaltonen <matti.j.aaltonen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/wl1273-core.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-
-#define DRIVER_DESC "Wl1273 FM Radio"
-
-#define WL1273_POWER_SET_OFF 0
-#define WL1273_POWER_SET_FM BIT(0)
-#define WL1273_POWER_SET_RDS BIT(1)
-#define WL1273_POWER_SET_RETENTION BIT(4)
-
-#define WL1273_PUPD_SET_OFF 0x00
-#define WL1273_PUPD_SET_ON 0x01
-#define WL1273_PUPD_SET_RETENTION 0x10
-
-#define WL1273_FREQ(x) (x * 10000 / 625)
-#define WL1273_INV_FREQ(x) (x * 625 / 10000)
-
-/*
- * static int radio_nr - The number of the radio device
- *
- * The default is 0.
- */
-static int radio_nr;
-module_param(radio_nr, int, 0);
-MODULE_PARM_DESC(radio_nr, "The number of the radio device. Default = 0");
-
-struct wl1273_device {
- char *bus_type;
-
- u8 forbidden;
- unsigned int preemphasis;
- unsigned int spacing;
- unsigned int tx_power;
- unsigned int rx_frequency;
- unsigned int tx_frequency;
- unsigned int rangelow;
- unsigned int rangehigh;
- unsigned int band;
- bool stereo;
-
- /* RDS */
- unsigned int rds_on;
-
- wait_queue_head_t read_queue;
- struct mutex lock; /* for serializing fm radio operations */
- struct completion busy;
-
- unsigned char *buffer;
- unsigned int buf_size;
- unsigned int rd_index;
- unsigned int wr_index;
-
- /* Selected interrupts */
- u16 irq_flags;
- u16 irq_received;
-
- struct v4l2_ctrl_handler ctrl_handler;
- struct v4l2_device v4l2dev;
- struct video_device videodev;
- struct device *dev;
- struct wl1273_core *core;
- struct file *owner;
- char *write_buf;
- unsigned int rds_users;
-};
-
-#define WL1273_IRQ_MASK (WL1273_FR_EVENT | \
- WL1273_POW_ENB_EVENT)
-
-/*
- * static unsigned int rds_buf - the number of RDS buffer blocks used.
- *
- * The default number is 100.
- */
-static unsigned int rds_buf = 100;
-module_param(rds_buf, uint, 0);
-MODULE_PARM_DESC(rds_buf, "Number of RDS buffer entries. Default = 100");
-
-static int wl1273_fm_write_fw(struct wl1273_core *core,
- __u8 *fw, int len)
-{
- struct i2c_client *client = core->client;
- struct i2c_msg msg;
- int i, r = 0;
-
- msg.addr = client->addr;
- msg.flags = 0;
-
- for (i = 0; i <= len; i++) {
- msg.len = fw[0];
- msg.buf = fw + 1;
-
- fw += msg.len + 1;
- dev_dbg(&client->dev, "%s:len[%d]: %d\n", __func__, i, msg.len);
-
- r = i2c_transfer(client->adapter, &msg, 1);
- if (r < 0 && i < len + 1)
- break;
- }
-
- dev_dbg(&client->dev, "%s: i: %d\n", __func__, i);
- dev_dbg(&client->dev, "%s: len + 1: %d\n", __func__, len + 1);
-
- /* Last transfer always fails. */
- if (i == len || r == 1)
- r = 0;
-
- return r;
-}
-
-#define WL1273_FIFO_HAS_DATA(status) (1 << 5 & status)
-#define WL1273_RDS_CORRECTABLE_ERROR (1 << 3)
-#define WL1273_RDS_UNCORRECTABLE_ERROR (1 << 4)
-
-static int wl1273_fm_rds(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
- struct i2c_client *client = core->client;
- u16 val;
- u8 b0 = WL1273_RDS_DATA_GET, status;
- struct v4l2_rds_data rds = { 0, 0, 0 };
- struct i2c_msg msg[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .buf = &b0,
- .len = 1,
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .buf = (u8 *) &rds,
- .len = sizeof(rds),
- }
- };
- int r;
-
- if (core->mode != WL1273_MODE_RX)
- return 0;
-
- r = core->read(core, WL1273_RDS_SYNC_GET, &val);
- if (r)
- return r;
-
- if ((val & 0x01) == 0) {
- /* RDS decoder not synchronized */
- return -EAGAIN;
- }
-
- /* copy all four RDS blocks to internal buffer */
- do {
- r = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
- if (r != ARRAY_SIZE(msg)) {
- dev_err(radio->dev, WL1273_FM_DRIVER_NAME
- ": %s: read_rds error r == %i)\n",
- __func__, r);
- }
-
- status = rds.block;
-
- if (!WL1273_FIFO_HAS_DATA(status))
- break;
-
- /* copy bits 0-2 (the block ID) to bits 3-5 */
- rds.block = V4L2_RDS_BLOCK_MSK & status;
- rds.block |= rds.block << 3;
-
- /* copy the error bits to standard positions */
- if (WL1273_RDS_UNCORRECTABLE_ERROR & status) {
- rds.block |= V4L2_RDS_BLOCK_ERROR;
- rds.block &= ~V4L2_RDS_BLOCK_CORRECTED;
- } else if (WL1273_RDS_CORRECTABLE_ERROR & status) {
- rds.block &= ~V4L2_RDS_BLOCK_ERROR;
- rds.block |= V4L2_RDS_BLOCK_CORRECTED;
- }
-
- /* copy RDS block to internal buffer */
- memcpy(&radio->buffer[radio->wr_index], &rds, RDS_BLOCK_SIZE);
- radio->wr_index += 3;
-
- /* wrap write pointer */
- if (radio->wr_index >= radio->buf_size)
- radio->wr_index = 0;
-
- /* check for overflow & start over */
- if (radio->wr_index == radio->rd_index) {
- dev_dbg(radio->dev, "RDS OVERFLOW");
-
- radio->rd_index = 0;
- radio->wr_index = 0;
- break;
- }
- } while (WL1273_FIFO_HAS_DATA(status));
-
- /* wake up read queue */
- if (radio->wr_index != radio->rd_index)
- wake_up_interruptible(&radio->read_queue);
-
- return 0;
-}
-
-static irqreturn_t wl1273_fm_irq_thread_handler(int irq, void *dev_id)
-{
- struct wl1273_device *radio = dev_id;
- struct wl1273_core *core = radio->core;
- u16 flags;
- int r;
-
- r = core->read(core, WL1273_FLAG_GET, &flags);
- if (r)
- goto out;
-
- if (flags & WL1273_BL_EVENT) {
- radio->irq_received = flags;
- dev_dbg(radio->dev, "IRQ: BL\n");
- }
-
- if (flags & WL1273_RDS_EVENT) {
- msleep(200);
-
- wl1273_fm_rds(radio);
- }
-
- if (flags & WL1273_BBLK_EVENT)
- dev_dbg(radio->dev, "IRQ: BBLK\n");
-
- if (flags & WL1273_LSYNC_EVENT)
- dev_dbg(radio->dev, "IRQ: LSYNC\n");
-
- if (flags & WL1273_LEV_EVENT) {
- u16 level;
-
- r = core->read(core, WL1273_RSSI_LVL_GET, &level);
- if (r)
- goto out;
-
- if (level > 14)
- dev_dbg(radio->dev, "IRQ: LEV: 0x%x04\n", level);
- }
-
- if (flags & WL1273_IFFR_EVENT)
- dev_dbg(radio->dev, "IRQ: IFFR\n");
-
- if (flags & WL1273_PI_EVENT)
- dev_dbg(radio->dev, "IRQ: PI\n");
-
- if (flags & WL1273_PD_EVENT)
- dev_dbg(radio->dev, "IRQ: PD\n");
-
- if (flags & WL1273_STIC_EVENT)
- dev_dbg(radio->dev, "IRQ: STIC\n");
-
- if (flags & WL1273_MAL_EVENT)
- dev_dbg(radio->dev, "IRQ: MAL\n");
-
- if (flags & WL1273_POW_ENB_EVENT) {
- complete(&radio->busy);
- dev_dbg(radio->dev, "NOT BUSY\n");
- dev_dbg(radio->dev, "IRQ: POW_ENB\n");
- }
-
- if (flags & WL1273_SCAN_OVER_EVENT)
- dev_dbg(radio->dev, "IRQ: SCAN_OVER\n");
-
- if (flags & WL1273_ERROR_EVENT)
- dev_dbg(radio->dev, "IRQ: ERROR\n");
-
- if (flags & WL1273_FR_EVENT) {
- u16 freq;
-
- dev_dbg(radio->dev, "IRQ: FR:\n");
-
- if (core->mode == WL1273_MODE_RX) {
- r = core->write(core, WL1273_TUNER_MODE_SET,
- TUNER_MODE_STOP_SEARCH);
- if (r) {
- dev_err(radio->dev,
- "%s: TUNER_MODE_SET fails: %d\n",
- __func__, r);
- goto out;
- }
-
- r = core->read(core, WL1273_FREQ_SET, &freq);
- if (r)
- goto out;
-
- if (radio->band == WL1273_BAND_JAPAN)
- radio->rx_frequency = WL1273_BAND_JAPAN_LOW +
- freq * 50;
- else
- radio->rx_frequency = WL1273_BAND_OTHER_LOW +
- freq * 50;
- /*
- * The driver works better with this msleep,
- * the documentation doesn't mention it.
- */
- usleep_range(10000, 15000);
-
- dev_dbg(radio->dev, "%dkHz\n", radio->rx_frequency);
-
- } else {
- r = core->read(core, WL1273_CHANL_SET, &freq);
- if (r)
- goto out;
-
- dev_dbg(radio->dev, "%dkHz\n", freq);
- }
- dev_dbg(radio->dev, "%s: NOT BUSY\n", __func__);
- }
-
-out:
- core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
- complete(&radio->busy);
-
- return IRQ_HANDLED;
-}
-
-static int wl1273_fm_set_tx_freq(struct wl1273_device *radio, unsigned int freq)
-{
- struct wl1273_core *core = radio->core;
- int r = 0;
-
- if (freq < WL1273_BAND_TX_LOW) {
- dev_err(radio->dev,
- "Frequency out of range: %d < %d\n", freq,
- WL1273_BAND_TX_LOW);
- return -ERANGE;
- }
-
- if (freq > WL1273_BAND_TX_HIGH) {
- dev_err(radio->dev,
- "Frequency out of range: %d > %d\n", freq,
- WL1273_BAND_TX_HIGH);
- return -ERANGE;
- }
-
- /*
- * The driver works better with this sleep,
- * the documentation doesn't mention it.
- */
- usleep_range(5000, 10000);
-
- dev_dbg(radio->dev, "%s: freq: %d kHz\n", __func__, freq);
-
- /* Set the current tx channel */
- r = core->write(core, WL1273_CHANL_SET, freq / 10);
- if (r)
- return r;
-
- INIT_COMPLETION(radio->busy);
-
- /* wait for the FR IRQ */
- r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
- if (!r)
- return -ETIMEDOUT;
-
- dev_dbg(radio->dev, "WL1273_CHANL_SET: %d\n", r);
-
- /* Enable the output power */
- r = core->write(core, WL1273_POWER_ENB_SET, 1);
- if (r)
- return r;
-
- INIT_COMPLETION(radio->busy);
-
- /* wait for the POWER_ENB IRQ */
- r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
- if (!r)
- return -ETIMEDOUT;
-
- radio->tx_frequency = freq;
- dev_dbg(radio->dev, "WL1273_POWER_ENB_SET: %d\n", r);
-
- return 0;
-}
-
-static int wl1273_fm_set_rx_freq(struct wl1273_device *radio, unsigned int freq)
-{
- struct wl1273_core *core = radio->core;
- int r, f;
-
- if (freq < radio->rangelow) {
- dev_err(radio->dev,
- "Frequency out of range: %d < %d\n", freq,
- radio->rangelow);
- r = -ERANGE;
- goto err;
- }
-
- if (freq > radio->rangehigh) {
- dev_err(radio->dev,
- "Frequency out of range: %d > %d\n", freq,
- radio->rangehigh);
- r = -ERANGE;
- goto err;
- }
-
- dev_dbg(radio->dev, "%s: %dkHz\n", __func__, freq);
-
- core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
-
- if (radio->band == WL1273_BAND_JAPAN)
- f = (freq - WL1273_BAND_JAPAN_LOW) / 50;
- else
- f = (freq - WL1273_BAND_OTHER_LOW) / 50;
-
- r = core->write(core, WL1273_FREQ_SET, f);
- if (r) {
- dev_err(radio->dev, "FREQ_SET fails\n");
- goto err;
- }
-
- r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET);
- if (r) {
- dev_err(radio->dev, "TUNER_MODE_SET fails\n");
- goto err;
- }
-
- INIT_COMPLETION(radio->busy);
-
- r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
- if (!r) {
- dev_err(radio->dev, "%s: TIMEOUT\n", __func__);
- return -ETIMEDOUT;
- }
-
- radio->rd_index = 0;
- radio->wr_index = 0;
- radio->rx_frequency = freq;
- return 0;
-err:
- return r;
-}
-
-static int wl1273_fm_get_freq(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
- unsigned int freq;
- u16 f;
- int r;
-
- if (core->mode == WL1273_MODE_RX) {
- r = core->read(core, WL1273_FREQ_SET, &f);
- if (r)
- return r;
-
- dev_dbg(radio->dev, "Freq get: 0x%04x\n", f);
- if (radio->band == WL1273_BAND_JAPAN)
- freq = WL1273_BAND_JAPAN_LOW + 50 * f;
- else
- freq = WL1273_BAND_OTHER_LOW + 50 * f;
- } else {
- r = core->read(core, WL1273_CHANL_SET, &f);
- if (r)
- return r;
-
- freq = f * 10;
- }
-
- return freq;
-}
-
-/**
- * wl1273_fm_upload_firmware_patch() - Upload the firmware.
- * @radio: A pointer to the device struct.
- *
- * The firmware file consists of arrays of bytes where the first byte
- * gives the array length. The first byte in the file gives the
- * number of these arrays.
- */
-static int wl1273_fm_upload_firmware_patch(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
- unsigned int packet_num;
- const struct firmware *fw_p;
- const char *fw_name = "radio-wl1273-fw.bin";
- struct device *dev = radio->dev;
- __u8 *ptr;
- int r;
-
- dev_dbg(dev, "%s:\n", __func__);
-
- /*
- * Uploading the firmware patch is not always necessary,
- * so we only print an info message.
- */
- if (request_firmware(&fw_p, fw_name, dev)) {
- dev_info(dev, "%s - %s not found\n", __func__, fw_name);
-
- return 0;
- }
-
- ptr = (__u8 *) fw_p->data;
- packet_num = ptr[0];
- dev_dbg(dev, "%s: packets: %d\n", __func__, packet_num);
-
- r = wl1273_fm_write_fw(core, ptr + 1, packet_num);
- if (r) {
- dev_err(dev, "FW upload error: %d\n", r);
- goto out;
- }
-
- /* ignore possible error here */
- core->write(core, WL1273_RESET, 0);
-
- dev_dbg(dev, "%s - download OK, r: %d\n", __func__, r);
-out:
- release_firmware(fw_p);
- return r;
-}
-
-static int wl1273_fm_stop(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
-
- if (core->mode == WL1273_MODE_RX) {
- int r = core->write(core, WL1273_POWER_SET,
- WL1273_POWER_SET_OFF);
- if (r)
- dev_err(radio->dev, "%s: POWER_SET fails: %d\n",
- __func__, r);
- } else if (core->mode == WL1273_MODE_TX) {
- int r = core->write(core, WL1273_PUPD_SET,
- WL1273_PUPD_SET_OFF);
- if (r)
- dev_err(radio->dev,
- "%s: PUPD_SET fails: %d\n", __func__, r);
- }
-
- if (core->pdata->disable) {
- core->pdata->disable();
- dev_dbg(radio->dev, "Back to reset\n");
- }
-
- return 0;
-}
-
-static int wl1273_fm_start(struct wl1273_device *radio, int new_mode)
-{
- struct wl1273_core *core = radio->core;
- struct wl1273_fm_platform_data *pdata = core->pdata;
- struct device *dev = radio->dev;
- int r = -EINVAL;
-
- if (pdata->enable && core->mode == WL1273_MODE_OFF) {
- dev_dbg(radio->dev, "Out of reset\n");
-
- pdata->enable();
- msleep(250);
- }
-
- if (new_mode == WL1273_MODE_RX) {
- u16 val = WL1273_POWER_SET_FM;
-
- if (radio->rds_on)
- val |= WL1273_POWER_SET_RDS;
-
- /* If this fails try again */
- r = core->write(core, WL1273_POWER_SET, val);
- if (r) {
- msleep(100);
-
- r = core->write(core, WL1273_POWER_SET, val);
- if (r) {
- dev_err(dev, "%s: POWER_SET fails\n", __func__);
- goto fail;
- }
- }
-
- /* rds buffer configuration */
- radio->wr_index = 0;
- radio->rd_index = 0;
-
- } else if (new_mode == WL1273_MODE_TX) {
- /* If this fails try again once */
- r = core->write(core, WL1273_PUPD_SET, WL1273_PUPD_SET_ON);
- if (r) {
- msleep(100);
- r = core->write(core, WL1273_PUPD_SET,
- WL1273_PUPD_SET_ON);
- if (r) {
- dev_err(dev, "%s: PUPD_SET fails\n", __func__);
- goto fail;
- }
- }
-
- if (radio->rds_on)
- r = core->write(core, WL1273_RDS_DATA_ENB, 1);
- else
- r = core->write(core, WL1273_RDS_DATA_ENB, 0);
- } else {
- dev_warn(dev, "%s: Illegal mode.\n", __func__);
- }
-
- if (core->mode == WL1273_MODE_OFF) {
- r = wl1273_fm_upload_firmware_patch(radio);
- if (r)
- dev_warn(dev, "Firmware upload failed.\n");
-
- /*
- * Sometimes the chip is in a wrong power state at this point.
- * So we set the power once again.
- */
- if (new_mode == WL1273_MODE_RX) {
- u16 val = WL1273_POWER_SET_FM;
-
- if (radio->rds_on)
- val |= WL1273_POWER_SET_RDS;
-
- r = core->write(core, WL1273_POWER_SET, val);
- if (r) {
- dev_err(dev, "%s: POWER_SET fails\n", __func__);
- goto fail;
- }
- } else if (new_mode == WL1273_MODE_TX) {
- r = core->write(core, WL1273_PUPD_SET,
- WL1273_PUPD_SET_ON);
- if (r) {
- dev_err(dev, "%s: PUPD_SET fails\n", __func__);
- goto fail;
- }
- }
- }
-
- return 0;
-fail:
- if (pdata->disable)
- pdata->disable();
-
- dev_dbg(dev, "%s: return: %d\n", __func__, r);
- return r;
-}
-
-static int wl1273_fm_suspend(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
- int r = 0;
-
- /* Cannot go from OFF to SUSPENDED */
- if (core->mode == WL1273_MODE_RX)
- r = core->write(core, WL1273_POWER_SET,
- WL1273_POWER_SET_RETENTION);
- else if (core->mode == WL1273_MODE_TX)
- r = core->write(core, WL1273_PUPD_SET,
- WL1273_PUPD_SET_RETENTION);
- else
- r = -EINVAL;
-
- if (r) {
- dev_err(radio->dev, "%s: POWER_SET fails: %d\n", __func__, r);
- goto out;
- }
-
-out:
- return r;
-}
-
-static int wl1273_fm_set_mode(struct wl1273_device *radio, int mode)
-{
- struct wl1273_core *core = radio->core;
- struct device *dev = radio->dev;
- int old_mode;
- int r;
-
- dev_dbg(dev, "%s\n", __func__);
- dev_dbg(dev, "Forbidden modes: 0x%02x\n", radio->forbidden);
-
- old_mode = core->mode;
- if (mode & radio->forbidden) {
- r = -EPERM;
- goto out;
- }
-
- switch (mode) {
- case WL1273_MODE_RX:
- case WL1273_MODE_TX:
- r = wl1273_fm_start(radio, mode);
- if (r) {
- dev_err(dev, "%s: Cannot start.\n", __func__);
- wl1273_fm_stop(radio);
- goto out;
- }
-
- core->mode = mode;
- r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
- if (r) {
- dev_err(dev, "INT_MASK_SET fails.\n");
- goto out;
- }
-
- /* remember previous settings */
- if (mode == WL1273_MODE_RX) {
- r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency);
- if (r) {
- dev_err(dev, "set freq fails: %d.\n", r);
- goto out;
- }
-
- r = core->set_volume(core, core->volume);
- if (r) {
- dev_err(dev, "set volume fails: %d.\n", r);
- goto out;
- }
-
- dev_dbg(dev, "%s: Set vol: %d.\n", __func__,
- core->volume);
- } else {
- r = wl1273_fm_set_tx_freq(radio, radio->tx_frequency);
- if (r) {
- dev_err(dev, "set freq fails: %d.\n", r);
- goto out;
- }
- }
-
- dev_dbg(radio->dev, "%s: Set audio mode.\n", __func__);
-
- r = core->set_audio(core, core->audio_mode);
- if (r)
- dev_err(dev, "Cannot set audio mode.\n");
- break;
-
- case WL1273_MODE_OFF:
- r = wl1273_fm_stop(radio);
- if (r)
- dev_err(dev, "%s: Off fails: %d\n", __func__, r);
- else
- core->mode = WL1273_MODE_OFF;
-
- break;
-
- case WL1273_MODE_SUSPENDED:
- r = wl1273_fm_suspend(radio);
- if (r)
- dev_err(dev, "%s: Suspend fails: %d\n", __func__, r);
- else
- core->mode = WL1273_MODE_SUSPENDED;
-
- break;
-
- default:
- dev_err(dev, "%s: Unknown mode: %d\n", __func__, mode);
- r = -EINVAL;
- break;
- }
-out:
- if (r)
- core->mode = old_mode;
-
- return r;
-}
-
-static int wl1273_fm_set_seek(struct wl1273_device *radio,
- unsigned int wrap_around,
- unsigned int seek_upward,
- int level)
-{
- struct wl1273_core *core = radio->core;
- int r = 0;
- unsigned int dir = (seek_upward == 0) ? 0 : 1;
- unsigned int f;
-
- f = radio->rx_frequency;
- dev_dbg(radio->dev, "rx_frequency: %d\n", f);
-
- if (dir && f + radio->spacing <= radio->rangehigh)
- r = wl1273_fm_set_rx_freq(radio, f + radio->spacing);
- else if (dir && wrap_around)
- r = wl1273_fm_set_rx_freq(radio, radio->rangelow);
- else if (f - radio->spacing >= radio->rangelow)
- r = wl1273_fm_set_rx_freq(radio, f - radio->spacing);
- else if (wrap_around)
- r = wl1273_fm_set_rx_freq(radio, radio->rangehigh);
-
- if (r)
- goto out;
-
- if (level < SCHAR_MIN || level > SCHAR_MAX)
- return -EINVAL;
-
- INIT_COMPLETION(radio->busy);
- dev_dbg(radio->dev, "%s: BUSY\n", __func__);
-
- r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
- if (r)
- goto out;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- r = core->write(core, WL1273_SEARCH_LVL_SET, level);
- if (r)
- goto out;
-
- r = core->write(core, WL1273_SEARCH_DIR_SET, dir);
- if (r)
- goto out;
-
- r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK);
- if (r)
- goto out;
-
- wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
- if (!(radio->irq_received & WL1273_BL_EVENT))
- goto out;
-
- radio->irq_received &= ~WL1273_BL_EVENT;
-
- if (!wrap_around)
- goto out;
-
- /* Wrap around */
- dev_dbg(radio->dev, "Wrap around in HW seek.\n");
-
- if (seek_upward)
- f = radio->rangelow;
- else
- f = radio->rangehigh;
-
- r = wl1273_fm_set_rx_freq(radio, f);
- if (r)
- goto out;
-
- INIT_COMPLETION(radio->busy);
- dev_dbg(radio->dev, "%s: BUSY\n", __func__);
-
- r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK);
- if (r)
- goto out;
-
- wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
-out:
- dev_dbg(radio->dev, "%s: Err: %d\n", __func__, r);
- return r;
-}
-
-/**
- * wl1273_fm_get_tx_ctune() - Get the TX tuning capacitor value.
- * @radio: A pointer to the device struct.
- */
-static unsigned int wl1273_fm_get_tx_ctune(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
- struct device *dev = radio->dev;
- u16 val;
- int r;
-
- if (core->mode == WL1273_MODE_OFF ||
- core->mode == WL1273_MODE_SUSPENDED)
- return -EPERM;
-
- r = core->read(core, WL1273_READ_FMANT_TUNE_VALUE, &val);
- if (r) {
- dev_err(dev, "%s: read error: %d\n", __func__, r);
- goto out;
- }
-
-out:
- return val;
-}
-
-/**
- * wl1273_fm_set_preemphasis() - Set the TX pre-emphasis value.
- * @radio: A pointer to the device struct.
- * @preemphasis: The new pre-amphasis value.
- *
- * Possible pre-emphasis values are: V4L2_PREEMPHASIS_DISABLED,
- * V4L2_PREEMPHASIS_50_uS and V4L2_PREEMPHASIS_75_uS.
- */
-static int wl1273_fm_set_preemphasis(struct wl1273_device *radio,
- unsigned int preemphasis)
-{
- struct wl1273_core *core = radio->core;
- int r;
- u16 em;
-
- if (core->mode == WL1273_MODE_OFF ||
- core->mode == WL1273_MODE_SUSPENDED)
- return -EPERM;
-
- mutex_lock(&core->lock);
-
- switch (preemphasis) {
- case V4L2_PREEMPHASIS_DISABLED:
- em = 1;
- break;
- case V4L2_PREEMPHASIS_50_uS:
- em = 0;
- break;
- case V4L2_PREEMPHASIS_75_uS:
- em = 2;
- break;
- default:
- r = -EINVAL;
- goto out;
- }
-
- r = core->write(core, WL1273_PREMPH_SET, em);
- if (r)
- goto out;
-
- radio->preemphasis = preemphasis;
-
-out:
- mutex_unlock(&core->lock);
- return r;
-}
-
-static int wl1273_fm_rds_on(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
- int r;
-
- dev_dbg(radio->dev, "%s\n", __func__);
- if (radio->rds_on)
- return 0;
-
- r = core->write(core, WL1273_POWER_SET,
- WL1273_POWER_SET_FM | WL1273_POWER_SET_RDS);
- if (r)
- goto out;
-
- r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency);
- if (r)
- dev_err(radio->dev, "set freq fails: %d.\n", r);
-out:
- return r;
-}
-
-static int wl1273_fm_rds_off(struct wl1273_device *radio)
-{
- struct wl1273_core *core = radio->core;
- int r;
-
- if (!radio->rds_on)
- return 0;
-
- radio->irq_flags &= ~WL1273_RDS_EVENT;
-
- r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
- if (r)
- goto out;
-
- /* Service pending read */
- wake_up_interruptible(&radio->read_queue);
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- r = core->write(core, WL1273_POWER_SET, WL1273_POWER_SET_FM);
- if (r)
- goto out;
-
- r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency);
- if (r)
- dev_err(radio->dev, "set freq fails: %d.\n", r);
-out:
- dev_dbg(radio->dev, "%s: exiting...\n", __func__);
-
- return r;
-}
-
-static int wl1273_fm_set_rds(struct wl1273_device *radio, unsigned int new_mode)
-{
- int r = 0;
- struct wl1273_core *core = radio->core;
-
- if (core->mode == WL1273_MODE_OFF ||
- core->mode == WL1273_MODE_SUSPENDED)
- return -EPERM;
-
- if (new_mode == WL1273_RDS_RESET) {
- r = core->write(core, WL1273_RDS_CNTRL_SET, 1);
- return r;
- }
-
- if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_OFF) {
- r = core->write(core, WL1273_RDS_DATA_ENB, 0);
- } else if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_ON) {
- r = core->write(core, WL1273_RDS_DATA_ENB, 1);
- } else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_OFF) {
- r = wl1273_fm_rds_off(radio);
- } else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_ON) {
- r = wl1273_fm_rds_on(radio);
- } else {
- dev_err(radio->dev, "%s: Unknown mode: %d\n",
- __func__, new_mode);
- r = -EINVAL;
- }
-
- if (!r)
- radio->rds_on = (new_mode == WL1273_RDS_ON) ? true : false;
-
- return r;
-}
-
-static ssize_t wl1273_fm_fops_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- u16 val;
- int r;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (core->mode != WL1273_MODE_TX)
- return count;
-
- if (radio->rds_users == 0) {
- dev_warn(radio->dev, "%s: RDS not on.\n", __func__);
- return 0;
- }
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
- /*
- * Multiple processes can open the device, but only
- * one gets to write to it.
- */
- if (radio->owner && radio->owner != file) {
- r = -EBUSY;
- goto out;
- }
- radio->owner = file;
-
- /* Manual Mode */
- if (count > 255)
- val = 255;
- else
- val = count;
-
- core->write(core, WL1273_RDS_CONFIG_DATA_SET, val);
-
- if (copy_from_user(radio->write_buf + 1, buf, val)) {
- r = -EFAULT;
- goto out;
- }
-
- dev_dbg(radio->dev, "Count: %d\n", val);
- dev_dbg(radio->dev, "From user: \"%s\"\n", radio->write_buf);
-
- radio->write_buf[0] = WL1273_RDS_DATA_SET;
- core->write_data(core, radio->write_buf, val + 1);
-
- r = val;
-out:
- mutex_unlock(&core->lock);
-
- return r;
-}
-
-static unsigned int wl1273_fm_fops_poll(struct file *file,
- struct poll_table_struct *pts)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
-
- if (radio->owner && radio->owner != file)
- return -EBUSY;
-
- radio->owner = file;
-
- if (core->mode == WL1273_MODE_RX) {
- poll_wait(file, &radio->read_queue, pts);
-
- if (radio->rd_index != radio->wr_index)
- return POLLIN | POLLRDNORM;
-
- } else if (core->mode == WL1273_MODE_TX) {
- return POLLOUT | POLLWRNORM;
- }
-
- return 0;
-}
-
-static int wl1273_fm_fops_open(struct file *file)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- int r = 0;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (core->mode == WL1273_MODE_RX && radio->rds_on &&
- !radio->rds_users) {
- dev_dbg(radio->dev, "%s: Mode: %d\n", __func__, core->mode);
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- radio->irq_flags |= WL1273_RDS_EVENT;
-
- r = core->write(core, WL1273_INT_MASK_SET,
- radio->irq_flags);
- if (r) {
- mutex_unlock(&core->lock);
- goto out;
- }
-
- radio->rds_users++;
-
- mutex_unlock(&core->lock);
- }
-out:
- return r;
-}
-
-static int wl1273_fm_fops_release(struct file *file)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- int r = 0;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (radio->rds_users > 0) {
- radio->rds_users--;
- if (radio->rds_users == 0) {
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- radio->irq_flags &= ~WL1273_RDS_EVENT;
-
- if (core->mode == WL1273_MODE_RX) {
- r = core->write(core,
- WL1273_INT_MASK_SET,
- radio->irq_flags);
- if (r) {
- mutex_unlock(&core->lock);
- goto out;
- }
- }
- mutex_unlock(&core->lock);
- }
- }
-
- if (file == radio->owner)
- radio->owner = NULL;
-out:
- return r;
-}
-
-static ssize_t wl1273_fm_fops_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- int r = 0;
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- unsigned int block_count = 0;
- u16 val;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (core->mode != WL1273_MODE_RX)
- return 0;
-
- if (radio->rds_users == 0) {
- dev_warn(radio->dev, "%s: RDS not on.\n", __func__);
- return 0;
- }
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- /*
- * Multiple processes can open the device, but only
- * one at a time gets read access.
- */
- if (radio->owner && radio->owner != file) {
- r = -EBUSY;
- goto out;
- }
- radio->owner = file;
-
- r = core->read(core, WL1273_RDS_SYNC_GET, &val);
- if (r) {
- dev_err(radio->dev, "%s: Get RDS_SYNC fails.\n", __func__);
- goto out;
- } else if (val == 0) {
- dev_info(radio->dev, "RDS_SYNC: Not synchronized\n");
- r = -ENODATA;
- goto out;
- }
-
- /* block if no new data available */
- while (radio->wr_index == radio->rd_index) {
- if (file->f_flags & O_NONBLOCK) {
- r = -EWOULDBLOCK;
- goto out;
- }
-
- dev_dbg(radio->dev, "%s: Wait for RDS data.\n", __func__);
- if (wait_event_interruptible(radio->read_queue,
- radio->wr_index !=
- radio->rd_index) < 0) {
- r = -EINTR;
- goto out;
- }
- }
-
- /* calculate block count from byte count */
- count /= RDS_BLOCK_SIZE;
-
- /* copy RDS blocks from the internal buffer and to user buffer */
- while (block_count < count) {
- if (radio->rd_index == radio->wr_index)
- break;
-
- /* always transfer complete RDS blocks */
- if (copy_to_user(buf, &radio->buffer[radio->rd_index],
- RDS_BLOCK_SIZE))
- break;
-
- /* increment and wrap the read pointer */
- radio->rd_index += RDS_BLOCK_SIZE;
- if (radio->rd_index >= radio->buf_size)
- radio->rd_index = 0;
-
- /* increment counters */
- block_count++;
- buf += RDS_BLOCK_SIZE;
- r += RDS_BLOCK_SIZE;
- }
-
-out:
- dev_dbg(radio->dev, "%s: exit\n", __func__);
- mutex_unlock(&core->lock);
-
- return r;
-}
-
-static const struct v4l2_file_operations wl1273_fops = {
- .owner = THIS_MODULE,
- .read = wl1273_fm_fops_read,
- .write = wl1273_fm_fops_write,
- .poll = wl1273_fm_fops_poll,
- .unlocked_ioctl = video_ioctl2,
- .open = wl1273_fm_fops_open,
- .release = wl1273_fm_fops_release,
-};
-
-static int wl1273_fm_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- strlcpy(capability->driver, WL1273_FM_DRIVER_NAME,
- sizeof(capability->driver));
- strlcpy(capability->card, "Texas Instruments Wl1273 FM Radio",
- sizeof(capability->card));
- strlcpy(capability->bus_info, radio->bus_type,
- sizeof(capability->bus_info));
-
- capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
- V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_AUDIO |
- V4L2_CAP_RDS_CAPTURE | V4L2_CAP_MODULATOR |
- V4L2_CAP_RDS_OUTPUT;
-
- return 0;
-}
-
-static int wl1273_fm_vidioc_g_input(struct file *file, void *priv,
- unsigned int *i)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- *i = 0;
-
- return 0;
-}
-
-static int wl1273_fm_vidioc_s_input(struct file *file, void *priv,
- unsigned int i)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (i != 0)
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * wl1273_fm_set_tx_power() - Set the transmission power value.
- * @core: A pointer to the device struct.
- * @power: The new power value.
- */
-static int wl1273_fm_set_tx_power(struct wl1273_device *radio, u16 power)
-{
- struct wl1273_core *core = radio->core;
- int r;
-
- if (core->mode == WL1273_MODE_OFF ||
- core->mode == WL1273_MODE_SUSPENDED)
- return -EPERM;
-
- mutex_lock(&core->lock);
-
- /* Convert the dBuV value to chip presentation */
- r = core->write(core, WL1273_POWER_LEV_SET, 122 - power);
- if (r)
- goto out;
-
- radio->tx_power = power;
-
-out:
- mutex_unlock(&core->lock);
- return r;
-}
-
-#define WL1273_SPACING_50kHz 1
-#define WL1273_SPACING_100kHz 2
-#define WL1273_SPACING_200kHz 4
-
-static int wl1273_fm_tx_set_spacing(struct wl1273_device *radio,
- unsigned int spacing)
-{
- struct wl1273_core *core = radio->core;
- int r;
-
- if (spacing == 0) {
- r = core->write(core, WL1273_SCAN_SPACING_SET,
- WL1273_SPACING_100kHz);
- radio->spacing = 100;
- } else if (spacing - 50000 < 25000) {
- r = core->write(core, WL1273_SCAN_SPACING_SET,
- WL1273_SPACING_50kHz);
- radio->spacing = 50;
- } else if (spacing - 100000 < 50000) {
- r = core->write(core, WL1273_SCAN_SPACING_SET,
- WL1273_SPACING_100kHz);
- radio->spacing = 100;
- } else {
- r = core->write(core, WL1273_SCAN_SPACING_SET,
- WL1273_SPACING_200kHz);
- radio->spacing = 200;
- }
-
- return r;
-}
-
-static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct wl1273_device *radio = ctrl->priv;
- struct wl1273_core *core = radio->core;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- switch (ctrl->id) {
- case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- ctrl->val = wl1273_fm_get_tx_ctune(radio);
- break;
-
- default:
- dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n",
- __func__, ctrl->id);
- break;
- }
-
- mutex_unlock(&core->lock);
-
- return 0;
-}
-
-#define WL1273_MUTE_SOFT_ENABLE (1 << 0)
-#define WL1273_MUTE_AC (1 << 1)
-#define WL1273_MUTE_HARD_LEFT (1 << 2)
-#define WL1273_MUTE_HARD_RIGHT (1 << 3)
-#define WL1273_MUTE_SOFT_FORCE (1 << 4)
-
-static inline struct wl1273_device *to_radio(struct v4l2_ctrl *ctrl)
-{
- return container_of(ctrl->handler, struct wl1273_device, ctrl_handler);
-}
-
-static int wl1273_fm_vidioc_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct wl1273_device *radio = to_radio(ctrl);
- struct wl1273_core *core = radio->core;
- int r = 0;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- if (core->mode == WL1273_MODE_RX && ctrl->val)
- r = core->write(core,
- WL1273_MUTE_STATUS_SET,
- WL1273_MUTE_HARD_LEFT |
- WL1273_MUTE_HARD_RIGHT);
- else if (core->mode == WL1273_MODE_RX)
- r = core->write(core,
- WL1273_MUTE_STATUS_SET, 0x0);
- else if (core->mode == WL1273_MODE_TX && ctrl->val)
- r = core->write(core, WL1273_MUTE, 1);
- else if (core->mode == WL1273_MODE_TX)
- r = core->write(core, WL1273_MUTE, 0);
-
- mutex_unlock(&core->lock);
- break;
-
- case V4L2_CID_AUDIO_VOLUME:
- if (ctrl->val == 0)
- r = wl1273_fm_set_mode(radio, WL1273_MODE_OFF);
- else
- r = core->set_volume(core, core->volume);
- break;
-
- case V4L2_CID_TUNE_PREEMPHASIS:
- r = wl1273_fm_set_preemphasis(radio, ctrl->val);
- break;
-
- case V4L2_CID_TUNE_POWER_LEVEL:
- r = wl1273_fm_set_tx_power(radio, ctrl->val);
- break;
-
- default:
- dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n",
- __func__, ctrl->id);
- break;
- }
-
- dev_dbg(radio->dev, "%s\n", __func__);
- return r;
-}
-
-static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (audio->index > 1)
- return -EINVAL;
-
- strlcpy(audio->name, "Radio", sizeof(audio->name));
- audio->capability = V4L2_AUDCAP_STEREO;
-
- return 0;
-}
-
-static int wl1273_fm_vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (audio->index != 0)
- return -EINVAL;
-
- return 0;
-}
-
-#define WL1273_RDS_NOT_SYNCHRONIZED 0
-#define WL1273_RDS_SYNCHRONIZED 1
-
-static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- u16 val;
- int r;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (tuner->index > 0)
- return -EINVAL;
-
- strlcpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name));
- tuner->type = V4L2_TUNER_RADIO;
-
- tuner->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW);
- tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH);
-
- tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS |
- V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO;
-
- if (radio->stereo)
- tuner->audmode = V4L2_TUNER_MODE_STEREO;
- else
- tuner->audmode = V4L2_TUNER_MODE_MONO;
-
- if (core->mode != WL1273_MODE_RX)
- return 0;
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- r = core->read(core, WL1273_STEREO_GET, &val);
- if (r)
- goto out;
-
- if (val == 1)
- tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
- else
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
-
- r = core->read(core, WL1273_RSSI_LVL_GET, &val);
- if (r)
- goto out;
-
- tuner->signal = (s16) val;
- dev_dbg(radio->dev, "Signal: %d\n", tuner->signal);
-
- tuner->afc = 0;
-
- r = core->read(core, WL1273_RDS_SYNC_GET, &val);
- if (r)
- goto out;
-
- if (val == WL1273_RDS_SYNCHRONIZED)
- tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
-out:
- mutex_unlock(&core->lock);
-
- return r;
-}
-
-static int wl1273_fm_vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- int r = 0;
-
- dev_dbg(radio->dev, "%s\n", __func__);
- dev_dbg(radio->dev, "tuner->index: %d\n", tuner->index);
- dev_dbg(radio->dev, "tuner->name: %s\n", tuner->name);
- dev_dbg(radio->dev, "tuner->capability: 0x%04x\n", tuner->capability);
- dev_dbg(radio->dev, "tuner->rxsubchans: 0x%04x\n", tuner->rxsubchans);
- dev_dbg(radio->dev, "tuner->rangelow: %d\n", tuner->rangelow);
- dev_dbg(radio->dev, "tuner->rangehigh: %d\n", tuner->rangehigh);
-
- if (tuner->index > 0)
- return -EINVAL;
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- r = wl1273_fm_set_mode(radio, WL1273_MODE_RX);
- if (r)
- goto out;
-
- if (tuner->rxsubchans & V4L2_TUNER_SUB_RDS)
- r = wl1273_fm_set_rds(radio, WL1273_RDS_ON);
- else
- r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF);
-
- if (r)
- dev_warn(radio->dev, "%s: RDS fails: %d\n", __func__, r);
-
- if (tuner->audmode == V4L2_TUNER_MODE_MONO) {
- r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO);
- if (r < 0) {
- dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
- __func__, r);
- goto out;
- }
- radio->stereo = false;
- } else if (tuner->audmode == V4L2_TUNER_MODE_STEREO) {
- r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO);
- if (r < 0) {
- dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
- __func__, r);
- goto out;
- }
- radio->stereo = true;
- } else {
- dev_err(radio->dev, "%s: tuner->audmode: %d\n",
- __func__, tuner->audmode);
- r = -EINVAL;
- goto out;
- }
-
-out:
- mutex_unlock(&core->lock);
-
- return r;
-}
-
-static int wl1273_fm_vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- freq->type = V4L2_TUNER_RADIO;
- freq->frequency = WL1273_FREQ(wl1273_fm_get_freq(radio));
-
- mutex_unlock(&core->lock);
-
- return 0;
-}
-
-static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- int r;
-
- dev_dbg(radio->dev, "%s: %d\n", __func__, freq->frequency);
-
- if (freq->type != V4L2_TUNER_RADIO) {
- dev_dbg(radio->dev,
- "freq->type != V4L2_TUNER_RADIO: %d\n", freq->type);
- return -EINVAL;
- }
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- if (core->mode == WL1273_MODE_RX) {
- dev_dbg(radio->dev, "freq: %d\n", freq->frequency);
-
- r = wl1273_fm_set_rx_freq(radio,
- WL1273_INV_FREQ(freq->frequency));
- if (r)
- dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
- ": set frequency failed with %d\n", r);
- } else {
- r = wl1273_fm_set_tx_freq(radio,
- WL1273_INV_FREQ(freq->frequency));
- if (r)
- dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
- ": set frequency failed with %d\n", r);
- }
-
- mutex_unlock(&core->lock);
-
- dev_dbg(radio->dev, "wl1273_vidioc_s_frequency: DONE\n");
- return r;
-}
-
-#define WL1273_DEFAULT_SEEK_LEVEL 7
-
-static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv,
- struct v4l2_hw_freq_seek *seek)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- int r;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (seek->tuner != 0 || seek->type != V4L2_TUNER_RADIO)
- return -EINVAL;
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- r = wl1273_fm_set_mode(radio, WL1273_MODE_RX);
- if (r)
- goto out;
-
- r = wl1273_fm_tx_set_spacing(radio, seek->spacing);
- if (r)
- dev_warn(radio->dev, "HW seek failed: %d\n", r);
-
- r = wl1273_fm_set_seek(radio, seek->wrap_around, seek->seek_upward,
- WL1273_DEFAULT_SEEK_LEVEL);
- if (r)
- dev_warn(radio->dev, "HW seek failed: %d\n", r);
-
-out:
- mutex_unlock(&core->lock);
- return r;
-}
-
-static int wl1273_fm_vidioc_s_modulator(struct file *file, void *priv,
- struct v4l2_modulator *modulator)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- int r = 0;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- if (modulator->index > 0)
- return -EINVAL;
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- r = wl1273_fm_set_mode(radio, WL1273_MODE_TX);
- if (r)
- goto out;
-
- if (modulator->txsubchans & V4L2_TUNER_SUB_RDS)
- r = wl1273_fm_set_rds(radio, WL1273_RDS_ON);
- else
- r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF);
-
- if (modulator->txsubchans & V4L2_TUNER_SUB_MONO)
- r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO);
- else
- r = core->write(core, WL1273_MONO_SET,
- WL1273_RX_STEREO);
- if (r < 0)
- dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
- "MONO_SET fails: %d\n", r);
-out:
- mutex_unlock(&core->lock);
-
- return r;
-}
-
-static int wl1273_fm_vidioc_g_modulator(struct file *file, void *priv,
- struct v4l2_modulator *modulator)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- u16 val;
- int r;
-
- dev_dbg(radio->dev, "%s\n", __func__);
-
- strlcpy(modulator->name, WL1273_FM_DRIVER_NAME,
- sizeof(modulator->name));
-
- modulator->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW);
- modulator->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH);
-
- modulator->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS |
- V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO;
-
- if (core->mode != WL1273_MODE_TX)
- return 0;
-
- if (mutex_lock_interruptible(&core->lock))
- return -EINTR;
-
- r = core->read(core, WL1273_MONO_SET, &val);
- if (r)
- goto out;
-
- if (val == WL1273_TX_STEREO)
- modulator->txsubchans = V4L2_TUNER_SUB_STEREO;
- else
- modulator->txsubchans = V4L2_TUNER_SUB_MONO;
-
- if (radio->rds_on)
- modulator->txsubchans |= V4L2_TUNER_SUB_RDS;
-out:
- mutex_unlock(&core->lock);
-
- return 0;
-}
-
-static int wl1273_fm_vidioc_log_status(struct file *file, void *priv)
-{
- struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
- struct wl1273_core *core = radio->core;
- struct device *dev = radio->dev;
- u16 val;
- int r;
-
- dev_info(dev, DRIVER_DESC);
-
- if (core->mode == WL1273_MODE_OFF) {
- dev_info(dev, "Mode: Off\n");
- return 0;
- }
-
- if (core->mode == WL1273_MODE_SUSPENDED) {
- dev_info(dev, "Mode: Suspended\n");
- return 0;
- }
-
- r = core->read(core, WL1273_ASIC_ID_GET, &val);
- if (r)
- dev_err(dev, "%s: Get ASIC_ID fails.\n", __func__);
- else
- dev_info(dev, "ASIC_ID: 0x%04x\n", val);
-
- r = core->read(core, WL1273_ASIC_VER_GET, &val);
- if (r)
- dev_err(dev, "%s: Get ASIC_VER fails.\n", __func__);
- else
- dev_info(dev, "ASIC Version: 0x%04x\n", val);
-
- r = core->read(core, WL1273_FIRM_VER_GET, &val);
- if (r)
- dev_err(dev, "%s: Get FIRM_VER fails.\n", __func__);
- else
- dev_info(dev, "FW version: %d(0x%04x)\n", val, val);
-
- r = core->read(core, WL1273_BAND_SET, &val);
- if (r)
- dev_err(dev, "%s: Get BAND fails.\n", __func__);
- else
- dev_info(dev, "BAND: %d\n", val);
-
- if (core->mode == WL1273_MODE_TX) {
- r = core->read(core, WL1273_PUPD_SET, &val);
- if (r)
- dev_err(dev, "%s: Get PUPD fails.\n", __func__);
- else
- dev_info(dev, "PUPD: 0x%04x\n", val);
-
- r = core->read(core, WL1273_CHANL_SET, &val);
- if (r)
- dev_err(dev, "%s: Get CHANL fails.\n", __func__);
- else
- dev_info(dev, "Tx frequency: %dkHz\n", val*10);
- } else if (core->mode == WL1273_MODE_RX) {
- int bf = radio->rangelow;
-
- r = core->read(core, WL1273_FREQ_SET, &val);
- if (r)
- dev_err(dev, "%s: Get FREQ fails.\n", __func__);
- else
- dev_info(dev, "RX Frequency: %dkHz\n", bf + val*50);
-
- r = core->read(core, WL1273_MOST_MODE_SET, &val);
- if (r)
- dev_err(dev, "%s: Get MOST_MODE fails.\n",
- __func__);
- else if (val == 0)
- dev_info(dev, "MOST_MODE: Stereo according to blend\n");
- else if (val == 1)
- dev_info(dev, "MOST_MODE: Force mono output\n");
- else
- dev_info(dev, "MOST_MODE: Unexpected value: %d\n", val);
-
- r = core->read(core, WL1273_MOST_BLEND_SET, &val);
- if (r)
- dev_err(dev, "%s: Get MOST_BLEND fails.\n", __func__);
- else if (val == 0)
- dev_info(dev,
- "MOST_BLEND: Switched blend & hysteresis.\n");
- else if (val == 1)
- dev_info(dev, "MOST_BLEND: Soft blend.\n");
- else
- dev_info(dev, "MOST_BLEND: Unexpected val: %d\n", val);
-
- r = core->read(core, WL1273_STEREO_GET, &val);
- if (r)
- dev_err(dev, "%s: Get STEREO fails.\n", __func__);
- else if (val == 0)
- dev_info(dev, "STEREO: Not detected\n");
- else if (val == 1)
- dev_info(dev, "STEREO: Detected\n");
- else
- dev_info(dev, "STEREO: Unexpected value: %d\n", val);
-
- r = core->read(core, WL1273_RSSI_LVL_GET, &val);
- if (r)
- dev_err(dev, "%s: Get RSSI_LVL fails.\n", __func__);
- else
- dev_info(dev, "RX signal strength: %d\n", (s16) val);
-
- r = core->read(core, WL1273_POWER_SET, &val);
- if (r)
- dev_err(dev, "%s: Get POWER fails.\n", __func__);
- else
- dev_info(dev, "POWER: 0x%04x\n", val);
-
- r = core->read(core, WL1273_INT_MASK_SET, &val);
- if (r)
- dev_err(dev, "%s: Get INT_MASK fails.\n", __func__);
- else
- dev_info(dev, "INT_MASK: 0x%04x\n", val);
-
- r = core->read(core, WL1273_RDS_SYNC_GET, &val);
- if (r)
- dev_err(dev, "%s: Get RDS_SYNC fails.\n",
- __func__);
- else if (val == 0)
- dev_info(dev, "RDS_SYNC: Not synchronized\n");
-
- else if (val == 1)
- dev_info(dev, "RDS_SYNC: Synchronized\n");
- else
- dev_info(dev, "RDS_SYNC: Unexpected value: %d\n", val);
-
- r = core->read(core, WL1273_I2S_MODE_CONFIG_SET, &val);
- if (r)
- dev_err(dev, "%s: Get I2S_MODE_CONFIG fails.\n",
- __func__);
- else
- dev_info(dev, "I2S_MODE_CONFIG: 0x%04x\n", val);
-
- r = core->read(core, WL1273_VOLUME_SET, &val);
- if (r)
- dev_err(dev, "%s: Get VOLUME fails.\n", __func__);
- else
- dev_info(dev, "VOLUME: 0x%04x\n", val);
- }
-
- return 0;
-}
-
-static void wl1273_vdev_release(struct video_device *dev)
-{
-}
-
-static const struct v4l2_ctrl_ops wl1273_ctrl_ops = {
- .s_ctrl = wl1273_fm_vidioc_s_ctrl,
- .g_volatile_ctrl = wl1273_fm_g_volatile_ctrl,
-};
-
-static const struct v4l2_ioctl_ops wl1273_ioctl_ops = {
- .vidioc_querycap = wl1273_fm_vidioc_querycap,
- .vidioc_g_input = wl1273_fm_vidioc_g_input,
- .vidioc_s_input = wl1273_fm_vidioc_s_input,
- .vidioc_g_audio = wl1273_fm_vidioc_g_audio,
- .vidioc_s_audio = wl1273_fm_vidioc_s_audio,
- .vidioc_g_tuner = wl1273_fm_vidioc_g_tuner,
- .vidioc_s_tuner = wl1273_fm_vidioc_s_tuner,
- .vidioc_g_frequency = wl1273_fm_vidioc_g_frequency,
- .vidioc_s_frequency = wl1273_fm_vidioc_s_frequency,
- .vidioc_s_hw_freq_seek = wl1273_fm_vidioc_s_hw_freq_seek,
- .vidioc_g_modulator = wl1273_fm_vidioc_g_modulator,
- .vidioc_s_modulator = wl1273_fm_vidioc_s_modulator,
- .vidioc_log_status = wl1273_fm_vidioc_log_status,
-};
-
-static struct video_device wl1273_viddev_template = {
- .fops = &wl1273_fops,
- .ioctl_ops = &wl1273_ioctl_ops,
- .name = WL1273_FM_DRIVER_NAME,
- .release = wl1273_vdev_release,
-};
-
-static int wl1273_fm_radio_remove(struct platform_device *pdev)
-{
- struct wl1273_device *radio = platform_get_drvdata(pdev);
- struct wl1273_core *core = radio->core;
-
- dev_info(&pdev->dev, "%s.\n", __func__);
-
- free_irq(core->client->irq, radio);
- core->pdata->free_resources();
-
- v4l2_ctrl_handler_free(&radio->ctrl_handler);
- video_unregister_device(&radio->videodev);
- v4l2_device_unregister(&radio->v4l2dev);
- kfree(radio->buffer);
- kfree(radio->write_buf);
- kfree(radio);
-
- return 0;
-}
-
-static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
-{
- struct wl1273_core **core = pdev->dev.platform_data;
- struct wl1273_device *radio;
- struct v4l2_ctrl *ctrl;
- int r = 0;
-
- pr_debug("%s\n", __func__);
-
- if (!core) {
- dev_err(&pdev->dev, "No platform data.\n");
- r = -EINVAL;
- goto pdata_err;
- }
-
- radio = kzalloc(sizeof(*radio), GFP_KERNEL);
- if (!radio) {
- r = -ENOMEM;
- goto pdata_err;
- }
-
- /* RDS buffer allocation */
- radio->buf_size = rds_buf * RDS_BLOCK_SIZE;
- radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
- if (!radio->buffer) {
- pr_err("Cannot allocate memory for RDS buffer.\n");
- r = -ENOMEM;
- goto err_kmalloc;
- }
-
- radio->core = *core;
- radio->irq_flags = WL1273_IRQ_MASK;
- radio->dev = &radio->core->client->dev;
- radio->rds_on = false;
- radio->core->mode = WL1273_MODE_OFF;
- radio->tx_power = 118;
- radio->core->audio_mode = WL1273_AUDIO_ANALOG;
- radio->band = WL1273_BAND_OTHER;
- radio->core->i2s_mode = WL1273_I2S_DEF_MODE;
- radio->core->channel_number = 2;
- radio->core->volume = WL1273_DEFAULT_VOLUME;
- radio->rx_frequency = WL1273_BAND_OTHER_LOW;
- radio->tx_frequency = WL1273_BAND_OTHER_HIGH;
- radio->rangelow = WL1273_BAND_OTHER_LOW;
- radio->rangehigh = WL1273_BAND_OTHER_HIGH;
- radio->stereo = true;
- radio->bus_type = "I2C";
-
- if (radio->core->pdata->request_resources) {
- r = radio->core->pdata->request_resources(radio->core->client);
- if (r) {
- dev_err(radio->dev, WL1273_FM_DRIVER_NAME
- ": Cannot get platform data\n");
- goto err_resources;
- }
-
- dev_dbg(radio->dev, "irq: %d\n", radio->core->client->irq);
-
- r = request_threaded_irq(radio->core->client->irq, NULL,
- wl1273_fm_irq_thread_handler,
- IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
- "wl1273-fm", radio);
- if (r < 0) {
- dev_err(radio->dev, WL1273_FM_DRIVER_NAME
- ": Unable to register IRQ handler: %d\n", r);
- goto err_request_irq;
- }
- } else {
- dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ"
- " not configured");
- r = -EINVAL;
- goto err_resources;
- }
-
- init_completion(&radio->busy);
- init_waitqueue_head(&radio->read_queue);
-
- radio->write_buf = kmalloc(256, GFP_KERNEL);
- if (!radio->write_buf) {
- r = -ENOMEM;
- goto write_buf_err;
- }
-
- radio->dev = &pdev->dev;
- radio->v4l2dev.ctrl_handler = &radio->ctrl_handler;
- radio->rds_users = 0;
-
- r = v4l2_device_register(&pdev->dev, &radio->v4l2dev);
- if (r) {
- dev_err(&pdev->dev, "Cannot register v4l2_device.\n");
- goto device_register_err;
- }
-
- /* V4L2 configuration */
- memcpy(&radio->videodev, &wl1273_viddev_template,
- sizeof(wl1273_viddev_template));
-
- radio->videodev.v4l2_dev = &radio->v4l2dev;
-
- v4l2_ctrl_handler_init(&radio->ctrl_handler, 6);
-
- /* add in ascending ID order */
- v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
- V4L2_CID_AUDIO_VOLUME, 0, WL1273_MAX_VOLUME, 1,
- WL1273_DEFAULT_VOLUME);
-
- v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
- V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
-
- v4l2_ctrl_new_std_menu(&radio->ctrl_handler, &wl1273_ctrl_ops,
- V4L2_CID_TUNE_PREEMPHASIS,
- V4L2_PREEMPHASIS_75_uS, 0x03,
- V4L2_PREEMPHASIS_50_uS);
-
- v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
- V4L2_CID_TUNE_POWER_LEVEL, 91, 122, 1, 118);
-
- ctrl = v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
- V4L2_CID_TUNE_ANTENNA_CAPACITOR,
- 0, 255, 1, 255);
- if (ctrl)
- ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
-
- if (radio->ctrl_handler.error) {
- r = radio->ctrl_handler.error;
- dev_err(&pdev->dev, "Ctrl handler error: %d\n", r);
- goto handler_init_err;
- }
-
- video_set_drvdata(&radio->videodev, radio);
- platform_set_drvdata(pdev, radio);
-
- /* register video device */
- r = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr);
- if (r) {
- dev_err(&pdev->dev, WL1273_FM_DRIVER_NAME
- ": Could not register video device\n");
- goto handler_init_err;
- }
-
- return 0;
-
-handler_init_err:
- v4l2_ctrl_handler_free(&radio->ctrl_handler);
- v4l2_device_unregister(&radio->v4l2dev);
-device_register_err:
- kfree(radio->write_buf);
-write_buf_err:
- free_irq(radio->core->client->irq, radio);
-err_request_irq:
- radio->core->pdata->free_resources();
-err_resources:
- kfree(radio->buffer);
-err_kmalloc:
- kfree(radio);
-pdata_err:
- return r;
-}
-
-static struct platform_driver wl1273_fm_radio_driver = {
- .probe = wl1273_fm_radio_probe,
- .remove = __devexit_p(wl1273_fm_radio_remove),
- .driver = {
- .name = "wl1273_fm_radio",
- .owner = THIS_MODULE,
- },
-};
-
-module_platform_driver(wl1273_fm_radio_driver);
-
-MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:wl1273_fm_radio");
diff --git a/ANDROID_3.4.5/drivers/media/radio/radio-zoltrix.c b/ANDROID_3.4.5/drivers/media/radio/radio-zoltrix.c
deleted file mode 100644
index 026e88ee..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/radio-zoltrix.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Zoltrix Radio Plus driver
- * Copyright 1998 C. van Schaik <carl@leg.uct.ac.za>
- *
- * BUGS
- * Due to the inconsistency in reading from the signal flags
- * it is difficult to get an accurate tuned signal.
- *
- * It seems that the card is not linear to 0 volume. It cuts off
- * at a low volume, and it is not possible (at least I have not found)
- * to get fine volume control over the low volume range.
- *
- * Some code derived from code by Romolo Manfredini
- * romolo@bicnet.it
- *
- * 1999-05-06 - (C. van Schaik)
- * - Make signal strength and stereo scans
- * kinder to cpu while in delay
- * 1999-01-05 - (C. van Schaik)
- * - Changed tuning to 1/160Mhz accuracy
- * - Added stereo support
- * (card defaults to stereo)
- * (can explicitly force mono on the card)
- * (can detect if station is in stereo)
- * - Added unmute function
- * - Reworked ioctl functions
- * 2002-07-15 - Fix Stereo typo
- *
- * 2006-07-24 - Converted to V4L2 API
- * by Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
- *
- * Note that this is the driver for the Zoltrix Radio Plus.
- * This driver does not work for the Zoltrix Radio Plus 108 or the
- * Zoltrix Radio Plus for Windows.
- *
- * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
- */
-
-#include <linux/module.h> /* Modules */
-#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* request_region */
-#include <linux/delay.h> /* udelay, msleep */
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <linux/mutex.h>
-#include <linux/io.h> /* outb, outb_p */
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include "radio-isa.h"
-
-MODULE_AUTHOR("C. van Schaik");
-MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1.99");
-
-#ifndef CONFIG_RADIO_ZOLTRIX_PORT
-#define CONFIG_RADIO_ZOLTRIX_PORT -1
-#endif
-
-#define ZOLTRIX_MAX 2
-
-static int io[ZOLTRIX_MAX] = { [0] = CONFIG_RADIO_ZOLTRIX_PORT,
- [1 ... (ZOLTRIX_MAX - 1)] = -1 };
-static int radio_nr[ZOLTRIX_MAX] = { [0 ... (ZOLTRIX_MAX - 1)] = -1 };
-
-module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "I/O addresses of the Zoltrix Radio Plus card (0x20c or 0x30c)");
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio device numbers");
-
-struct zoltrix {
- struct radio_isa_card isa;
- int curvol;
- bool muted;
-};
-
-static struct radio_isa_card *zoltrix_alloc(void)
-{
- struct zoltrix *zol = kzalloc(sizeof(*zol), GFP_KERNEL);
-
- return zol ? &zol->isa : NULL;
-}
-
-static int zoltrix_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
-{
- struct zoltrix *zol = container_of(isa, struct zoltrix, isa);
-
- zol->curvol = vol;
- zol->muted = mute;
- if (mute || vol == 0) {
- outb(0, isa->io);
- outb(0, isa->io);
- inb(isa->io + 3); /* Zoltrix needs to be read to confirm */
- return 0;
- }
-
- outb(vol - 1, isa->io);
- msleep(10);
- inb(isa->io + 2);
- return 0;
-}
-
-/* tunes the radio to the desired frequency */
-static int zoltrix_s_frequency(struct radio_isa_card *isa, u32 freq)
-{
- struct zoltrix *zol = container_of(isa, struct zoltrix, isa);
- struct v4l2_device *v4l2_dev = &isa->v4l2_dev;
- unsigned long long bitmask, f, m;
- bool stereo = isa->stereo;
- int i;
-
- if (freq == 0) {
- v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n");
- return -EINVAL;
- }
-
- m = (freq / 160 - 8800) * 2;
- f = (unsigned long long)m + 0x4d1c;
-
- bitmask = 0xc480402c10080000ull;
- i = 45;
-
- outb(0, isa->io);
- outb(0, isa->io);
- inb(isa->io + 3); /* Zoltrix needs to be read to confirm */
-
- outb(0x40, isa->io);
- outb(0xc0, isa->io);
-
- bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31));
- while (i--) {
- if ((bitmask & 0x8000000000000000ull) != 0) {
- outb(0x80, isa->io);
- udelay(50);
- outb(0x00, isa->io);
- udelay(50);
- outb(0x80, isa->io);
- udelay(50);
- } else {
- outb(0xc0, isa->io);
- udelay(50);
- outb(0x40, isa->io);
- udelay(50);
- outb(0xc0, isa->io);
- udelay(50);
- }
- bitmask *= 2;
- }
- /* termination sequence */
- outb(0x80, isa->io);
- outb(0xc0, isa->io);
- outb(0x40, isa->io);
- udelay(1000);
- inb(isa->io + 2);
- udelay(1000);
-
- return zoltrix_s_mute_volume(isa, zol->muted, zol->curvol);
-}
-
-/* Get signal strength */
-static u32 zoltrix_g_rxsubchans(struct radio_isa_card *isa)
-{
- struct zoltrix *zol = container_of(isa, struct zoltrix, isa);
- int a, b;
-
- outb(0x00, isa->io); /* This stuff I found to do nothing */
- outb(zol->curvol, isa->io);
- msleep(20);
-
- a = inb(isa->io);
- msleep(10);
- b = inb(isa->io);
-
- return (a == b && a == 0xcf) ?
- V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
-}
-
-static u32 zoltrix_g_signal(struct radio_isa_card *isa)
-{
- struct zoltrix *zol = container_of(isa, struct zoltrix, isa);
- int a, b;
-
- outb(0x00, isa->io); /* This stuff I found to do nothing */
- outb(zol->curvol, isa->io);
- msleep(20);
-
- a = inb(isa->io);
- msleep(10);
- b = inb(isa->io);
-
- if (a != b)
- return 0;
-
- /* I found this out by playing with a binary scanner on the card io */
- return (a == 0xcf || a == 0xdf || a == 0xef) ? 0xffff : 0;
-}
-
-static int zoltrix_s_stereo(struct radio_isa_card *isa, bool stereo)
-{
- return zoltrix_s_frequency(isa, isa->freq);
-}
-
-static const struct radio_isa_ops zoltrix_ops = {
- .alloc = zoltrix_alloc,
- .s_mute_volume = zoltrix_s_mute_volume,
- .s_frequency = zoltrix_s_frequency,
- .s_stereo = zoltrix_s_stereo,
- .g_rxsubchans = zoltrix_g_rxsubchans,
- .g_signal = zoltrix_g_signal,
-};
-
-static const int zoltrix_ioports[] = { 0x20c, 0x30c };
-
-static struct radio_isa_driver zoltrix_driver = {
- .driver = {
- .match = radio_isa_match,
- .probe = radio_isa_probe,
- .remove = radio_isa_remove,
- .driver = {
- .name = "radio-zoltrix",
- },
- },
- .io_params = io,
- .radio_nr_params = radio_nr,
- .io_ports = zoltrix_ioports,
- .num_of_io_ports = ARRAY_SIZE(zoltrix_ioports),
- .region_size = 2,
- .card = "Zoltrix Radio Plus",
- .ops = &zoltrix_ops,
- .has_stereo = true,
- .max_volume = 15,
-};
-
-static int __init zoltrix_init(void)
-{
- return isa_register_driver(&zoltrix_driver.driver, ZOLTRIX_MAX);
-}
-
-static void __exit zoltrix_exit(void)
-{
- isa_unregister_driver(&zoltrix_driver.driver);
-}
-
-module_init(zoltrix_init);
-module_exit(zoltrix_exit);
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/saa7706h.c b/ANDROID_3.4.5/drivers/media/radio/saa7706h.c
deleted file mode 100644
index 94747063..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/saa7706h.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * saa7706.c Philips SAA7706H Car Radio DSP driver
- * Copyright (c) 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-chip-ident.h>
-
-#define DRIVER_NAME "saa7706h"
-
-/* the I2C memory map looks like this
-
- $1C00 - $FFFF Not Used
- $2200 - $3FFF Reserved YRAM (DSP2) space
- $2000 - $21FF YRAM (DSP2)
- $1FF0 - $1FFF Hardware Registers
- $1280 - $1FEF Reserved XRAM (DSP2) space
- $1000 - $127F XRAM (DSP2)
- $0FFF DSP CONTROL
- $0A00 - $0FFE Reserved
- $0980 - $09FF Reserved YRAM (DSP1) space
- $0800 - $097F YRAM (DSP1)
- $0200 - $07FF Not Used
- $0180 - $01FF Reserved XRAM (DSP1) space
- $0000 - $017F XRAM (DSP1)
-*/
-
-#define SAA7706H_REG_CTRL 0x0fff
-#define SAA7706H_CTRL_BYP_PLL 0x0001
-#define SAA7706H_CTRL_PLL_DIV_MASK 0x003e
-#define SAA7706H_CTRL_PLL3_62975MHZ 0x003e
-#define SAA7706H_CTRL_DSP_TURBO 0x0040
-#define SAA7706H_CTRL_PC_RESET_DSP1 0x0080
-#define SAA7706H_CTRL_PC_RESET_DSP2 0x0100
-#define SAA7706H_CTRL_DSP1_ROM_EN_MASK 0x0600
-#define SAA7706H_CTRL_DSP1_FUNC_PROM 0x0000
-#define SAA7706H_CTRL_DSP2_ROM_EN_MASK 0x1800
-#define SAA7706H_CTRL_DSP2_FUNC_PROM 0x0000
-#define SAA7706H_CTRL_DIG_SIL_INTERPOL 0x8000
-
-#define SAA7706H_REG_EVALUATION 0x1ff0
-#define SAA7706H_EVAL_DISABLE_CHARGE_PUMP 0x000001
-#define SAA7706H_EVAL_DCS_CLOCK 0x000002
-#define SAA7706H_EVAL_GNDRC1_ENABLE 0x000004
-#define SAA7706H_EVAL_GNDRC2_ENABLE 0x000008
-
-#define SAA7706H_REG_CL_GEN1 0x1ff3
-#define SAA7706H_CL_GEN1_MIN_LOOPGAIN_MASK 0x00000f
-#define SAA7706H_CL_GEN1_LOOPGAIN_MASK 0x0000f0
-#define SAA7706H_CL_GEN1_COARSE_RATION 0xffff00
-
-#define SAA7706H_REG_CL_GEN2 0x1ff4
-#define SAA7706H_CL_GEN2_WSEDGE_FALLING 0x000001
-#define SAA7706H_CL_GEN2_STOP_VCO 0x000002
-#define SAA7706H_CL_GEN2_FRERUN 0x000004
-#define SAA7706H_CL_GEN2_ADAPTIVE 0x000008
-#define SAA7706H_CL_GEN2_FINE_RATIO_MASK 0x0ffff0
-
-#define SAA7706H_REG_CL_GEN4 0x1ff6
-#define SAA7706H_CL_GEN4_BYPASS_PLL1 0x001000
-#define SAA7706H_CL_GEN4_PLL1_DIV_MASK 0x03e000
-#define SAA7706H_CL_GEN4_DSP1_TURBO 0x040000
-
-#define SAA7706H_REG_SEL 0x1ff7
-#define SAA7706H_SEL_DSP2_SRCA_MASK 0x000007
-#define SAA7706H_SEL_DSP2_FMTA_MASK 0x000031
-#define SAA7706H_SEL_DSP2_SRCB_MASK 0x0001c0
-#define SAA7706H_SEL_DSP2_FMTB_MASK 0x000e00
-#define SAA7706H_SEL_DSP1_SRC_MASK 0x003000
-#define SAA7706H_SEL_DSP1_FMT_MASK 0x01c003
-#define SAA7706H_SEL_SPDIF2 0x020000
-#define SAA7706H_SEL_HOST_IO_FMT_MASK 0x1c0000
-#define SAA7706H_SEL_EN_HOST_IO 0x200000
-
-#define SAA7706H_REG_IAC 0x1ff8
-#define SAA7706H_REG_CLK_SET 0x1ff9
-#define SAA7706H_REG_CLK_COEFF 0x1ffa
-#define SAA7706H_REG_INPUT_SENS 0x1ffb
-#define SAA7706H_INPUT_SENS_RDS_VOL_MASK 0x0003f
-#define SAA7706H_INPUT_SENS_FM_VOL_MASK 0x00fc0
-#define SAA7706H_INPUT_SENS_FM_MPX 0x01000
-#define SAA7706H_INPUT_SENS_OFF_FILTER_A_EN 0x02000
-#define SAA7706H_INPUT_SENS_OFF_FILTER_B_EN 0x04000
-#define SAA7706H_REG_PHONE_NAV_AUDIO 0x1ffc
-#define SAA7706H_REG_IO_CONF_DSP2 0x1ffd
-#define SAA7706H_REG_STATUS_DSP2 0x1ffe
-#define SAA7706H_REG_PC_DSP2 0x1fff
-
-#define SAA7706H_DSP1_MOD0 0x0800
-#define SAA7706H_DSP1_ROM_VER 0x097f
-#define SAA7706H_DSP2_MPTR0 0x1000
-
-#define SAA7706H_DSP1_MODPNTR 0x0000
-
-#define SAA7706H_DSP2_XMEM_CONTLLCW 0x113e
-#define SAA7706H_DSP2_XMEM_BUSAMP 0x114a
-#define SAA7706H_DSP2_XMEM_FDACPNTR 0x11f9
-#define SAA7706H_DSP2_XMEM_IIS1PNTR 0x11fb
-
-#define SAA7706H_DSP2_YMEM_PVGA 0x212a
-#define SAA7706H_DSP2_YMEM_PVAT1 0x212b
-#define SAA7706H_DSP2_YMEM_PVAT 0x212c
-#define SAA7706H_DSP2_YMEM_ROM_VER 0x21ff
-
-#define SUPPORTED_DSP1_ROM_VER 0x667
-
-struct saa7706h_state {
- struct v4l2_subdev sd;
- unsigned muted;
-};
-
-static inline struct saa7706h_state *to_state(struct v4l2_subdev *sd)
-{
- return container_of(sd, struct saa7706h_state, sd);
-}
-
-static int saa7706h_i2c_send(struct i2c_client *client, const u8 *data, int len)
-{
- int err = i2c_master_send(client, data, len);
- if (err == len)
- return 0;
- return err > 0 ? -EIO : err;
-}
-
-static int saa7706h_i2c_transfer(struct i2c_client *client,
- struct i2c_msg *msgs, int num)
-{
- int err = i2c_transfer(client->adapter, msgs, num);
- if (err == num)
- return 0;
- return err > 0 ? -EIO : err;
-}
-
-static int saa7706h_set_reg24(struct v4l2_subdev *sd, u16 reg, u32 val)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- u8 buf[5];
- int pos = 0;
-
- buf[pos++] = reg >> 8;
- buf[pos++] = reg;
- buf[pos++] = val >> 16;
- buf[pos++] = val >> 8;
- buf[pos++] = val;
-
- return saa7706h_i2c_send(client, buf, pos);
-}
-
-static int saa7706h_set_reg24_err(struct v4l2_subdev *sd, u16 reg, u32 val,
- int *err)
-{
- return *err ? *err : saa7706h_set_reg24(sd, reg, val);
-}
-
-static int saa7706h_set_reg16(struct v4l2_subdev *sd, u16 reg, u16 val)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- u8 buf[4];
- int pos = 0;
-
- buf[pos++] = reg >> 8;
- buf[pos++] = reg;
- buf[pos++] = val >> 8;
- buf[pos++] = val;
-
- return saa7706h_i2c_send(client, buf, pos);
-}
-
-static int saa7706h_set_reg16_err(struct v4l2_subdev *sd, u16 reg, u16 val,
- int *err)
-{
- return *err ? *err : saa7706h_set_reg16(sd, reg, val);
-}
-
-static int saa7706h_get_reg16(struct v4l2_subdev *sd, u16 reg)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- u8 buf[2];
- int err;
- u8 regaddr[] = {reg >> 8, reg};
- struct i2c_msg msg[] = { {client->addr, 0, sizeof(regaddr), regaddr},
- {client->addr, I2C_M_RD, sizeof(buf), buf} };
-
- err = saa7706h_i2c_transfer(client, msg, ARRAY_SIZE(msg));
- if (err)
- return err;
-
- return buf[0] << 8 | buf[1];
-}
-
-static int saa7706h_unmute(struct v4l2_subdev *sd)
-{
- struct saa7706h_state *state = to_state(sd);
- int err = 0;
-
- err = saa7706h_set_reg16_err(sd, SAA7706H_REG_CTRL,
- SAA7706H_CTRL_PLL3_62975MHZ | SAA7706H_CTRL_PC_RESET_DSP1 |
- SAA7706H_CTRL_PC_RESET_DSP2, &err);
-
- /* newer versions of the chip requires a small sleep after reset */
- msleep(1);
-
- err = saa7706h_set_reg16_err(sd, SAA7706H_REG_CTRL,
- SAA7706H_CTRL_PLL3_62975MHZ, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_EVALUATION, 0, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN1, 0x040022, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN2,
- SAA7706H_CL_GEN2_WSEDGE_FALLING, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN4, 0x024080, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_SEL, 0x200080, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_IAC, 0xf4caed, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CLK_SET, 0x124334, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CLK_COEFF, 0x004a1a,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_INPUT_SENS, 0x0071c7,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_PHONE_NAV_AUDIO,
- 0x0e22ff, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_IO_CONF_DSP2, 0x001ff8,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_STATUS_DSP2, 0x080003,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_REG_PC_DSP2, 0x000004, &err);
-
- err = saa7706h_set_reg16_err(sd, SAA7706H_DSP1_MOD0, 0x0c6c, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_MPTR0, 0x000b4b, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP1_MODPNTR, 0x000600, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP1_MODPNTR, 0x0000c0, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x000819,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x00085a,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_BUSAMP, 0x7fffff,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_FDACPNTR, 0x2000cb,
- &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_IIS1PNTR, 0x2000cb,
- &err);
-
- err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVGA, 0x0f80, &err);
-
- err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVAT1, 0x0800,
- &err);
-
- err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVAT, 0x0800, &err);
-
- err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x000905,
- &err);
- if (!err)
- state->muted = 0;
- return err;
-}
-
-static int saa7706h_mute(struct v4l2_subdev *sd)
-{
- struct saa7706h_state *state = to_state(sd);
- int err;
-
- err = saa7706h_set_reg16(sd, SAA7706H_REG_CTRL,
- SAA7706H_CTRL_PLL3_62975MHZ | SAA7706H_CTRL_PC_RESET_DSP1 |
- SAA7706H_CTRL_PC_RESET_DSP2);
- if (!err)
- state->muted = 1;
- return err;
-}
-
-static int saa7706h_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
- return -EINVAL;
-}
-
-static int saa7706h_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
- struct saa7706h_state *state = to_state(sd);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = state->muted;
- return 0;
- }
- return -EINVAL;
-}
-
-static int saa7706h_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value)
- return saa7706h_mute(sd);
- return saa7706h_unmute(sd);
- }
- return -EINVAL;
-}
-
-static int saa7706h_g_chip_ident(struct v4l2_subdev *sd,
- struct v4l2_dbg_chip_ident *chip)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
-
- return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7706H, 0);
-}
-
-static const struct v4l2_subdev_core_ops saa7706h_core_ops = {
- .g_chip_ident = saa7706h_g_chip_ident,
- .queryctrl = saa7706h_queryctrl,
- .g_ctrl = saa7706h_g_ctrl,
- .s_ctrl = saa7706h_s_ctrl,
-};
-
-static const struct v4l2_subdev_ops saa7706h_ops = {
- .core = &saa7706h_core_ops,
-};
-
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-
-static int __devinit saa7706h_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct saa7706h_state *state;
- struct v4l2_subdev *sd;
- int err;
-
- /* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EIO;
-
- v4l_info(client, "chip found @ 0x%02x (%s)\n",
- client->addr << 1, client->adapter->name);
-
- state = kzalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
- if (state == NULL)
- return -ENOMEM;
- sd = &state->sd;
- v4l2_i2c_subdev_init(sd, client, &saa7706h_ops);
-
- /* check the rom versions */
- err = saa7706h_get_reg16(sd, SAA7706H_DSP1_ROM_VER);
- if (err < 0)
- goto err;
- if (err != SUPPORTED_DSP1_ROM_VER)
- v4l2_warn(sd, "Unknown DSP1 ROM code version: 0x%x\n", err);
-
- state->muted = 1;
-
- /* startup in a muted state */
- err = saa7706h_mute(sd);
- if (err)
- goto err;
-
- return 0;
-
-err:
- v4l2_device_unregister_subdev(sd);
- kfree(to_state(sd));
-
- printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", err);
-
- return err;
-}
-
-static int __devexit saa7706h_remove(struct i2c_client *client)
-{
- struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
- saa7706h_mute(sd);
- v4l2_device_unregister_subdev(sd);
- kfree(to_state(sd));
- return 0;
-}
-
-static const struct i2c_device_id saa7706h_id[] = {
- {DRIVER_NAME, 0},
- {},
-};
-
-MODULE_DEVICE_TABLE(i2c, saa7706h_id);
-
-static struct i2c_driver saa7706h_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = DRIVER_NAME,
- },
- .probe = saa7706h_probe,
- .remove = saa7706h_remove,
- .id_table = saa7706h_id,
-};
-
-module_i2c_driver(saa7706h_driver);
-
-MODULE_DESCRIPTION("SAA7706H Car Radio DSP driver");
-MODULE_AUTHOR("Mocean Laboratories");
-MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/media/radio/si470x/Kconfig b/ANDROID_3.4.5/drivers/media/radio/si470x/Kconfig
deleted file mode 100644
index a466654e..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si470x/Kconfig
+++ /dev/null
@@ -1,37 +0,0 @@
-config USB_SI470X
- tristate "Silicon Labs Si470x FM Radio Receiver support with USB"
- depends on USB && RADIO_SI470X
- ---help---
- This is a driver for USB devices with the Silicon Labs SI470x
- chip. Currently these devices are known to work:
- - 10c4:818a: Silicon Labs USB FM Radio Reference Design
- - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music)
- - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
- - 10c5:819a: Sanei Electric FM USB Radio (aka DealExtreme.com PCear)
-
- Sound is provided by the ALSA USB Audio/MIDI driver. Therefore
- if you don't want to use the device solely for RDS receiving,
- it is recommended to also select SND_USB_AUDIO.
-
- Please have a look at the documentation, especially on how
- to redirect the audio stream from the radio to your sound device:
- Documentation/video4linux/si470x.txt
-
- Say Y here if you want to connect this type of radio to your
- computer's USB port.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-usb-si470x.
-
-config I2C_SI470X
- tristate "Silicon Labs Si470x FM Radio Receiver support with I2C"
- depends on I2C && RADIO_SI470X && !USB_SI470X
- ---help---
- This is a driver for I2C devices with the Silicon Labs SI470x
- chip.
-
- Say Y here if you want to connect this type of radio to your
- computer's I2C port.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-i2c-si470x.
diff --git a/ANDROID_3.4.5/drivers/media/radio/si470x/Makefile b/ANDROID_3.4.5/drivers/media/radio/si470x/Makefile
deleted file mode 100644
index 06964816..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si470x/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for radios with Silicon Labs Si470x FM Radio Receivers
-#
-
-radio-usb-si470x-objs := radio-si470x-usb.o radio-si470x-common.o
-radio-i2c-si470x-objs := radio-si470x-i2c.o radio-si470x-common.o
-
-obj-$(CONFIG_USB_SI470X) += radio-usb-si470x.o
-obj-$(CONFIG_I2C_SI470X) += radio-i2c-si470x.o
diff --git a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-common.c b/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-common.c
deleted file mode 100644
index 0e740c98..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-common.c
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * drivers/media/radio/si470x/radio-si470x-common.c
- *
- * Driver for radios with Silicon Labs Si470x FM Radio Receivers
- *
- * Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * History:
- * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Version 1.0.0
- * - First working version
- * 2008-01-13 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Version 1.0.1
- * - Improved error handling, every function now returns errno
- * - Improved multi user access (start/mute/stop)
- * - Channel doesn't get lost anymore after start/mute/stop
- * - RDS support added (polling mode via interrupt EP 1)
- * - marked default module parameters with *value*
- * - switched from bit structs to bit masks
- * - header file cleaned and integrated
- * 2008-01-14 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Version 1.0.2
- * - hex values are now lower case
- * - commented USB ID for ADS/Tech moved on todo list
- * - blacklisted si470x in hid-quirks.c
- * - rds buffer handling functions integrated into *_work, *_read
- * - rds_command in si470x_poll exchanged against simple retval
- * - check for firmware version 15
- * - code order and prototypes still remain the same
- * - spacing and bottom of band codes remain the same
- * 2008-01-16 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Version 1.0.3
- * - code reordered to avoid function prototypes
- * - switch/case defaults are now more user-friendly
- * - unified comment style
- * - applied all checkpatch.pl v1.12 suggestions
- * except the warning about the too long lines with bit comments
- * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
- * 2008-01-22 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Version 1.0.4
- * - avoid poss. locking when doing copy_to_user which may sleep
- * - RDS is automatically activated on read now
- * - code cleaned of unnecessary rds_commands
- * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified
- * (thanks to Guillaume RAMOUSSE)
- * 2008-01-27 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Version 1.0.5
- * - number of seek_retries changed to tune_timeout
- * - fixed problem with incomplete tune operations by own buffers
- * - optimization of variables and printf types
- * - improved error logging
- * 2008-01-31 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Oliver Neukum <oliver@neukum.org>
- * Version 1.0.6
- * - fixed coverity checker warnings in *_usb_driver_disconnect
- * - probe()/open() race by correct ordering in probe()
- * - DMA coherency rules by separate allocation of all buffers
- * - use of endianness macros
- * - abuse of spinlock, replaced by mutex
- * - racy handling of timer in disconnect,
- * replaced by delayed_work
- * - racy interruptible_sleep_on(),
- * replaced with wait_event_interruptible()
- * - handle signals in read()
- * 2008-02-08 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Oliver Neukum <oliver@neukum.org>
- * Version 1.0.7
- * - usb autosuspend support
- * - unplugging fixed
- * 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net>
- * Version 1.0.8
- * - hardware frequency seek support
- * - afc indication
- * - more safety checks, let si470x_get_freq return errno
- * - vidioc behavior corrected according to v4l2 spec
- * 2008-10-20 Alexey Klimov <klimov.linux@gmail.com>
- * - add support for KWorld USB FM Radio FM700
- * - blacklisted KWorld radio in hid-core.c and hid-ids.h
- * 2008-12-03 Mark Lord <mlord@pobox.com>
- * - add support for DealExtreme USB Radio
- * 2009-01-31 Bob Ross <pigiron@gmx.com>
- * - correction of stereo detection/setting
- * - correction of signal strength indicator scaling
- * 2009-01-31 Rick Bronson <rick@efn.org>
- * Tobias Lorenz <tobias.lorenz@gmx.net>
- * - add LED status output
- * - get HW/SW version from scratchpad
- * 2009-06-16 Edouard Lafargue <edouard@lafargue.name>
- * Version 1.0.10
- * - add support for interrupt mode for RDS endpoint,
- * instead of polling.
- * Improves RDS reception significantly
- */
-
-
-/* kernel includes */
-#include "radio-si470x.h"
-
-
-
-/**************************************************************************
- * Module Parameters
- **************************************************************************/
-
-/* Spacing (kHz) */
-/* 0: 200 kHz (USA, Australia) */
-/* 1: 100 kHz (Europe, Japan) */
-/* 2: 50 kHz */
-static unsigned short space = 2;
-module_param(space, ushort, 0444);
-MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
-
-/* Bottom of Band (MHz) */
-/* 0: 87.5 - 108 MHz (USA, Europe)*/
-/* 1: 76 - 108 MHz (Japan wide band) */
-/* 2: 76 - 90 MHz (Japan) */
-static unsigned short band = 1;
-module_param(band, ushort, 0444);
-MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
-
-/* De-emphasis */
-/* 0: 75 us (USA) */
-/* 1: 50 us (Europe, Australia, Japan) */
-static unsigned short de = 1;
-module_param(de, ushort, 0444);
-MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");
-
-/* Tune timeout */
-static unsigned int tune_timeout = 3000;
-module_param(tune_timeout, uint, 0644);
-MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
-
-/* Seek timeout */
-static unsigned int seek_timeout = 5000;
-module_param(seek_timeout, uint, 0644);
-MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
-
-
-
-/**************************************************************************
- * Generic Functions
- **************************************************************************/
-
-/*
- * si470x_set_chan - set the channel
- */
-static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
-{
- int retval;
- unsigned long timeout;
- bool timed_out = 0;
-
- /* start tuning */
- radio->registers[CHANNEL] &= ~CHANNEL_CHAN;
- radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
- retval = si470x_set_register(radio, CHANNEL);
- if (retval < 0)
- goto done;
-
- /* currently I2C driver only uses interrupt way to tune */
- if (radio->stci_enabled) {
- INIT_COMPLETION(radio->completion);
-
- /* wait till tune operation has completed */
- retval = wait_for_completion_timeout(&radio->completion,
- msecs_to_jiffies(tune_timeout));
- if (!retval)
- timed_out = true;
- } else {
- /* wait till tune operation has completed */
- timeout = jiffies + msecs_to_jiffies(tune_timeout);
- do {
- retval = si470x_get_register(radio, STATUSRSSI);
- if (retval < 0)
- goto stop;
- timed_out = time_after(jiffies, timeout);
- } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
- && (!timed_out));
- }
-
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
- dev_warn(&radio->videodev->dev, "tune does not complete\n");
- if (timed_out)
- dev_warn(&radio->videodev->dev,
- "tune timed out after %u ms\n", tune_timeout);
-
-stop:
- /* stop tuning */
- radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
- retval = si470x_set_register(radio, CHANNEL);
-
-done:
- return retval;
-}
-
-
-/*
- * si470x_get_freq - get the frequency
- */
-static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
-{
- unsigned int spacing, band_bottom;
- unsigned short chan;
- int retval;
-
- /* Spacing (kHz) */
- switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
- /* 0: 200 kHz (USA, Australia) */
- case 0:
- spacing = 0.200 * FREQ_MUL; break;
- /* 1: 100 kHz (Europe, Japan) */
- case 1:
- spacing = 0.100 * FREQ_MUL; break;
- /* 2: 50 kHz */
- default:
- spacing = 0.050 * FREQ_MUL; break;
- };
-
- /* Bottom of Band (MHz) */
- switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
- /* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0:
- band_bottom = 87.5 * FREQ_MUL; break;
- /* 1: 76 - 108 MHz (Japan wide band) */
- default:
- band_bottom = 76 * FREQ_MUL; break;
- /* 2: 76 - 90 MHz (Japan) */
- case 2:
- band_bottom = 76 * FREQ_MUL; break;
- };
-
- /* read channel */
- retval = si470x_get_register(radio, READCHAN);
- chan = radio->registers[READCHAN] & READCHAN_READCHAN;
-
- /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
- *freq = chan * spacing + band_bottom;
-
- return retval;
-}
-
-
-/*
- * si470x_set_freq - set the frequency
- */
-int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
-{
- unsigned int spacing, band_bottom;
- unsigned short chan;
-
- /* Spacing (kHz) */
- switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
- /* 0: 200 kHz (USA, Australia) */
- case 0:
- spacing = 0.200 * FREQ_MUL; break;
- /* 1: 100 kHz (Europe, Japan) */
- case 1:
- spacing = 0.100 * FREQ_MUL; break;
- /* 2: 50 kHz */
- default:
- spacing = 0.050 * FREQ_MUL; break;
- };
-
- /* Bottom of Band (MHz) */
- switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
- /* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0:
- band_bottom = 87.5 * FREQ_MUL; break;
- /* 1: 76 - 108 MHz (Japan wide band) */
- default:
- band_bottom = 76 * FREQ_MUL; break;
- /* 2: 76 - 90 MHz (Japan) */
- case 2:
- band_bottom = 76 * FREQ_MUL; break;
- };
-
- /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
- chan = (freq - band_bottom) / spacing;
-
- return si470x_set_chan(radio, chan);
-}
-
-
-/*
- * si470x_set_seek - set seek
- */
-static int si470x_set_seek(struct si470x_device *radio,
- unsigned int wrap_around, unsigned int seek_upward)
-{
- int retval = 0;
- unsigned long timeout;
- bool timed_out = 0;
-
- /* start seeking */
- radio->registers[POWERCFG] |= POWERCFG_SEEK;
- if (wrap_around == 1)
- radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
- else
- radio->registers[POWERCFG] |= POWERCFG_SKMODE;
- if (seek_upward == 1)
- radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
- else
- radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
- retval = si470x_set_register(radio, POWERCFG);
- if (retval < 0)
- goto done;
-
- /* currently I2C driver only uses interrupt way to seek */
- if (radio->stci_enabled) {
- INIT_COMPLETION(radio->completion);
-
- /* wait till seek operation has completed */
- retval = wait_for_completion_timeout(&radio->completion,
- msecs_to_jiffies(seek_timeout));
- if (!retval)
- timed_out = true;
- } else {
- /* wait till seek operation has completed */
- timeout = jiffies + msecs_to_jiffies(seek_timeout);
- do {
- retval = si470x_get_register(radio, STATUSRSSI);
- if (retval < 0)
- goto stop;
- timed_out = time_after(jiffies, timeout);
- } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
- && (!timed_out));
- }
-
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
- dev_warn(&radio->videodev->dev, "seek does not complete\n");
- if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
- dev_warn(&radio->videodev->dev,
- "seek failed / band limit reached\n");
- if (timed_out)
- dev_warn(&radio->videodev->dev,
- "seek timed out after %u ms\n", seek_timeout);
-
-stop:
- /* stop seeking */
- radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
- retval = si470x_set_register(radio, POWERCFG);
-
-done:
- /* try again, if timed out */
- if ((retval == 0) && timed_out)
- retval = -EAGAIN;
-
- return retval;
-}
-
-
-/*
- * si470x_start - switch on radio
- */
-int si470x_start(struct si470x_device *radio)
-{
- int retval;
-
- /* powercfg */
- radio->registers[POWERCFG] =
- POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
- retval = si470x_set_register(radio, POWERCFG);
- if (retval < 0)
- goto done;
-
- /* sysconfig 1 */
- radio->registers[SYSCONFIG1] =
- (de << 11) & SYSCONFIG1_DE; /* DE*/
- retval = si470x_set_register(radio, SYSCONFIG1);
- if (retval < 0)
- goto done;
-
- /* sysconfig 2 */
- radio->registers[SYSCONFIG2] =
- (0x3f << 8) | /* SEEKTH */
- ((band << 6) & SYSCONFIG2_BAND) | /* BAND */
- ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */
- 15; /* VOLUME (max) */
- retval = si470x_set_register(radio, SYSCONFIG2);
- if (retval < 0)
- goto done;
-
- /* reset last channel */
- retval = si470x_set_chan(radio,
- radio->registers[CHANNEL] & CHANNEL_CHAN);
-
-done:
- return retval;
-}
-
-
-/*
- * si470x_stop - switch off radio
- */
-int si470x_stop(struct si470x_device *radio)
-{
- int retval;
-
- /* sysconfig 1 */
- radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
- retval = si470x_set_register(radio, SYSCONFIG1);
- if (retval < 0)
- goto done;
-
- /* powercfg */
- radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
- /* POWERCFG_ENABLE has to automatically go low */
- radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
- retval = si470x_set_register(radio, POWERCFG);
-
-done:
- return retval;
-}
-
-
-/*
- * si470x_rds_on - switch on rds reception
- */
-static int si470x_rds_on(struct si470x_device *radio)
-{
- int retval;
-
- /* sysconfig 1 */
- radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
- retval = si470x_set_register(radio, SYSCONFIG1);
- if (retval < 0)
- radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
-
- return retval;
-}
-
-
-
-/**************************************************************************
- * File Operations Interface
- **************************************************************************/
-
-/*
- * si470x_fops_read - read RDS data
- */
-static ssize_t si470x_fops_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
- unsigned int block_count = 0;
-
- /* switch on rds reception */
- mutex_lock(&radio->lock);
- if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
- si470x_rds_on(radio);
-
- /* block if no new data available */
- while (radio->wr_index == radio->rd_index) {
- if (file->f_flags & O_NONBLOCK) {
- retval = -EWOULDBLOCK;
- goto done;
- }
- if (wait_event_interruptible(radio->read_queue,
- radio->wr_index != radio->rd_index) < 0) {
- retval = -EINTR;
- goto done;
- }
- }
-
- /* calculate block count from byte count */
- count /= 3;
-
- /* copy RDS block out of internal buffer and to user buffer */
- while (block_count < count) {
- if (radio->rd_index == radio->wr_index)
- break;
-
- /* always transfer rds complete blocks */
- if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
- /* retval = -EFAULT; */
- break;
-
- /* increment and wrap read pointer */
- radio->rd_index += 3;
- if (radio->rd_index >= radio->buf_size)
- radio->rd_index = 0;
-
- /* increment counters */
- block_count++;
- buf += 3;
- retval += 3;
- }
-
-done:
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_fops_poll - poll RDS data
- */
-static unsigned int si470x_fops_poll(struct file *file,
- struct poll_table_struct *pts)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- /* switch on rds reception */
-
- mutex_lock(&radio->lock);
- if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
- si470x_rds_on(radio);
- mutex_unlock(&radio->lock);
-
- poll_wait(file, &radio->read_queue, pts);
-
- if (radio->rd_index != radio->wr_index)
- retval = POLLIN | POLLRDNORM;
-
- return retval;
-}
-
-
-/*
- * si470x_fops - file operations interface
- */
-static const struct v4l2_file_operations si470x_fops = {
- .owner = THIS_MODULE,
- .read = si470x_fops_read,
- .poll = si470x_fops_poll,
- .unlocked_ioctl = video_ioctl2,
- .open = si470x_fops_open,
- .release = si470x_fops_release,
-};
-
-
-
-/**************************************************************************
- * Video4Linux Interface
- **************************************************************************/
-
-/*
- * si470x_vidioc_queryctrl - enumerate control items
- */
-static int si470x_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = -EINVAL;
-
- /* abort if qc->id is below V4L2_CID_BASE */
- if (qc->id < V4L2_CID_BASE)
- goto done;
-
- /* search video control */
- switch (qc->id) {
- case V4L2_CID_AUDIO_VOLUME:
- return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15);
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
-
- /* disable unsupported base controls */
- /* to satisfy kradio and such apps */
- if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
- qc->flags = V4L2_CTRL_FLAG_DISABLED;
- retval = 0;
- }
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "query controls failed with %d\n", retval);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_g_ctrl - get the value of a control
- */
-static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- mutex_lock(&radio->lock);
- /* safety checks */
- retval = si470x_disconnect_check(radio);
- if (retval)
- goto done;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_VOLUME:
- ctrl->value = radio->registers[SYSCONFIG2] &
- SYSCONFIG2_VOLUME;
- break;
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = ((radio->registers[POWERCFG] &
- POWERCFG_DMUTE) == 0) ? 1 : 0;
- break;
- default:
- retval = -EINVAL;
- }
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "get control failed with %d\n", retval);
-
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_s_ctrl - set the value of a control
- */
-static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- mutex_lock(&radio->lock);
- /* safety checks */
- retval = si470x_disconnect_check(radio);
- if (retval)
- goto done;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_VOLUME:
- radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
- radio->registers[SYSCONFIG2] |= ctrl->value;
- retval = si470x_set_register(radio, SYSCONFIG2);
- break;
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value == 1)
- radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
- else
- radio->registers[POWERCFG] |= POWERCFG_DMUTE;
- retval = si470x_set_register(radio, POWERCFG);
- break;
- default:
- retval = -EINVAL;
- }
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "set control failed with %d\n", retval);
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_g_audio - get audio attributes
- */
-static int si470x_vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- /* driver constants */
- audio->index = 0;
- strcpy(audio->name, "Radio");
- audio->capability = V4L2_AUDCAP_STEREO;
- audio->mode = 0;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_g_tuner - get tuner attributes
- */
-static int si470x_vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- mutex_lock(&radio->lock);
- /* safety checks */
- retval = si470x_disconnect_check(radio);
- if (retval)
- goto done;
-
- if (tuner->index != 0) {
- retval = -EINVAL;
- goto done;
- }
-
- retval = si470x_get_register(radio, STATUSRSSI);
- if (retval < 0)
- goto done;
-
- /* driver constants */
- strcpy(tuner->name, "FM");
- tuner->type = V4L2_TUNER_RADIO;
- tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
-
- /* range limits */
- switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
- /* 0: 87.5 - 108 MHz (USA, Europe, default) */
- default:
- tuner->rangelow = 87.5 * FREQ_MUL;
- tuner->rangehigh = 108 * FREQ_MUL;
- break;
- /* 1: 76 - 108 MHz (Japan wide band) */
- case 1:
- tuner->rangelow = 76 * FREQ_MUL;
- tuner->rangehigh = 108 * FREQ_MUL;
- break;
- /* 2: 76 - 90 MHz (Japan) */
- case 2:
- tuner->rangelow = 76 * FREQ_MUL;
- tuner->rangehigh = 90 * FREQ_MUL;
- break;
- };
-
- /* stereo indicator == stereo (instead of mono) */
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
- else
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- /* If there is a reliable method of detecting an RDS channel,
- then this code should check for that before setting this
- RDS subchannel. */
- tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
-
- /* mono/stereo selector */
- if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
- tuner->audmode = V4L2_TUNER_MODE_STEREO;
- else
- tuner->audmode = V4L2_TUNER_MODE_MONO;
-
- /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
- /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
- tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
- /* the ideal factor is 0xffff/75 = 873,8 */
- tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
-
- /* automatic frequency control: -1: freq to low, 1 freq to high */
- /* AFCRL does only indicate that freq. differs, not if too low/high */
- tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "get tuner failed with %d\n", retval);
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_s_tuner - set tuner attributes
- */
-static int si470x_vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- mutex_lock(&radio->lock);
- /* safety checks */
- retval = si470x_disconnect_check(radio);
- if (retval)
- goto done;
-
- if (tuner->index != 0)
- goto done;
-
- /* mono/stereo selector */
- switch (tuner->audmode) {
- case V4L2_TUNER_MODE_MONO:
- radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
- break;
- case V4L2_TUNER_MODE_STEREO:
- radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
- break;
- default:
- goto done;
- }
-
- retval = si470x_set_register(radio, POWERCFG);
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "set tuner failed with %d\n", retval);
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_g_frequency - get tuner or modulator radio frequency
- */
-static int si470x_vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- /* safety checks */
- mutex_lock(&radio->lock);
- retval = si470x_disconnect_check(radio);
- if (retval)
- goto done;
-
- if (freq->tuner != 0) {
- retval = -EINVAL;
- goto done;
- }
-
- freq->type = V4L2_TUNER_RADIO;
- retval = si470x_get_freq(radio, &freq->frequency);
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "get frequency failed with %d\n", retval);
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_s_frequency - set tuner or modulator radio frequency
- */
-static int si470x_vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- mutex_lock(&radio->lock);
- /* safety checks */
- retval = si470x_disconnect_check(radio);
- if (retval)
- goto done;
-
- if (freq->tuner != 0) {
- retval = -EINVAL;
- goto done;
- }
-
- retval = si470x_set_freq(radio, freq->frequency);
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "set frequency failed with %d\n", retval);
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
- */
-static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
- struct v4l2_hw_freq_seek *seek)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- mutex_lock(&radio->lock);
- /* safety checks */
- retval = si470x_disconnect_check(radio);
- if (retval)
- goto done;
-
- if (seek->tuner != 0) {
- retval = -EINVAL;
- goto done;
- }
-
- retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
-
-done:
- if (retval < 0)
- dev_warn(&radio->videodev->dev,
- "set hardware frequency seek failed with %d\n", retval);
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_ioctl_ops - video device ioctl operations
- */
-static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
- .vidioc_querycap = si470x_vidioc_querycap,
- .vidioc_queryctrl = si470x_vidioc_queryctrl,
- .vidioc_g_ctrl = si470x_vidioc_g_ctrl,
- .vidioc_s_ctrl = si470x_vidioc_s_ctrl,
- .vidioc_g_audio = si470x_vidioc_g_audio,
- .vidioc_g_tuner = si470x_vidioc_g_tuner,
- .vidioc_s_tuner = si470x_vidioc_s_tuner,
- .vidioc_g_frequency = si470x_vidioc_g_frequency,
- .vidioc_s_frequency = si470x_vidioc_s_frequency,
- .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
-};
-
-
-/*
- * si470x_viddev_template - video device interface
- */
-struct video_device si470x_viddev_template = {
- .fops = &si470x_fops,
- .name = DRIVER_NAME,
- .release = video_device_release,
- .ioctl_ops = &si470x_ioctl_ops,
-};
diff --git a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-i2c.c b/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-i2c.c
deleted file mode 100644
index 9b546a55..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * drivers/media/radio/si470x/radio-si470x-i2c.c
- *
- * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers
- *
- * Copyright (c) 2009 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/* driver definitions */
-#define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
-#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
-#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.2"
-
-/* kernel includes */
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-
-#include "radio-si470x.h"
-
-
-/* I2C Device ID List */
-static const struct i2c_device_id si470x_i2c_id[] = {
- /* Generic Entry */
- { "si470x", 0 },
- /* Terminating entry */
- { }
-};
-MODULE_DEVICE_TABLE(i2c, si470x_i2c_id);
-
-
-
-/**************************************************************************
- * Module Parameters
- **************************************************************************/
-
-/* Radio Nr */
-static int radio_nr = -1;
-module_param(radio_nr, int, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio Nr");
-
-/* RDS buffer blocks */
-static unsigned int rds_buf = 100;
-module_param(rds_buf, uint, 0444);
-MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
-
-/* RDS maximum block errors */
-static unsigned short max_rds_errors = 1;
-/* 0 means 0 errors requiring correction */
-/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
-/* 2 means 3-5 errors requiring correction */
-/* 3 means 6+ errors or errors in checkword, correction not possible */
-module_param(max_rds_errors, ushort, 0644);
-MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
-
-
-
-/**************************************************************************
- * I2C Definitions
- **************************************************************************/
-
-/* Write starts with the upper byte of register 0x02 */
-#define WRITE_REG_NUM 8
-#define WRITE_INDEX(i) (i + 0x02)
-
-/* Read starts with the upper byte of register 0x0a */
-#define READ_REG_NUM RADIO_REGISTER_NUM
-#define READ_INDEX(i) ((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM)
-
-
-
-/**************************************************************************
- * General Driver Functions - REGISTERs
- **************************************************************************/
-
-/*
- * si470x_get_register - read register
- */
-int si470x_get_register(struct si470x_device *radio, int regnr)
-{
- u16 buf[READ_REG_NUM];
- struct i2c_msg msgs[1] = {
- { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM,
- (void *)buf },
- };
-
- if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
- return -EIO;
-
- radio->registers[regnr] = __be16_to_cpu(buf[READ_INDEX(regnr)]);
-
- return 0;
-}
-
-
-/*
- * si470x_set_register - write register
- */
-int si470x_set_register(struct si470x_device *radio, int regnr)
-{
- int i;
- u16 buf[WRITE_REG_NUM];
- struct i2c_msg msgs[1] = {
- { radio->client->addr, 0, sizeof(u16) * WRITE_REG_NUM,
- (void *)buf },
- };
-
- for (i = 0; i < WRITE_REG_NUM; i++)
- buf[i] = __cpu_to_be16(radio->registers[WRITE_INDEX(i)]);
-
- if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
- return -EIO;
-
- return 0;
-}
-
-
-
-/**************************************************************************
- * General Driver Functions - ENTIRE REGISTERS
- **************************************************************************/
-
-/*
- * si470x_get_all_registers - read entire registers
- */
-static int si470x_get_all_registers(struct si470x_device *radio)
-{
- int i;
- u16 buf[READ_REG_NUM];
- struct i2c_msg msgs[1] = {
- { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM,
- (void *)buf },
- };
-
- if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
- return -EIO;
-
- for (i = 0; i < READ_REG_NUM; i++)
- radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]);
-
- return 0;
-}
-
-
-
-/**************************************************************************
- * General Driver Functions - DISCONNECT_CHECK
- **************************************************************************/
-
-/*
- * si470x_disconnect_check - check whether radio disconnects
- */
-int si470x_disconnect_check(struct si470x_device *radio)
-{
- return 0;
-}
-
-
-
-/**************************************************************************
- * File Operations Interface
- **************************************************************************/
-
-/*
- * si470x_fops_open - file open
- */
-int si470x_fops_open(struct file *file)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- mutex_lock(&radio->lock);
- radio->users++;
-
- if (radio->users == 1) {
- /* start radio */
- retval = si470x_start(radio);
- if (retval < 0)
- goto done;
-
- /* enable RDS / STC interrupt */
- radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
- radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN;
- radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
- radio->registers[SYSCONFIG1] |= 0x1 << 2;
- retval = si470x_set_register(radio, SYSCONFIG1);
- }
-
-done:
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_fops_release - file release
- */
-int si470x_fops_release(struct file *file)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- /* safety check */
- if (!radio)
- return -ENODEV;
-
- mutex_lock(&radio->lock);
- radio->users--;
- if (radio->users == 0)
- /* stop radio */
- retval = si470x_stop(radio);
-
- mutex_unlock(&radio->lock);
-
- return retval;
-}
-
-
-
-/**************************************************************************
- * Video4Linux Interface
- **************************************************************************/
-
-/*
- * si470x_vidioc_querycap - query device capabilities
- */
-int si470x_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability)
-{
- strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
- strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
- capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
- V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-
- return 0;
-}
-
-
-
-/**************************************************************************
- * I2C Interface
- **************************************************************************/
-
-/*
- * si470x_i2c_interrupt - interrupt handler
- */
-static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
-{
- struct si470x_device *radio = dev_id;
- unsigned char regnr;
- unsigned char blocknum;
- unsigned short bler; /* rds block errors */
- unsigned short rds;
- unsigned char tmpbuf[3];
- int retval = 0;
-
- /* check Seek/Tune Complete */
- retval = si470x_get_register(radio, STATUSRSSI);
- if (retval < 0)
- goto end;
-
- if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)
- complete(&radio->completion);
-
- /* safety checks */
- if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
- goto end;
-
- /* Update RDS registers */
- for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) {
- retval = si470x_get_register(radio, STATUSRSSI + regnr);
- if (retval < 0)
- goto end;
- }
-
- /* get rds blocks */
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0)
- /* No RDS group ready, better luck next time */
- goto end;
-
- for (blocknum = 0; blocknum < 4; blocknum++) {
- switch (blocknum) {
- default:
- bler = (radio->registers[STATUSRSSI] &
- STATUSRSSI_BLERA) >> 9;
- rds = radio->registers[RDSA];
- break;
- case 1:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERB) >> 14;
- rds = radio->registers[RDSB];
- break;
- case 2:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERC) >> 12;
- rds = radio->registers[RDSC];
- break;
- case 3:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERD) >> 10;
- rds = radio->registers[RDSD];
- break;
- };
-
- /* Fill the V4L2 RDS buffer */
- put_unaligned_le16(rds, &tmpbuf);
- tmpbuf[2] = blocknum; /* offset name */
- tmpbuf[2] |= blocknum << 3; /* received offset */
- if (bler > max_rds_errors)
- tmpbuf[2] |= 0x80; /* uncorrectable errors */
- else if (bler > 0)
- tmpbuf[2] |= 0x40; /* corrected error(s) */
-
- /* copy RDS block to internal buffer */
- memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
- radio->wr_index += 3;
-
- /* wrap write pointer */
- if (radio->wr_index >= radio->buf_size)
- radio->wr_index = 0;
-
- /* check for overflow */
- if (radio->wr_index == radio->rd_index) {
- /* increment and wrap read pointer */
- radio->rd_index += 3;
- if (radio->rd_index >= radio->buf_size)
- radio->rd_index = 0;
- }
- }
-
- if (radio->wr_index != radio->rd_index)
- wake_up_interruptible(&radio->read_queue);
-
-end:
- return IRQ_HANDLED;
-}
-
-
-/*
- * si470x_i2c_probe - probe for the device
- */
-static int __devinit si470x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct si470x_device *radio;
- int retval = 0;
- unsigned char version_warning = 0;
-
- /* private data allocation and initialization */
- radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
- if (!radio) {
- retval = -ENOMEM;
- goto err_initial;
- }
-
- radio->users = 0;
- radio->client = client;
- mutex_init(&radio->lock);
-
- /* video device allocation and initialization */
- radio->videodev = video_device_alloc();
- if (!radio->videodev) {
- retval = -ENOMEM;
- goto err_radio;
- }
- memcpy(radio->videodev, &si470x_viddev_template,
- sizeof(si470x_viddev_template));
- video_set_drvdata(radio->videodev, radio);
-
- /* power up : need 110ms */
- radio->registers[POWERCFG] = POWERCFG_ENABLE;
- if (si470x_set_register(radio, POWERCFG) < 0) {
- retval = -EIO;
- goto err_video;
- }
- msleep(110);
-
- /* get device and chip versions */
- if (si470x_get_all_registers(radio) < 0) {
- retval = -EIO;
- goto err_video;
- }
- dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
- radio->registers[DEVICEID], radio->registers[CHIPID]);
- if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
- dev_warn(&client->dev,
- "This driver is known to work with "
- "firmware version %hu,\n", RADIO_FW_VERSION);
- dev_warn(&client->dev,
- "but the device has firmware version %hu.\n",
- radio->registers[CHIPID] & CHIPID_FIRMWARE);
- version_warning = 1;
- }
-
- /* give out version warning */
- if (version_warning == 1) {
- dev_warn(&client->dev,
- "If you have some trouble using this driver,\n");
- dev_warn(&client->dev,
- "please report to V4L ML at "
- "linux-media@vger.kernel.org\n");
- }
-
- /* set initial frequency */
- si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
-
- /* rds buffer allocation */
- radio->buf_size = rds_buf * 3;
- radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
- if (!radio->buffer) {
- retval = -EIO;
- goto err_video;
- }
-
- /* rds buffer configuration */
- radio->wr_index = 0;
- radio->rd_index = 0;
- init_waitqueue_head(&radio->read_queue);
-
- /* mark Seek/Tune Complete Interrupt enabled */
- radio->stci_enabled = true;
- init_completion(&radio->completion);
-
- retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt,
- IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
- if (retval) {
- dev_err(&client->dev, "Failed to register interrupt\n");
- goto err_rds;
- }
-
- /* register video device */
- retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
- radio_nr);
- if (retval) {
- dev_warn(&client->dev, "Could not register video device\n");
- goto err_all;
- }
- i2c_set_clientdata(client, radio);
-
- return 0;
-err_all:
- free_irq(client->irq, radio);
-err_rds:
- kfree(radio->buffer);
-err_video:
- video_device_release(radio->videodev);
-err_radio:
- kfree(radio);
-err_initial:
- return retval;
-}
-
-
-/*
- * si470x_i2c_remove - remove the device
- */
-static __devexit int si470x_i2c_remove(struct i2c_client *client)
-{
- struct si470x_device *radio = i2c_get_clientdata(client);
-
- free_irq(client->irq, radio);
- video_unregister_device(radio->videodev);
- kfree(radio);
-
- return 0;
-}
-
-
-#ifdef CONFIG_PM
-/*
- * si470x_i2c_suspend - suspend the device
- */
-static int si470x_i2c_suspend(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct si470x_device *radio = i2c_get_clientdata(client);
-
- /* power down */
- radio->registers[POWERCFG] |= POWERCFG_DISABLE;
- if (si470x_set_register(radio, POWERCFG) < 0)
- return -EIO;
-
- return 0;
-}
-
-
-/*
- * si470x_i2c_resume - resume the device
- */
-static int si470x_i2c_resume(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct si470x_device *radio = i2c_get_clientdata(client);
-
- /* power up : need 110ms */
- radio->registers[POWERCFG] |= POWERCFG_ENABLE;
- if (si470x_set_register(radio, POWERCFG) < 0)
- return -EIO;
- msleep(110);
-
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume);
-#endif
-
-
-/*
- * si470x_i2c_driver - i2c driver interface
- */
-static struct i2c_driver si470x_i2c_driver = {
- .driver = {
- .name = "si470x",
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .pm = &si470x_i2c_pm,
-#endif
- },
- .probe = si470x_i2c_probe,
- .remove = __devexit_p(si470x_i2c_remove),
- .id_table = si470x_i2c_id,
-};
-
-module_i2c_driver(si470x_i2c_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
diff --git a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-usb.c b/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-usb.c
deleted file mode 100644
index b7debb67..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x-usb.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
- * drivers/media/radio/si470x/radio-si470x-usb.c
- *
- * USB driver for radios with Silicon Labs Si470x FM Radio Receivers
- *
- * Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/*
- * ToDo:
- * - add firmware download/update support
- */
-
-
-/* driver definitions */
-#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
-#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
-#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.10"
-
-/* kernel includes */
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include <linux/slab.h>
-
-#include "radio-si470x.h"
-
-
-/* USB Device ID List */
-static struct usb_device_id si470x_usb_driver_id_table[] = {
- /* Silicon Labs USB FM Radio Reference Design */
- { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
- /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
- { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
- /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */
- { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) },
- /* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */
- { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) },
- /* Terminating entry */
- { }
-};
-MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);
-
-
-
-/**************************************************************************
- * Module Parameters
- **************************************************************************/
-
-/* Radio Nr */
-static int radio_nr = -1;
-module_param(radio_nr, int, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio Nr");
-
-/* USB timeout */
-static unsigned int usb_timeout = 500;
-module_param(usb_timeout, uint, 0644);
-MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");
-
-/* RDS buffer blocks */
-static unsigned int rds_buf = 100;
-module_param(rds_buf, uint, 0444);
-MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
-
-/* RDS maximum block errors */
-static unsigned short max_rds_errors = 1;
-/* 0 means 0 errors requiring correction */
-/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
-/* 2 means 3-5 errors requiring correction */
-/* 3 means 6+ errors or errors in checkword, correction not possible */
-module_param(max_rds_errors, ushort, 0644);
-MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
-
-
-
-/**************************************************************************
- * USB HID Reports
- **************************************************************************/
-
-/* Reports 1-16 give direct read/write access to the 16 Si470x registers */
-/* with the (REPORT_ID - 1) corresponding to the register address across USB */
-/* endpoint 0 using GET_REPORT and SET_REPORT */
-#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1)
-#define REGISTER_REPORT(reg) ((reg) + 1)
-
-/* Report 17 gives direct read/write access to the entire Si470x register */
-/* map across endpoint 0 using GET_REPORT and SET_REPORT */
-#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
-#define ENTIRE_REPORT 17
-
-/* Report 18 is used to send the lowest 6 Si470x registers up the HID */
-/* interrupt endpoint 1 to Windows every 20 milliseconds for status */
-#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
-#define RDS_REPORT 18
-
-/* Report 19: LED state */
-#define LED_REPORT_SIZE 3
-#define LED_REPORT 19
-
-/* Report 19: stream */
-#define STREAM_REPORT_SIZE 3
-#define STREAM_REPORT 19
-
-/* Report 20: scratch */
-#define SCRATCH_PAGE_SIZE 63
-#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1)
-#define SCRATCH_REPORT 20
-
-/* Reports 19-22: flash upgrade of the C8051F321 */
-#define WRITE_REPORT_SIZE 4
-#define WRITE_REPORT 19
-#define FLASH_REPORT_SIZE 64
-#define FLASH_REPORT 20
-#define CRC_REPORT_SIZE 3
-#define CRC_REPORT 21
-#define RESPONSE_REPORT_SIZE 2
-#define RESPONSE_REPORT 22
-
-/* Report 23: currently unused, but can accept 60 byte reports on the HID */
-/* interrupt out endpoint 2 every 1 millisecond */
-#define UNUSED_REPORT 23
-
-
-
-/**************************************************************************
- * Software/Hardware Versions from Scratch Page
- **************************************************************************/
-#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6
-#define RADIO_SW_VERSION 7
-#define RADIO_HW_VERSION 1
-
-
-
-/**************************************************************************
- * LED State Definitions
- **************************************************************************/
-#define LED_COMMAND 0x35
-
-#define NO_CHANGE_LED 0x00
-#define ALL_COLOR_LED 0x01 /* streaming state */
-#define BLINK_GREEN_LED 0x02 /* connect state */
-#define BLINK_RED_LED 0x04
-#define BLINK_ORANGE_LED 0x10 /* disconnect state */
-#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */
-#define SOLID_RED_LED 0x40 /* bootload state */
-#define SOLID_ORANGE_LED 0x80
-
-
-
-/**************************************************************************
- * Stream State Definitions
- **************************************************************************/
-#define STREAM_COMMAND 0x36
-#define STREAM_VIDPID 0x00
-#define STREAM_AUDIO 0xff
-
-
-
-/**************************************************************************
- * Bootloader / Flash Commands
- **************************************************************************/
-
-/* unique id sent to bootloader and required to put into a bootload state */
-#define UNIQUE_BL_ID 0x34
-
-/* mask for the flash data */
-#define FLASH_DATA_MASK 0x55
-
-/* bootloader commands */
-#define GET_SW_VERSION_COMMAND 0x00
-#define SET_PAGE_COMMAND 0x01
-#define ERASE_PAGE_COMMAND 0x02
-#define WRITE_PAGE_COMMAND 0x03
-#define CRC_ON_PAGE_COMMAND 0x04
-#define READ_FLASH_BYTE_COMMAND 0x05
-#define RESET_DEVICE_COMMAND 0x06
-#define GET_HW_VERSION_COMMAND 0x07
-#define BLANK 0xff
-
-/* bootloader command responses */
-#define COMMAND_OK 0x01
-#define COMMAND_FAILED 0x02
-#define COMMAND_PENDING 0x03
-
-
-
-/**************************************************************************
- * General Driver Functions - REGISTER_REPORTs
- **************************************************************************/
-
-/*
- * si470x_get_report - receive a HID report
- */
-static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
-{
- unsigned char *report = (unsigned char *) buf;
- int retval;
-
- retval = usb_control_msg(radio->usbdev,
- usb_rcvctrlpipe(radio->usbdev, 0),
- HID_REQ_GET_REPORT,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- report[0], 2,
- buf, size, usb_timeout);
-
- if (retval < 0)
- dev_warn(&radio->intf->dev,
- "si470x_get_report: usb_control_msg returned %d\n",
- retval);
- return retval;
-}
-
-
-/*
- * si470x_set_report - send a HID report
- */
-static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
-{
- unsigned char *report = (unsigned char *) buf;
- int retval;
-
- retval = usb_control_msg(radio->usbdev,
- usb_sndctrlpipe(radio->usbdev, 0),
- HID_REQ_SET_REPORT,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- report[0], 2,
- buf, size, usb_timeout);
-
- if (retval < 0)
- dev_warn(&radio->intf->dev,
- "si470x_set_report: usb_control_msg returned %d\n",
- retval);
- return retval;
-}
-
-
-/*
- * si470x_get_register - read register
- */
-int si470x_get_register(struct si470x_device *radio, int regnr)
-{
- unsigned char buf[REGISTER_REPORT_SIZE];
- int retval;
-
- buf[0] = REGISTER_REPORT(regnr);
-
- retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
-
- if (retval >= 0)
- radio->registers[regnr] = get_unaligned_be16(&buf[1]);
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-/*
- * si470x_set_register - write register
- */
-int si470x_set_register(struct si470x_device *radio, int regnr)
-{
- unsigned char buf[REGISTER_REPORT_SIZE];
- int retval;
-
- buf[0] = REGISTER_REPORT(regnr);
- put_unaligned_be16(radio->registers[regnr], &buf[1]);
-
- retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-
-/**************************************************************************
- * General Driver Functions - ENTIRE_REPORT
- **************************************************************************/
-
-/*
- * si470x_get_all_registers - read entire registers
- */
-static int si470x_get_all_registers(struct si470x_device *radio)
-{
- unsigned char buf[ENTIRE_REPORT_SIZE];
- int retval;
- unsigned char regnr;
-
- buf[0] = ENTIRE_REPORT;
-
- retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
-
- if (retval >= 0)
- for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
- radio->registers[regnr] = get_unaligned_be16(
- &buf[regnr * RADIO_REGISTER_SIZE + 1]);
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-
-/**************************************************************************
- * General Driver Functions - LED_REPORT
- **************************************************************************/
-
-/*
- * si470x_set_led_state - sets the led state
- */
-static int si470x_set_led_state(struct si470x_device *radio,
- unsigned char led_state)
-{
- unsigned char buf[LED_REPORT_SIZE];
- int retval;
-
- buf[0] = LED_REPORT;
- buf[1] = LED_COMMAND;
- buf[2] = led_state;
-
- retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-
-/**************************************************************************
- * General Driver Functions - SCRATCH_REPORT
- **************************************************************************/
-
-/*
- * si470x_get_scratch_versions - gets the scratch page and version infos
- */
-static int si470x_get_scratch_page_versions(struct si470x_device *radio)
-{
- unsigned char buf[SCRATCH_REPORT_SIZE];
- int retval;
-
- buf[0] = SCRATCH_REPORT;
-
- retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
-
- if (retval < 0)
- dev_warn(&radio->intf->dev, "si470x_get_scratch: "
- "si470x_get_report returned %d\n", retval);
- else {
- radio->software_version = buf[1];
- radio->hardware_version = buf[2];
- }
-
- return (retval < 0) ? -EINVAL : 0;
-}
-
-
-
-/**************************************************************************
- * General Driver Functions - DISCONNECT_CHECK
- **************************************************************************/
-
-/*
- * si470x_disconnect_check - check whether radio disconnects
- */
-int si470x_disconnect_check(struct si470x_device *radio)
-{
- if (radio->disconnected)
- return -EIO;
- else
- return 0;
-}
-
-
-
-/**************************************************************************
- * RDS Driver Functions
- **************************************************************************/
-
-/*
- * si470x_int_in_callback - rds callback and processing function
- *
- * TODO: do we need to use mutex locks in some sections?
- */
-static void si470x_int_in_callback(struct urb *urb)
-{
- struct si470x_device *radio = urb->context;
- int retval;
- unsigned char regnr;
- unsigned char blocknum;
- unsigned short bler; /* rds block errors */
- unsigned short rds;
- unsigned char tmpbuf[3];
-
- if (urb->status) {
- if (urb->status == -ENOENT ||
- urb->status == -ECONNRESET ||
- urb->status == -ESHUTDOWN) {
- return;
- } else {
- dev_warn(&radio->intf->dev,
- "non-zero urb status (%d)\n", urb->status);
- goto resubmit; /* Maybe we can recover. */
- }
- }
-
- /* safety checks */
- if (radio->disconnected)
- return;
- if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
- goto resubmit;
-
- if (urb->actual_length > 0) {
- /* Update RDS registers with URB data */
- for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
- radio->registers[STATUSRSSI + regnr] =
- get_unaligned_be16(&radio->int_in_buffer[
- regnr * RADIO_REGISTER_SIZE + 1]);
- /* get rds blocks */
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) {
- /* No RDS group ready, better luck next time */
- goto resubmit;
- }
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) {
- /* RDS decoder not synchronized */
- goto resubmit;
- }
- for (blocknum = 0; blocknum < 4; blocknum++) {
- switch (blocknum) {
- default:
- bler = (radio->registers[STATUSRSSI] &
- STATUSRSSI_BLERA) >> 9;
- rds = radio->registers[RDSA];
- break;
- case 1:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERB) >> 14;
- rds = radio->registers[RDSB];
- break;
- case 2:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERC) >> 12;
- rds = radio->registers[RDSC];
- break;
- case 3:
- bler = (radio->registers[READCHAN] &
- READCHAN_BLERD) >> 10;
- rds = radio->registers[RDSD];
- break;
- };
-
- /* Fill the V4L2 RDS buffer */
- put_unaligned_le16(rds, &tmpbuf);
- tmpbuf[2] = blocknum; /* offset name */
- tmpbuf[2] |= blocknum << 3; /* received offset */
- if (bler > max_rds_errors)
- tmpbuf[2] |= 0x80; /* uncorrectable errors */
- else if (bler > 0)
- tmpbuf[2] |= 0x40; /* corrected error(s) */
-
- /* copy RDS block to internal buffer */
- memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
- radio->wr_index += 3;
-
- /* wrap write pointer */
- if (radio->wr_index >= radio->buf_size)
- radio->wr_index = 0;
-
- /* check for overflow */
- if (radio->wr_index == radio->rd_index) {
- /* increment and wrap read pointer */
- radio->rd_index += 3;
- if (radio->rd_index >= radio->buf_size)
- radio->rd_index = 0;
- }
- }
- if (radio->wr_index != radio->rd_index)
- wake_up_interruptible(&radio->read_queue);
- }
-
-resubmit:
- /* Resubmit if we're still running. */
- if (radio->int_in_running && radio->usbdev) {
- retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC);
- if (retval) {
- dev_warn(&radio->intf->dev,
- "resubmitting urb failed (%d)", retval);
- radio->int_in_running = 0;
- }
- }
-}
-
-
-
-/**************************************************************************
- * File Operations Interface
- **************************************************************************/
-
-/*
- * si470x_fops_open - file open
- */
-int si470x_fops_open(struct file *file)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval;
-
- mutex_lock(&radio->lock);
- radio->users++;
-
- retval = usb_autopm_get_interface(radio->intf);
- if (retval < 0) {
- radio->users--;
- retval = -EIO;
- goto done;
- }
-
- if (radio->users == 1) {
- /* start radio */
- retval = si470x_start(radio);
- if (retval < 0) {
- usb_autopm_put_interface(radio->intf);
- goto done;
- }
-
- /* initialize interrupt urb */
- usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
- usb_rcvintpipe(radio->usbdev,
- radio->int_in_endpoint->bEndpointAddress),
- radio->int_in_buffer,
- le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),
- si470x_int_in_callback,
- radio,
- radio->int_in_endpoint->bInterval);
-
- radio->int_in_running = 1;
- mb();
-
- retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);
- if (retval) {
- dev_info(&radio->intf->dev,
- "submitting int urb failed (%d)\n", retval);
- radio->int_in_running = 0;
- usb_autopm_put_interface(radio->intf);
- }
- }
-
-done:
- mutex_unlock(&radio->lock);
- return retval;
-}
-
-
-/*
- * si470x_fops_release - file release
- */
-int si470x_fops_release(struct file *file)
-{
- struct si470x_device *radio = video_drvdata(file);
- int retval = 0;
-
- /* safety check */
- if (!radio) {
- retval = -ENODEV;
- goto done;
- }
-
- mutex_lock(&radio->lock);
- radio->users--;
- if (radio->users == 0) {
- /* shutdown interrupt handler */
- if (radio->int_in_running) {
- radio->int_in_running = 0;
- if (radio->int_in_urb)
- usb_kill_urb(radio->int_in_urb);
- }
-
- if (radio->disconnected) {
- video_unregister_device(radio->videodev);
- kfree(radio->int_in_buffer);
- kfree(radio->buffer);
- mutex_unlock(&radio->lock);
- kfree(radio);
- goto done;
- }
-
- /* cancel read processes */
- wake_up_interruptible(&radio->read_queue);
-
- /* stop radio */
- retval = si470x_stop(radio);
- usb_autopm_put_interface(radio->intf);
- }
- mutex_unlock(&radio->lock);
-done:
- return retval;
-}
-
-
-
-/**************************************************************************
- * Video4Linux Interface
- **************************************************************************/
-
-/*
- * si470x_vidioc_querycap - query device capabilities
- */
-int si470x_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability)
-{
- struct si470x_device *radio = video_drvdata(file);
-
- strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
- strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
- usb_make_path(radio->usbdev, capability->bus_info,
- sizeof(capability->bus_info));
- capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
- V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
-
- return 0;
-}
-
-
-
-/**************************************************************************
- * USB Interface
- **************************************************************************/
-
-/*
- * si470x_usb_driver_probe - probe for the device
- */
-static int si470x_usb_driver_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct si470x_device *radio;
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
- int i, int_end_size, retval = 0;
- unsigned char version_warning = 0;
-
- /* private data allocation and initialization */
- radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
- if (!radio) {
- retval = -ENOMEM;
- goto err_initial;
- }
- radio->users = 0;
- radio->disconnected = 0;
- radio->usbdev = interface_to_usbdev(intf);
- radio->intf = intf;
- mutex_init(&radio->lock);
-
- iface_desc = intf->cur_altsetting;
-
- /* Set up interrupt endpoint information. */
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
- if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
- USB_DIR_IN) && ((endpoint->bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT))
- radio->int_in_endpoint = endpoint;
- }
- if (!radio->int_in_endpoint) {
- dev_info(&intf->dev, "could not find interrupt in endpoint\n");
- retval = -EIO;
- goto err_radio;
- }
-
- int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize);
-
- radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL);
- if (!radio->int_in_buffer) {
- dev_info(&intf->dev, "could not allocate int_in_buffer");
- retval = -ENOMEM;
- goto err_radio;
- }
-
- radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!radio->int_in_urb) {
- dev_info(&intf->dev, "could not allocate int_in_urb");
- retval = -ENOMEM;
- goto err_intbuffer;
- }
-
- /* video device allocation and initialization */
- radio->videodev = video_device_alloc();
- if (!radio->videodev) {
- retval = -ENOMEM;
- goto err_urb;
- }
- memcpy(radio->videodev, &si470x_viddev_template,
- sizeof(si470x_viddev_template));
- video_set_drvdata(radio->videodev, radio);
-
- /* get device and chip versions */
- if (si470x_get_all_registers(radio) < 0) {
- retval = -EIO;
- goto err_video;
- }
- dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
- radio->registers[DEVICEID], radio->registers[CHIPID]);
- if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
- dev_warn(&intf->dev,
- "This driver is known to work with "
- "firmware version %hu,\n", RADIO_FW_VERSION);
- dev_warn(&intf->dev,
- "but the device has firmware version %hu.\n",
- radio->registers[CHIPID] & CHIPID_FIRMWARE);
- version_warning = 1;
- }
-
- /* get software and hardware versions */
- if (si470x_get_scratch_page_versions(radio) < 0) {
- retval = -EIO;
- goto err_video;
- }
- dev_info(&intf->dev, "software version %d, hardware version %d\n",
- radio->software_version, radio->hardware_version);
- if (radio->software_version < RADIO_SW_VERSION) {
- dev_warn(&intf->dev,
- "This driver is known to work with "
- "software version %hu,\n", RADIO_SW_VERSION);
- dev_warn(&intf->dev,
- "but the device has software version %hu.\n",
- radio->software_version);
- version_warning = 1;
- }
- if (radio->hardware_version < RADIO_HW_VERSION) {
- dev_warn(&intf->dev,
- "This driver is known to work with "
- "hardware version %hu,\n", RADIO_HW_VERSION);
- dev_warn(&intf->dev,
- "but the device has hardware version %hu.\n",
- radio->hardware_version);
- version_warning = 1;
- }
-
- /* give out version warning */
- if (version_warning == 1) {
- dev_warn(&intf->dev,
- "If you have some trouble using this driver,\n");
- dev_warn(&intf->dev,
- "please report to V4L ML at "
- "linux-media@vger.kernel.org\n");
- }
-
- /* set initial frequency */
- si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
-
- /* set led to connect state */
- si470x_set_led_state(radio, BLINK_GREEN_LED);
-
- /* rds buffer allocation */
- radio->buf_size = rds_buf * 3;
- radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
- if (!radio->buffer) {
- retval = -EIO;
- goto err_video;
- }
-
- /* rds buffer configuration */
- radio->wr_index = 0;
- radio->rd_index = 0;
- init_waitqueue_head(&radio->read_queue);
-
- /* register video device */
- retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
- radio_nr);
- if (retval) {
- dev_warn(&intf->dev, "Could not register video device\n");
- goto err_all;
- }
- usb_set_intfdata(intf, radio);
-
- return 0;
-err_all:
- kfree(radio->buffer);
-err_video:
- video_device_release(radio->videodev);
-err_urb:
- usb_free_urb(radio->int_in_urb);
-err_intbuffer:
- kfree(radio->int_in_buffer);
-err_radio:
- kfree(radio);
-err_initial:
- return retval;
-}
-
-
-/*
- * si470x_usb_driver_suspend - suspend the device
- */
-static int si470x_usb_driver_suspend(struct usb_interface *intf,
- pm_message_t message)
-{
- dev_info(&intf->dev, "suspending now...\n");
-
- return 0;
-}
-
-
-/*
- * si470x_usb_driver_resume - resume the device
- */
-static int si470x_usb_driver_resume(struct usb_interface *intf)
-{
- dev_info(&intf->dev, "resuming now...\n");
-
- return 0;
-}
-
-
-/*
- * si470x_usb_driver_disconnect - disconnect the device
- */
-static void si470x_usb_driver_disconnect(struct usb_interface *intf)
-{
- struct si470x_device *radio = usb_get_intfdata(intf);
-
- mutex_lock(&radio->lock);
- radio->disconnected = 1;
- usb_set_intfdata(intf, NULL);
- if (radio->users == 0) {
- /* set led to disconnect state */
- si470x_set_led_state(radio, BLINK_ORANGE_LED);
-
- /* Free data structures. */
- usb_free_urb(radio->int_in_urb);
-
- kfree(radio->int_in_buffer);
- video_unregister_device(radio->videodev);
- kfree(radio->buffer);
- mutex_unlock(&radio->lock);
- kfree(radio);
- } else {
- mutex_unlock(&radio->lock);
- }
-}
-
-
-/*
- * si470x_usb_driver - usb driver interface
- */
-static struct usb_driver si470x_usb_driver = {
- .name = DRIVER_NAME,
- .probe = si470x_usb_driver_probe,
- .disconnect = si470x_usb_driver_disconnect,
- .suspend = si470x_usb_driver_suspend,
- .resume = si470x_usb_driver_resume,
- .id_table = si470x_usb_driver_id_table,
- .supports_autosuspend = 1,
-};
-
-module_usb_driver(si470x_usb_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
diff --git a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x.h b/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x.h
deleted file mode 100644
index f300a55e..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si470x/radio-si470x.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * drivers/media/radio/si470x/radio-si470x.h
- *
- * Driver for radios with Silicon Labs Si470x FM Radio Receivers
- *
- * Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/* driver definitions */
-#define DRIVER_NAME "radio-si470x"
-
-
-/* kernel includes */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/videodev2.h>
-#include <linux/mutex.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <asm/unaligned.h>
-
-
-
-/**************************************************************************
- * Register Definitions
- **************************************************************************/
-#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */
-#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */
-#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */
-
-#define DEVICEID 0 /* Device ID */
-#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */
-#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */
-
-#define CHIPID 1 /* Chip ID */
-#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */
-#define CHIPID_DEV 0x0200 /* bits 09..09: Device */
-#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */
-
-#define POWERCFG 2 /* Power Configuration */
-#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */
-#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */
-#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */
-#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */
-#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */
-#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */
-#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */
-#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */
-#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */
-
-#define CHANNEL 3 /* Channel */
-#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */
-#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */
-
-#define SYSCONFIG1 4 /* System Configuration 1 */
-#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */
-#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */
-#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */
-#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */
-#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */
-#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */
-#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */
-#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */
-#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */
-
-#define SYSCONFIG2 5 /* System Configuration 2 */
-#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */
-#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */
-#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */
-#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */
-
-#define SYSCONFIG3 6 /* System Configuration 3 */
-#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */
-#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */
-#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */
-#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */
-
-#define TEST1 7 /* Test 1 */
-#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */
-
-#define TEST2 8 /* Test 2 */
-/* TEST2 only contains reserved bits */
-
-#define BOOTCONFIG 9 /* Boot Configuration */
-/* BOOTCONFIG only contains reserved bits */
-
-#define STATUSRSSI 10 /* Status RSSI */
-#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */
-#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */
-#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */
-#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */
-#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */
-#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */
-#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */
-#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */
-
-#define READCHAN 11 /* Read Channel */
-#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */
-#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */
-#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */
-#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */
-
-#define RDSA 12 /* RDSA */
-#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */
-
-#define RDSB 13 /* RDSB */
-#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */
-
-#define RDSC 14 /* RDSC */
-#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */
-
-#define RDSD 15 /* RDSD */
-#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */
-
-
-
-/**************************************************************************
- * General Driver Definitions
- **************************************************************************/
-
-/*
- * si470x_device - private data
- */
-struct si470x_device {
- struct video_device *videodev;
-
- /* driver management */
- unsigned int users;
-
- /* Silabs internal registers (0..15) */
- unsigned short registers[RADIO_REGISTER_NUM];
-
- /* RDS receive buffer */
- wait_queue_head_t read_queue;
- struct mutex lock; /* buffer locking */
- unsigned char *buffer; /* size is always multiple of three */
- unsigned int buf_size;
- unsigned int rd_index;
- unsigned int wr_index;
-
- struct completion completion;
- bool stci_enabled; /* Seek/Tune Complete Interrupt */
-
-#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
- /* reference to USB and video device */
- struct usb_device *usbdev;
- struct usb_interface *intf;
-
- /* Interrupt endpoint handling */
- char *int_in_buffer;
- struct usb_endpoint_descriptor *int_in_endpoint;
- struct urb *int_in_urb;
- int int_in_running;
-
- /* scratch page */
- unsigned char software_version;
- unsigned char hardware_version;
-
- /* driver management */
- unsigned char disconnected;
-#endif
-
-#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
- struct i2c_client *client;
-#endif
-};
-
-
-
-/**************************************************************************
- * Firmware Versions
- **************************************************************************/
-
-#define RADIO_FW_VERSION 15
-
-
-
-/**************************************************************************
- * Frequency Multiplicator
- **************************************************************************/
-
-/*
- * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
- * 62.5 kHz otherwise.
- * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
- * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW
- * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000
- */
-#define FREQ_MUL (1000000 / 62.5)
-
-
-
-/**************************************************************************
- * Common Functions
- **************************************************************************/
-extern struct video_device si470x_viddev_template;
-int si470x_get_register(struct si470x_device *radio, int regnr);
-int si470x_set_register(struct si470x_device *radio, int regnr);
-int si470x_disconnect_check(struct si470x_device *radio);
-int si470x_set_freq(struct si470x_device *radio, unsigned int freq);
-int si470x_start(struct si470x_device *radio);
-int si470x_stop(struct si470x_device *radio);
-int si470x_fops_open(struct file *file);
-int si470x_fops_release(struct file *file);
-int si470x_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability);
diff --git a/ANDROID_3.4.5/drivers/media/radio/si4713-i2c.c b/ANDROID_3.4.5/drivers/media/radio/si4713-i2c.c
deleted file mode 100644
index b898c892..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si4713-i2c.c
+++ /dev/null
@@ -1,2109 +0,0 @@
-/*
- * drivers/media/radio/si4713-i2c.c
- *
- * Silicon Labs Si4713 FM Radio Transmitter I2C commands.
- *
- * Copyright (c) 2009 Nokia Corporation
- * Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/mutex.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
-#include <linux/module.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-
-#include "si4713-i2c.h"
-
-/* module parameters */
-static int debug;
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug level (0 - 2)");
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>");
-MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter");
-MODULE_VERSION("0.0.1");
-
-static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = {
- "vio",
- "vdd",
-};
-
-#define DEFAULT_RDS_PI 0x00
-#define DEFAULT_RDS_PTY 0x00
-#define DEFAULT_RDS_PS_NAME ""
-#define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME
-#define DEFAULT_RDS_DEVIATION 0x00C8
-#define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003
-#define DEFAULT_LIMITER_RTIME 0x1392
-#define DEFAULT_LIMITER_DEV 0x102CA
-#define DEFAULT_PILOT_FREQUENCY 0x4A38
-#define DEFAULT_PILOT_DEVIATION 0x1A5E
-#define DEFAULT_ACOMP_ATIME 0x0000
-#define DEFAULT_ACOMP_RTIME 0xF4240L
-#define DEFAULT_ACOMP_GAIN 0x0F
-#define DEFAULT_ACOMP_THRESHOLD (-0x28)
-#define DEFAULT_MUTE 0x01
-#define DEFAULT_POWER_LEVEL 88
-#define DEFAULT_FREQUENCY 8800
-#define DEFAULT_PREEMPHASIS FMPE_EU
-#define DEFAULT_TUNE_RNL 0xFF
-
-#define to_si4713_device(sd) container_of(sd, struct si4713_device, sd)
-
-/* frequency domain transformation (using times 10 to avoid floats) */
-#define FREQDEV_UNIT 100000
-#define FREQV4L2_MULTI 625
-#define si4713_to_v4l2(f) ((f * FREQDEV_UNIT) / FREQV4L2_MULTI)
-#define v4l2_to_si4713(f) ((f * FREQV4L2_MULTI) / FREQDEV_UNIT)
-#define FREQ_RANGE_LOW 7600
-#define FREQ_RANGE_HIGH 10800
-
-#define MAX_ARGS 7
-
-#define RDS_BLOCK 8
-#define RDS_BLOCK_CLEAR 0x03
-#define RDS_BLOCK_LOAD 0x04
-#define RDS_RADIOTEXT_2A 0x20
-#define RDS_RADIOTEXT_BLK_SIZE 4
-#define RDS_RADIOTEXT_INDEX_MAX 0x0F
-#define RDS_CARRIAGE_RETURN 0x0D
-
-#define rds_ps_nblocks(len) ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0))
-
-#define get_status_bit(p, b, m) (((p) & (m)) >> (b))
-#define set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b)))
-
-#define ATTACK_TIME_UNIT 500
-
-#define POWER_OFF 0x00
-#define POWER_ON 0x01
-
-#define msb(x) ((u8)((u16) x >> 8))
-#define lsb(x) ((u8)((u16) x & 0x00FF))
-#define compose_u16(msb, lsb) (((u16)msb << 8) | lsb)
-#define check_command_failed(status) (!(status & SI4713_CTS) || \
- (status & SI4713_ERR))
-/* mute definition */
-#define set_mute(p) ((p & 1) | ((p & 1) << 1));
-#define get_mute(p) (p & 0x01)
-
-#ifdef DEBUG
-#define DBG_BUFFER(device, message, buffer, size) \
- { \
- int i; \
- char str[(size)*5]; \
- for (i = 0; i < size; i++) \
- sprintf(str + i * 5, " 0x%02x", buffer[i]); \
- v4l2_dbg(2, debug, device, "%s:%s\n", message, str); \
- }
-#else
-#define DBG_BUFFER(device, message, buffer, size)
-#endif
-
-/*
- * Values for limiter release time (sorted by second column)
- * device release
- * value time (us)
- */
-static long limiter_times[] = {
- 2000, 250,
- 1000, 500,
- 510, 1000,
- 255, 2000,
- 170, 3000,
- 127, 4020,
- 102, 5010,
- 85, 6020,
- 73, 7010,
- 64, 7990,
- 57, 8970,
- 51, 10030,
- 25, 20470,
- 17, 30110,
- 13, 39380,
- 10, 51190,
- 8, 63690,
- 7, 73140,
- 6, 85330,
- 5, 102390,
-};
-
-/*
- * Values for audio compression release time (sorted by second column)
- * device release
- * value time (us)
- */
-static unsigned long acomp_rtimes[] = {
- 0, 100000,
- 1, 200000,
- 2, 350000,
- 3, 525000,
- 4, 1000000,
-};
-
-/*
- * Values for preemphasis (sorted by second column)
- * device preemphasis
- * value value (v4l2)
- */
-static unsigned long preemphasis_values[] = {
- FMPE_DISABLED, V4L2_PREEMPHASIS_DISABLED,
- FMPE_EU, V4L2_PREEMPHASIS_50_uS,
- FMPE_USA, V4L2_PREEMPHASIS_75_uS,
-};
-
-static int usecs_to_dev(unsigned long usecs, unsigned long const array[],
- int size)
-{
- int i;
- int rval = -EINVAL;
-
- for (i = 0; i < size / 2; i++)
- if (array[(i * 2) + 1] >= usecs) {
- rval = array[i * 2];
- break;
- }
-
- return rval;
-}
-
-static unsigned long dev_to_usecs(int value, unsigned long const array[],
- int size)
-{
- int i;
- int rval = -EINVAL;
-
- for (i = 0; i < size / 2; i++)
- if (array[i * 2] == value) {
- rval = array[(i * 2) + 1];
- break;
- }
-
- return rval;
-}
-
-/* si4713_handler: IRQ handler, just complete work */
-static irqreturn_t si4713_handler(int irq, void *dev)
-{
- struct si4713_device *sdev = dev;
-
- v4l2_dbg(2, debug, &sdev->sd,
- "%s: sending signal to completion work.\n", __func__);
- complete(&sdev->work);
-
- return IRQ_HANDLED;
-}
-
-/*
- * si4713_send_command - sends a command to si4713 and waits its response
- * @sdev: si4713_device structure for the device we are communicating
- * @command: command id
- * @args: command arguments we are sending (up to 7)
- * @argn: actual size of @args
- * @response: buffer to place the expected response from the device (up to 15)
- * @respn: actual size of @response
- * @usecs: amount of time to wait before reading the response (in usecs)
- */
-static int si4713_send_command(struct si4713_device *sdev, const u8 command,
- const u8 args[], const int argn,
- u8 response[], const int respn, const int usecs)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
- u8 data1[MAX_ARGS + 1];
- int err;
-
- if (!client->adapter)
- return -ENODEV;
-
- /* First send the command and its arguments */
- data1[0] = command;
- memcpy(data1 + 1, args, argn);
- DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1);
-
- err = i2c_master_send(client, data1, argn + 1);
- if (err != argn + 1) {
- v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
- command);
- return (err > 0) ? -EIO : err;
- }
-
- /* Wait response from interrupt */
- if (!wait_for_completion_timeout(&sdev->work,
- usecs_to_jiffies(usecs) + 1))
- v4l2_warn(&sdev->sd,
- "(%s) Device took too much time to answer.\n",
- __func__);
-
- /* Then get the response */
- err = i2c_master_recv(client, response, respn);
- if (err != respn) {
- v4l2_err(&sdev->sd,
- "Error while reading response for command 0x%02x\n",
- command);
- return (err > 0) ? -EIO : err;
- }
-
- DBG_BUFFER(&sdev->sd, "Response", response, respn);
- if (check_command_failed(response[0]))
- return -EBUSY;
-
- return 0;
-}
-
-/*
- * si4713_read_property - reads a si4713 property
- * @sdev: si4713_device structure for the device we are communicating
- * @prop: property identification number
- * @pv: property value to be returned on success
- */
-static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv)
-{
- int err;
- u8 val[SI4713_GET_PROP_NRESP];
- /*
- * .First byte = 0
- * .Second byte = property's MSB
- * .Third byte = property's LSB
- */
- const u8 args[SI4713_GET_PROP_NARGS] = {
- 0x00,
- msb(prop),
- lsb(prop),
- };
-
- err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY,
- args, ARRAY_SIZE(args), val,
- ARRAY_SIZE(val), DEFAULT_TIMEOUT);
-
- if (err < 0)
- return err;
-
- *pv = compose_u16(val[2], val[3]);
-
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: property=0x%02x value=0x%02x status=0x%02x\n",
- __func__, prop, *pv, val[0]);
-
- return err;
-}
-
-/*
- * si4713_write_property - modifies a si4713 property
- * @sdev: si4713_device structure for the device we are communicating
- * @prop: property identification number
- * @val: new value for that property
- */
-static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val)
-{
- int rval;
- u8 resp[SI4713_SET_PROP_NRESP];
- /*
- * .First byte = 0
- * .Second byte = property's MSB
- * .Third byte = property's LSB
- * .Fourth byte = value's MSB
- * .Fifth byte = value's LSB
- */
- const u8 args[SI4713_SET_PROP_NARGS] = {
- 0x00,
- msb(prop),
- lsb(prop),
- msb(val),
- lsb(val),
- };
-
- rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY,
- args, ARRAY_SIZE(args),
- resp, ARRAY_SIZE(resp),
- DEFAULT_TIMEOUT);
-
- if (rval < 0)
- return rval;
-
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: property=0x%02x value=0x%02x status=0x%02x\n",
- __func__, prop, val, resp[0]);
-
- /*
- * As there is no command response for SET_PROPERTY,
- * wait Tcomp time to finish before proceed, in order
- * to have property properly set.
- */
- msleep(TIMEOUT_SET_PROPERTY);
-
- return rval;
-}
-
-/*
- * si4713_powerup - Powers the device up
- * @sdev: si4713_device structure for the device we are communicating
- */
-static int si4713_powerup(struct si4713_device *sdev)
-{
- int err;
- u8 resp[SI4713_PWUP_NRESP];
- /*
- * .First byte = Enabled interrupts and boot function
- * .Second byte = Input operation mode
- */
- const u8 args[SI4713_PWUP_NARGS] = {
- SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
- SI4713_PWUP_OPMOD_ANALOG,
- };
-
- if (sdev->power_state)
- return 0;
-
- err = regulator_bulk_enable(ARRAY_SIZE(sdev->supplies),
- sdev->supplies);
- if (err) {
- v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err);
- return err;
- }
- if (gpio_is_valid(sdev->gpio_reset)) {
- udelay(50);
- gpio_set_value(sdev->gpio_reset, 1);
- }
-
- err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,
- args, ARRAY_SIZE(args),
- resp, ARRAY_SIZE(resp),
- TIMEOUT_POWER_UP);
-
- if (!err) {
- v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n",
- resp[0]);
- v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n");
- sdev->power_state = POWER_ON;
-
- err = si4713_write_property(sdev, SI4713_GPO_IEN,
- SI4713_STC_INT | SI4713_CTS);
- } else {
- if (gpio_is_valid(sdev->gpio_reset))
- gpio_set_value(sdev->gpio_reset, 0);
- err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
- sdev->supplies);
- if (err)
- v4l2_err(&sdev->sd,
- "Failed to disable supplies: %d\n", err);
- }
-
- return err;
-}
-
-/*
- * si4713_powerdown - Powers the device down
- * @sdev: si4713_device structure for the device we are communicating
- */
-static int si4713_powerdown(struct si4713_device *sdev)
-{
- int err;
- u8 resp[SI4713_PWDN_NRESP];
-
- if (!sdev->power_state)
- return 0;
-
- err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN,
- NULL, 0,
- resp, ARRAY_SIZE(resp),
- DEFAULT_TIMEOUT);
-
- if (!err) {
- v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
- resp[0]);
- v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
- if (gpio_is_valid(sdev->gpio_reset))
- gpio_set_value(sdev->gpio_reset, 0);
- err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
- sdev->supplies);
- if (err)
- v4l2_err(&sdev->sd,
- "Failed to disable supplies: %d\n", err);
- sdev->power_state = POWER_OFF;
- }
-
- return err;
-}
-
-/*
- * si4713_checkrev - Checks if we are treating a device with the correct rev.
- * @sdev: si4713_device structure for the device we are communicating
- */
-static int si4713_checkrev(struct si4713_device *sdev)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
- int rval;
- u8 resp[SI4713_GETREV_NRESP];
-
- mutex_lock(&sdev->mutex);
-
- rval = si4713_send_command(sdev, SI4713_CMD_GET_REV,
- NULL, 0,
- resp, ARRAY_SIZE(resp),
- DEFAULT_TIMEOUT);
-
- if (rval < 0)
- goto unlock;
-
- if (resp[1] == SI4713_PRODUCT_NUMBER) {
- v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n",
- client->addr << 1, client->adapter->name);
- } else {
- v4l2_err(&sdev->sd, "Invalid product number\n");
- rval = -EINVAL;
- }
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-/*
- * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful
- * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS
- * @sdev: si4713_device structure for the device we are communicating
- * @usecs: timeout to wait for STC interrupt signal
- */
-static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
-{
- int err;
- u8 resp[SI4713_GET_STATUS_NRESP];
-
- /* Wait response from STC interrupt */
- if (!wait_for_completion_timeout(&sdev->work,
- usecs_to_jiffies(usecs) + 1))
- v4l2_warn(&sdev->sd,
- "%s: device took too much time to answer (%d usec).\n",
- __func__, usecs);
-
- /* Clear status bits */
- err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
- NULL, 0,
- resp, ARRAY_SIZE(resp),
- DEFAULT_TIMEOUT);
-
- if (err < 0)
- goto exit;
-
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: status bits: 0x%02x\n", __func__, resp[0]);
-
- if (!(resp[0] & SI4713_STC_INT))
- err = -EIO;
-
-exit:
- return err;
-}
-
-/*
- * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning
- * frequency between 76 and 108 MHz in 10 kHz units and
- * steps of 50 kHz.
- * @sdev: si4713_device structure for the device we are communicating
- * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
- */
-static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency)
-{
- int err;
- u8 val[SI4713_TXFREQ_NRESP];
- /*
- * .First byte = 0
- * .Second byte = frequency's MSB
- * .Third byte = frequency's LSB
- */
- const u8 args[SI4713_TXFREQ_NARGS] = {
- 0x00,
- msb(frequency),
- lsb(frequency),
- };
-
- err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ,
- args, ARRAY_SIZE(args), val,
- ARRAY_SIZE(val), DEFAULT_TIMEOUT);
-
- if (err < 0)
- return err;
-
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: frequency=0x%02x status=0x%02x\n", __func__,
- frequency, val[0]);
-
- err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
- if (err < 0)
- return err;
-
- return compose_u16(args[1], args[2]);
-}
-
-/*
- * si4713_tx_tune_power - Sets the RF voltage level between 88 and 115 dBuV in
- * 1 dB units. A value of 0x00 indicates off. The command
- * also sets the antenna tuning capacitance. A value of 0
- * indicates autotuning, and a value of 1 - 191 indicates
- * a manual override, which results in a tuning
- * capacitance of 0.25 pF x @antcap.
- * @sdev: si4713_device structure for the device we are communicating
- * @power: tuning power (88 - 115 dBuV, unit/step 1 dB)
- * @antcap: value of antenna tuning capacitor (0 - 191)
- */
-static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power,
- u8 antcap)
-{
- int err;
- u8 val[SI4713_TXPWR_NRESP];
- /*
- * .First byte = 0
- * .Second byte = 0
- * .Third byte = power
- * .Fourth byte = antcap
- */
- const u8 args[SI4713_TXPWR_NARGS] = {
- 0x00,
- 0x00,
- power,
- antcap,
- };
-
- if (((power > 0) && (power < SI4713_MIN_POWER)) ||
- power > SI4713_MAX_POWER || antcap > SI4713_MAX_ANTCAP)
- return -EDOM;
-
- err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER,
- args, ARRAY_SIZE(args), val,
- ARRAY_SIZE(val), DEFAULT_TIMEOUT);
-
- if (err < 0)
- return err;
-
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: power=0x%02x antcap=0x%02x status=0x%02x\n",
- __func__, power, antcap, val[0]);
-
- return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER);
-}
-
-/*
- * si4713_tx_tune_measure - Enters receive mode and measures the received noise
- * level in units of dBuV on the selected frequency.
- * The Frequency must be between 76 and 108 MHz in 10 kHz
- * units and steps of 50 kHz. The command also sets the
- * antenna tuning capacitance. A value of 0 means
- * autotuning, and a value of 1 to 191 indicates manual
- * override.
- * @sdev: si4713_device structure for the device we are communicating
- * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
- * @antcap: value of antenna tuning capacitor (0 - 191)
- */
-static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency,
- u8 antcap)
-{
- int err;
- u8 val[SI4713_TXMEA_NRESP];
- /*
- * .First byte = 0
- * .Second byte = frequency's MSB
- * .Third byte = frequency's LSB
- * .Fourth byte = antcap
- */
- const u8 args[SI4713_TXMEA_NARGS] = {
- 0x00,
- msb(frequency),
- lsb(frequency),
- antcap,
- };
-
- sdev->tune_rnl = DEFAULT_TUNE_RNL;
-
- if (antcap > SI4713_MAX_ANTCAP)
- return -EDOM;
-
- err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE,
- args, ARRAY_SIZE(args), val,
- ARRAY_SIZE(val), DEFAULT_TIMEOUT);
-
- if (err < 0)
- return err;
-
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n",
- __func__, frequency, antcap, val[0]);
-
- return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
-}
-
-/*
- * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or
- * tx_tune_power commands. This command return the current
- * frequency, output voltage in dBuV, the antenna tunning
- * capacitance value and the received noise level. The
- * command also clears the stcint interrupt bit when the
- * first bit of its arguments is high.
- * @sdev: si4713_device structure for the device we are communicating
- * @intack: 0x01 to clear the seek/tune complete interrupt status indicator.
- * @frequency: returned frequency
- * @power: returned power
- * @antcap: returned antenna capacitance
- * @noise: returned noise level
- */
-static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack,
- u16 *frequency, u8 *power,
- u8 *antcap, u8 *noise)
-{
- int err;
- u8 val[SI4713_TXSTATUS_NRESP];
- /*
- * .First byte = intack bit
- */
- const u8 args[SI4713_TXSTATUS_NARGS] = {
- intack & SI4713_INTACK_MASK,
- };
-
- err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS,
- args, ARRAY_SIZE(args), val,
- ARRAY_SIZE(val), DEFAULT_TIMEOUT);
-
- if (!err) {
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: status=0x%02x\n", __func__, val[0]);
- *frequency = compose_u16(val[2], val[3]);
- sdev->frequency = *frequency;
- *power = val[5];
- *antcap = val[6];
- *noise = val[7];
- v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz "
- "(power %d, antcap %d, rnl %d)\n", __func__,
- *frequency, *power, *antcap, *noise);
- }
-
- return err;
-}
-
-/*
- * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer.
- * @sdev: si4713_device structure for the device we are communicating
- * @mode: the buffer operation mode.
- * @rdsb: RDS Block B
- * @rdsc: RDS Block C
- * @rdsd: RDS Block D
- * @cbleft: returns the number of available circular buffer blocks minus the
- * number of used circular buffer blocks.
- */
-static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb,
- u16 rdsc, u16 rdsd, s8 *cbleft)
-{
- int err;
- u8 val[SI4713_RDSBUFF_NRESP];
-
- const u8 args[SI4713_RDSBUFF_NARGS] = {
- mode & SI4713_RDSBUFF_MODE_MASK,
- msb(rdsb),
- lsb(rdsb),
- msb(rdsc),
- lsb(rdsc),
- msb(rdsd),
- lsb(rdsd),
- };
-
- err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF,
- args, ARRAY_SIZE(args), val,
- ARRAY_SIZE(val), DEFAULT_TIMEOUT);
-
- if (!err) {
- v4l2_dbg(1, debug, &sdev->sd,
- "%s: status=0x%02x\n", __func__, val[0]);
- *cbleft = (s8)val[2] - val[3];
- v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts"
- " 0x%02x cb avail: %d cb used %d fifo avail"
- " %d fifo used %d\n", __func__, val[1],
- val[2], val[3], val[4], val[5]);
- }
-
- return err;
-}
-
-/*
- * si4713_tx_rds_ps - Loads the program service buffer.
- * @sdev: si4713_device structure for the device we are communicating
- * @psid: program service id to be loaded.
- * @pschar: assumed 4 size char array to be loaded into the program service
- */
-static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid,
- unsigned char *pschar)
-{
- int err;
- u8 val[SI4713_RDSPS_NRESP];
-
- const u8 args[SI4713_RDSPS_NARGS] = {
- psid & SI4713_RDSPS_PSID_MASK,
- pschar[0],
- pschar[1],
- pschar[2],
- pschar[3],
- };
-
- err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS,
- args, ARRAY_SIZE(args), val,
- ARRAY_SIZE(val), DEFAULT_TIMEOUT);
-
- if (err < 0)
- return err;
-
- v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]);
-
- return err;
-}
-
-static int si4713_set_power_state(struct si4713_device *sdev, u8 value)
-{
- int rval;
-
- mutex_lock(&sdev->mutex);
-
- if (value)
- rval = si4713_powerup(sdev);
- else
- rval = si4713_powerdown(sdev);
-
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-static int si4713_set_mute(struct si4713_device *sdev, u16 mute)
-{
- int rval = 0;
-
- mute = set_mute(mute);
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state)
- rval = si4713_write_property(sdev,
- SI4713_TX_LINE_INPUT_MUTE, mute);
-
- if (rval >= 0)
- sdev->mute = get_mute(mute);
-
- mutex_unlock(&sdev->mutex);
-
- return rval;
-}
-
-static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name)
-{
- int rval = 0, i;
- u8 len = 0;
-
- /* We want to clear the whole thing */
- if (!strlen(ps_name))
- memset(ps_name, 0, MAX_RDS_PS_NAME + 1);
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- /* Write the new ps name and clear the padding */
- for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) {
- rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)),
- ps_name + i);
- if (rval < 0)
- goto unlock;
- }
-
- /* Setup the size to be sent */
- if (strlen(ps_name))
- len = strlen(ps_name) - 1;
- else
- len = 1;
-
- rval = si4713_write_property(sdev,
- SI4713_TX_RDS_PS_MESSAGE_COUNT,
- rds_ps_nblocks(len));
- if (rval < 0)
- goto unlock;
-
- rval = si4713_write_property(sdev,
- SI4713_TX_RDS_PS_REPEAT_COUNT,
- DEFAULT_RDS_PS_REPEAT_COUNT * 2);
- if (rval < 0)
- goto unlock;
- }
-
- strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME);
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt)
-{
- int rval = 0, i;
- u16 t_index = 0;
- u8 b_index = 0, cr_inserted = 0;
- s8 left;
-
- mutex_lock(&sdev->mutex);
-
- if (!sdev->power_state)
- goto copy;
-
- rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left);
- if (rval < 0)
- goto unlock;
-
- if (!strlen(rt))
- goto copy;
-
- do {
- /* RDS spec says that if the last block isn't used,
- * then apply a carriage return
- */
- if (t_index < (RDS_RADIOTEXT_INDEX_MAX *
- RDS_RADIOTEXT_BLK_SIZE)) {
- for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) {
- if (!rt[t_index + i] || rt[t_index + i] ==
- RDS_CARRIAGE_RETURN) {
- rt[t_index + i] = RDS_CARRIAGE_RETURN;
- cr_inserted = 1;
- break;
- }
- }
- }
-
- rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD,
- compose_u16(RDS_RADIOTEXT_2A, b_index++),
- compose_u16(rt[t_index], rt[t_index + 1]),
- compose_u16(rt[t_index + 2], rt[t_index + 3]),
- &left);
- if (rval < 0)
- goto unlock;
-
- t_index += RDS_RADIOTEXT_BLK_SIZE;
-
- if (cr_inserted)
- break;
- } while (left > 0);
-
-copy:
- strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT);
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
- u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul,
- unsigned long **table, int *size)
-{
- s32 rval = 0;
-
- switch (id) {
- /* FM_TX class controls */
- case V4L2_CID_RDS_TX_PI:
- *property = SI4713_TX_RDS_PI;
- *mul = 1;
- *shadow = &sdev->rds_info.pi;
- break;
- case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
- *property = SI4713_TX_ACOMP_THRESHOLD;
- *mul = 1;
- *shadow = &sdev->acomp_info.threshold;
- break;
- case V4L2_CID_AUDIO_COMPRESSION_GAIN:
- *property = SI4713_TX_ACOMP_GAIN;
- *mul = 1;
- *shadow = &sdev->acomp_info.gain;
- break;
- case V4L2_CID_PILOT_TONE_FREQUENCY:
- *property = SI4713_TX_PILOT_FREQUENCY;
- *mul = 1;
- *shadow = &sdev->pilot_info.frequency;
- break;
- case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
- *property = SI4713_TX_ACOMP_ATTACK_TIME;
- *mul = ATTACK_TIME_UNIT;
- *shadow = &sdev->acomp_info.attack_time;
- break;
- case V4L2_CID_PILOT_TONE_DEVIATION:
- *property = SI4713_TX_PILOT_DEVIATION;
- *mul = 10;
- *shadow = &sdev->pilot_info.deviation;
- break;
- case V4L2_CID_AUDIO_LIMITER_DEVIATION:
- *property = SI4713_TX_AUDIO_DEVIATION;
- *mul = 10;
- *shadow = &sdev->limiter_info.deviation;
- break;
- case V4L2_CID_RDS_TX_DEVIATION:
- *property = SI4713_TX_RDS_DEVIATION;
- *mul = 1;
- *shadow = &sdev->rds_info.deviation;
- break;
-
- case V4L2_CID_RDS_TX_PTY:
- *property = SI4713_TX_RDS_PS_MISC;
- *bit = 5;
- *mask = 0x1F << 5;
- *shadow = &sdev->rds_info.pty;
- break;
- case V4L2_CID_AUDIO_LIMITER_ENABLED:
- *property = SI4713_TX_ACOMP_ENABLE;
- *bit = 1;
- *mask = 1 << 1;
- *shadow = &sdev->limiter_info.enabled;
- break;
- case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
- *property = SI4713_TX_ACOMP_ENABLE;
- *bit = 0;
- *mask = 1 << 0;
- *shadow = &sdev->acomp_info.enabled;
- break;
- case V4L2_CID_PILOT_TONE_ENABLED:
- *property = SI4713_TX_COMPONENT_ENABLE;
- *bit = 0;
- *mask = 1 << 0;
- *shadow = &sdev->pilot_info.enabled;
- break;
-
- case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
- *property = SI4713_TX_LIMITER_RELEASE_TIME;
- *table = limiter_times;
- *size = ARRAY_SIZE(limiter_times);
- *shadow = &sdev->limiter_info.release_time;
- break;
- case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
- *property = SI4713_TX_ACOMP_RELEASE_TIME;
- *table = acomp_rtimes;
- *size = ARRAY_SIZE(acomp_rtimes);
- *shadow = &sdev->acomp_info.release_time;
- break;
- case V4L2_CID_TUNE_PREEMPHASIS:
- *property = SI4713_TX_PREEMPHASIS;
- *table = preemphasis_values;
- *size = ARRAY_SIZE(preemphasis_values);
- *shadow = &sdev->preemphasis;
- break;
-
- default:
- rval = -EINVAL;
- };
-
- return rval;
-}
-
-static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc);
-
-/* write string property */
-static int si4713_write_econtrol_string(struct si4713_device *sdev,
- struct v4l2_ext_control *control)
-{
- struct v4l2_queryctrl vqc;
- int len;
- s32 rval = 0;
-
- vqc.id = control->id;
- rval = si4713_queryctrl(&sdev->sd, &vqc);
- if (rval < 0)
- goto exit;
-
- switch (control->id) {
- case V4L2_CID_RDS_TX_PS_NAME: {
- char ps_name[MAX_RDS_PS_NAME + 1];
-
- len = control->size - 1;
- if (len < 0 || len > MAX_RDS_PS_NAME) {
- rval = -ERANGE;
- goto exit;
- }
- rval = copy_from_user(ps_name, control->string, len);
- if (rval) {
- rval = -EFAULT;
- goto exit;
- }
- ps_name[len] = '\0';
-
- if (strlen(ps_name) % vqc.step) {
- rval = -ERANGE;
- goto exit;
- }
-
- rval = si4713_set_rds_ps_name(sdev, ps_name);
- }
- break;
-
- case V4L2_CID_RDS_TX_RADIO_TEXT: {
- char radio_text[MAX_RDS_RADIO_TEXT + 1];
-
- len = control->size - 1;
- if (len < 0 || len > MAX_RDS_RADIO_TEXT) {
- rval = -ERANGE;
- goto exit;
- }
- rval = copy_from_user(radio_text, control->string, len);
- if (rval) {
- rval = -EFAULT;
- goto exit;
- }
- radio_text[len] = '\0';
-
- if (strlen(radio_text) % vqc.step) {
- rval = -ERANGE;
- goto exit;
- }
-
- rval = si4713_set_rds_radio_text(sdev, radio_text);
- }
- break;
-
- default:
- rval = -EINVAL;
- break;
- };
-
-exit:
- return rval;
-}
-
-static int validate_range(struct v4l2_subdev *sd,
- struct v4l2_ext_control *control)
-{
- struct v4l2_queryctrl vqc;
- int rval;
-
- vqc.id = control->id;
- rval = si4713_queryctrl(sd, &vqc);
- if (rval < 0)
- goto exit;
-
- if (control->value < vqc.minimum || control->value > vqc.maximum)
- rval = -ERANGE;
-
-exit:
- return rval;
-}
-
-/* properties which use tx_tune_power*/
-static int si4713_write_econtrol_tune(struct si4713_device *sdev,
- struct v4l2_ext_control *control)
-{
- s32 rval = 0;
- u8 power, antcap;
-
- rval = validate_range(&sdev->sd, control);
- if (rval < 0)
- goto exit;
-
- mutex_lock(&sdev->mutex);
-
- switch (control->id) {
- case V4L2_CID_TUNE_POWER_LEVEL:
- power = control->value;
- antcap = sdev->antenna_capacitor;
- break;
- case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- power = sdev->power_level;
- antcap = control->value;
- break;
- default:
- rval = -EINVAL;
- goto unlock;
- };
-
- if (sdev->power_state)
- rval = si4713_tx_tune_power(sdev, power, antcap);
-
- if (rval == 0) {
- sdev->power_level = power;
- sdev->antenna_capacitor = antcap;
- }
-
-unlock:
- mutex_unlock(&sdev->mutex);
-exit:
- return rval;
-}
-
-static int si4713_write_econtrol_integers(struct si4713_device *sdev,
- struct v4l2_ext_control *control)
-{
- s32 rval;
- u32 *shadow = NULL, val = 0;
- s32 bit = 0, mask = 0;
- u16 property = 0;
- int mul = 0;
- unsigned long *table = NULL;
- int size = 0;
-
- rval = validate_range(&sdev->sd, control);
- if (rval < 0)
- goto exit;
-
- rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit,
- &mask, &property, &mul, &table, &size);
- if (rval < 0)
- goto exit;
-
- val = control->value;
- if (mul) {
- val = control->value / mul;
- } else if (table) {
- rval = usecs_to_dev(control->value, table, size);
- if (rval < 0)
- goto exit;
- val = rval;
- rval = 0;
- }
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- if (mask) {
- rval = si4713_read_property(sdev, property, &val);
- if (rval < 0)
- goto unlock;
- val = set_bits(val, control->value, bit, mask);
- }
-
- rval = si4713_write_property(sdev, property, val);
- if (rval < 0)
- goto unlock;
- if (mask)
- val = control->value;
- }
-
- if (mul) {
- *shadow = val * mul;
- } else if (table) {
- rval = dev_to_usecs(val, table, size);
- if (rval < 0)
- goto unlock;
- *shadow = rval;
- rval = 0;
- } else {
- *shadow = val;
- }
-
-unlock:
- mutex_unlock(&sdev->mutex);
-exit:
- return rval;
-}
-
-static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f);
-static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *);
-/*
- * si4713_setup - Sets the device up with current configuration.
- * @sdev: si4713_device structure for the device we are communicating
- */
-static int si4713_setup(struct si4713_device *sdev)
-{
- struct v4l2_ext_control ctrl;
- struct v4l2_frequency f;
- struct v4l2_modulator vm;
- struct si4713_device *tmp;
- int rval = 0;
-
- tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
- if (!tmp)
- return -ENOMEM;
-
- /* Get a local copy to avoid race */
- mutex_lock(&sdev->mutex);
- memcpy(tmp, sdev, sizeof(*sdev));
- mutex_unlock(&sdev->mutex);
-
- ctrl.id = V4L2_CID_RDS_TX_PI;
- ctrl.value = tmp->rds_info.pi;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD;
- ctrl.value = tmp->acomp_info.threshold;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN;
- ctrl.value = tmp->acomp_info.gain;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY;
- ctrl.value = tmp->pilot_info.frequency;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME;
- ctrl.value = tmp->acomp_info.attack_time;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION;
- ctrl.value = tmp->pilot_info.deviation;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION;
- ctrl.value = tmp->limiter_info.deviation;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_RDS_TX_DEVIATION;
- ctrl.value = tmp->rds_info.deviation;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_RDS_TX_PTY;
- ctrl.value = tmp->rds_info.pty;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED;
- ctrl.value = tmp->limiter_info.enabled;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED;
- ctrl.value = tmp->acomp_info.enabled;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_PILOT_TONE_ENABLED;
- ctrl.value = tmp->pilot_info.enabled;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME;
- ctrl.value = tmp->limiter_info.release_time;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME;
- ctrl.value = tmp->acomp_info.release_time;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_TUNE_PREEMPHASIS;
- ctrl.value = tmp->preemphasis;
- rval |= si4713_write_econtrol_integers(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_RDS_TX_PS_NAME;
- rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name);
-
- ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT;
- rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text);
-
- /* Device procedure needs to set frequency first */
- f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY;
- f.frequency = si4713_to_v4l2(f.frequency);
- rval |= si4713_s_frequency(&sdev->sd, &f);
-
- ctrl.id = V4L2_CID_TUNE_POWER_LEVEL;
- ctrl.value = tmp->power_level;
- rval |= si4713_write_econtrol_tune(sdev, &ctrl);
-
- ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR;
- ctrl.value = tmp->antenna_capacitor;
- rval |= si4713_write_econtrol_tune(sdev, &ctrl);
-
- vm.index = 0;
- if (tmp->stereo)
- vm.txsubchans = V4L2_TUNER_SUB_STEREO;
- else
- vm.txsubchans = V4L2_TUNER_SUB_MONO;
- if (tmp->rds_info.enabled)
- vm.txsubchans |= V4L2_TUNER_SUB_RDS;
- si4713_s_modulator(&sdev->sd, &vm);
-
- kfree(tmp);
-
- return rval;
-}
-
-/*
- * si4713_initialize - Sets the device up with default configuration.
- * @sdev: si4713_device structure for the device we are communicating
- */
-static int si4713_initialize(struct si4713_device *sdev)
-{
- int rval;
-
- rval = si4713_set_power_state(sdev, POWER_ON);
- if (rval < 0)
- goto exit;
-
- rval = si4713_checkrev(sdev);
- if (rval < 0)
- goto exit;
-
- rval = si4713_set_power_state(sdev, POWER_OFF);
- if (rval < 0)
- goto exit;
-
- mutex_lock(&sdev->mutex);
-
- sdev->rds_info.pi = DEFAULT_RDS_PI;
- sdev->rds_info.pty = DEFAULT_RDS_PTY;
- sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION;
- strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME);
- strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT,
- MAX_RDS_RADIO_TEXT);
- sdev->rds_info.enabled = 1;
-
- sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME;
- sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV;
- sdev->limiter_info.enabled = 1;
-
- sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION;
- sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY;
- sdev->pilot_info.enabled = 1;
-
- sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME;
- sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME;
- sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD;
- sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN;
- sdev->acomp_info.enabled = 1;
-
- sdev->frequency = DEFAULT_FREQUENCY;
- sdev->preemphasis = DEFAULT_PREEMPHASIS;
- sdev->mute = DEFAULT_MUTE;
- sdev->power_level = DEFAULT_POWER_LEVEL;
- sdev->antenna_capacitor = 0;
- sdev->stereo = 1;
- sdev->tune_rnl = DEFAULT_TUNE_RNL;
-
- mutex_unlock(&sdev->mutex);
-
-exit:
- return rval;
-}
-
-/* read string property */
-static int si4713_read_econtrol_string(struct si4713_device *sdev,
- struct v4l2_ext_control *control)
-{
- s32 rval = 0;
-
- switch (control->id) {
- case V4L2_CID_RDS_TX_PS_NAME:
- if (strlen(sdev->rds_info.ps_name) + 1 > control->size) {
- control->size = MAX_RDS_PS_NAME + 1;
- rval = -ENOSPC;
- goto exit;
- }
- rval = copy_to_user(control->string, sdev->rds_info.ps_name,
- strlen(sdev->rds_info.ps_name) + 1);
- if (rval)
- rval = -EFAULT;
- break;
-
- case V4L2_CID_RDS_TX_RADIO_TEXT:
- if (strlen(sdev->rds_info.radio_text) + 1 > control->size) {
- control->size = MAX_RDS_RADIO_TEXT + 1;
- rval = -ENOSPC;
- goto exit;
- }
- rval = copy_to_user(control->string, sdev->rds_info.radio_text,
- strlen(sdev->rds_info.radio_text) + 1);
- if (rval)
- rval = -EFAULT;
- break;
-
- default:
- rval = -EINVAL;
- break;
- };
-
-exit:
- return rval;
-}
-
-/*
- * si4713_update_tune_status - update properties from tx_tune_status
- * command. Must be called with sdev->mutex held.
- * @sdev: si4713_device structure for the device we are communicating
- */
-static int si4713_update_tune_status(struct si4713_device *sdev)
-{
- int rval;
- u16 f = 0;
- u8 p = 0, a = 0, n = 0;
-
- rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n);
-
- if (rval < 0)
- goto exit;
-
- sdev->power_level = p;
- sdev->antenna_capacitor = a;
- sdev->tune_rnl = n;
-
-exit:
- return rval;
-}
-
-/* properties which use tx_tune_status */
-static int si4713_read_econtrol_tune(struct si4713_device *sdev,
- struct v4l2_ext_control *control)
-{
- s32 rval = 0;
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- rval = si4713_update_tune_status(sdev);
- if (rval < 0)
- goto unlock;
- }
-
- switch (control->id) {
- case V4L2_CID_TUNE_POWER_LEVEL:
- control->value = sdev->power_level;
- break;
- case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- control->value = sdev->antenna_capacitor;
- break;
- default:
- rval = -EINVAL;
- };
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-static int si4713_read_econtrol_integers(struct si4713_device *sdev,
- struct v4l2_ext_control *control)
-{
- s32 rval;
- u32 *shadow = NULL, val = 0;
- s32 bit = 0, mask = 0;
- u16 property = 0;
- int mul = 0;
- unsigned long *table = NULL;
- int size = 0;
-
- rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit,
- &mask, &property, &mul, &table, &size);
- if (rval < 0)
- goto exit;
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- rval = si4713_read_property(sdev, property, &val);
- if (rval < 0)
- goto unlock;
-
- /* Keep negative values for threshold */
- if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD)
- *shadow = (s16)val;
- else if (mask)
- *shadow = get_status_bit(val, bit, mask);
- else if (mul)
- *shadow = val * mul;
- else
- *shadow = dev_to_usecs(val, table, size);
- }
-
- control->value = *shadow;
-
-unlock:
- mutex_unlock(&sdev->mutex);
-exit:
- return rval;
-}
-
-/*
- * Video4Linux Subdev Interface
- */
-/* si4713_s_ext_ctrls - set extended controls value */
-static int si4713_s_ext_ctrls(struct v4l2_subdev *sd,
- struct v4l2_ext_controls *ctrls)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int i;
-
- if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
- return -EINVAL;
-
- for (i = 0; i < ctrls->count; i++) {
- int err;
-
- switch ((ctrls->controls + i)->id) {
- case V4L2_CID_RDS_TX_PS_NAME:
- case V4L2_CID_RDS_TX_RADIO_TEXT:
- err = si4713_write_econtrol_string(sdev,
- ctrls->controls + i);
- break;
- case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- case V4L2_CID_TUNE_POWER_LEVEL:
- err = si4713_write_econtrol_tune(sdev,
- ctrls->controls + i);
- break;
- default:
- err = si4713_write_econtrol_integers(sdev,
- ctrls->controls + i);
- }
-
- if (err < 0) {
- ctrls->error_idx = i;
- return err;
- }
- }
-
- return 0;
-}
-
-/* si4713_g_ext_ctrls - get extended controls value */
-static int si4713_g_ext_ctrls(struct v4l2_subdev *sd,
- struct v4l2_ext_controls *ctrls)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int i;
-
- if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
- return -EINVAL;
-
- for (i = 0; i < ctrls->count; i++) {
- int err;
-
- switch ((ctrls->controls + i)->id) {
- case V4L2_CID_RDS_TX_PS_NAME:
- case V4L2_CID_RDS_TX_RADIO_TEXT:
- err = si4713_read_econtrol_string(sdev,
- ctrls->controls + i);
- break;
- case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- case V4L2_CID_TUNE_POWER_LEVEL:
- err = si4713_read_econtrol_tune(sdev,
- ctrls->controls + i);
- break;
- default:
- err = si4713_read_econtrol_integers(sdev,
- ctrls->controls + i);
- }
-
- if (err < 0) {
- ctrls->error_idx = i;
- return err;
- }
- }
-
- return 0;
-}
-
-/* si4713_queryctrl - enumerate control items */
-static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
- int rval = 0;
-
- switch (qc->id) {
- /* User class controls */
- case V4L2_CID_AUDIO_MUTE:
- rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE);
- break;
- /* FM_TX class controls */
- case V4L2_CID_RDS_TX_PI:
- rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI);
- break;
- case V4L2_CID_RDS_TX_PTY:
- rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY);
- break;
- case V4L2_CID_RDS_TX_DEVIATION:
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION,
- 10, DEFAULT_RDS_DEVIATION);
- break;
- case V4L2_CID_RDS_TX_PS_NAME:
- /*
- * Report step as 8. From RDS spec, psname
- * should be 8. But there are receivers which scroll strings
- * sized as 8xN.
- */
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0);
- break;
- case V4L2_CID_RDS_TX_RADIO_TEXT:
- /*
- * Report step as 32 (2A block). From RDS spec,
- * radio text should be 32 for 2A block. But there are receivers
- * which scroll strings sized as 32xN. Setting default to 32.
- */
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0);
- break;
-
- case V4L2_CID_AUDIO_LIMITER_ENABLED:
- rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- break;
- case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
- rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME,
- 50, DEFAULT_LIMITER_RTIME);
- break;
- case V4L2_CID_AUDIO_LIMITER_DEVIATION:
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION,
- 10, DEFAULT_LIMITER_DEV);
- break;
-
- case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
- rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- break;
- case V4L2_CID_AUDIO_COMPRESSION_GAIN:
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1,
- DEFAULT_ACOMP_GAIN);
- break;
- case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
- rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD,
- MAX_ACOMP_THRESHOLD, 1,
- DEFAULT_ACOMP_THRESHOLD);
- break;
- case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME,
- 500, DEFAULT_ACOMP_ATIME);
- break;
- case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
- rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME,
- 100000, DEFAULT_ACOMP_RTIME);
- break;
-
- case V4L2_CID_PILOT_TONE_ENABLED:
- rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- break;
- case V4L2_CID_PILOT_TONE_DEVIATION:
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION,
- 10, DEFAULT_PILOT_DEVIATION);
- break;
- case V4L2_CID_PILOT_TONE_FREQUENCY:
- rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY,
- 1, DEFAULT_PILOT_FREQUENCY);
- break;
-
- case V4L2_CID_TUNE_PREEMPHASIS:
- rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED,
- V4L2_PREEMPHASIS_75_uS, 1,
- V4L2_PREEMPHASIS_50_uS);
- break;
- case V4L2_CID_TUNE_POWER_LEVEL:
- rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL);
- break;
- case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0);
- break;
- default:
- rval = -EINVAL;
- break;
- };
-
- return rval;
-}
-
-/* si4713_g_ctrl - get the value of a control */
-static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int rval = 0;
-
- if (!sdev)
- return -ENODEV;
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE,
- &sdev->mute);
-
- if (rval < 0)
- goto unlock;
- }
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = get_mute(sdev->mute);
- break;
- }
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-/* si4713_s_ctrl - set the value of a control */
-static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int rval = 0;
-
- if (!sdev)
- return -ENODEV;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value) {
- rval = si4713_set_mute(sdev, ctrl->value);
- if (rval < 0)
- goto exit;
-
- rval = si4713_set_power_state(sdev, POWER_DOWN);
- } else {
- rval = si4713_set_power_state(sdev, POWER_UP);
- if (rval < 0)
- goto exit;
-
- rval = si4713_setup(sdev);
- if (rval < 0)
- goto exit;
-
- rval = si4713_set_mute(sdev, ctrl->value);
- }
- break;
- }
-
-exit:
- return rval;
-}
-
-/* si4713_ioctl - deal with private ioctls (only rnl for now) */
-long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- struct si4713_rnl *rnl = arg;
- u16 frequency;
- int rval = 0;
-
- if (!arg)
- return -EINVAL;
-
- mutex_lock(&sdev->mutex);
- switch (cmd) {
- case SI4713_IOC_MEASURE_RNL:
- frequency = v4l2_to_si4713(rnl->frequency);
-
- if (sdev->power_state) {
- /* Set desired measurement frequency */
- rval = si4713_tx_tune_measure(sdev, frequency, 0);
- if (rval < 0)
- goto unlock;
- /* get results from tune status */
- rval = si4713_update_tune_status(sdev);
- if (rval < 0)
- goto unlock;
- }
- rnl->rnl = sdev->tune_rnl;
- break;
-
- default:
- /* nothing */
- rval = -ENOIOCTLCMD;
- }
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {
- .queryctrl = si4713_queryctrl,
- .g_ext_ctrls = si4713_g_ext_ctrls,
- .s_ext_ctrls = si4713_s_ext_ctrls,
- .g_ctrl = si4713_g_ctrl,
- .s_ctrl = si4713_s_ctrl,
- .ioctl = si4713_ioctl,
-};
-
-/* si4713_g_modulator - get modulator attributes */
-static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int rval = 0;
-
- if (!sdev) {
- rval = -ENODEV;
- goto exit;
- }
-
- if (vm->index > 0) {
- rval = -EINVAL;
- goto exit;
- }
-
- strncpy(vm->name, "FM Modulator", 32);
- vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW |
- V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS;
-
- /* Report current frequency range limits */
- vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW);
- vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH);
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- u32 comp_en = 0;
-
- rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE,
- &comp_en);
- if (rval < 0)
- goto unlock;
-
- sdev->stereo = get_status_bit(comp_en, 1, 1 << 1);
- sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2);
- }
-
- /* Report current audio mode: mono or stereo */
- if (sdev->stereo)
- vm->txsubchans = V4L2_TUNER_SUB_STEREO;
- else
- vm->txsubchans = V4L2_TUNER_SUB_MONO;
-
- /* Report rds feature status */
- if (sdev->rds_info.enabled)
- vm->txsubchans |= V4L2_TUNER_SUB_RDS;
- else
- vm->txsubchans &= ~V4L2_TUNER_SUB_RDS;
-
-unlock:
- mutex_unlock(&sdev->mutex);
-exit:
- return rval;
-}
-
-/* si4713_s_modulator - set modulator attributes */
-static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int rval = 0;
- u16 stereo, rds;
- u32 p;
-
- if (!sdev)
- return -ENODEV;
-
- if (vm->index > 0)
- return -EINVAL;
-
- /* Set audio mode: mono or stereo */
- if (vm->txsubchans & V4L2_TUNER_SUB_STEREO)
- stereo = 1;
- else if (vm->txsubchans & V4L2_TUNER_SUB_MONO)
- stereo = 0;
- else
- return -EINVAL;
-
- rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS);
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- rval = si4713_read_property(sdev,
- SI4713_TX_COMPONENT_ENABLE, &p);
- if (rval < 0)
- goto unlock;
-
- p = set_bits(p, stereo, 1, 1 << 1);
- p = set_bits(p, rds, 2, 1 << 2);
-
- rval = si4713_write_property(sdev,
- SI4713_TX_COMPONENT_ENABLE, p);
- if (rval < 0)
- goto unlock;
- }
-
- sdev->stereo = stereo;
- sdev->rds_info.enabled = rds;
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-/* si4713_g_frequency - get tuner or modulator radio frequency */
-static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int rval = 0;
-
- f->type = V4L2_TUNER_RADIO;
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- u16 freq;
- u8 p, a, n;
-
- rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n);
- if (rval < 0)
- goto unlock;
-
- sdev->frequency = freq;
- }
-
- f->frequency = si4713_to_v4l2(sdev->frequency);
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-/* si4713_s_frequency - set tuner or modulator radio frequency */
-static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
-{
- struct si4713_device *sdev = to_si4713_device(sd);
- int rval = 0;
- u16 frequency = v4l2_to_si4713(f->frequency);
-
- /* Check frequency range */
- if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH)
- return -EDOM;
-
- mutex_lock(&sdev->mutex);
-
- if (sdev->power_state) {
- rval = si4713_tx_tune_freq(sdev, frequency);
- if (rval < 0)
- goto unlock;
- frequency = rval;
- rval = 0;
- }
- sdev->frequency = frequency;
- f->frequency = si4713_to_v4l2(frequency);
-
-unlock:
- mutex_unlock(&sdev->mutex);
- return rval;
-}
-
-static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = {
- .g_frequency = si4713_g_frequency,
- .s_frequency = si4713_s_frequency,
- .g_modulator = si4713_g_modulator,
- .s_modulator = si4713_s_modulator,
-};
-
-static const struct v4l2_subdev_ops si4713_subdev_ops = {
- .core = &si4713_subdev_core_ops,
- .tuner = &si4713_subdev_tuner_ops,
-};
-
-/*
- * I2C driver interface
- */
-/* si4713_probe - probe for the device */
-static int si4713_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct si4713_device *sdev;
- struct si4713_platform_data *pdata = client->dev.platform_data;
- int rval, i;
-
- sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
- if (!sdev) {
- dev_err(&client->dev, "Failed to alloc video device.\n");
- rval = -ENOMEM;
- goto exit;
- }
-
- sdev->gpio_reset = -1;
- if (pdata && gpio_is_valid(pdata->gpio_reset)) {
- rval = gpio_request(pdata->gpio_reset, "si4713 reset");
- if (rval) {
- dev_err(&client->dev,
- "Failed to request gpio: %d\n", rval);
- goto free_sdev;
- }
- sdev->gpio_reset = pdata->gpio_reset;
- gpio_direction_output(sdev->gpio_reset, 0);
- }
-
- for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++)
- sdev->supplies[i].supply = si4713_supply_names[i];
-
- rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies),
- sdev->supplies);
- if (rval) {
- dev_err(&client->dev, "Cannot get regulators: %d\n", rval);
- goto free_gpio;
- }
-
- v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
-
- mutex_init(&sdev->mutex);
- init_completion(&sdev->work);
-
- if (client->irq) {
- rval = request_irq(client->irq,
- si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
- client->name, sdev);
- if (rval < 0) {
- v4l2_err(&sdev->sd, "Could not request IRQ\n");
- goto put_reg;
- }
- v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
- } else {
- v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
- }
-
- rval = si4713_initialize(sdev);
- if (rval < 0) {
- v4l2_err(&sdev->sd, "Failed to probe device information.\n");
- goto free_irq;
- }
-
- return 0;
-
-free_irq:
- if (client->irq)
- free_irq(client->irq, sdev);
-put_reg:
- regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
-free_gpio:
- if (gpio_is_valid(sdev->gpio_reset))
- gpio_free(sdev->gpio_reset);
-free_sdev:
- kfree(sdev);
-exit:
- return rval;
-}
-
-/* si4713_remove - remove the device */
-static int si4713_remove(struct i2c_client *client)
-{
- struct v4l2_subdev *sd = i2c_get_clientdata(client);
- struct si4713_device *sdev = to_si4713_device(sd);
-
- if (sdev->power_state)
- si4713_set_power_state(sdev, POWER_DOWN);
-
- if (client->irq > 0)
- free_irq(client->irq, sdev);
-
- v4l2_device_unregister_subdev(sd);
- regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
- if (gpio_is_valid(sdev->gpio_reset))
- gpio_free(sdev->gpio_reset);
- kfree(sdev);
-
- return 0;
-}
-
-/* si4713_i2c_driver - i2c driver interface */
-static const struct i2c_device_id si4713_id[] = {
- { "si4713" , 0 },
- { },
-};
-MODULE_DEVICE_TABLE(i2c, si4713_id);
-
-static struct i2c_driver si4713_i2c_driver = {
- .driver = {
- .name = "si4713",
- },
- .probe = si4713_probe,
- .remove = si4713_remove,
- .id_table = si4713_id,
-};
-
-module_i2c_driver(si4713_i2c_driver);
diff --git a/ANDROID_3.4.5/drivers/media/radio/si4713-i2c.h b/ANDROID_3.4.5/drivers/media/radio/si4713-i2c.h
deleted file mode 100644
index c6dfa7fb..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/si4713-i2c.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * drivers/media/radio/si4713-i2c.h
- *
- * Property and commands definitions for Si4713 radio transmitter chip.
- *
- * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
- * Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- */
-
-#ifndef SI4713_I2C_H
-#define SI4713_I2C_H
-
-#include <media/v4l2-subdev.h>
-#include <media/si4713.h>
-
-#define SI4713_PRODUCT_NUMBER 0x0D
-
-/* Command Timeouts */
-#define DEFAULT_TIMEOUT 500
-#define TIMEOUT_SET_PROPERTY 20
-#define TIMEOUT_TX_TUNE_POWER 30000
-#define TIMEOUT_TX_TUNE 110000
-#define TIMEOUT_POWER_UP 200000
-
-/*
- * Command and its arguments definitions
- */
-#define SI4713_PWUP_CTSIEN (1<<7)
-#define SI4713_PWUP_GPO2OEN (1<<6)
-#define SI4713_PWUP_PATCH (1<<5)
-#define SI4713_PWUP_XOSCEN (1<<4)
-#define SI4713_PWUP_FUNC_TX 0x02
-#define SI4713_PWUP_FUNC_PATCH 0x0F
-#define SI4713_PWUP_OPMOD_ANALOG 0x50
-#define SI4713_PWUP_OPMOD_DIGITAL 0x0F
-#define SI4713_PWUP_NARGS 2
-#define SI4713_PWUP_NRESP 1
-#define SI4713_CMD_POWER_UP 0x01
-
-#define SI4713_GETREV_NRESP 9
-#define SI4713_CMD_GET_REV 0x10
-
-#define SI4713_PWDN_NRESP 1
-#define SI4713_CMD_POWER_DOWN 0x11
-
-#define SI4713_SET_PROP_NARGS 5
-#define SI4713_SET_PROP_NRESP 1
-#define SI4713_CMD_SET_PROPERTY 0x12
-
-#define SI4713_GET_PROP_NARGS 3
-#define SI4713_GET_PROP_NRESP 4
-#define SI4713_CMD_GET_PROPERTY 0x13
-
-#define SI4713_GET_STATUS_NRESP 1
-#define SI4713_CMD_GET_INT_STATUS 0x14
-
-#define SI4713_CMD_PATCH_ARGS 0x15
-#define SI4713_CMD_PATCH_DATA 0x16
-
-#define SI4713_MAX_FREQ 10800
-#define SI4713_MIN_FREQ 7600
-#define SI4713_TXFREQ_NARGS 3
-#define SI4713_TXFREQ_NRESP 1
-#define SI4713_CMD_TX_TUNE_FREQ 0x30
-
-#define SI4713_MAX_POWER 120
-#define SI4713_MIN_POWER 88
-#define SI4713_MAX_ANTCAP 191
-#define SI4713_MIN_ANTCAP 0
-#define SI4713_TXPWR_NARGS 4
-#define SI4713_TXPWR_NRESP 1
-#define SI4713_CMD_TX_TUNE_POWER 0x31
-
-#define SI4713_TXMEA_NARGS 4
-#define SI4713_TXMEA_NRESP 1
-#define SI4713_CMD_TX_TUNE_MEASURE 0x32
-
-#define SI4713_INTACK_MASK 0x01
-#define SI4713_TXSTATUS_NARGS 1
-#define SI4713_TXSTATUS_NRESP 8
-#define SI4713_CMD_TX_TUNE_STATUS 0x33
-
-#define SI4713_OVERMOD_BIT (1 << 2)
-#define SI4713_IALH_BIT (1 << 1)
-#define SI4713_IALL_BIT (1 << 0)
-#define SI4713_ASQSTATUS_NARGS 1
-#define SI4713_ASQSTATUS_NRESP 5
-#define SI4713_CMD_TX_ASQ_STATUS 0x34
-
-#define SI4713_RDSBUFF_MODE_MASK 0x87
-#define SI4713_RDSBUFF_NARGS 7
-#define SI4713_RDSBUFF_NRESP 6
-#define SI4713_CMD_TX_RDS_BUFF 0x35
-
-#define SI4713_RDSPS_PSID_MASK 0x1F
-#define SI4713_RDSPS_NARGS 5
-#define SI4713_RDSPS_NRESP 1
-#define SI4713_CMD_TX_RDS_PS 0x36
-
-#define SI4713_CMD_GPO_CTL 0x80
-#define SI4713_CMD_GPO_SET 0x81
-
-/*
- * Bits from status response
- */
-#define SI4713_CTS (1<<7)
-#define SI4713_ERR (1<<6)
-#define SI4713_RDS_INT (1<<2)
-#define SI4713_ASQ_INT (1<<1)
-#define SI4713_STC_INT (1<<0)
-
-/*
- * Property definitions
- */
-#define SI4713_GPO_IEN 0x0001
-#define SI4713_DIG_INPUT_FORMAT 0x0101
-#define SI4713_DIG_INPUT_SAMPLE_RATE 0x0103
-#define SI4713_REFCLK_FREQ 0x0201
-#define SI4713_REFCLK_PRESCALE 0x0202
-#define SI4713_TX_COMPONENT_ENABLE 0x2100
-#define SI4713_TX_AUDIO_DEVIATION 0x2101
-#define SI4713_TX_PILOT_DEVIATION 0x2102
-#define SI4713_TX_RDS_DEVIATION 0x2103
-#define SI4713_TX_LINE_INPUT_LEVEL 0x2104
-#define SI4713_TX_LINE_INPUT_MUTE 0x2105
-#define SI4713_TX_PREEMPHASIS 0x2106
-#define SI4713_TX_PILOT_FREQUENCY 0x2107
-#define SI4713_TX_ACOMP_ENABLE 0x2200
-#define SI4713_TX_ACOMP_THRESHOLD 0x2201
-#define SI4713_TX_ACOMP_ATTACK_TIME 0x2202
-#define SI4713_TX_ACOMP_RELEASE_TIME 0x2203
-#define SI4713_TX_ACOMP_GAIN 0x2204
-#define SI4713_TX_LIMITER_RELEASE_TIME 0x2205
-#define SI4713_TX_ASQ_INTERRUPT_SOURCE 0x2300
-#define SI4713_TX_ASQ_LEVEL_LOW 0x2301
-#define SI4713_TX_ASQ_DURATION_LOW 0x2302
-#define SI4713_TX_ASQ_LEVEL_HIGH 0x2303
-#define SI4713_TX_ASQ_DURATION_HIGH 0x2304
-#define SI4713_TX_RDS_INTERRUPT_SOURCE 0x2C00
-#define SI4713_TX_RDS_PI 0x2C01
-#define SI4713_TX_RDS_PS_MIX 0x2C02
-#define SI4713_TX_RDS_PS_MISC 0x2C03
-#define SI4713_TX_RDS_PS_REPEAT_COUNT 0x2C04
-#define SI4713_TX_RDS_PS_MESSAGE_COUNT 0x2C05
-#define SI4713_TX_RDS_PS_AF 0x2C06
-#define SI4713_TX_RDS_FIFO_SIZE 0x2C07
-
-#define PREEMPHASIS_USA 75
-#define PREEMPHASIS_EU 50
-#define PREEMPHASIS_DISABLED 0
-#define FMPE_USA 0x00
-#define FMPE_EU 0x01
-#define FMPE_DISABLED 0x02
-
-#define POWER_UP 0x01
-#define POWER_DOWN 0x00
-
-struct rds_info {
- u32 pi;
-#define MAX_RDS_PTY 31
- u32 pty;
-#define MAX_RDS_DEVIATION 90000
- u32 deviation;
-/*
- * PSNAME is known to be defined as 8 character sized (RDS Spec).
- * However, there is receivers which scroll PSNAME 8xN sized.
- */
-#define MAX_RDS_PS_NAME 96
- u8 ps_name[MAX_RDS_PS_NAME + 1];
-/*
- * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group)
- * character sized (RDS Spec).
- * However, there is receivers which scroll them as well.
- */
-#define MAX_RDS_RADIO_TEXT 384
- u8 radio_text[MAX_RDS_RADIO_TEXT + 1];
- u32 enabled;
-};
-
-struct limiter_info {
-#define MAX_LIMITER_RELEASE_TIME 102390
- u32 release_time;
-#define MAX_LIMITER_DEVIATION 90000
- u32 deviation;
- u32 enabled;
-};
-
-struct pilot_info {
-#define MAX_PILOT_DEVIATION 90000
- u32 deviation;
-#define MAX_PILOT_FREQUENCY 19000
- u32 frequency;
- u32 enabled;
-};
-
-struct acomp_info {
-#define MAX_ACOMP_RELEASE_TIME 1000000
- u32 release_time;
-#define MAX_ACOMP_ATTACK_TIME 5000
- u32 attack_time;
-#define MAX_ACOMP_THRESHOLD 0
-#define MIN_ACOMP_THRESHOLD (-40)
- s32 threshold;
-#define MAX_ACOMP_GAIN 20
- u32 gain;
- u32 enabled;
-};
-
-#define SI4713_NUM_SUPPLIES 2
-
-/*
- * si4713_device - private data
- */
-struct si4713_device {
- /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */
- struct v4l2_subdev sd;
- /* private data structures */
- struct mutex mutex;
- struct completion work;
- struct rds_info rds_info;
- struct limiter_info limiter_info;
- struct pilot_info pilot_info;
- struct acomp_info acomp_info;
- struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES];
- int gpio_reset;
- u32 frequency;
- u32 preemphasis;
- u32 mute;
- u32 power_level;
- u32 power_state;
- u32 antenna_capacitor;
- u32 stereo;
- u32 tune_rnl;
-};
-#endif /* ifndef SI4713_I2C_H */
diff --git a/ANDROID_3.4.5/drivers/media/radio/tef6862.c b/ANDROID_3.4.5/drivers/media/radio/tef6862.c
deleted file mode 100644
index 6418c4c9..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/tef6862.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * tef6862.c Philips TEF6862 Car Radio Enhanced Selectivity Tuner
- * Copyright (c) 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-chip-ident.h>
-
-#define DRIVER_NAME "tef6862"
-
-#define FREQ_MUL 16000
-
-#define TEF6862_LO_FREQ (875 * FREQ_MUL / 10)
-#define TEF6862_HI_FREQ (108 * FREQ_MUL)
-
-/* Write mode sub addresses */
-#define WM_SUB_BANDWIDTH 0x0
-#define WM_SUB_PLLM 0x1
-#define WM_SUB_PLLL 0x2
-#define WM_SUB_DAA 0x3
-#define WM_SUB_AGC 0x4
-#define WM_SUB_BAND 0x5
-#define WM_SUB_CONTROL 0x6
-#define WM_SUB_LEVEL 0x7
-#define WM_SUB_IFCF 0x8
-#define WM_SUB_IFCAP 0x9
-#define WM_SUB_ACD 0xA
-#define WM_SUB_TEST 0xF
-
-/* Different modes of the MSA register */
-#define MODE_BUFFER 0x0
-#define MODE_PRESET 0x1
-#define MODE_SEARCH 0x2
-#define MODE_AF_UPDATE 0x3
-#define MODE_JUMP 0x4
-#define MODE_CHECK 0x5
-#define MODE_LOAD 0x6
-#define MODE_END 0x7
-#define MODE_SHIFT 5
-
-struct tef6862_state {
- struct v4l2_subdev sd;
- unsigned long freq;
-};
-
-static inline struct tef6862_state *to_state(struct v4l2_subdev *sd)
-{
- return container_of(sd, struct tef6862_state, sd);
-}
-
-static u16 tef6862_sigstr(struct i2c_client *client)
-{
- u8 buf[4];
- int err = i2c_master_recv(client, buf, sizeof(buf));
- if (err == sizeof(buf))
- return buf[3] << 8;
- return 0;
-}
-
-static int tef6862_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
-{
- if (v->index > 0)
- return -EINVAL;
-
- /* only support FM for now */
- strlcpy(v->name, "FM", sizeof(v->name));
- v->type = V4L2_TUNER_RADIO;
- v->rangelow = TEF6862_LO_FREQ;
- v->rangehigh = TEF6862_HI_FREQ;
- v->rxsubchans = V4L2_TUNER_SUB_MONO;
- v->capability = V4L2_TUNER_CAP_LOW;
- v->audmode = V4L2_TUNER_MODE_STEREO;
- v->signal = tef6862_sigstr(v4l2_get_subdevdata(sd));
-
- return 0;
-}
-
-static int tef6862_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
-{
- return v->index ? -EINVAL : 0;
-}
-
-static int tef6862_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
-{
- struct tef6862_state *state = to_state(sd);
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- u16 pll;
- u8 i2cmsg[3];
- int err;
-
- if (f->tuner != 0)
- return -EINVAL;
-
- pll = 1964 + ((f->frequency - TEF6862_LO_FREQ) * 20) / FREQ_MUL;
- i2cmsg[0] = (MODE_PRESET << MODE_SHIFT) | WM_SUB_PLLM;
- i2cmsg[1] = (pll >> 8) & 0xff;
- i2cmsg[2] = pll & 0xff;
-
- err = i2c_master_send(client, i2cmsg, sizeof(i2cmsg));
- if (err != sizeof(i2cmsg))
- return err < 0 ? err : -EIO;
-
- state->freq = f->frequency;
- return 0;
-}
-
-static int tef6862_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
-{
- struct tef6862_state *state = to_state(sd);
-
- if (f->tuner != 0)
- return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = state->freq;
- return 0;
-}
-
-static int tef6862_g_chip_ident(struct v4l2_subdev *sd,
- struct v4l2_dbg_chip_ident *chip)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
-
- return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEF6862, 0);
-}
-
-static const struct v4l2_subdev_tuner_ops tef6862_tuner_ops = {
- .g_tuner = tef6862_g_tuner,
- .s_tuner = tef6862_s_tuner,
- .s_frequency = tef6862_s_frequency,
- .g_frequency = tef6862_g_frequency,
-};
-
-static const struct v4l2_subdev_core_ops tef6862_core_ops = {
- .g_chip_ident = tef6862_g_chip_ident,
-};
-
-static const struct v4l2_subdev_ops tef6862_ops = {
- .core = &tef6862_core_ops,
- .tuner = &tef6862_tuner_ops,
-};
-
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-
-static int __devinit tef6862_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct tef6862_state *state;
- struct v4l2_subdev *sd;
-
- /* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EIO;
-
- v4l_info(client, "chip found @ 0x%02x (%s)\n",
- client->addr << 1, client->adapter->name);
-
- state = kzalloc(sizeof(struct tef6862_state), GFP_KERNEL);
- if (state == NULL)
- return -ENOMEM;
- state->freq = TEF6862_LO_FREQ;
-
- sd = &state->sd;
- v4l2_i2c_subdev_init(sd, client, &tef6862_ops);
-
- return 0;
-}
-
-static int __devexit tef6862_remove(struct i2c_client *client)
-{
- struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
- v4l2_device_unregister_subdev(sd);
- kfree(to_state(sd));
- return 0;
-}
-
-static const struct i2c_device_id tef6862_id[] = {
- {DRIVER_NAME, 0},
- {},
-};
-
-MODULE_DEVICE_TABLE(i2c, tef6862_id);
-
-static struct i2c_driver tef6862_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = DRIVER_NAME,
- },
- .probe = tef6862_probe,
- .remove = tef6862_remove,
- .id_table = tef6862_id,
-};
-
-module_i2c_driver(tef6862_driver);
-
-MODULE_DESCRIPTION("TEF6862 Car Radio Enhanced Selectivity Tuner");
-MODULE_AUTHOR("Mocean Laboratories");
-MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/Kconfig b/ANDROID_3.4.5/drivers/media/radio/wl128x/Kconfig
deleted file mode 100644
index ea1e6545..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# TI's wl128x FM driver based on TI's ST driver.
-#
-menu "Texas Instruments WL128x FM driver (ST based)"
-config RADIO_WL128X
- tristate "Texas Instruments WL128x FM Radio"
- depends on VIDEO_V4L2 && RFKILL && GPIOLIB
- select TI_ST if NET
- 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
- <file:Documentation/video4linux/API.html>.
-
-endmenu
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/Makefile b/ANDROID_3.4.5/drivers/media/radio/wl128x/Makefile
deleted file mode 100644
index 32a0ead0..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for TI's shared transport driver based wl128x
-# FM radio.
-#
-obj-$(CONFIG_RADIO_WL128X) += fm_drv.o
-fm_drv-objs := fmdrv_common.o fmdrv_rx.o fmdrv_tx.o fmdrv_v4l2.o
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv.h b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv.h
deleted file mode 100644
index d84ad9da..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- *
- * Common header for all FM driver sub-modules.
- *
- * Copyright (C) 2011 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef _FM_DRV_H
-#define _FM_DRV_H
-
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <linux/timer.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
-
-#define FM_DRV_VERSION "0.1.1"
-#define FM_DRV_NAME "ti_fmdrv"
-#define FM_DRV_CARD_SHORT_NAME "TI FM Radio"
-#define FM_DRV_CARD_LONG_NAME "Texas Instruments FM Radio"
-
-/* Flag info */
-#define FM_INTTASK_RUNNING 0
-#define FM_INTTASK_SCHEDULE_PENDING 1
-#define FM_FW_DW_INPROGRESS 2
-#define FM_CORE_READY 3
-#define FM_CORE_TRANSPORT_READY 4
-#define FM_AF_SWITCH_INPROGRESS 5
-#define FM_CORE_TX_XMITING 6
-
-#define FM_TUNE_COMPLETE 0x1
-#define FM_BAND_LIMIT 0x2
-
-#define FM_DRV_TX_TIMEOUT (5*HZ) /* 5 seconds */
-#define FM_DRV_RX_SEEK_TIMEOUT (20*HZ) /* 20 seconds */
-
-#define fmerr(format, ...) \
- printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__)
-#define fmwarn(format, ...) \
- printk(KERN_WARNING "fmdrv: " format, ##__VA_ARGS__)
-#ifdef DEBUG
-#define fmdbg(format, ...) \
- printk(KERN_DEBUG "fmdrv: " format, ## __VA_ARGS__)
-#else /* DEBUG */
-#define fmdbg(format, ...)
-#endif
-enum {
- FM_MODE_OFF,
- FM_MODE_TX,
- FM_MODE_RX,
- FM_MODE_ENTRY_MAX
-};
-
-#define FM_RX_RDS_INFO_FIELD_MAX 8 /* 4 Group * 2 Bytes */
-
-/* RX RDS data format */
-struct fm_rdsdata_format {
- union {
- struct {
- u8 buff[FM_RX_RDS_INFO_FIELD_MAX];
- } groupdatabuff;
- struct {
- u16 pidata;
- u8 blk_b[2];
- u8 blk_c[2];
- u8 blk_d[2];
- } groupgeneral;
- struct {
- u16 pidata;
- u8 blk_b[2];
- u8 af[2];
- u8 ps[2];
- } group0A;
- struct {
- u16 pi[2];
- u8 blk_b[2];
- u8 ps[2];
- } group0B;
- } data;
-};
-
-/* FM region (Europe/US, Japan) info */
-struct region_info {
- u32 chanl_space;
- u32 bot_freq;
- u32 top_freq;
- u8 fm_band;
-};
-struct fmdev;
-typedef void (*int_handler_prototype) (struct fmdev *);
-
-/* FM Interrupt processing related info */
-struct fm_irq {
- u8 stage;
- u16 flag; /* FM interrupt flag */
- u16 mask; /* FM interrupt mask */
- /* Interrupt process timeout handler */
- struct timer_list timer;
- u8 retry;
- int_handler_prototype *handlers;
-};
-
-/* RDS info */
-struct fm_rds {
- u8 flag; /* RX RDS on/off status */
- u8 last_blk_idx; /* Last received RDS block */
-
- /* RDS buffer */
- wait_queue_head_t read_queue;
- u32 buf_size; /* Size is always multiple of 3 */
- u32 wr_idx;
- u32 rd_idx;
- u8 *buff;
-};
-
-#define FM_RDS_MAX_AF_LIST 25
-
-/*
- * Current RX channel Alternate Frequency cache.
- * This info is used to switch to other freq (AF)
- * when current channel signal strengh is below RSSI threshold.
- */
-struct tuned_station_info {
- u16 picode;
- u32 af_cache[FM_RDS_MAX_AF_LIST];
- u8 afcache_size;
- u8 af_list_max;
-};
-
-/* FM RX mode info */
-struct fm_rx {
- struct region_info region; /* Current selected band */
- u32 freq; /* Current RX frquency */
- u8 mute_mode; /* Current mute mode */
- u8 deemphasis_mode; /* Current deemphasis mode */
- /* RF dependent soft mute mode */
- u8 rf_depend_mute;
- u16 volume; /* Current volume level */
- u16 rssi_threshold; /* Current RSSI threshold level */
- /* Holds the index of the current AF jump */
- u8 afjump_idx;
- /* Will hold the frequency before the jump */
- u32 freq_before_jump;
- u8 rds_mode; /* RDS operation mode (RDS/RDBS) */
- u8 af_mode; /* Alternate frequency on/off */
- struct tuned_station_info stat_info;
- struct fm_rds rds;
-};
-
-#define FMTX_RDS_TXT_STR_SIZE 25
-/*
- * FM TX RDS data
- *
- * @ text_type: is the text following PS or RT
- * @ text: radio text string which could either be PS or RT
- * @ af_freq: alternate frequency for Tx
- * TODO: to be declared in application
- */
-struct tx_rds {
- u8 text_type;
- u8 text[FMTX_RDS_TXT_STR_SIZE];
- u8 flag;
- u32 af_freq;
-};
-/*
- * FM TX global data
- *
- * @ pwr_lvl: Power Level of the Transmission from mixer control
- * @ xmit_state: Transmission state = Updated locally upon Start/Stop
- * @ audio_io: i2S/Analog
- * @ tx_frq: Transmission frequency
- */
-struct fmtx_data {
- u8 pwr_lvl;
- u8 xmit_state;
- u8 audio_io;
- u8 region;
- u16 aud_mode;
- u32 preemph;
- u32 tx_frq;
- struct tx_rds rds;
-};
-
-/* FM driver operation structure */
-struct fmdev {
- struct video_device *radio_dev; /* V4L2 video device pointer */
- struct snd_card *card; /* Card which holds FM mixer controls */
- u16 asci_id;
- spinlock_t rds_buff_lock; /* To protect access to RDS buffer */
- spinlock_t resp_skb_lock; /* To protect access to received SKB */
-
- long flag; /* FM driver state machine info */
- u8 streg_cbdata; /* status of ST registration */
-
- struct sk_buff_head rx_q; /* RX queue */
- struct tasklet_struct rx_task; /* RX Tasklet */
-
- struct sk_buff_head tx_q; /* TX queue */
- struct tasklet_struct tx_task; /* TX Tasklet */
- unsigned long last_tx_jiffies; /* Timestamp of last pkt sent */
- atomic_t tx_cnt; /* Number of packets can send at a time */
-
- struct sk_buff *resp_skb; /* Response from the chip */
- /* Main task completion handler */
- struct completion maintask_comp;
- /* Opcode of last command sent to the chip */
- u8 pre_op;
- /* Handler used for wakeup when response packet is received */
- struct completion *resp_comp;
- struct fm_irq irq_info;
- u8 curr_fmmode; /* Current FM chip mode (TX, RX, OFF) */
- struct fm_rx rx; /* FM receiver info */
- struct fmtx_data tx_data;
-
- /* V4L2 ctrl framwork handler*/
- struct v4l2_ctrl_handler ctrl_handler;
-
- /* For core assisted locking */
- struct mutex mutex;
-};
-#endif
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.c b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.c
deleted file mode 100644
index bf867a6b..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.c
+++ /dev/null
@@ -1,1685 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- *
- * This sub-module of FM driver is common for FM RX and TX
- * functionality. This module is responsible for:
- * 1) Forming group of Channel-8 commands to perform particular
- * functionality (eg., frequency set require more than
- * one Channel-8 command to be sent to the chip).
- * 2) Sending each Channel-8 command to the chip and reading
- * response back over Shared Transport.
- * 3) Managing TX and RX Queues and Tasklets.
- * 4) Handling FM Interrupt packet and taking appropriate action.
- * 5) Loading FM firmware to the chip (common, FM TX, and FM RX
- * firmware files based on mode selection)
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Raja Mani <raja_mani@ti.com>
- * Author: Manjunatha Halli <manjunatha_halli@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include "fmdrv.h"
-#include "fmdrv_v4l2.h"
-#include "fmdrv_common.h"
-#include <linux/ti_wilink_st.h>
-#include "fmdrv_rx.h"
-#include "fmdrv_tx.h"
-
-/* Region info */
-static struct region_info region_configs[] = {
- /* Europe/US */
- {
- .chanl_space = FM_CHANNEL_SPACING_200KHZ * FM_FREQ_MUL,
- .bot_freq = 87500, /* 87.5 MHz */
- .top_freq = 108000, /* 108 MHz */
- .fm_band = 0,
- },
- /* Japan */
- {
- .chanl_space = FM_CHANNEL_SPACING_200KHZ * FM_FREQ_MUL,
- .bot_freq = 76000, /* 76 MHz */
- .top_freq = 90000, /* 90 MHz */
- .fm_band = 1,
- },
-};
-
-/* Band selection */
-static u8 default_radio_region; /* Europe/US */
-module_param(default_radio_region, byte, 0);
-MODULE_PARM_DESC(default_radio_region, "Region: 0=Europe/US, 1=Japan");
-
-/* RDS buffer blocks */
-static u32 default_rds_buf = 300;
-module_param(default_rds_buf, uint, 0444);
-MODULE_PARM_DESC(rds_buf, "RDS buffer entries");
-
-/* Radio Nr */
-static u32 radio_nr = -1;
-module_param(radio_nr, int, 0444);
-MODULE_PARM_DESC(radio_nr, "Radio Nr");
-
-/* FM irq handlers forward declaration */
-static void fm_irq_send_flag_getcmd(struct fmdev *);
-static void fm_irq_handle_flag_getcmd_resp(struct fmdev *);
-static void fm_irq_handle_hw_malfunction(struct fmdev *);
-static void fm_irq_handle_rds_start(struct fmdev *);
-static void fm_irq_send_rdsdata_getcmd(struct fmdev *);
-static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *);
-static void fm_irq_handle_rds_finish(struct fmdev *);
-static void fm_irq_handle_tune_op_ended(struct fmdev *);
-static void fm_irq_handle_power_enb(struct fmdev *);
-static void fm_irq_handle_low_rssi_start(struct fmdev *);
-static void fm_irq_afjump_set_pi(struct fmdev *);
-static void fm_irq_handle_set_pi_resp(struct fmdev *);
-static void fm_irq_afjump_set_pimask(struct fmdev *);
-static void fm_irq_handle_set_pimask_resp(struct fmdev *);
-static void fm_irq_afjump_setfreq(struct fmdev *);
-static void fm_irq_handle_setfreq_resp(struct fmdev *);
-static void fm_irq_afjump_enableint(struct fmdev *);
-static void fm_irq_afjump_enableint_resp(struct fmdev *);
-static void fm_irq_start_afjump(struct fmdev *);
-static void fm_irq_handle_start_afjump_resp(struct fmdev *);
-static void fm_irq_afjump_rd_freq(struct fmdev *);
-static void fm_irq_afjump_rd_freq_resp(struct fmdev *);
-static void fm_irq_handle_low_rssi_finish(struct fmdev *);
-static void fm_irq_send_intmsk_cmd(struct fmdev *);
-static void fm_irq_handle_intmsk_cmd_resp(struct fmdev *);
-
-/*
- * When FM common module receives interrupt packet, following handlers
- * will be executed one after another to service the interrupt(s)
- */
-enum fmc_irq_handler_index {
- FM_SEND_FLAG_GETCMD_IDX,
- FM_HANDLE_FLAG_GETCMD_RESP_IDX,
-
- /* HW malfunction irq handler */
- FM_HW_MAL_FUNC_IDX,
-
- /* RDS threshold reached irq handler */
- FM_RDS_START_IDX,
- FM_RDS_SEND_RDS_GETCMD_IDX,
- FM_RDS_HANDLE_RDS_GETCMD_RESP_IDX,
- FM_RDS_FINISH_IDX,
-
- /* Tune operation ended irq handler */
- FM_HW_TUNE_OP_ENDED_IDX,
-
- /* TX power enable irq handler */
- FM_HW_POWER_ENB_IDX,
-
- /* Low RSSI irq handler */
- FM_LOW_RSSI_START_IDX,
- FM_AF_JUMP_SETPI_IDX,
- FM_AF_JUMP_HANDLE_SETPI_RESP_IDX,
- FM_AF_JUMP_SETPI_MASK_IDX,
- FM_AF_JUMP_HANDLE_SETPI_MASK_RESP_IDX,
- FM_AF_JUMP_SET_AF_FREQ_IDX,
- FM_AF_JUMP_HANDLE_SET_AFFREQ_RESP_IDX,
- FM_AF_JUMP_ENABLE_INT_IDX,
- FM_AF_JUMP_ENABLE_INT_RESP_IDX,
- FM_AF_JUMP_START_AFJUMP_IDX,
- FM_AF_JUMP_HANDLE_START_AFJUMP_RESP_IDX,
- FM_AF_JUMP_RD_FREQ_IDX,
- FM_AF_JUMP_RD_FREQ_RESP_IDX,
- FM_LOW_RSSI_FINISH_IDX,
-
- /* Interrupt process post action */
- FM_SEND_INTMSK_CMD_IDX,
- FM_HANDLE_INTMSK_CMD_RESP_IDX,
-};
-
-/* FM interrupt handler table */
-static int_handler_prototype int_handler_table[] = {
- fm_irq_send_flag_getcmd,
- fm_irq_handle_flag_getcmd_resp,
- fm_irq_handle_hw_malfunction,
- fm_irq_handle_rds_start, /* RDS threshold reached irq handler */
- fm_irq_send_rdsdata_getcmd,
- fm_irq_handle_rdsdata_getcmd_resp,
- fm_irq_handle_rds_finish,
- fm_irq_handle_tune_op_ended,
- fm_irq_handle_power_enb, /* TX power enable irq handler */
- fm_irq_handle_low_rssi_start,
- fm_irq_afjump_set_pi,
- fm_irq_handle_set_pi_resp,
- fm_irq_afjump_set_pimask,
- fm_irq_handle_set_pimask_resp,
- fm_irq_afjump_setfreq,
- fm_irq_handle_setfreq_resp,
- fm_irq_afjump_enableint,
- fm_irq_afjump_enableint_resp,
- fm_irq_start_afjump,
- fm_irq_handle_start_afjump_resp,
- fm_irq_afjump_rd_freq,
- fm_irq_afjump_rd_freq_resp,
- fm_irq_handle_low_rssi_finish,
- fm_irq_send_intmsk_cmd, /* Interrupt process post action */
- fm_irq_handle_intmsk_cmd_resp
-};
-
-long (*g_st_write) (struct sk_buff *skb);
-static struct completion wait_for_fmdrv_reg_comp;
-
-static inline void fm_irq_call(struct fmdev *fmdev)
-{
- fmdev->irq_info.handlers[fmdev->irq_info.stage](fmdev);
-}
-
-/* Continue next function in interrupt handler table */
-static inline void fm_irq_call_stage(struct fmdev *fmdev, u8 stage)
-{
- fmdev->irq_info.stage = stage;
- fm_irq_call(fmdev);
-}
-
-static inline void fm_irq_timeout_stage(struct fmdev *fmdev, u8 stage)
-{
- fmdev->irq_info.stage = stage;
- mod_timer(&fmdev->irq_info.timer, jiffies + FM_DRV_TX_TIMEOUT);
-}
-
-#ifdef FM_DUMP_TXRX_PKT
- /* To dump outgoing FM Channel-8 packets */
-inline void dump_tx_skb_data(struct sk_buff *skb)
-{
- int len, len_org;
- u8 index;
- struct fm_cmd_msg_hdr *cmd_hdr;
-
- cmd_hdr = (struct fm_cmd_msg_hdr *)skb->data;
- printk(KERN_INFO "<<%shdr:%02x len:%02x opcode:%02x type:%s dlen:%02x",
- fm_cb(skb)->completion ? " " : "*", cmd_hdr->hdr,
- cmd_hdr->len, cmd_hdr->op,
- cmd_hdr->rd_wr ? "RD" : "WR", cmd_hdr->dlen);
-
- len_org = skb->len - FM_CMD_MSG_HDR_SIZE;
- if (len_org > 0) {
- printk("\n data(%d): ", cmd_hdr->dlen);
- len = min(len_org, 14);
- for (index = 0; index < len; index++)
- printk("%x ",
- skb->data[FM_CMD_MSG_HDR_SIZE + index]);
- printk("%s", (len_org > 14) ? ".." : "");
- }
- printk("\n");
-}
-
- /* To dump incoming FM Channel-8 packets */
-inline void dump_rx_skb_data(struct sk_buff *skb)
-{
- int len, len_org;
- u8 index;
- struct fm_event_msg_hdr *evt_hdr;
-
- evt_hdr = (struct fm_event_msg_hdr *)skb->data;
- printk(KERN_INFO ">> hdr:%02x len:%02x sts:%02x numhci:%02x "
- "opcode:%02x type:%s dlen:%02x", evt_hdr->hdr, evt_hdr->len,
- evt_hdr->status, evt_hdr->num_fm_hci_cmds, evt_hdr->op,
- (evt_hdr->rd_wr) ? "RD" : "WR", evt_hdr->dlen);
-
- len_org = skb->len - FM_EVT_MSG_HDR_SIZE;
- if (len_org > 0) {
- printk("\n data(%d): ", evt_hdr->dlen);
- len = min(len_org, 14);
- for (index = 0; index < len; index++)
- printk("%x ",
- skb->data[FM_EVT_MSG_HDR_SIZE + index]);
- printk("%s", (len_org > 14) ? ".." : "");
- }
- printk("\n");
-}
-#endif
-
-void fmc_update_region_info(struct fmdev *fmdev, u8 region_to_set)
-{
- fmdev->rx.region = region_configs[region_to_set];
-}
-
-/*
- * FM common sub-module will schedule this tasklet whenever it receives
- * FM packet from ST driver.
- */
-static void recv_tasklet(unsigned long arg)
-{
- struct fmdev *fmdev;
- struct fm_irq *irq_info;
- struct fm_event_msg_hdr *evt_hdr;
- struct sk_buff *skb;
- u8 num_fm_hci_cmds;
- unsigned long flags;
-
- fmdev = (struct fmdev *)arg;
- irq_info = &fmdev->irq_info;
- /* Process all packets in the RX queue */
- while ((skb = skb_dequeue(&fmdev->rx_q))) {
- if (skb->len < sizeof(struct fm_event_msg_hdr)) {
- fmerr("skb(%p) has only %d bytes, "
- "at least need %zu bytes to decode\n", skb,
- skb->len, sizeof(struct fm_event_msg_hdr));
- kfree_skb(skb);
- continue;
- }
-
- evt_hdr = (void *)skb->data;
- num_fm_hci_cmds = evt_hdr->num_fm_hci_cmds;
-
- /* FM interrupt packet? */
- if (evt_hdr->op == FM_INTERRUPT) {
- /* FM interrupt handler started already? */
- if (!test_bit(FM_INTTASK_RUNNING, &fmdev->flag)) {
- set_bit(FM_INTTASK_RUNNING, &fmdev->flag);
- if (irq_info->stage != 0) {
- fmerr("Inval stage resetting to zero\n");
- irq_info->stage = 0;
- }
-
- /*
- * Execute first function in interrupt handler
- * table.
- */
- irq_info->handlers[irq_info->stage](fmdev);
- } else {
- set_bit(FM_INTTASK_SCHEDULE_PENDING, &fmdev->flag);
- }
- kfree_skb(skb);
- }
- /* Anyone waiting for this with completion handler? */
- else if (evt_hdr->op == fmdev->pre_op && fmdev->resp_comp != NULL) {
-
- spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
- fmdev->resp_skb = skb;
- spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
- complete(fmdev->resp_comp);
-
- fmdev->resp_comp = NULL;
- atomic_set(&fmdev->tx_cnt, 1);
- }
- /* Is this for interrupt handler? */
- else if (evt_hdr->op == fmdev->pre_op && fmdev->resp_comp == NULL) {
- if (fmdev->resp_skb != NULL)
- fmerr("Response SKB ptr not NULL\n");
-
- spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
- fmdev->resp_skb = skb;
- spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
-
- /* Execute interrupt handler where state index points */
- irq_info->handlers[irq_info->stage](fmdev);
-
- kfree_skb(skb);
- atomic_set(&fmdev->tx_cnt, 1);
- } else {
- fmerr("Nobody claimed SKB(%p),purging\n", skb);
- }
-
- /*
- * Check flow control field. If Num_FM_HCI_Commands field is
- * not zero, schedule FM TX tasklet.
- */
- if (num_fm_hci_cmds && atomic_read(&fmdev->tx_cnt))
- if (!skb_queue_empty(&fmdev->tx_q))
- tasklet_schedule(&fmdev->tx_task);
- }
-}
-
-/* FM send tasklet: is scheduled when FM packet has to be sent to chip */
-static void send_tasklet(unsigned long arg)
-{
- struct fmdev *fmdev;
- struct sk_buff *skb;
- int len;
-
- fmdev = (struct fmdev *)arg;
-
- if (!atomic_read(&fmdev->tx_cnt))
- return;
-
- /* Check, is there any timeout happened to last transmitted packet */
- if ((jiffies - fmdev->last_tx_jiffies) > FM_DRV_TX_TIMEOUT) {
- fmerr("TX timeout occurred\n");
- atomic_set(&fmdev->tx_cnt, 1);
- }
-
- /* Send queued FM TX packets */
- skb = skb_dequeue(&fmdev->tx_q);
- if (!skb)
- return;
-
- atomic_dec(&fmdev->tx_cnt);
- fmdev->pre_op = fm_cb(skb)->fm_op;
-
- if (fmdev->resp_comp != NULL)
- fmerr("Response completion handler is not NULL\n");
-
- fmdev->resp_comp = fm_cb(skb)->completion;
-
- /* Write FM packet to ST driver */
- len = g_st_write(skb);
- if (len < 0) {
- kfree_skb(skb);
- fmdev->resp_comp = NULL;
- fmerr("TX tasklet failed to send skb(%p)\n", skb);
- atomic_set(&fmdev->tx_cnt, 1);
- } else {
- fmdev->last_tx_jiffies = jiffies;
- }
-}
-
-/*
- * Queues FM Channel-8 packet to FM TX queue and schedules FM TX tasklet for
- * transmission
- */
-static int fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
- int payload_len, struct completion *wait_completion)
-{
- struct sk_buff *skb;
- struct fm_cmd_msg_hdr *hdr;
- int size;
-
- if (fm_op >= FM_INTERRUPT) {
- fmerr("Invalid fm opcode - %d\n", fm_op);
- return -EINVAL;
- }
- if (test_bit(FM_FW_DW_INPROGRESS, &fmdev->flag) && payload == NULL) {
- fmerr("Payload data is NULL during fw download\n");
- return -EINVAL;
- }
- if (!test_bit(FM_FW_DW_INPROGRESS, &fmdev->flag))
- size =
- FM_CMD_MSG_HDR_SIZE + ((payload == NULL) ? 0 : payload_len);
- else
- size = payload_len;
-
- skb = alloc_skb(size, GFP_ATOMIC);
- if (!skb) {
- fmerr("No memory to create new SKB\n");
- return -ENOMEM;
- }
- /*
- * Don't fill FM header info for the commands which come from
- * FM firmware file.
- */
- if (!test_bit(FM_FW_DW_INPROGRESS, &fmdev->flag) ||
- test_bit(FM_INTTASK_RUNNING, &fmdev->flag)) {
- /* Fill command header info */
- hdr = (struct fm_cmd_msg_hdr *)skb_put(skb, FM_CMD_MSG_HDR_SIZE);
- hdr->hdr = FM_PKT_LOGICAL_CHAN_NUMBER; /* 0x08 */
-
- /* 3 (fm_opcode,rd_wr,dlen) + payload len) */
- hdr->len = ((payload == NULL) ? 0 : payload_len) + 3;
-
- /* FM opcode */
- hdr->op = fm_op;
-
- /* read/write type */
- hdr->rd_wr = type;
- hdr->dlen = payload_len;
- fm_cb(skb)->fm_op = fm_op;
-
- /*
- * If firmware download has finished and the command is
- * not a read command then payload is != NULL - a write
- * command with u16 payload - convert to be16
- */
- if (payload != NULL)
- *(u16 *)payload = cpu_to_be16(*(u16 *)payload);
-
- } else if (payload != NULL) {
- fm_cb(skb)->fm_op = *((u8 *)payload + 2);
- }
- if (payload != NULL)
- memcpy(skb_put(skb, payload_len), payload, payload_len);
-
- fm_cb(skb)->completion = wait_completion;
- skb_queue_tail(&fmdev->tx_q, skb);
- tasklet_schedule(&fmdev->tx_task);
-
- return 0;
-}
-
-/* Sends FM Channel-8 command to the chip and waits for the response */
-int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
- unsigned int payload_len, void *response, int *response_len)
-{
- struct sk_buff *skb;
- struct fm_event_msg_hdr *evt_hdr;
- unsigned long flags;
- int ret;
-
- init_completion(&fmdev->maintask_comp);
- ret = fm_send_cmd(fmdev, fm_op, type, payload, payload_len,
- &fmdev->maintask_comp);
- if (ret)
- return ret;
-
- if (!wait_for_completion_timeout(&fmdev->maintask_comp,
- FM_DRV_TX_TIMEOUT)) {
- fmerr("Timeout(%d sec),didn't get reg"
- "completion signal from RX tasklet\n",
- jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
- return -ETIMEDOUT;
- }
- if (!fmdev->resp_skb) {
- fmerr("Response SKB is missing\n");
- return -EFAULT;
- }
- spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
- skb = fmdev->resp_skb;
- fmdev->resp_skb = NULL;
- spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
-
- evt_hdr = (void *)skb->data;
- if (evt_hdr->status != 0) {
- fmerr("Received event pkt status(%d) is not zero\n",
- evt_hdr->status);
- kfree_skb(skb);
- return -EIO;
- }
- /* Send response data to caller */
- if (response != NULL && response_len != NULL && evt_hdr->dlen) {
- /* Skip header info and copy only response data */
- skb_pull(skb, sizeof(struct fm_event_msg_hdr));
- memcpy(response, skb->data, evt_hdr->dlen);
- *response_len = evt_hdr->dlen;
- } else if (response_len != NULL && evt_hdr->dlen == 0) {
- *response_len = 0;
- }
- kfree_skb(skb);
-
- return 0;
-}
-
-/* --- Helper functions used in FM interrupt handlers ---*/
-static inline int check_cmdresp_status(struct fmdev *fmdev,
- struct sk_buff **skb)
-{
- struct fm_event_msg_hdr *fm_evt_hdr;
- unsigned long flags;
-
- del_timer(&fmdev->irq_info.timer);
-
- spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
- *skb = fmdev->resp_skb;
- fmdev->resp_skb = NULL;
- spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
-
- fm_evt_hdr = (void *)(*skb)->data;
- if (fm_evt_hdr->status != 0) {
- fmerr("irq: opcode %x response status is not zero "
- "Initiating irq recovery process\n",
- fm_evt_hdr->op);
-
- mod_timer(&fmdev->irq_info.timer, jiffies + FM_DRV_TX_TIMEOUT);
- return -1;
- }
-
- return 0;
-}
-
-static inline void fm_irq_common_cmd_resp_helper(struct fmdev *fmdev, u8 stage)
-{
- struct sk_buff *skb;
-
- if (!check_cmdresp_status(fmdev, &skb))
- fm_irq_call_stage(fmdev, stage);
-}
-
-/*
- * Interrupt process timeout handler.
- * One of the irq handler did not get proper response from the chip. So take
- * recovery action here. FM interrupts are disabled in the beginning of
- * interrupt process. Therefore reset stage index to re-enable default
- * interrupts. So that next interrupt will be processed as usual.
- */
-static void int_timeout_handler(unsigned long data)
-{
- struct fmdev *fmdev;
- struct fm_irq *fmirq;
-
- fmdbg("irq: timeout,trying to re-enable fm interrupts\n");
- fmdev = (struct fmdev *)data;
- fmirq = &fmdev->irq_info;
- fmirq->retry++;
-
- if (fmirq->retry > FM_IRQ_TIMEOUT_RETRY_MAX) {
- /* Stop recovery action (interrupt reenable process) and
- * reset stage index & retry count values */
- fmirq->stage = 0;
- fmirq->retry = 0;
- fmerr("Recovery action failed during"
- "irq processing, max retry reached\n");
- return;
- }
- fm_irq_call_stage(fmdev, FM_SEND_INTMSK_CMD_IDX);
-}
-
-/* --------- FM interrupt handlers ------------*/
-static void fm_irq_send_flag_getcmd(struct fmdev *fmdev)
-{
- u16 flag;
-
- /* Send FLAG_GET command , to know the source of interrupt */
- if (!fm_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, sizeof(flag), NULL))
- fm_irq_timeout_stage(fmdev, FM_HANDLE_FLAG_GETCMD_RESP_IDX);
-}
-
-static void fm_irq_handle_flag_getcmd_resp(struct fmdev *fmdev)
-{
- struct sk_buff *skb;
- struct fm_event_msg_hdr *fm_evt_hdr;
-
- if (check_cmdresp_status(fmdev, &skb))
- return;
-
- fm_evt_hdr = (void *)skb->data;
-
- /* Skip header info and copy only response data */
- skb_pull(skb, sizeof(struct fm_event_msg_hdr));
- memcpy(&fmdev->irq_info.flag, skb->data, fm_evt_hdr->dlen);
-
- fmdev->irq_info.flag = be16_to_cpu(fmdev->irq_info.flag);
- fmdbg("irq: flag register(0x%x)\n", fmdev->irq_info.flag);
-
- /* Continue next function in interrupt handler table */
- fm_irq_call_stage(fmdev, FM_HW_MAL_FUNC_IDX);
-}
-
-static void fm_irq_handle_hw_malfunction(struct fmdev *fmdev)
-{
- if (fmdev->irq_info.flag & FM_MAL_EVENT & fmdev->irq_info.mask)
- fmerr("irq: HW MAL int received - do nothing\n");
-
- /* Continue next function in interrupt handler table */
- fm_irq_call_stage(fmdev, FM_RDS_START_IDX);
-}
-
-static void fm_irq_handle_rds_start(struct fmdev *fmdev)
-{
- if (fmdev->irq_info.flag & FM_RDS_EVENT & fmdev->irq_info.mask) {
- fmdbg("irq: rds threshold reached\n");
- fmdev->irq_info.stage = FM_RDS_SEND_RDS_GETCMD_IDX;
- } else {
- /* Continue next function in interrupt handler table */
- fmdev->irq_info.stage = FM_HW_TUNE_OP_ENDED_IDX;
- }
-
- fm_irq_call(fmdev);
-}
-
-static void fm_irq_send_rdsdata_getcmd(struct fmdev *fmdev)
-{
- /* Send the command to read RDS data from the chip */
- if (!fm_send_cmd(fmdev, RDS_DATA_GET, REG_RD, NULL,
- (FM_RX_RDS_FIFO_THRESHOLD * 3), NULL))
- fm_irq_timeout_stage(fmdev, FM_RDS_HANDLE_RDS_GETCMD_RESP_IDX);
-}
-
-/* Keeps track of current RX channel AF (Alternate Frequency) */
-static void fm_rx_update_af_cache(struct fmdev *fmdev, u8 af)
-{
- struct tuned_station_info *stat_info = &fmdev->rx.stat_info;
- u8 reg_idx = fmdev->rx.region.fm_band;
- u8 index;
- u32 freq;
-
- /* First AF indicates the number of AF follows. Reset the list */
- if ((af >= FM_RDS_1_AF_FOLLOWS) && (af <= FM_RDS_25_AF_FOLLOWS)) {
- fmdev->rx.stat_info.af_list_max = (af - FM_RDS_1_AF_FOLLOWS + 1);
- fmdev->rx.stat_info.afcache_size = 0;
- fmdbg("No of expected AF : %d\n", fmdev->rx.stat_info.af_list_max);
- return;
- }
-
- if (af < FM_RDS_MIN_AF)
- return;
- if (reg_idx == FM_BAND_EUROPE_US && af > FM_RDS_MAX_AF)
- return;
- if (reg_idx == FM_BAND_JAPAN && af > FM_RDS_MAX_AF_JAPAN)
- return;
-
- freq = fmdev->rx.region.bot_freq + (af * 100);
- if (freq == fmdev->rx.freq) {
- fmdbg("Current freq(%d) is matching with received AF(%d)\n",
- fmdev->rx.freq, freq);
- return;
- }
- /* Do check in AF cache */
- for (index = 0; index < stat_info->afcache_size; index++) {
- if (stat_info->af_cache[index] == freq)
- break;
- }
- /* Reached the limit of the list - ignore the next AF */
- if (index == stat_info->af_list_max) {
- fmdbg("AF cache is full\n");
- return;
- }
- /*
- * If we reached the end of the list then this AF is not
- * in the list - add it.
- */
- if (index == stat_info->afcache_size) {
- fmdbg("Storing AF %d to cache index %d\n", freq, index);
- stat_info->af_cache[index] = freq;
- stat_info->afcache_size++;
- }
-}
-
-/*
- * Converts RDS buffer data from big endian format
- * to little endian format.
- */
-static void fm_rdsparse_swapbytes(struct fmdev *fmdev,
- struct fm_rdsdata_format *rds_format)
-{
- u8 byte1;
- u8 index = 0;
- u8 *rds_buff;
-
- /*
- * Since in Orca the 2 RDS Data bytes are in little endian and
- * in Dolphin they are in big endian, the parsing of the RDS data
- * is chip dependent
- */
- if (fmdev->asci_id != 0x6350) {
- rds_buff = &rds_format->data.groupdatabuff.buff[0];
- while (index + 1 < FM_RX_RDS_INFO_FIELD_MAX) {
- byte1 = rds_buff[index];
- rds_buff[index] = rds_buff[index + 1];
- rds_buff[index + 1] = byte1;
- index += 2;
- }
- }
-}
-
-static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *fmdev)
-{
- struct sk_buff *skb;
- struct fm_rdsdata_format rds_fmt;
- struct fm_rds *rds = &fmdev->rx.rds;
- unsigned long group_idx, flags;
- u8 *rds_data, meta_data, tmpbuf[3];
- u8 type, blk_idx;
- u16 cur_picode;
- u32 rds_len;
-
- if (check_cmdresp_status(fmdev, &skb))
- return;
-
- /* Skip header info */
- skb_pull(skb, sizeof(struct fm_event_msg_hdr));
- rds_data = skb->data;
- rds_len = skb->len;
-
- /* Parse the RDS data */
- while (rds_len >= FM_RDS_BLK_SIZE) {
- meta_data = rds_data[2];
- /* Get the type: 0=A, 1=B, 2=C, 3=C', 4=D, 5=E */
- type = (meta_data & 0x07);
-
- /* Transform the blk type into index sequence (0, 1, 2, 3, 4) */
- blk_idx = (type <= FM_RDS_BLOCK_C ? type : (type - 1));
- fmdbg("Block index:%d(%s)\n", blk_idx,
- (meta_data & FM_RDS_STATUS_ERR_MASK) ? "Bad" : "Ok");
-
- if ((meta_data & FM_RDS_STATUS_ERR_MASK) != 0)
- break;
-
- if (blk_idx < FM_RDS_BLK_IDX_A || blk_idx > FM_RDS_BLK_IDX_D) {
- fmdbg("Block sequence mismatch\n");
- rds->last_blk_idx = -1;
- break;
- }
-
- /* Skip checkword (control) byte and copy only data byte */
- memcpy(&rds_fmt.data.groupdatabuff.
- buff[blk_idx * (FM_RDS_BLK_SIZE - 1)],
- rds_data, (FM_RDS_BLK_SIZE - 1));
-
- rds->last_blk_idx = blk_idx;
-
- /* If completed a whole group then handle it */
- if (blk_idx == FM_RDS_BLK_IDX_D) {
- fmdbg("Good block received\n");
- fm_rdsparse_swapbytes(fmdev, &rds_fmt);
-
- /*
- * Extract PI code and store in local cache.
- * We need this during AF switch processing.
- */
- cur_picode = be16_to_cpu(rds_fmt.data.groupgeneral.pidata);
- if (fmdev->rx.stat_info.picode != cur_picode)
- fmdev->rx.stat_info.picode = cur_picode;
-
- fmdbg("picode:%d\n", cur_picode);
-
- group_idx = (rds_fmt.data.groupgeneral.blk_b[0] >> 3);
- fmdbg("(fmdrv):Group:%ld%s\n", group_idx/2,
- (group_idx % 2) ? "B" : "A");
-
- group_idx = 1 << (rds_fmt.data.groupgeneral.blk_b[0] >> 3);
- if (group_idx == FM_RDS_GROUP_TYPE_MASK_0A) {
- fm_rx_update_af_cache(fmdev, rds_fmt.data.group0A.af[0]);
- fm_rx_update_af_cache(fmdev, rds_fmt.data.group0A.af[1]);
- }
- }
- rds_len -= FM_RDS_BLK_SIZE;
- rds_data += FM_RDS_BLK_SIZE;
- }
-
- /* Copy raw rds data to internal rds buffer */
- rds_data = skb->data;
- rds_len = skb->len;
-
- spin_lock_irqsave(&fmdev->rds_buff_lock, flags);
- while (rds_len > 0) {
- /*
- * Fill RDS buffer as per V4L2 specification.
- * Store control byte
- */
- type = (rds_data[2] & 0x07);
- blk_idx = (type <= FM_RDS_BLOCK_C ? type : (type - 1));
- tmpbuf[2] = blk_idx; /* Offset name */
- tmpbuf[2] |= blk_idx << 3; /* Received offset */
-
- /* Store data byte */
- tmpbuf[0] = rds_data[0];
- tmpbuf[1] = rds_data[1];
-
- memcpy(&rds->buff[rds->wr_idx], &tmpbuf, FM_RDS_BLK_SIZE);
- rds->wr_idx = (rds->wr_idx + FM_RDS_BLK_SIZE) % rds->buf_size;
-
- /* Check for overflow & start over */
- if (rds->wr_idx == rds->rd_idx) {
- fmdbg("RDS buffer overflow\n");
- rds->wr_idx = 0;
- rds->rd_idx = 0;
- break;
- }
- rds_len -= FM_RDS_BLK_SIZE;
- rds_data += FM_RDS_BLK_SIZE;
- }
- spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags);
-
- /* Wakeup read queue */
- if (rds->wr_idx != rds->rd_idx)
- wake_up_interruptible(&rds->read_queue);
-
- fm_irq_call_stage(fmdev, FM_RDS_FINISH_IDX);
-}
-
-static void fm_irq_handle_rds_finish(struct fmdev *fmdev)
-{
- fm_irq_call_stage(fmdev, FM_HW_TUNE_OP_ENDED_IDX);
-}
-
-static void fm_irq_handle_tune_op_ended(struct fmdev *fmdev)
-{
- if (fmdev->irq_info.flag & (FM_FR_EVENT | FM_BL_EVENT) & fmdev->
- irq_info.mask) {
- fmdbg("irq: tune ended/bandlimit reached\n");
- if (test_and_clear_bit(FM_AF_SWITCH_INPROGRESS, &fmdev->flag)) {
- fmdev->irq_info.stage = FM_AF_JUMP_RD_FREQ_IDX;
- } else {
- complete(&fmdev->maintask_comp);
- fmdev->irq_info.stage = FM_HW_POWER_ENB_IDX;
- }
- } else
- fmdev->irq_info.stage = FM_HW_POWER_ENB_IDX;
-
- fm_irq_call(fmdev);
-}
-
-static void fm_irq_handle_power_enb(struct fmdev *fmdev)
-{
- if (fmdev->irq_info.flag & FM_POW_ENB_EVENT) {
- fmdbg("irq: Power Enabled/Disabled\n");
- complete(&fmdev->maintask_comp);
- }
-
- fm_irq_call_stage(fmdev, FM_LOW_RSSI_START_IDX);
-}
-
-static void fm_irq_handle_low_rssi_start(struct fmdev *fmdev)
-{
- if ((fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON) &&
- (fmdev->irq_info.flag & FM_LEV_EVENT & fmdev->irq_info.mask) &&
- (fmdev->rx.freq != FM_UNDEFINED_FREQ) &&
- (fmdev->rx.stat_info.afcache_size != 0)) {
- fmdbg("irq: rssi level has fallen below threshold level\n");
-
- /* Disable further low RSSI interrupts */
- fmdev->irq_info.mask &= ~FM_LEV_EVENT;
-
- fmdev->rx.afjump_idx = 0;
- fmdev->rx.freq_before_jump = fmdev->rx.freq;
- fmdev->irq_info.stage = FM_AF_JUMP_SETPI_IDX;
- } else {
- /* Continue next function in interrupt handler table */
- fmdev->irq_info.stage = FM_SEND_INTMSK_CMD_IDX;
- }
-
- fm_irq_call(fmdev);
-}
-
-static void fm_irq_afjump_set_pi(struct fmdev *fmdev)
-{
- u16 payload;
-
- /* Set PI code - must be updated if the AF list is not empty */
- payload = fmdev->rx.stat_info.picode;
- if (!fm_send_cmd(fmdev, RDS_PI_SET, REG_WR, &payload, sizeof(payload), NULL))
- fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_SETPI_RESP_IDX);
-}
-
-static void fm_irq_handle_set_pi_resp(struct fmdev *fmdev)
-{
- fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_SETPI_MASK_IDX);
-}
-
-/*
- * Set PI mask.
- * 0xFFFF = Enable PI code matching
- * 0x0000 = Disable PI code matching
- */
-static void fm_irq_afjump_set_pimask(struct fmdev *fmdev)
-{
- u16 payload;
-
- payload = 0x0000;
- if (!fm_send_cmd(fmdev, RDS_PI_MASK_SET, REG_WR, &payload, sizeof(payload), NULL))
- fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_SETPI_MASK_RESP_IDX);
-}
-
-static void fm_irq_handle_set_pimask_resp(struct fmdev *fmdev)
-{
- fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_SET_AF_FREQ_IDX);
-}
-
-static void fm_irq_afjump_setfreq(struct fmdev *fmdev)
-{
- u16 frq_index;
- u16 payload;
-
- fmdbg("Swtich to %d KHz\n", fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx]);
- frq_index = (fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx] -
- fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
-
- payload = frq_index;
- if (!fm_send_cmd(fmdev, AF_FREQ_SET, REG_WR, &payload, sizeof(payload), NULL))
- fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_SET_AFFREQ_RESP_IDX);
-}
-
-static void fm_irq_handle_setfreq_resp(struct fmdev *fmdev)
-{
- fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_ENABLE_INT_IDX);
-}
-
-static void fm_irq_afjump_enableint(struct fmdev *fmdev)
-{
- u16 payload;
-
- /* Enable FR (tuning operation ended) interrupt */
- payload = FM_FR_EVENT;
- if (!fm_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, sizeof(payload), NULL))
- fm_irq_timeout_stage(fmdev, FM_AF_JUMP_ENABLE_INT_RESP_IDX);
-}
-
-static void fm_irq_afjump_enableint_resp(struct fmdev *fmdev)
-{
- fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_START_AFJUMP_IDX);
-}
-
-static void fm_irq_start_afjump(struct fmdev *fmdev)
-{
- u16 payload;
-
- payload = FM_TUNER_AF_JUMP_MODE;
- if (!fm_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
- sizeof(payload), NULL))
- fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_START_AFJUMP_RESP_IDX);
-}
-
-static void fm_irq_handle_start_afjump_resp(struct fmdev *fmdev)
-{
- struct sk_buff *skb;
-
- if (check_cmdresp_status(fmdev, &skb))
- return;
-
- fmdev->irq_info.stage = FM_SEND_FLAG_GETCMD_IDX;
- set_bit(FM_AF_SWITCH_INPROGRESS, &fmdev->flag);
- clear_bit(FM_INTTASK_RUNNING, &fmdev->flag);
-}
-
-static void fm_irq_afjump_rd_freq(struct fmdev *fmdev)
-{
- u16 payload;
-
- if (!fm_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, sizeof(payload), NULL))
- fm_irq_timeout_stage(fmdev, FM_AF_JUMP_RD_FREQ_RESP_IDX);
-}
-
-static void fm_irq_afjump_rd_freq_resp(struct fmdev *fmdev)
-{
- struct sk_buff *skb;
- u16 read_freq;
- u32 curr_freq, jumped_freq;
-
- if (check_cmdresp_status(fmdev, &skb))
- return;
-
- /* Skip header info and copy only response data */
- skb_pull(skb, sizeof(struct fm_event_msg_hdr));
- memcpy(&read_freq, skb->data, sizeof(read_freq));
- read_freq = be16_to_cpu(read_freq);
- curr_freq = fmdev->rx.region.bot_freq + ((u32)read_freq * FM_FREQ_MUL);
-
- jumped_freq = fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx];
-
- /* If the frequency was changed the jump succeeded */
- if ((curr_freq != fmdev->rx.freq_before_jump) && (curr_freq == jumped_freq)) {
- fmdbg("Successfully switched to alternate freq %d\n", curr_freq);
- fmdev->rx.freq = curr_freq;
- fm_rx_reset_rds_cache(fmdev);
-
- /* AF feature is on, enable low level RSSI interrupt */
- if (fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
- fmdev->irq_info.mask |= FM_LEV_EVENT;
-
- fmdev->irq_info.stage = FM_LOW_RSSI_FINISH_IDX;
- } else { /* jump to the next freq in the AF list */
- fmdev->rx.afjump_idx++;
-
- /* If we reached the end of the list - stop searching */
- if (fmdev->rx.afjump_idx >= fmdev->rx.stat_info.afcache_size) {
- fmdbg("AF switch processing failed\n");
- fmdev->irq_info.stage = FM_LOW_RSSI_FINISH_IDX;
- } else { /* AF List is not over - try next one */
-
- fmdbg("Trying next freq in AF cache\n");
- fmdev->irq_info.stage = FM_AF_JUMP_SETPI_IDX;
- }
- }
- fm_irq_call(fmdev);
-}
-
-static void fm_irq_handle_low_rssi_finish(struct fmdev *fmdev)
-{
- fm_irq_call_stage(fmdev, FM_SEND_INTMSK_CMD_IDX);
-}
-
-static void fm_irq_send_intmsk_cmd(struct fmdev *fmdev)
-{
- u16 payload;
-
- /* Re-enable FM interrupts */
- payload = fmdev->irq_info.mask;
-
- if (!fm_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL))
- fm_irq_timeout_stage(fmdev, FM_HANDLE_INTMSK_CMD_RESP_IDX);
-}
-
-static void fm_irq_handle_intmsk_cmd_resp(struct fmdev *fmdev)
-{
- struct sk_buff *skb;
-
- if (check_cmdresp_status(fmdev, &skb))
- return;
- /*
- * This is last function in interrupt table to be executed.
- * So, reset stage index to 0.
- */
- fmdev->irq_info.stage = FM_SEND_FLAG_GETCMD_IDX;
-
- /* Start processing any pending interrupt */
- if (test_and_clear_bit(FM_INTTASK_SCHEDULE_PENDING, &fmdev->flag))
- fmdev->irq_info.handlers[fmdev->irq_info.stage](fmdev);
- else
- clear_bit(FM_INTTASK_RUNNING, &fmdev->flag);
-}
-
-/* Returns availability of RDS data in internel buffer */
-int fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
- struct poll_table_struct *pts)
-{
- poll_wait(file, &fmdev->rx.rds.read_queue, pts);
- if (fmdev->rx.rds.rd_idx != fmdev->rx.rds.wr_idx)
- return 0;
-
- return -EAGAIN;
-}
-
-/* Copies RDS data from internal buffer to user buffer */
-int fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
- u8 __user *buf, size_t count)
-{
- u32 block_count;
- unsigned long flags;
- int ret;
-
- if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx) {
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
-
- ret = wait_event_interruptible(fmdev->rx.rds.read_queue,
- (fmdev->rx.rds.wr_idx != fmdev->rx.rds.rd_idx));
- if (ret)
- return -EINTR;
- }
-
- /* Calculate block count from byte count */
- count /= 3;
- block_count = 0;
- ret = 0;
-
- spin_lock_irqsave(&fmdev->rds_buff_lock, flags);
-
- while (block_count < count) {
- if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx)
- break;
-
- if (copy_to_user(buf, &fmdev->rx.rds.buff[fmdev->rx.rds.rd_idx],
- FM_RDS_BLK_SIZE))
- break;
-
- fmdev->rx.rds.rd_idx += FM_RDS_BLK_SIZE;
- if (fmdev->rx.rds.rd_idx >= fmdev->rx.rds.buf_size)
- fmdev->rx.rds.rd_idx = 0;
-
- block_count++;
- buf += FM_RDS_BLK_SIZE;
- ret += FM_RDS_BLK_SIZE;
- }
- spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags);
- return ret;
-}
-
-int fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
-{
- switch (fmdev->curr_fmmode) {
- case FM_MODE_RX:
- return fm_rx_set_freq(fmdev, freq_to_set);
-
- case FM_MODE_TX:
- return fm_tx_set_freq(fmdev, freq_to_set);
-
- default:
- return -EINVAL;
- }
-}
-
-int fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
-{
- if (fmdev->rx.freq == FM_UNDEFINED_FREQ) {
- fmerr("RX frequency is not set\n");
- return -EPERM;
- }
- if (cur_tuned_frq == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- switch (fmdev->curr_fmmode) {
- case FM_MODE_RX:
- *cur_tuned_frq = fmdev->rx.freq;
- return 0;
-
- case FM_MODE_TX:
- *cur_tuned_frq = 0; /* TODO : Change this later */
- return 0;
-
- default:
- return -EINVAL;
- }
-
-}
-
-int fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
-{
- switch (fmdev->curr_fmmode) {
- case FM_MODE_RX:
- return fm_rx_set_region(fmdev, region_to_set);
-
- case FM_MODE_TX:
- return fm_tx_set_region(fmdev, region_to_set);
-
- default:
- return -EINVAL;
- }
-}
-
-int fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
-{
- switch (fmdev->curr_fmmode) {
- case FM_MODE_RX:
- return fm_rx_set_mute_mode(fmdev, mute_mode_toset);
-
- case FM_MODE_TX:
- return fm_tx_set_mute_mode(fmdev, mute_mode_toset);
-
- default:
- return -EINVAL;
- }
-}
-
-int fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
-{
- switch (fmdev->curr_fmmode) {
- case FM_MODE_RX:
- return fm_rx_set_stereo_mono(fmdev, mode);
-
- case FM_MODE_TX:
- return fm_tx_set_stereo_mono(fmdev, mode);
-
- default:
- return -EINVAL;
- }
-}
-
-int fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
-{
- switch (fmdev->curr_fmmode) {
- case FM_MODE_RX:
- return fm_rx_set_rds_mode(fmdev, rds_en_dis);
-
- case FM_MODE_TX:
- return fm_tx_set_rds_mode(fmdev, rds_en_dis);
-
- default:
- return -EINVAL;
- }
-}
-
-/* Sends power off command to the chip */
-static int fm_power_down(struct fmdev *fmdev)
-{
- u16 payload;
- int ret;
-
- if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
- fmerr("FM core is not ready\n");
- return -EPERM;
- }
- if (fmdev->curr_fmmode == FM_MODE_OFF) {
- fmdbg("FM chip is already in OFF state\n");
- return 0;
- }
-
- payload = 0x0;
- ret = fmc_send_cmd(fmdev, FM_POWER_MODE, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return fmc_release(fmdev);
-}
-
-/* Reads init command from FM firmware file and loads to the chip */
-static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
-{
- const struct firmware *fw_entry;
- struct bts_header *fw_header;
- struct bts_action *action;
- struct bts_action_delay *delay;
- u8 *fw_data;
- int ret, fw_len, cmd_cnt;
-
- cmd_cnt = 0;
- set_bit(FM_FW_DW_INPROGRESS, &fmdev->flag);
-
- ret = request_firmware(&fw_entry, fw_name,
- &fmdev->radio_dev->dev);
- if (ret < 0) {
- fmerr("Unable to read firmware(%s) content\n", fw_name);
- return ret;
- }
- fmdbg("Firmware(%s) length : %d bytes\n", fw_name, fw_entry->size);
-
- fw_data = (void *)fw_entry->data;
- fw_len = fw_entry->size;
-
- fw_header = (struct bts_header *)fw_data;
- if (fw_header->magic != FM_FW_FILE_HEADER_MAGIC) {
- fmerr("%s not a legal TI firmware file\n", fw_name);
- ret = -EINVAL;
- goto rel_fw;
- }
- fmdbg("FW(%s) magic number : 0x%x\n", fw_name, fw_header->magic);
-
- /* Skip file header info , we already verified it */
- fw_data += sizeof(struct bts_header);
- fw_len -= sizeof(struct bts_header);
-
- while (fw_data && fw_len > 0) {
- action = (struct bts_action *)fw_data;
-
- switch (action->type) {
- case ACTION_SEND_COMMAND: /* Send */
- if (fmc_send_cmd(fmdev, 0, 0, action->data,
- action->size, NULL, NULL))
- goto rel_fw;
-
- cmd_cnt++;
- break;
-
- case ACTION_DELAY: /* Delay */
- delay = (struct bts_action_delay *)action->data;
- mdelay(delay->msec);
- break;
- }
-
- fw_data += (sizeof(struct bts_action) + (action->size));
- fw_len -= (sizeof(struct bts_action) + (action->size));
- }
- fmdbg("Firmware commands(%d) loaded to chip\n", cmd_cnt);
-rel_fw:
- release_firmware(fw_entry);
- clear_bit(FM_FW_DW_INPROGRESS, &fmdev->flag);
-
- return ret;
-}
-
-/* Loads default RX configuration to the chip */
-static int load_default_rx_configuration(struct fmdev *fmdev)
-{
- int ret;
-
- ret = fm_rx_set_volume(fmdev, FM_DEFAULT_RX_VOLUME);
- if (ret < 0)
- return ret;
-
- return fm_rx_set_rssi_threshold(fmdev, FM_DEFAULT_RSSI_THRESHOLD);
-}
-
-/* Does FM power on sequence */
-static int fm_power_up(struct fmdev *fmdev, u8 mode)
-{
- u16 payload, asic_id, asic_ver;
- int resp_len, ret;
- u8 fw_name[50];
-
- if (mode >= FM_MODE_ENTRY_MAX) {
- fmerr("Invalid firmware download option\n");
- return -EINVAL;
- }
-
- /*
- * Initialize FM common module. FM GPIO toggling is
- * taken care in Shared Transport driver.
- */
- ret = fmc_prepare(fmdev);
- if (ret < 0) {
- fmerr("Unable to prepare FM Common\n");
- return ret;
- }
-
- payload = FM_ENABLE;
- if (fmc_send_cmd(fmdev, FM_POWER_MODE, REG_WR, &payload,
- sizeof(payload), NULL, NULL))
- goto rel;
-
- /* Allow the chip to settle down in Channel-8 mode */
- msleep(20);
-
- if (fmc_send_cmd(fmdev, ASIC_ID_GET, REG_RD, NULL,
- sizeof(asic_id), &asic_id, &resp_len))
- goto rel;
-
- if (fmc_send_cmd(fmdev, ASIC_VER_GET, REG_RD, NULL,
- sizeof(asic_ver), &asic_ver, &resp_len))
- goto rel;
-
- fmdbg("ASIC ID: 0x%x , ASIC Version: %d\n",
- be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
-
- sprintf(fw_name, "%s_%x.%d.bts", FM_FMC_FW_FILE_START,
- be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
-
- ret = fm_download_firmware(fmdev, fw_name);
- if (ret < 0) {
- fmdbg("Failed to download firmware file %s\n", fw_name);
- goto rel;
- }
- sprintf(fw_name, "%s_%x.%d.bts", (mode == FM_MODE_RX) ?
- FM_RX_FW_FILE_START : FM_TX_FW_FILE_START,
- be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
-
- ret = fm_download_firmware(fmdev, fw_name);
- if (ret < 0) {
- fmdbg("Failed to download firmware file %s\n", fw_name);
- goto rel;
- } else
- return ret;
-rel:
- return fmc_release(fmdev);
-}
-
-/* Set FM Modes(TX, RX, OFF) */
-int fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
-{
- int ret = 0;
-
- if (fm_mode >= FM_MODE_ENTRY_MAX) {
- fmerr("Invalid FM mode\n");
- return -EINVAL;
- }
- if (fmdev->curr_fmmode == fm_mode) {
- fmdbg("Already fm is in mode(%d)\n", fm_mode);
- return ret;
- }
-
- switch (fm_mode) {
- case FM_MODE_OFF: /* OFF Mode */
- ret = fm_power_down(fmdev);
- if (ret < 0) {
- fmerr("Failed to set OFF mode\n");
- return ret;
- }
- break;
-
- case FM_MODE_TX: /* TX Mode */
- case FM_MODE_RX: /* RX Mode */
- /* Power down before switching to TX or RX mode */
- if (fmdev->curr_fmmode != FM_MODE_OFF) {
- ret = fm_power_down(fmdev);
- if (ret < 0) {
- fmerr("Failed to set OFF mode\n");
- return ret;
- }
- msleep(30);
- }
- ret = fm_power_up(fmdev, fm_mode);
- if (ret < 0) {
- fmerr("Failed to load firmware\n");
- return ret;
- }
- }
- fmdev->curr_fmmode = fm_mode;
-
- /* Set default configuration */
- if (fmdev->curr_fmmode == FM_MODE_RX) {
- fmdbg("Loading default rx configuration..\n");
- ret = load_default_rx_configuration(fmdev);
- if (ret < 0)
- fmerr("Failed to load default values\n");
- }
-
- return ret;
-}
-
-/* Returns current FM mode (TX, RX, OFF) */
-int fmc_get_mode(struct fmdev *fmdev, u8 *fmmode)
-{
- if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
- fmerr("FM core is not ready\n");
- return -EPERM;
- }
- if (fmmode == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *fmmode = fmdev->curr_fmmode;
- return 0;
-}
-
-/* Called by ST layer when FM packet is available */
-static long fm_st_receive(void *arg, struct sk_buff *skb)
-{
- struct fmdev *fmdev;
-
- fmdev = (struct fmdev *)arg;
-
- if (skb == NULL) {
- fmerr("Invalid SKB received from ST\n");
- return -EFAULT;
- }
-
- if (skb->cb[0] != FM_PKT_LOGICAL_CHAN_NUMBER) {
- fmerr("Received SKB (%p) is not FM Channel 8 pkt\n", skb);
- return -EINVAL;
- }
-
- memcpy(skb_push(skb, 1), &skb->cb[0], 1);
- skb_queue_tail(&fmdev->rx_q, skb);
- tasklet_schedule(&fmdev->rx_task);
-
- return 0;
-}
-
-/*
- * Called by ST layer to indicate protocol registration completion
- * status.
- */
-static void fm_st_reg_comp_cb(void *arg, char data)
-{
- struct fmdev *fmdev;
-
- fmdev = (struct fmdev *)arg;
- fmdev->streg_cbdata = data;
- complete(&wait_for_fmdrv_reg_comp);
-}
-
-/*
- * This function will be called from FM V4L2 open function.
- * Register with ST driver and initialize driver data.
- */
-int fmc_prepare(struct fmdev *fmdev)
-{
- static struct st_proto_s fm_st_proto;
- int ret;
-
- if (test_bit(FM_CORE_READY, &fmdev->flag)) {
- fmdbg("FM Core is already up\n");
- return 0;
- }
-
- memset(&fm_st_proto, 0, sizeof(fm_st_proto));
- fm_st_proto.recv = fm_st_receive;
- fm_st_proto.match_packet = NULL;
- fm_st_proto.reg_complete_cb = fm_st_reg_comp_cb;
- fm_st_proto.write = NULL; /* TI ST driver will fill write pointer */
- fm_st_proto.priv_data = fmdev;
- fm_st_proto.chnl_id = 0x08;
- fm_st_proto.max_frame_size = 0xff;
- fm_st_proto.hdr_len = 1;
- fm_st_proto.offset_len_in_hdr = 0;
- fm_st_proto.len_size = 1;
- fm_st_proto.reserve = 1;
-
- ret = st_register(&fm_st_proto);
- if (ret == -EINPROGRESS) {
- init_completion(&wait_for_fmdrv_reg_comp);
- fmdev->streg_cbdata = -EINPROGRESS;
- fmdbg("%s waiting for ST reg completion signal\n", __func__);
-
- if (!wait_for_completion_timeout(&wait_for_fmdrv_reg_comp,
- FM_ST_REG_TIMEOUT)) {
- fmerr("Timeout(%d sec), didn't get reg "
- "completion signal from ST\n",
- jiffies_to_msecs(FM_ST_REG_TIMEOUT) / 1000);
- return -ETIMEDOUT;
- }
- if (fmdev->streg_cbdata != 0) {
- fmerr("ST reg comp CB called with error "
- "status %d\n", fmdev->streg_cbdata);
- return -EAGAIN;
- }
-
- ret = 0;
- } else if (ret == -1) {
- fmerr("st_register failed %d\n", ret);
- return -EAGAIN;
- }
-
- if (fm_st_proto.write != NULL) {
- g_st_write = fm_st_proto.write;
- } else {
- fmerr("Failed to get ST write func pointer\n");
- ret = st_unregister(&fm_st_proto);
- if (ret < 0)
- fmerr("st_unregister failed %d\n", ret);
- return -EAGAIN;
- }
-
- spin_lock_init(&fmdev->rds_buff_lock);
- spin_lock_init(&fmdev->resp_skb_lock);
-
- /* Initialize TX queue and TX tasklet */
- skb_queue_head_init(&fmdev->tx_q);
- tasklet_init(&fmdev->tx_task, send_tasklet, (unsigned long)fmdev);
-
- /* Initialize RX Queue and RX tasklet */
- skb_queue_head_init(&fmdev->rx_q);
- tasklet_init(&fmdev->rx_task, recv_tasklet, (unsigned long)fmdev);
-
- fmdev->irq_info.stage = 0;
- atomic_set(&fmdev->tx_cnt, 1);
- fmdev->resp_comp = NULL;
-
- init_timer(&fmdev->irq_info.timer);
- fmdev->irq_info.timer.function = &int_timeout_handler;
- fmdev->irq_info.timer.data = (unsigned long)fmdev;
- /*TODO: add FM_STIC_EVENT later */
- fmdev->irq_info.mask = FM_MAL_EVENT;
-
- /* Region info */
- memcpy(&fmdev->rx.region, &region_configs[default_radio_region],
- sizeof(struct region_info));
-
- fmdev->rx.mute_mode = FM_MUTE_OFF;
- fmdev->rx.rf_depend_mute = FM_RX_RF_DEPENDENT_MUTE_OFF;
- fmdev->rx.rds.flag = FM_RDS_DISABLE;
- fmdev->rx.freq = FM_UNDEFINED_FREQ;
- fmdev->rx.rds_mode = FM_RDS_SYSTEM_RDS;
- fmdev->rx.af_mode = FM_RX_RDS_AF_SWITCH_MODE_OFF;
- fmdev->irq_info.retry = 0;
-
- fm_rx_reset_rds_cache(fmdev);
- init_waitqueue_head(&fmdev->rx.rds.read_queue);
-
- fm_rx_reset_station_info(fmdev);
- set_bit(FM_CORE_READY, &fmdev->flag);
-
- return ret;
-}
-
-/*
- * This function will be called from FM V4L2 release function.
- * Unregister from ST driver.
- */
-int fmc_release(struct fmdev *fmdev)
-{
- static struct st_proto_s fm_st_proto;
- int ret;
-
- if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
- fmdbg("FM Core is already down\n");
- return 0;
- }
- /* Service pending read */
- wake_up_interruptible(&fmdev->rx.rds.read_queue);
-
- tasklet_kill(&fmdev->tx_task);
- tasklet_kill(&fmdev->rx_task);
-
- skb_queue_purge(&fmdev->tx_q);
- skb_queue_purge(&fmdev->rx_q);
-
- fmdev->resp_comp = NULL;
- fmdev->rx.freq = 0;
-
- memset(&fm_st_proto, 0, sizeof(fm_st_proto));
- fm_st_proto.chnl_id = 0x08;
-
- ret = st_unregister(&fm_st_proto);
-
- if (ret < 0)
- fmerr("Failed to de-register FM from ST %d\n", ret);
- else
- fmdbg("Successfully unregistered from ST\n");
-
- clear_bit(FM_CORE_READY, &fmdev->flag);
- return ret;
-}
-
-/*
- * Module init function. Ask FM V4L module to register video device.
- * Allocate memory for FM driver context and RX RDS buffer.
- */
-static int __init fm_drv_init(void)
-{
- struct fmdev *fmdev = NULL;
- int ret = -ENOMEM;
-
- fmdbg("FM driver version %s\n", FM_DRV_VERSION);
-
- fmdev = kzalloc(sizeof(struct fmdev), GFP_KERNEL);
- if (NULL == fmdev) {
- fmerr("Can't allocate operation structure memory\n");
- return ret;
- }
- fmdev->rx.rds.buf_size = default_rds_buf * FM_RDS_BLK_SIZE;
- fmdev->rx.rds.buff = kzalloc(fmdev->rx.rds.buf_size, GFP_KERNEL);
- if (NULL == fmdev->rx.rds.buff) {
- fmerr("Can't allocate rds ring buffer\n");
- goto rel_dev;
- }
-
- ret = fm_v4l2_init_video_device(fmdev, radio_nr);
- if (ret < 0)
- goto rel_rdsbuf;
-
- fmdev->irq_info.handlers = int_handler_table;
- fmdev->curr_fmmode = FM_MODE_OFF;
- fmdev->tx_data.pwr_lvl = FM_PWR_LVL_DEF;
- fmdev->tx_data.preemph = FM_TX_PREEMPH_50US;
- return ret;
-
-rel_rdsbuf:
- kfree(fmdev->rx.rds.buff);
-rel_dev:
- kfree(fmdev);
-
- return ret;
-}
-
-/* Module exit function. Ask FM V4L module to unregister video device */
-static void __exit fm_drv_exit(void)
-{
- struct fmdev *fmdev = NULL;
-
- fmdev = fm_v4l2_deinit_video_device();
- if (fmdev != NULL) {
- kfree(fmdev->rx.rds.buff);
- kfree(fmdev);
- }
-}
-
-module_init(fm_drv_init);
-module_exit(fm_drv_exit);
-
-/* ------------- Module Info ------------- */
-MODULE_AUTHOR("Manjunatha Halli <manjunatha_halli@ti.com>");
-MODULE_DESCRIPTION("FM Driver for TI's Connectivity chip. " FM_DRV_VERSION);
-MODULE_VERSION(FM_DRV_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.h b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.h
deleted file mode 100644
index d9b9c6cf..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_common.h
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- * FM Common module header file
- *
- * Copyright (C) 2011 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef _FMDRV_COMMON_H
-#define _FMDRV_COMMON_H
-
-#define FM_ST_REG_TIMEOUT msecs_to_jiffies(6000) /* 6 sec */
-#define FM_PKT_LOGICAL_CHAN_NUMBER 0x08 /* Logical channel 8 */
-
-#define REG_RD 0x1
-#define REG_WR 0x0
-
-struct fm_reg_table {
- u8 opcode;
- u8 type;
- u8 *name;
-};
-
-#define STEREO_GET 0
-#define RSSI_LVL_GET 1
-#define IF_COUNT_GET 2
-#define FLAG_GET 3
-#define RDS_SYNC_GET 4
-#define RDS_DATA_GET 5
-#define FREQ_SET 10
-#define AF_FREQ_SET 11
-#define MOST_MODE_SET 12
-#define MOST_BLEND_SET 13
-#define DEMPH_MODE_SET 14
-#define SEARCH_LVL_SET 15
-#define BAND_SET 16
-#define MUTE_STATUS_SET 17
-#define RDS_PAUSE_LVL_SET 18
-#define RDS_PAUSE_DUR_SET 19
-#define RDS_MEM_SET 20
-#define RDS_BLK_B_SET 21
-#define RDS_MSK_B_SET 22
-#define RDS_PI_MASK_SET 23
-#define RDS_PI_SET 24
-#define RDS_SYSTEM_SET 25
-#define INT_MASK_SET 26
-#define SEARCH_DIR_SET 27
-#define VOLUME_SET 28
-#define AUDIO_ENABLE_SET 29
-#define PCM_MODE_SET 30
-#define I2S_MODE_CONFIG_SET 31
-#define POWER_SET 32
-#define INTX_CONFIG_SET 33
-#define PULL_EN_SET 34
-#define HILO_SET 35
-#define SWITCH2FREF 36
-#define FREQ_DRIFT_REPORT 37
-
-#define PCE_GET 40
-#define FIRM_VER_GET 41
-#define ASIC_VER_GET 42
-#define ASIC_ID_GET 43
-#define MAN_ID_GET 44
-#define TUNER_MODE_SET 45
-#define STOP_SEARCH 46
-#define RDS_CNTRL_SET 47
-
-#define WRITE_HARDWARE_REG 100
-#define CODE_DOWNLOAD 101
-#define RESET 102
-
-#define FM_POWER_MODE 254
-#define FM_INTERRUPT 255
-
-/* Transmitter API */
-
-#define CHANL_SET 55
-#define CHANL_BW_SET 56
-#define REF_SET 57
-#define POWER_ENB_SET 90
-#define POWER_ATT_SET 58
-#define POWER_LEV_SET 59
-#define AUDIO_DEV_SET 60
-#define PILOT_DEV_SET 61
-#define RDS_DEV_SET 62
-#define TX_BAND_SET 65
-#define PUPD_SET 91
-#define AUDIO_IO_SET 63
-#define PREMPH_SET 64
-#define MONO_SET 66
-#define MUTE 92
-#define MPX_LMT_ENABLE 67
-#define PI_SET 93
-#define ECC_SET 69
-#define PTY 70
-#define AF 71
-#define DISPLAY_MODE 74
-#define RDS_REP_SET 77
-#define RDS_CONFIG_DATA_SET 98
-#define RDS_DATA_SET 99
-#define RDS_DATA_ENB 94
-#define TA_SET 78
-#define TP_SET 79
-#define DI_SET 80
-#define MS_SET 81
-#define PS_SCROLL_SPEED 82
-#define TX_AUDIO_LEVEL_TEST 96
-#define TX_AUDIO_LEVEL_TEST_THRESHOLD 73
-#define TX_AUDIO_INPUT_LEVEL_RANGE_SET 54
-#define RX_ANTENNA_SELECT 87
-#define I2C_DEV_ADDR_SET 86
-#define REF_ERR_CALIB_PARAM_SET 88
-#define REF_ERR_CALIB_PERIODICITY_SET 89
-#define SOC_INT_TRIGGER 52
-#define SOC_AUDIO_PATH_SET 83
-#define SOC_PCMI_OVERRIDE 84
-#define SOC_I2S_OVERRIDE 85
-#define RSSI_BLOCK_SCAN_FREQ_SET 95
-#define RSSI_BLOCK_SCAN_START 97
-#define RSSI_BLOCK_SCAN_DATA_GET 5
-#define READ_FMANT_TUNE_VALUE 104
-
-/* SKB helpers */
-struct fm_skb_cb {
- __u8 fm_op;
- struct completion *completion;
-};
-
-#define fm_cb(skb) ((struct fm_skb_cb *)(skb->cb))
-
-/* FM Channel-8 command message format */
-struct fm_cmd_msg_hdr {
- __u8 hdr; /* Logical Channel-8 */
- __u8 len; /* Number of bytes follows */
- __u8 op; /* FM Opcode */
- __u8 rd_wr; /* Read/Write command */
- __u8 dlen; /* Length of payload */
-} __attribute__ ((packed));
-
-#define FM_CMD_MSG_HDR_SIZE 5 /* sizeof(struct fm_cmd_msg_hdr) */
-
-/* FM Channel-8 event messgage format */
-struct fm_event_msg_hdr {
- __u8 header; /* Logical Channel-8 */
- __u8 len; /* Number of bytes follows */
- __u8 status; /* Event status */
- __u8 num_fm_hci_cmds; /* Number of pkts the host allowed to send */
- __u8 op; /* FM Opcode */
- __u8 rd_wr; /* Read/Write command */
- __u8 dlen; /* Length of payload */
-} __attribute__ ((packed));
-
-#define FM_EVT_MSG_HDR_SIZE 7 /* sizeof(struct fm_event_msg_hdr) */
-
-/* TI's magic number in firmware file */
-#define FM_FW_FILE_HEADER_MAGIC 0x42535442
-
-#define FM_ENABLE 1
-#define FM_DISABLE 0
-
-/* FLAG_GET register bits */
-#define FM_FR_EVENT (1 << 0)
-#define FM_BL_EVENT (1 << 1)
-#define FM_RDS_EVENT (1 << 2)
-#define FM_BBLK_EVENT (1 << 3)
-#define FM_LSYNC_EVENT (1 << 4)
-#define FM_LEV_EVENT (1 << 5)
-#define FM_IFFR_EVENT (1 << 6)
-#define FM_PI_EVENT (1 << 7)
-#define FM_PD_EVENT (1 << 8)
-#define FM_STIC_EVENT (1 << 9)
-#define FM_MAL_EVENT (1 << 10)
-#define FM_POW_ENB_EVENT (1 << 11)
-
-/*
- * Firmware files of FM. ASIC ID and ASIC version will be appened to this,
- * later.
- */
-#define FM_FMC_FW_FILE_START ("fmc_ch8")
-#define FM_RX_FW_FILE_START ("fm_rx_ch8")
-#define FM_TX_FW_FILE_START ("fm_tx_ch8")
-
-#define FM_UNDEFINED_FREQ 0xFFFFFFFF
-
-/* Band types */
-#define FM_BAND_EUROPE_US 0
-#define FM_BAND_JAPAN 1
-
-/* Seek directions */
-#define FM_SEARCH_DIRECTION_DOWN 0
-#define FM_SEARCH_DIRECTION_UP 1
-
-/* Tunner modes */
-#define FM_TUNER_STOP_SEARCH_MODE 0
-#define FM_TUNER_PRESET_MODE 1
-#define FM_TUNER_AUTONOMOUS_SEARCH_MODE 2
-#define FM_TUNER_AF_JUMP_MODE 3
-
-/* Min and Max volume */
-#define FM_RX_VOLUME_MIN 0
-#define FM_RX_VOLUME_MAX 70
-
-/* Volume gain step */
-#define FM_RX_VOLUME_GAIN_STEP 0x370
-
-/* Mute modes */
-#define FM_MUTE_ON 0
-#define FM_MUTE_OFF 1
-#define FM_MUTE_ATTENUATE 2
-
-#define FM_RX_UNMUTE_MODE 0x00
-#define FM_RX_RF_DEP_MODE 0x01
-#define FM_RX_AC_MUTE_MODE 0x02
-#define FM_RX_HARD_MUTE_LEFT_MODE 0x04
-#define FM_RX_HARD_MUTE_RIGHT_MODE 0x08
-#define FM_RX_SOFT_MUTE_FORCE_MODE 0x10
-
-/* RF dependent mute mode */
-#define FM_RX_RF_DEPENDENT_MUTE_ON 1
-#define FM_RX_RF_DEPENDENT_MUTE_OFF 0
-
-/* RSSI threshold min and max */
-#define FM_RX_RSSI_THRESHOLD_MIN -128
-#define FM_RX_RSSI_THRESHOLD_MAX 127
-
-/* Stereo/Mono mode */
-#define FM_STEREO_MODE 0
-#define FM_MONO_MODE 1
-#define FM_STEREO_SOFT_BLEND 1
-
-/* FM RX De-emphasis filter modes */
-#define FM_RX_EMPHASIS_FILTER_50_USEC 0
-#define FM_RX_EMPHASIS_FILTER_75_USEC 1
-
-/* FM RDS modes */
-#define FM_RDS_DISABLE 0
-#define FM_RDS_ENABLE 1
-
-#define FM_NO_PI_CODE 0
-
-/* FM and RX RDS block enable/disable */
-#define FM_RX_PWR_SET_FM_ON_RDS_OFF 0x1
-#define FM_RX_PWR_SET_FM_AND_RDS_BLK_ON 0x3
-#define FM_RX_PWR_SET_FM_AND_RDS_BLK_OFF 0x0
-
-/* RX RDS */
-#define FM_RX_RDS_FLUSH_FIFO 0x1
-#define FM_RX_RDS_FIFO_THRESHOLD 64 /* tuples */
-#define FM_RDS_BLK_SIZE 3 /* 3 bytes */
-
-/* RDS block types */
-#define FM_RDS_BLOCK_A 0
-#define FM_RDS_BLOCK_B 1
-#define FM_RDS_BLOCK_C 2
-#define FM_RDS_BLOCK_Ctag 3
-#define FM_RDS_BLOCK_D 4
-#define FM_RDS_BLOCK_E 5
-
-#define FM_RDS_BLK_IDX_A 0
-#define FM_RDS_BLK_IDX_B 1
-#define FM_RDS_BLK_IDX_C 2
-#define FM_RDS_BLK_IDX_D 3
-#define FM_RDS_BLK_IDX_UNKNOWN 0xF0
-
-#define FM_RDS_STATUS_ERR_MASK 0x18
-
-/*
- * Represents an RDS group type & version.
- * There are 15 groups, each group has 2 versions: A and B.
- */
-#define FM_RDS_GROUP_TYPE_MASK_0A ((unsigned long)1<<0)
-#define FM_RDS_GROUP_TYPE_MASK_0B ((unsigned long)1<<1)
-#define FM_RDS_GROUP_TYPE_MASK_1A ((unsigned long)1<<2)
-#define FM_RDS_GROUP_TYPE_MASK_1B ((unsigned long)1<<3)
-#define FM_RDS_GROUP_TYPE_MASK_2A ((unsigned long)1<<4)
-#define FM_RDS_GROUP_TYPE_MASK_2B ((unsigned long)1<<5)
-#define FM_RDS_GROUP_TYPE_MASK_3A ((unsigned long)1<<6)
-#define FM_RDS_GROUP_TYPE_MASK_3B ((unsigned long)1<<7)
-#define FM_RDS_GROUP_TYPE_MASK_4A ((unsigned long)1<<8)
-#define FM_RDS_GROUP_TYPE_MASK_4B ((unsigned long)1<<9)
-#define FM_RDS_GROUP_TYPE_MASK_5A ((unsigned long)1<<10)
-#define FM_RDS_GROUP_TYPE_MASK_5B ((unsigned long)1<<11)
-#define FM_RDS_GROUP_TYPE_MASK_6A ((unsigned long)1<<12)
-#define FM_RDS_GROUP_TYPE_MASK_6B ((unsigned long)1<<13)
-#define FM_RDS_GROUP_TYPE_MASK_7A ((unsigned long)1<<14)
-#define FM_RDS_GROUP_TYPE_MASK_7B ((unsigned long)1<<15)
-#define FM_RDS_GROUP_TYPE_MASK_8A ((unsigned long)1<<16)
-#define FM_RDS_GROUP_TYPE_MASK_8B ((unsigned long)1<<17)
-#define FM_RDS_GROUP_TYPE_MASK_9A ((unsigned long)1<<18)
-#define FM_RDS_GROUP_TYPE_MASK_9B ((unsigned long)1<<19)
-#define FM_RDS_GROUP_TYPE_MASK_10A ((unsigned long)1<<20)
-#define FM_RDS_GROUP_TYPE_MASK_10B ((unsigned long)1<<21)
-#define FM_RDS_GROUP_TYPE_MASK_11A ((unsigned long)1<<22)
-#define FM_RDS_GROUP_TYPE_MASK_11B ((unsigned long)1<<23)
-#define FM_RDS_GROUP_TYPE_MASK_12A ((unsigned long)1<<24)
-#define FM_RDS_GROUP_TYPE_MASK_12B ((unsigned long)1<<25)
-#define FM_RDS_GROUP_TYPE_MASK_13A ((unsigned long)1<<26)
-#define FM_RDS_GROUP_TYPE_MASK_13B ((unsigned long)1<<27)
-#define FM_RDS_GROUP_TYPE_MASK_14A ((unsigned long)1<<28)
-#define FM_RDS_GROUP_TYPE_MASK_14B ((unsigned long)1<<29)
-#define FM_RDS_GROUP_TYPE_MASK_15A ((unsigned long)1<<30)
-#define FM_RDS_GROUP_TYPE_MASK_15B ((unsigned long)1<<31)
-
-/* RX Alternate Frequency info */
-#define FM_RDS_MIN_AF 1
-#define FM_RDS_MAX_AF 204
-#define FM_RDS_MAX_AF_JAPAN 140
-#define FM_RDS_1_AF_FOLLOWS 225
-#define FM_RDS_25_AF_FOLLOWS 249
-
-/* RDS system type (RDS/RBDS) */
-#define FM_RDS_SYSTEM_RDS 0
-#define FM_RDS_SYSTEM_RBDS 1
-
-/* AF on/off */
-#define FM_RX_RDS_AF_SWITCH_MODE_ON 1
-#define FM_RX_RDS_AF_SWITCH_MODE_OFF 0
-
-/* Retry count when interrupt process goes wrong */
-#define FM_IRQ_TIMEOUT_RETRY_MAX 5 /* 5 times */
-
-/* Audio IO set values */
-#define FM_RX_AUDIO_ENABLE_I2S 0x01
-#define FM_RX_AUDIO_ENABLE_ANALOG 0x02
-#define FM_RX_AUDIO_ENABLE_I2S_AND_ANALOG 0x03
-#define FM_RX_AUDIO_ENABLE_DISABLE 0x00
-
-/* HI/LO set values */
-#define FM_RX_IFFREQ_TO_HI_SIDE 0x0
-#define FM_RX_IFFREQ_TO_LO_SIDE 0x1
-#define FM_RX_IFFREQ_HILO_AUTOMATIC 0x2
-
-/*
- * Default RX mode configuration. Chip will be configured
- * with this default values after loading RX firmware.
- */
-#define FM_DEFAULT_RX_VOLUME 10
-#define FM_DEFAULT_RSSI_THRESHOLD 3
-
-/* Range for TX power level in units for dB/uV */
-#define FM_PWR_LVL_LOW 91
-#define FM_PWR_LVL_HIGH 122
-
-/* Chip specific default TX power level value */
-#define FM_PWR_LVL_DEF 4
-
-/* FM TX Pre-emphasis filter values */
-#define FM_TX_PREEMPH_OFF 1
-#define FM_TX_PREEMPH_50US 0
-#define FM_TX_PREEMPH_75US 2
-
-/* FM TX antenna impedance values */
-#define FM_TX_ANT_IMP_50 0
-#define FM_TX_ANT_IMP_200 1
-#define FM_TX_ANT_IMP_500 2
-
-/* Functions exported by FM common sub-module */
-int fmc_prepare(struct fmdev *);
-int fmc_release(struct fmdev *);
-
-void fmc_update_region_info(struct fmdev *, u8);
-int fmc_send_cmd(struct fmdev *, u8, u16,
- void *, unsigned int, void *, int *);
-int fmc_is_rds_data_available(struct fmdev *, struct file *,
- struct poll_table_struct *);
-int fmc_transfer_rds_from_internal_buff(struct fmdev *, struct file *,
- u8 __user *, size_t);
-
-int fmc_set_freq(struct fmdev *, u32);
-int fmc_set_mode(struct fmdev *, u8);
-int fmc_set_region(struct fmdev *, u8);
-int fmc_set_mute_mode(struct fmdev *, u8);
-int fmc_set_stereo_mono(struct fmdev *, u16);
-int fmc_set_rds_mode(struct fmdev *, u8);
-
-int fmc_get_freq(struct fmdev *, u32 *);
-int fmc_get_region(struct fmdev *, u8 *);
-int fmc_get_mode(struct fmdev *, u8 *);
-
-/*
- * channel spacing
- */
-#define FM_CHANNEL_SPACING_50KHZ 1
-#define FM_CHANNEL_SPACING_100KHZ 2
-#define FM_CHANNEL_SPACING_200KHZ 4
-#define FM_FREQ_MUL 50
-
-#endif
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.c b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.c
deleted file mode 100644
index 43fb7229..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- * This sub-module of FM driver implements FM RX functionality.
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Raja Mani <raja_mani@ti.com>
- * Author: Manjunatha Halli <manjunatha_halli@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "fmdrv.h"
-#include "fmdrv_common.h"
-#include "fmdrv_rx.h"
-
-void fm_rx_reset_rds_cache(struct fmdev *fmdev)
-{
- fmdev->rx.rds.flag = FM_RDS_DISABLE;
- fmdev->rx.rds.last_blk_idx = 0;
- fmdev->rx.rds.wr_idx = 0;
- fmdev->rx.rds.rd_idx = 0;
-
- if (fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
- fmdev->irq_info.mask |= FM_LEV_EVENT;
-}
-
-void fm_rx_reset_station_info(struct fmdev *fmdev)
-{
- fmdev->rx.stat_info.picode = FM_NO_PI_CODE;
- fmdev->rx.stat_info.afcache_size = 0;
- fmdev->rx.stat_info.af_list_max = 0;
-}
-
-int fm_rx_set_freq(struct fmdev *fmdev, u32 freq)
-{
- unsigned long timeleft;
- u16 payload, curr_frq, intr_flag;
- u32 curr_frq_in_khz;
- u32 resp_len;
- int ret;
-
- if (freq < fmdev->rx.region.bot_freq || freq > fmdev->rx.region.top_freq) {
- fmerr("Invalid frequency %d\n", freq);
- return -EINVAL;
- }
-
- /* Set audio enable */
- payload = FM_RX_AUDIO_ENABLE_I2S_AND_ANALOG;
-
- ret = fmc_send_cmd(fmdev, AUDIO_ENABLE_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Set hilo to automatic selection */
- payload = FM_RX_IFFREQ_HILO_AUTOMATIC;
- ret = fmc_send_cmd(fmdev, HILO_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Calculate frequency index and set*/
- payload = (freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
-
- ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Read flags - just to clear any pending interrupts if we had */
- ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Enable FR, BL interrupts */
- intr_flag = fmdev->irq_info.mask;
- fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT);
- payload = fmdev->irq_info.mask;
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Start tune */
- payload = FM_TUNER_PRESET_MODE;
- ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- goto exit;
-
- /* Wait for tune ended interrupt */
- init_completion(&fmdev->maintask_comp);
- timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
- FM_DRV_TX_TIMEOUT);
- if (!timeleft) {
- fmerr("Timeout(%d sec),didn't get tune ended int\n",
- jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
- ret = -ETIMEDOUT;
- goto exit;
- }
-
- /* Read freq back to confirm */
- ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2, &curr_frq, &resp_len);
- if (ret < 0)
- goto exit;
-
- curr_frq = be16_to_cpu(curr_frq);
- curr_frq_in_khz = (fmdev->rx.region.bot_freq + ((u32)curr_frq * FM_FREQ_MUL));
-
- if (curr_frq_in_khz != freq) {
- pr_info("Frequency is set to (%d) but "
- "requested freq is (%d)\n", curr_frq_in_khz, freq);
- }
-
- /* Update local cache */
- fmdev->rx.freq = curr_frq_in_khz;
-exit:
- /* Re-enable default FM interrupts */
- fmdev->irq_info.mask = intr_flag;
- payload = fmdev->irq_info.mask;
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Reset RDS cache and current station pointers */
- fm_rx_reset_rds_cache(fmdev);
- fm_rx_reset_station_info(fmdev);
-
- return ret;
-}
-
-static int fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
-{
- u16 payload;
- int ret;
-
- if (spacing > 0 && spacing <= 50000)
- spacing = FM_CHANNEL_SPACING_50KHZ;
- else if (spacing > 50000 && spacing <= 100000)
- spacing = FM_CHANNEL_SPACING_100KHZ;
- else
- spacing = FM_CHANNEL_SPACING_200KHZ;
-
- /* set channel spacing */
- payload = spacing;
- ret = fmc_send_cmd(fmdev, CHANL_BW_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmdev->rx.region.chanl_space = spacing * FM_FREQ_MUL;
-
- return ret;
-}
-
-int fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
- u32 wrap_around, u32 spacing)
-{
- u32 resp_len;
- u16 curr_frq, next_frq, last_frq;
- u16 payload, int_reason, intr_flag;
- u16 offset, space_idx;
- unsigned long timeleft;
- int ret;
-
- /* Set channel spacing */
- ret = fm_rx_set_channel_spacing(fmdev, spacing);
- if (ret < 0) {
- fmerr("Failed to set channel spacing\n");
- return ret;
- }
-
- /* Read the current frequency from chip */
- ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL,
- sizeof(curr_frq), &curr_frq, &resp_len);
- if (ret < 0)
- return ret;
-
- curr_frq = be16_to_cpu(curr_frq);
- last_frq = (fmdev->rx.region.top_freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
-
- /* Check the offset in order to be aligned to the channel spacing*/
- space_idx = fmdev->rx.region.chanl_space / FM_FREQ_MUL;
- offset = curr_frq % space_idx;
-
- next_frq = seek_upward ? curr_frq + space_idx /* Seek Up */ :
- curr_frq - space_idx /* Seek Down */ ;
-
- /*
- * Add or subtract offset in order to stay aligned to the channel
- * spacing.
- */
- if ((short)next_frq < 0)
- next_frq = last_frq - offset;
- else if (next_frq > last_frq)
- next_frq = 0 + offset;
-
-again:
- /* Set calculated next frequency to perform seek */
- payload = next_frq;
- ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Set search direction (0:Seek Down, 1:Seek Up) */
- payload = (seek_upward ? FM_SEARCH_DIRECTION_UP : FM_SEARCH_DIRECTION_DOWN);
- ret = fmc_send_cmd(fmdev, SEARCH_DIR_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Read flags - just to clear any pending interrupts if we had */
- ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Enable FR, BL interrupts */
- intr_flag = fmdev->irq_info.mask;
- fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT);
- payload = fmdev->irq_info.mask;
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Start seek */
- payload = FM_TUNER_AUTONOMOUS_SEARCH_MODE;
- ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Wait for tune ended/band limit reached interrupt */
- init_completion(&fmdev->maintask_comp);
- timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
- FM_DRV_RX_SEEK_TIMEOUT);
- if (!timeleft) {
- fmerr("Timeout(%d sec),didn't get tune ended int\n",
- jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000);
- return -ETIMEDOUT;
- }
-
- int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT);
-
- /* Re-enable default FM interrupts */
- fmdev->irq_info.mask = intr_flag;
- payload = fmdev->irq_info.mask;
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- if (int_reason & FM_BL_EVENT) {
- if (wrap_around == 0) {
- fmdev->rx.freq = seek_upward ?
- fmdev->rx.region.top_freq :
- fmdev->rx.region.bot_freq;
- } else {
- fmdev->rx.freq = seek_upward ?
- fmdev->rx.region.bot_freq :
- fmdev->rx.region.top_freq;
- /* Calculate frequency index to write */
- next_frq = (fmdev->rx.freq -
- fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
- goto again;
- }
- } else {
- /* Read freq to know where operation tune operation stopped */
- ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2,
- &curr_frq, &resp_len);
- if (ret < 0)
- return ret;
-
- curr_frq = be16_to_cpu(curr_frq);
- fmdev->rx.freq = (fmdev->rx.region.bot_freq +
- ((u32)curr_frq * FM_FREQ_MUL));
-
- }
- /* Reset RDS cache and current station pointers */
- fm_rx_reset_rds_cache(fmdev);
- fm_rx_reset_station_info(fmdev);
-
- return ret;
-}
-
-int fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
-{
- u16 payload;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (vol_to_set < FM_RX_VOLUME_MIN || vol_to_set > FM_RX_VOLUME_MAX) {
- fmerr("Volume is not within(%d-%d) range\n",
- FM_RX_VOLUME_MIN, FM_RX_VOLUME_MAX);
- return -EINVAL;
- }
- vol_to_set *= FM_RX_VOLUME_GAIN_STEP;
-
- payload = vol_to_set;
- ret = fmc_send_cmd(fmdev, VOLUME_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmdev->rx.volume = vol_to_set;
- return ret;
-}
-
-/* Get volume */
-int fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (curr_vol == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *curr_vol = fmdev->rx.volume / FM_RX_VOLUME_GAIN_STEP;
-
- return 0;
-}
-
-/* To get current band's bottom and top frequency */
-int fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq)
-{
- if (bot_freq != NULL)
- *bot_freq = fmdev->rx.region.bot_freq;
-
- if (top_freq != NULL)
- *top_freq = fmdev->rx.region.top_freq;
-
- return 0;
-}
-
-/* Returns current band index (0-Europe/US; 1-Japan) */
-void fm_rx_get_region(struct fmdev *fmdev, u8 *region)
-{
- *region = fmdev->rx.region.fm_band;
-}
-
-/* Sets band (0-Europe/US; 1-Japan) */
-int fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
-{
- u16 payload;
- u32 new_frq = 0;
- int ret;
-
- if (region_to_set != FM_BAND_EUROPE_US &&
- region_to_set != FM_BAND_JAPAN) {
- fmerr("Invalid band\n");
- return -EINVAL;
- }
-
- if (fmdev->rx.region.fm_band == region_to_set) {
- fmerr("Requested band is already configured\n");
- return 0;
- }
-
- /* Send cmd to set the band */
- payload = (u16)region_to_set;
- ret = fmc_send_cmd(fmdev, BAND_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmc_update_region_info(fmdev, region_to_set);
-
- /* Check whether current RX frequency is within band boundary */
- if (fmdev->rx.freq < fmdev->rx.region.bot_freq)
- new_frq = fmdev->rx.region.bot_freq;
- else if (fmdev->rx.freq > fmdev->rx.region.top_freq)
- new_frq = fmdev->rx.region.top_freq;
-
- if (new_frq) {
- fmdbg("Current freq is not within band limit boundary,"
- "switching to %d KHz\n", new_frq);
- /* Current RX frequency is not in range. So, update it */
- ret = fm_rx_set_freq(fmdev, new_frq);
- }
-
- return ret;
-}
-
-/* Reads current mute mode (Mute Off/On/Attenuate)*/
-int fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (curr_mute_mode == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *curr_mute_mode = fmdev->rx.mute_mode;
-
- return 0;
-}
-
-static int fm_config_rx_mute_reg(struct fmdev *fmdev)
-{
- u16 payload, muteval;
- int ret;
-
- muteval = 0;
- switch (fmdev->rx.mute_mode) {
- case FM_MUTE_ON:
- muteval = FM_RX_AC_MUTE_MODE;
- break;
-
- case FM_MUTE_OFF:
- muteval = FM_RX_UNMUTE_MODE;
- break;
-
- case FM_MUTE_ATTENUATE:
- muteval = FM_RX_SOFT_MUTE_FORCE_MODE;
- break;
- }
- if (fmdev->rx.rf_depend_mute == FM_RX_RF_DEPENDENT_MUTE_ON)
- muteval |= FM_RX_RF_DEP_MODE;
- else
- muteval &= ~FM_RX_RF_DEP_MODE;
-
- payload = muteval;
- ret = fmc_send_cmd(fmdev, MUTE_STATUS_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-/* Configures mute mode (Mute Off/On/Attenuate) */
-int fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
-{
- u8 org_state;
- int ret;
-
- if (fmdev->rx.mute_mode == mute_mode_toset)
- return 0;
-
- org_state = fmdev->rx.mute_mode;
- fmdev->rx.mute_mode = mute_mode_toset;
-
- ret = fm_config_rx_mute_reg(fmdev);
- if (ret < 0) {
- fmdev->rx.mute_mode = org_state;
- return ret;
- }
-
- return 0;
-}
-
-/* Gets RF dependent soft mute mode enable/disable status */
-int fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (curr_mute_mode == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *curr_mute_mode = fmdev->rx.rf_depend_mute;
-
- return 0;
-}
-
-/* Sets RF dependent soft mute mode */
-int fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
-{
- u8 org_state;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_ON &&
- rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_OFF) {
- fmerr("Invalid RF dependent soft mute\n");
- return -EINVAL;
- }
- if (fmdev->rx.rf_depend_mute == rfdepend_mute)
- return 0;
-
- org_state = fmdev->rx.rf_depend_mute;
- fmdev->rx.rf_depend_mute = rfdepend_mute;
-
- ret = fm_config_rx_mute_reg(fmdev);
- if (ret < 0) {
- fmdev->rx.rf_depend_mute = org_state;
- return ret;
- }
-
- return 0;
-}
-
-/* Returns the signal strength level of current channel */
-int fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
-{
- u16 curr_rssi_lel;
- u32 resp_len;
- int ret;
-
- if (rssilvl == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
- /* Read current RSSI level */
- ret = fmc_send_cmd(fmdev, RSSI_LVL_GET, REG_RD, NULL, 2,
- &curr_rssi_lel, &resp_len);
- if (ret < 0)
- return ret;
-
- *rssilvl = be16_to_cpu(curr_rssi_lel);
-
- return 0;
-}
-
-/*
- * Sets the signal strength level that once reached
- * will stop the auto search process
- */
-int fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
-{
- u16 payload;
- int ret;
-
- if (rssi_lvl_toset < FM_RX_RSSI_THRESHOLD_MIN ||
- rssi_lvl_toset > FM_RX_RSSI_THRESHOLD_MAX) {
- fmerr("Invalid RSSI threshold level\n");
- return -EINVAL;
- }
- payload = (u16)rssi_lvl_toset;
- ret = fmc_send_cmd(fmdev, SEARCH_LVL_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmdev->rx.rssi_threshold = rssi_lvl_toset;
-
- return 0;
-}
-
-/* Returns current RX RSSI threshold value */
-int fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (curr_rssi_lvl == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *curr_rssi_lvl = fmdev->rx.rssi_threshold;
-
- return 0;
-}
-
-/* Sets RX stereo/mono modes */
-int fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
-{
- u16 payload;
- int ret;
-
- if (mode != FM_STEREO_MODE && mode != FM_MONO_MODE) {
- fmerr("Invalid mode\n");
- return -EINVAL;
- }
-
- /* Set stereo/mono mode */
- payload = (u16)mode;
- ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Set stereo blending mode */
- payload = FM_STEREO_SOFT_BLEND;
- ret = fmc_send_cmd(fmdev, MOST_BLEND_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-/* Gets current RX stereo/mono mode */
-int fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
-{
- u16 curr_mode;
- u32 resp_len;
- int ret;
-
- if (mode == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_RD, NULL, 2,
- &curr_mode, &resp_len);
- if (ret < 0)
- return ret;
-
- *mode = be16_to_cpu(curr_mode);
-
- return 0;
-}
-
-/* Choose RX de-emphasis filter mode (50us/75us) */
-int fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
-{
- u16 payload;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (mode != FM_RX_EMPHASIS_FILTER_50_USEC &&
- mode != FM_RX_EMPHASIS_FILTER_75_USEC) {
- fmerr("Invalid rx de-emphasis mode (%d)\n", mode);
- return -EINVAL;
- }
-
- payload = mode;
- ret = fmc_send_cmd(fmdev, DEMPH_MODE_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmdev->rx.deemphasis_mode = mode;
-
- return 0;
-}
-
-/* Gets current RX de-emphasis filter mode */
-int fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (curr_deemphasis_mode == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *curr_deemphasis_mode = fmdev->rx.deemphasis_mode;
-
- return 0;
-}
-
-/* Enable/Disable RX RDS */
-int fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
-{
- u16 payload;
- int ret;
-
- if (rds_en_dis != FM_RDS_ENABLE && rds_en_dis != FM_RDS_DISABLE) {
- fmerr("Invalid rds option\n");
- return -EINVAL;
- }
-
- if (rds_en_dis == FM_RDS_ENABLE
- && fmdev->rx.rds.flag == FM_RDS_DISABLE) {
- /* Turn on RX RDS and RDS circuit */
- payload = FM_RX_PWR_SET_FM_AND_RDS_BLK_ON;
- ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Clear and reset RDS FIFO */
- payload = FM_RX_RDS_FLUSH_FIFO;
- ret = fmc_send_cmd(fmdev, RDS_CNTRL_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Read flags - just to clear any pending interrupts. */
- ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2,
- NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Set RDS FIFO threshold value */
- payload = FM_RX_RDS_FIFO_THRESHOLD;
- ret = fmc_send_cmd(fmdev, RDS_MEM_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Enable RDS interrupt */
- fmdev->irq_info.mask |= FM_RDS_EVENT;
- payload = fmdev->irq_info.mask;
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0) {
- fmdev->irq_info.mask &= ~FM_RDS_EVENT;
- return ret;
- }
-
- /* Update our local flag */
- fmdev->rx.rds.flag = FM_RDS_ENABLE;
- } else if (rds_en_dis == FM_RDS_DISABLE
- && fmdev->rx.rds.flag == FM_RDS_ENABLE) {
- /* Turn off RX RDS */
- payload = FM_RX_PWR_SET_FM_ON_RDS_OFF;
- ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Reset RDS pointers */
- fmdev->rx.rds.last_blk_idx = 0;
- fmdev->rx.rds.wr_idx = 0;
- fmdev->rx.rds.rd_idx = 0;
- fm_rx_reset_station_info(fmdev);
-
- /* Update RDS local cache */
- fmdev->irq_info.mask &= ~(FM_RDS_EVENT);
- fmdev->rx.rds.flag = FM_RDS_DISABLE;
- }
-
- return 0;
-}
-
-/* Returns current RX RDS enable/disable status */
-int fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (curr_rds_en_dis == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *curr_rds_en_dis = fmdev->rx.rds.flag;
-
- return 0;
-}
-
-/* Sets RDS operation mode (RDS/RDBS) */
-int fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
-{
- u16 payload;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (rds_mode != FM_RDS_SYSTEM_RDS && rds_mode != FM_RDS_SYSTEM_RBDS) {
- fmerr("Invalid rds mode\n");
- return -EINVAL;
- }
- /* Set RDS operation mode */
- payload = (u16)rds_mode;
- ret = fmc_send_cmd(fmdev, RDS_SYSTEM_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmdev->rx.rds_mode = rds_mode;
-
- return 0;
-}
-
-/* Returns current RDS operation mode */
-int fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (rds_mode == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *rds_mode = fmdev->rx.rds_mode;
-
- return 0;
-}
-
-/* Configures Alternate Frequency switch mode */
-int fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
-{
- u16 payload;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (af_mode != FM_RX_RDS_AF_SWITCH_MODE_ON &&
- af_mode != FM_RX_RDS_AF_SWITCH_MODE_OFF) {
- fmerr("Invalid af mode\n");
- return -EINVAL;
- }
- /* Enable/disable low RSSI interrupt based on af_mode */
- if (af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
- fmdev->irq_info.mask |= FM_LEV_EVENT;
- else
- fmdev->irq_info.mask &= ~FM_LEV_EVENT;
-
- payload = fmdev->irq_info.mask;
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmdev->rx.af_mode = af_mode;
-
- return 0;
-}
-
-/* Returns Alternate Frequency switch status */
-int fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode)
-{
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- if (af_mode == NULL) {
- fmerr("Invalid memory\n");
- return -ENOMEM;
- }
-
- *af_mode = fmdev->rx.af_mode;
-
- return 0;
-}
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.h b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.h
deleted file mode 100644
index 32add81f..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_rx.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- * FM RX module header.
- *
- * Copyright (C) 2011 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef _FMDRV_RX_H
-#define _FMDRV_RX_H
-
-int fm_rx_set_freq(struct fmdev *, u32);
-int fm_rx_set_mute_mode(struct fmdev *, u8);
-int fm_rx_set_stereo_mono(struct fmdev *, u16);
-int fm_rx_set_rds_mode(struct fmdev *, u8);
-int fm_rx_set_rds_system(struct fmdev *, u8);
-int fm_rx_set_volume(struct fmdev *, u16);
-int fm_rx_set_rssi_threshold(struct fmdev *, short);
-int fm_rx_set_region(struct fmdev *, u8);
-int fm_rx_set_rfdepend_softmute(struct fmdev *, u8);
-int fm_rx_set_deemphasis_mode(struct fmdev *, u16);
-int fm_rx_set_af_switch(struct fmdev *, u8);
-
-void fm_rx_reset_rds_cache(struct fmdev *);
-void fm_rx_reset_station_info(struct fmdev *);
-
-int fm_rx_seek(struct fmdev *, u32, u32, u32);
-
-int fm_rx_get_rds_mode(struct fmdev *, u8 *);
-int fm_rx_get_rds_system(struct fmdev *, u8 *);
-int fm_rx_get_mute_mode(struct fmdev *, u8 *);
-int fm_rx_get_volume(struct fmdev *, u16 *);
-int fm_rx_get_band_freq_range(struct fmdev *,
- u32 *, u32 *);
-int fm_rx_get_stereo_mono(struct fmdev *, u16 *);
-int fm_rx_get_rssi_level(struct fmdev *, u16 *);
-int fm_rx_get_rssi_threshold(struct fmdev *, short *);
-int fm_rx_get_rfdepend_softmute(struct fmdev *, u8 *);
-int fm_rx_get_deemph_mode(struct fmdev *, u16 *);
-int fm_rx_get_af_switch(struct fmdev *, u8 *);
-void fm_rx_get_region(struct fmdev *, u8 *);
-
-int fm_rx_set_chanl_spacing(struct fmdev *, u8);
-int fm_rx_get_chanl_spacing(struct fmdev *, u8 *);
-#endif
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.c b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.c
deleted file mode 100644
index 6ea33e09..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- * This sub-module of FM driver implements FM TX functionality.
- *
- * Copyright (C) 2011 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/delay.h>
-#include "fmdrv.h"
-#include "fmdrv_common.h"
-#include "fmdrv_tx.h"
-
-int fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
-{
- u16 payload;
- int ret;
-
- if (fmdev->tx_data.aud_mode == mode)
- return 0;
-
- fmdbg("stereo mode: %d\n", mode);
-
- /* Set Stereo/Mono mode */
- payload = (1 - mode);
- ret = fmc_send_cmd(fmdev, MONO_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fmdev->tx_data.aud_mode = mode;
-
- return ret;
-}
-
-static int set_rds_text(struct fmdev *fmdev, u8 *rds_text)
-{
- u16 payload;
- int ret;
-
- ret = fmc_send_cmd(fmdev, RDS_DATA_SET, REG_WR, rds_text,
- strlen(rds_text), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Scroll mode */
- payload = (u16)0x1;
- ret = fmc_send_cmd(fmdev, DISPLAY_MODE, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int set_rds_data_mode(struct fmdev *fmdev, u8 mode)
-{
- u16 payload;
- int ret;
-
- /* Setting unique PI TODO: how unique? */
- payload = (u16)0xcafe;
- ret = fmc_send_cmd(fmdev, PI_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Set decoder id */
- payload = (u16)0xa;
- ret = fmc_send_cmd(fmdev, DI_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* TODO: RDS_MODE_GET? */
- return 0;
-}
-
-static int set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
-{
- u16 payload;
- int ret;
-
- len |= type << 8;
- payload = len;
- ret = fmc_send_cmd(fmdev, RDS_CONFIG_DATA_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* TODO: LENGTH_GET? */
- return 0;
-}
-
-int fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
-{
- u16 payload;
- int ret;
- u8 rds_text[] = "Zoom2\n";
-
- fmdbg("rds_en_dis:%d(E:%d, D:%d)\n", rds_en_dis,
- FM_RDS_ENABLE, FM_RDS_DISABLE);
-
- if (rds_en_dis == FM_RDS_ENABLE) {
- /* Set RDS length */
- set_rds_len(fmdev, 0, strlen(rds_text));
-
- /* Set RDS text */
- set_rds_text(fmdev, rds_text);
-
- /* Set RDS mode */
- set_rds_data_mode(fmdev, 0x0);
- }
-
- /* Send command to enable RDS */
- if (rds_en_dis == FM_RDS_ENABLE)
- payload = 0x01;
- else
- payload = 0x00;
-
- ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- if (rds_en_dis == FM_RDS_ENABLE) {
- /* Set RDS length */
- set_rds_len(fmdev, 0, strlen(rds_text));
-
- /* Set RDS text */
- set_rds_text(fmdev, rds_text);
- }
- fmdev->tx_data.rds.flag = rds_en_dis;
-
- return 0;
-}
-
-int fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
-{
- u16 payload;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_TX)
- return -EPERM;
-
- fm_tx_set_rds_mode(fmdev, 0);
-
- /* Set RDS length */
- set_rds_len(fmdev, rds_type, strlen(rds_text));
-
- /* Set RDS text */
- set_rds_text(fmdev, rds_text);
-
- /* Set RDS mode */
- set_rds_data_mode(fmdev, 0x0);
-
- payload = 1;
- ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int fm_tx_set_af(struct fmdev *fmdev, u32 af)
-{
- u16 payload;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_TX)
- return -EPERM;
-
- fmdbg("AF: %d\n", af);
-
- af = (af - 87500) / 100;
- payload = (u16)af;
- ret = fmc_send_cmd(fmdev, TA_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int fm_tx_set_region(struct fmdev *fmdev, u8 region)
-{
- u16 payload;
- int ret;
-
- if (region != FM_BAND_EUROPE_US && region != FM_BAND_JAPAN) {
- fmerr("Invalid band\n");
- return -EINVAL;
- }
-
- /* Send command to set the band */
- payload = (u16)region;
- ret = fmc_send_cmd(fmdev, TX_BAND_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
-{
- u16 payload;
- int ret;
-
- fmdbg("tx: mute mode %d\n", mute_mode_toset);
-
- payload = mute_mode_toset;
- ret = fmc_send_cmd(fmdev, MUTE, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-/* Set TX Audio I/O */
-static int set_audio_io(struct fmdev *fmdev)
-{
- struct fmtx_data *tx = &fmdev->tx_data;
- u16 payload;
- int ret;
-
- /* Set Audio I/O Enable */
- payload = tx->audio_io;
- ret = fmc_send_cmd(fmdev, AUDIO_IO_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* TODO: is audio set? */
- return 0;
-}
-
-/* Start TX Transmission */
-static int enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
-{
- struct fmtx_data *tx = &fmdev->tx_data;
- unsigned long timeleft;
- u16 payload;
- int ret;
-
- /* Enable POWER_ENB interrupts */
- payload = FM_POW_ENB_EVENT;
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Set Power Enable */
- payload = new_xmit_state;
- ret = fmc_send_cmd(fmdev, POWER_ENB_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Wait for Power Enabled */
- init_completion(&fmdev->maintask_comp);
- timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
- FM_DRV_TX_TIMEOUT);
- if (!timeleft) {
- fmerr("Timeout(%d sec),didn't get tune ended interrupt\n",
- jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
- return -ETIMEDOUT;
- }
-
- set_bit(FM_CORE_TX_XMITING, &fmdev->flag);
- tx->xmit_state = new_xmit_state;
-
- return 0;
-}
-
-/* Set TX power level */
-int fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
-{
- u16 payload;
- struct fmtx_data *tx = &fmdev->tx_data;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_TX)
- return -EPERM;
- fmdbg("tx: pwr_level_to_set %ld\n", (long int)new_pwr_lvl);
-
- /* If the core isn't ready update global variable */
- if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
- tx->pwr_lvl = new_pwr_lvl;
- return 0;
- }
-
- /* Set power level: Application will specify power level value in
- * units of dB/uV, whereas range and step are specific to FM chip.
- * For TI's WL chips, convert application specified power level value
- * to chip specific value by subtracting 122 from it. Refer to TI FM
- * data sheet for details.
- * */
-
- payload = (FM_PWR_LVL_HIGH - new_pwr_lvl);
- ret = fmc_send_cmd(fmdev, POWER_LEV_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* TODO: is the power level set? */
- tx->pwr_lvl = new_pwr_lvl;
-
- return 0;
-}
-
-/*
- * Sets FM TX pre-emphasis filter value (OFF, 50us, or 75us)
- * Convert V4L2 specified filter values to chip specific filter values.
- */
-int fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
-{
- struct fmtx_data *tx = &fmdev->tx_data;
- u16 payload;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_TX)
- return -EPERM;
-
- switch (preemphasis) {
- case V4L2_PREEMPHASIS_DISABLED:
- payload = FM_TX_PREEMPH_OFF;
- break;
- case V4L2_PREEMPHASIS_50_uS:
- payload = FM_TX_PREEMPH_50US;
- break;
- case V4L2_PREEMPHASIS_75_uS:
- payload = FM_TX_PREEMPH_75US;
- break;
- }
-
- ret = fmc_send_cmd(fmdev, PREMPH_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- tx->preemph = payload;
-
- return ret;
-}
-
-/* Get the TX tuning capacitor value.*/
-int fm_tx_get_tune_cap_val(struct fmdev *fmdev)
-{
- u16 curr_val;
- u32 resp_len;
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_TX)
- return -EPERM;
-
- ret = fmc_send_cmd(fmdev, READ_FMANT_TUNE_VALUE, REG_RD,
- NULL, sizeof(curr_val), &curr_val, &resp_len);
- if (ret < 0)
- return ret;
-
- curr_val = be16_to_cpu(curr_val);
-
- return curr_val;
-}
-
-/* Set TX Frequency */
-int fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set)
-{
- struct fmtx_data *tx = &fmdev->tx_data;
- u16 payload, chanl_index;
- int ret;
-
- if (test_bit(FM_CORE_TX_XMITING, &fmdev->flag)) {
- enable_xmit(fmdev, 0);
- clear_bit(FM_CORE_TX_XMITING, &fmdev->flag);
- }
-
- /* Enable FR, BL interrupts */
- payload = (FM_FR_EVENT | FM_BL_EVENT);
- ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- tx->tx_frq = (unsigned long)freq_to_set;
- fmdbg("tx: freq_to_set %ld\n", (long int)tx->tx_frq);
-
- chanl_index = freq_to_set / 10;
-
- /* Set current tuner channel */
- payload = chanl_index;
- ret = fmc_send_cmd(fmdev, CHANL_SET, REG_WR, &payload,
- sizeof(payload), NULL, NULL);
- if (ret < 0)
- return ret;
-
- fm_tx_set_pwr_lvl(fmdev, tx->pwr_lvl);
- fm_tx_set_preemph_filter(fmdev, tx->preemph);
-
- tx->audio_io = 0x01; /* I2S */
- set_audio_io(fmdev);
-
- enable_xmit(fmdev, 0x01); /* Enable transmission */
-
- tx->aud_mode = FM_STEREO_MODE;
- tx->rds.flag = FM_RDS_DISABLE;
-
- return 0;
-}
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.h b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.h
deleted file mode 100644
index 11ae2e4c..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_tx.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- * FM TX module header.
- *
- * Copyright (C) 2011 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef _FMDRV_TX_H
-#define _FMDRV_TX_H
-
-int fm_tx_set_freq(struct fmdev *, u32);
-int fm_tx_set_pwr_lvl(struct fmdev *, u8);
-int fm_tx_set_region(struct fmdev *, u8);
-int fm_tx_set_mute_mode(struct fmdev *, u8);
-int fm_tx_set_stereo_mono(struct fmdev *, u16);
-int fm_tx_set_rds_mode(struct fmdev *, u8);
-int fm_tx_set_radio_text(struct fmdev *, u8 *, u8);
-int fm_tx_set_af(struct fmdev *, u32);
-int fm_tx_set_preemph_filter(struct fmdev *, u32);
-int fm_tx_get_tune_cap_val(struct fmdev *);
-
-#endif
-
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.c b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.c
deleted file mode 100644
index 077d369a..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- * This file provides interfaces to V4L2 subsystem.
- *
- * This module registers with V4L2 subsystem as Radio
- * data system interface (/dev/radio). During the registration,
- * it will expose two set of function pointers.
- *
- * 1) File operation related API (open, close, read, write, poll...etc).
- * 2) Set of V4L2 IOCTL complaint API.
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Raja Mani <raja_mani@ti.com>
- * Author: Manjunatha Halli <manjunatha_halli@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/export.h>
-
-#include "fmdrv.h"
-#include "fmdrv_v4l2.h"
-#include "fmdrv_common.h"
-#include "fmdrv_rx.h"
-#include "fmdrv_tx.h"
-
-static struct video_device *gradio_dev;
-static u8 radio_disconnected;
-
-/* -- V4L2 RADIO (/dev/radioX) device file operation interfaces --- */
-
-/* Read RX RDS data */
-static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
- size_t count, loff_t *ppos)
-{
- u8 rds_mode;
- int ret;
- struct fmdev *fmdev;
-
- fmdev = video_drvdata(file);
-
- if (!radio_disconnected) {
- fmerr("FM device is already disconnected\n");
- return -EIO;
- }
-
- /* Turn on RDS mode , if it is disabled */
- ret = fm_rx_get_rds_mode(fmdev, &rds_mode);
- if (ret < 0) {
- fmerr("Unable to read current rds mode\n");
- return ret;
- }
-
- if (rds_mode == FM_RDS_DISABLE) {
- ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
- if (ret < 0) {
- fmerr("Failed to enable rds mode\n");
- return ret;
- }
- }
-
- /* Copy RDS data from internal buffer to user buffer */
- return fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
-}
-
-/* Write TX RDS data */
-static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
- size_t count, loff_t *ppos)
-{
- struct tx_rds rds;
- int ret;
- struct fmdev *fmdev;
-
- ret = copy_from_user(&rds, buf, sizeof(rds));
- rds.text[sizeof(rds.text) - 1] = '\0';
- fmdbg("(%d)type: %d, text %s, af %d\n",
- ret, rds.text_type, rds.text, rds.af_freq);
- if (ret)
- return -EFAULT;
-
- fmdev = video_drvdata(file);
- fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
- fm_tx_set_af(fmdev, rds.af_freq);
-
- return sizeof(rds);
-}
-
-static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
-{
- int ret;
- struct fmdev *fmdev;
-
- fmdev = video_drvdata(file);
- ret = fmc_is_rds_data_available(fmdev, file, pts);
- if (ret < 0)
- return POLLIN | POLLRDNORM;
-
- return 0;
-}
-
-/*
- * Handle open request for "/dev/radioX" device.
- * Start with FM RX mode as default.
- */
-static int fm_v4l2_fops_open(struct file *file)
-{
- int ret;
- struct fmdev *fmdev = NULL;
-
- /* Don't allow multiple open */
- if (radio_disconnected) {
- fmerr("FM device is already opened\n");
- return -EBUSY;
- }
-
- fmdev = video_drvdata(file);
-
- ret = fmc_prepare(fmdev);
- if (ret < 0) {
- fmerr("Unable to prepare FM CORE\n");
- return ret;
- }
-
- fmdbg("Load FM RX firmware..\n");
-
- ret = fmc_set_mode(fmdev, FM_MODE_RX);
- if (ret < 0) {
- fmerr("Unable to load FM RX firmware\n");
- return ret;
- }
- radio_disconnected = 1;
-
- return ret;
-}
-
-static int fm_v4l2_fops_release(struct file *file)
-{
- int ret;
- struct fmdev *fmdev;
-
- fmdev = video_drvdata(file);
- if (!radio_disconnected) {
- fmdbg("FM device is already closed\n");
- return 0;
- }
-
- ret = fmc_set_mode(fmdev, FM_MODE_OFF);
- if (ret < 0) {
- fmerr("Unable to turn off the chip\n");
- return ret;
- }
-
- ret = fmc_release(fmdev);
- if (ret < 0) {
- fmerr("FM CORE release failed\n");
- return ret;
- }
- radio_disconnected = 0;
-
- return ret;
-}
-
-/* V4L2 RADIO (/dev/radioX) device IOCTL interfaces */
-static int fm_v4l2_vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *capability)
-{
- strlcpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver));
- strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME,
- sizeof(capability->card));
- sprintf(capability->bus_info, "UART");
- capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
- V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
- V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
- V4L2_CAP_RDS_CAPTURE;
-
- return 0;
-}
-
-static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct fmdev *fmdev = container_of(ctrl->handler,
- struct fmdev, ctrl_handler);
-
- switch (ctrl->id) {
- case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
- ctrl->val = fm_tx_get_tune_cap_val(fmdev);
- break;
- default:
- fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
- break;
- }
-
- return 0;
-}
-
-static int fm_v4l2_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct fmdev *fmdev = container_of(ctrl->handler,
- struct fmdev, ctrl_handler);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_VOLUME: /* set volume */
- return fm_rx_set_volume(fmdev, (u16)ctrl->val);
-
- case V4L2_CID_AUDIO_MUTE: /* set mute */
- return fmc_set_mute_mode(fmdev, (u8)ctrl->val);
-
- case V4L2_CID_TUNE_POWER_LEVEL:
- /* set TX power level - ext control */
- return fm_tx_set_pwr_lvl(fmdev, (u8)ctrl->val);
-
- case V4L2_CID_TUNE_PREEMPHASIS:
- return fm_tx_set_preemph_filter(fmdev, (u8) ctrl->val);
-
- default:
- return -EINVAL;
- }
-}
-
-static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- memset(audio, 0, sizeof(*audio));
- strcpy(audio->name, "Radio");
- audio->capability = V4L2_AUDCAP_STEREO;
-
- return 0;
-}
-
-static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- if (audio->index != 0)
- return -EINVAL;
-
- return 0;
-}
-
-/* Get tuner attributes. If current mode is NOT RX, return error */
-static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- struct fmdev *fmdev = video_drvdata(file);
- u32 bottom_freq;
- u32 top_freq;
- u16 stereo_mono_mode;
- u16 rssilvl;
- int ret;
-
- if (tuner->index != 0)
- return -EINVAL;
-
- if (fmdev->curr_fmmode != FM_MODE_RX)
- return -EPERM;
-
- ret = fm_rx_get_band_freq_range(fmdev, &bottom_freq, &top_freq);
- if (ret != 0)
- return ret;
-
- ret = fm_rx_get_stereo_mono(fmdev, &stereo_mono_mode);
- if (ret != 0)
- return ret;
-
- ret = fm_rx_get_rssi_level(fmdev, &rssilvl);
- if (ret != 0)
- return ret;
-
- strcpy(tuner->name, "FM");
- tuner->type = V4L2_TUNER_RADIO;
- /* Store rangelow and rangehigh freq in unit of 62.5 Hz */
- tuner->rangelow = bottom_freq * 16;
- tuner->rangehigh = top_freq * 16;
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO |
- ((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
- tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
- V4L2_TUNER_CAP_LOW;
- tuner->audmode = (stereo_mono_mode ?
- V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);
-
- /*
- * Actual rssi value lies in between -128 to +127.
- * Convert this range from 0 to 255 by adding +128
- */
- rssilvl += 128;
-
- /*
- * Return signal strength value should be within 0 to 65535.
- * Find out correct signal radio by multiplying (65535/255) = 257
- */
- tuner->signal = rssilvl * 257;
- tuner->afc = 0;
-
- return ret;
-}
-
-/*
- * Set tuner attributes. If current mode is NOT RX, set to RX.
- * Currently, we set only audio mode (mono/stereo) and RDS state (on/off).
- * Should we set other tuner attributes, too?
- */
-static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *tuner)
-{
- struct fmdev *fmdev = video_drvdata(file);
- u16 aud_mode;
- u8 rds_mode;
- int ret;
-
- if (tuner->index != 0)
- return -EINVAL;
-
- aud_mode = (tuner->audmode == V4L2_TUNER_MODE_STEREO) ?
- FM_STEREO_MODE : FM_MONO_MODE;
- rds_mode = (tuner->rxsubchans & V4L2_TUNER_SUB_RDS) ?
- FM_RDS_ENABLE : FM_RDS_DISABLE;
-
- if (fmdev->curr_fmmode != FM_MODE_RX) {
- ret = fmc_set_mode(fmdev, FM_MODE_RX);
- if (ret < 0) {
- fmerr("Failed to set RX mode\n");
- return ret;
- }
- }
-
- ret = fmc_set_stereo_mono(fmdev, aud_mode);
- if (ret < 0) {
- fmerr("Failed to set RX stereo/mono mode\n");
- return ret;
- }
-
- ret = fmc_set_rds_mode(fmdev, rds_mode);
- if (ret < 0)
- fmerr("Failed to set RX RDS mode\n");
-
- return ret;
-}
-
-/* Get tuner or modulator radio frequency */
-static int fm_v4l2_vidioc_g_freq(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct fmdev *fmdev = video_drvdata(file);
- int ret;
-
- ret = fmc_get_freq(fmdev, &freq->frequency);
- if (ret < 0) {
- fmerr("Failed to get frequency\n");
- return ret;
- }
-
- /* Frequency unit of 62.5 Hz*/
- freq->frequency = (u32) freq->frequency * 16;
-
- return 0;
-}
-
-/* Set tuner or modulator radio frequency */
-static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
- struct v4l2_frequency *freq)
-{
- struct fmdev *fmdev = video_drvdata(file);
-
- /*
- * As V4L2_TUNER_CAP_LOW is set 1 user sends the frequency
- * in units of 62.5 Hz.
- */
- freq->frequency = (u32)(freq->frequency / 16);
-
- return fmc_set_freq(fmdev, freq->frequency);
-}
-
-/* Set hardware frequency seek. If current mode is NOT RX, set it RX. */
-static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
- struct v4l2_hw_freq_seek *seek)
-{
- struct fmdev *fmdev = video_drvdata(file);
- int ret;
-
- if (fmdev->curr_fmmode != FM_MODE_RX) {
- ret = fmc_set_mode(fmdev, FM_MODE_RX);
- if (ret != 0) {
- fmerr("Failed to set RX mode\n");
- return ret;
- }
- }
-
- ret = fm_rx_seek(fmdev, seek->seek_upward, seek->wrap_around,
- seek->spacing);
- if (ret < 0)
- fmerr("RX seek failed - %d\n", ret);
-
- return ret;
-}
-/* Get modulator attributes. If mode is not TX, return no attributes. */
-static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
- struct v4l2_modulator *mod)
-{
- struct fmdev *fmdev = video_drvdata(file);
-
- if (mod->index != 0)
- return -EINVAL;
-
- if (fmdev->curr_fmmode != FM_MODE_TX)
- return -EPERM;
-
- mod->txsubchans = ((fmdev->tx_data.aud_mode == FM_STEREO_MODE) ?
- V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO) |
- ((fmdev->tx_data.rds.flag == FM_RDS_ENABLE) ?
- V4L2_TUNER_SUB_RDS : 0);
-
- mod->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
- V4L2_TUNER_CAP_LOW;
-
- return 0;
-}
-
-/* Set modulator attributes. If mode is not TX, set to TX. */
-static int fm_v4l2_vidioc_s_modulator(struct file *file, void *priv,
- struct v4l2_modulator *mod)
-{
- struct fmdev *fmdev = video_drvdata(file);
- u8 rds_mode;
- u16 aud_mode;
- int ret;
-
- if (mod->index != 0)
- return -EINVAL;
-
- if (fmdev->curr_fmmode != FM_MODE_TX) {
- ret = fmc_set_mode(fmdev, FM_MODE_TX);
- if (ret != 0) {
- fmerr("Failed to set TX mode\n");
- return ret;
- }
- }
-
- aud_mode = (mod->txsubchans & V4L2_TUNER_SUB_STEREO) ?
- FM_STEREO_MODE : FM_MONO_MODE;
- rds_mode = (mod->txsubchans & V4L2_TUNER_SUB_RDS) ?
- FM_RDS_ENABLE : FM_RDS_DISABLE;
- ret = fm_tx_set_stereo_mono(fmdev, aud_mode);
- if (ret < 0) {
- fmerr("Failed to set mono/stereo mode for TX\n");
- return ret;
- }
- ret = fm_tx_set_rds_mode(fmdev, rds_mode);
- if (ret < 0)
- fmerr("Failed to set rds mode for TX\n");
-
- return ret;
-}
-
-static const struct v4l2_file_operations fm_drv_fops = {
- .owner = THIS_MODULE,
- .read = fm_v4l2_fops_read,
- .write = fm_v4l2_fops_write,
- .poll = fm_v4l2_fops_poll,
- .unlocked_ioctl = video_ioctl2,
- .open = fm_v4l2_fops_open,
- .release = fm_v4l2_fops_release,
-};
-
-static const struct v4l2_ctrl_ops fm_ctrl_ops = {
- .s_ctrl = fm_v4l2_s_ctrl,
- .g_volatile_ctrl = fm_g_volatile_ctrl,
-};
-static const struct v4l2_ioctl_ops fm_drv_ioctl_ops = {
- .vidioc_querycap = fm_v4l2_vidioc_querycap,
- .vidioc_g_audio = fm_v4l2_vidioc_g_audio,
- .vidioc_s_audio = fm_v4l2_vidioc_s_audio,
- .vidioc_g_tuner = fm_v4l2_vidioc_g_tuner,
- .vidioc_s_tuner = fm_v4l2_vidioc_s_tuner,
- .vidioc_g_frequency = fm_v4l2_vidioc_g_freq,
- .vidioc_s_frequency = fm_v4l2_vidioc_s_freq,
- .vidioc_s_hw_freq_seek = fm_v4l2_vidioc_s_hw_freq_seek,
- .vidioc_g_modulator = fm_v4l2_vidioc_g_modulator,
- .vidioc_s_modulator = fm_v4l2_vidioc_s_modulator
-};
-
-/* V4L2 RADIO device parent structure */
-static struct video_device fm_viddev_template = {
- .fops = &fm_drv_fops,
- .ioctl_ops = &fm_drv_ioctl_ops,
- .name = FM_DRV_NAME,
- .release = video_device_release,
-};
-
-int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
-{
- struct v4l2_ctrl *ctrl;
- int ret;
-
- /* Init mutex for core locking */
- mutex_init(&fmdev->mutex);
-
- /* Allocate new video device */
- gradio_dev = video_device_alloc();
- if (NULL == gradio_dev) {
- fmerr("Can't allocate video device\n");
- return -ENOMEM;
- }
-
- /* Setup FM driver's V4L2 properties */
- memcpy(gradio_dev, &fm_viddev_template, sizeof(fm_viddev_template));
-
- video_set_drvdata(gradio_dev, fmdev);
-
- gradio_dev->lock = &fmdev->mutex;
-
- /* Register with V4L2 subsystem as RADIO device */
- if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
- video_device_release(gradio_dev);
- fmerr("Could not register video device\n");
- return -ENOMEM;
- }
-
- fmdev->radio_dev = gradio_dev;
-
- /* Register to v4l2 ctrl handler framework */
- fmdev->radio_dev->ctrl_handler = &fmdev->ctrl_handler;
-
- ret = v4l2_ctrl_handler_init(&fmdev->ctrl_handler, 5);
- if (ret < 0) {
- fmerr("(fmdev): Can't init ctrl handler\n");
- v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
- return -EBUSY;
- }
-
- /*
- * Following controls are handled by V4L2 control framework.
- * Added in ascending ID order.
- */
- v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
- V4L2_CID_AUDIO_VOLUME, FM_RX_VOLUME_MIN,
- FM_RX_VOLUME_MAX, 1, FM_RX_VOLUME_MAX);
-
- v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
- V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
-
- v4l2_ctrl_new_std_menu(&fmdev->ctrl_handler, &fm_ctrl_ops,
- V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS,
- 0, V4L2_PREEMPHASIS_75_uS);
-
- v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
- V4L2_CID_TUNE_POWER_LEVEL, FM_PWR_LVL_LOW,
- FM_PWR_LVL_HIGH, 1, FM_PWR_LVL_HIGH);
-
- ctrl = v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
- V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0,
- 255, 1, 255);
-
- if (ctrl)
- ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
-
- return 0;
-}
-
-void *fm_v4l2_deinit_video_device(void)
-{
- struct fmdev *fmdev;
-
-
- fmdev = video_get_drvdata(gradio_dev);
-
- /* Unregister to v4l2 ctrl handler framework*/
- v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
-
- /* Unregister RADIO device from V4L2 subsystem */
- video_unregister_device(gradio_dev);
-
- return fmdev;
-}
diff --git a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.h b/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.h
deleted file mode 100644
index 0ba79d74..00000000
--- a/ANDROID_3.4.5/drivers/media/radio/wl128x/fmdrv_v4l2.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * FM Driver for Connectivity chip of Texas Instruments.
- *
- * FM V4L2 module header.
- *
- * Copyright (C) 2011 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef _FMDRV_V4L2_H
-#define _FMDRV_V4L2_H
-
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
-
-int fm_v4l2_init_video_device(struct fmdev *, int);
-void *fm_v4l2_deinit_video_device(void);
-
-#endif