diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/media/radio')
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 = >->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 ? >->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, ®ion_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 |