diff options
Diffstat (limited to 'drivers/media/radio/stfm1000/stfm1000.h')
-rw-r--r-- | drivers/media/radio/stfm1000/stfm1000.h | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/drivers/media/radio/stfm1000/stfm1000.h b/drivers/media/radio/stfm1000/stfm1000.h new file mode 100644 index 000000000000..5ae6f38db3b0 --- /dev/null +++ b/drivers/media/radio/stfm1000/stfm1000.h @@ -0,0 +1,254 @@ +/* + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef STFM1000_H +#define STFM1000_H + +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <linux/i2c.h> +#include <linux/list.h> +#include <linux/wait.h> +#include <linux/irq.h> +#include <media/videobuf-dma-sg.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <mach/dma.h> + +#include "stfm1000-regs.h" + +#include "stfm1000-filter.h" +#include "stfm1000-rds.h" + +struct stfm1000 { + struct list_head devlist; + int idx; + + struct i2c_client *client; + struct video_device radio; + + /* alsa */ + struct snd_card *card; + struct snd_pcm *pcm; + struct snd_pcm_substream *substream; + struct stmp3xxx_dma_descriptor *dma; + int desc_num; + int dma_ch; + int dma_irq; + int attn_irq; + + struct mutex state_lock; + int read_count; + int read_offset; + int blocks; + int blksize; + int bufsize; + + struct mutex deffered_work_lock; + struct execute_work snd_capture_start_work; + struct execute_work snd_capture_stop_work; + + int now_recording; + int alsa_initialized; + int stopping_recording; + + /* actual DRI buffer */ + dma_addr_t dri_phys; + void *dri_buf; + int dri_bufsz; + + /* various */ + u16 curvol; + int users; + int removed; + struct mutex xfer_lock; + u8 revid; + + unsigned int dbgflg; + + /* shadow registers */ + u32 shadow_regs[STFM1000_NUM_REGS]; + u32 reg_rw_set[(STFM1000_NUM_REGS + 31) / 32]; + u32 reg_ra_set[(STFM1000_NUM_REGS + 31) / 32]; + u32 reg_dirty_set[(STFM1000_NUM_REGS + 31) / 32]; + + /* tuning parameters (not everything is used for now) */ + u16 tune_rssi_th; /* sd_ctl_TuneRssiTh_u16 */ + u16 tune_mpx_dc_th; /* sd_ctl_TuneMpxDcTh_u16 */ + u16 adj_chan_th; /* sd_ctl_AdjChanTh_u16 */ + u16 pilot_est_th; /* sd_ctl_PilotEstTh_u16 */ + u16 coef_lna_turn_off_th; /* sd_ctl_pCoefLnaTurnOffTh_u16 */ + u16 coef_lna_turn_on_th; /* sd_ctl_pCoefLnaTurnOnTh_u16 */ + u16 reg_agc_ref_lna_off; /* sd_ctl_pRegAgcRefLnaOff_u16 */ + u16 reg_agc_ref_lna_on; /* sd_ctl_pRegAgcRefLnaOn_u16 */ + + u32 sdnominal_pivot; /* sd_ctl_SdnominalData_u32 */ + + /* jiffies of the next monitor cycle */ + unsigned long next_quality_monitor; + unsigned long next_agc_monitor; + + unsigned int mute : 1; /* XXX */ + unsigned int lna_driving : 1; /* sd_ctl_LnaDriving_u1 */ + unsigned int weak_signal : 1; /* sd_ctl_WeakSignal_u1 */ + unsigned int is_station : 1; /* XXX */ + unsigned int force_mono : 1; /* XXX */ + unsigned int signal_indicator : 1; /* XXX */ + unsigned int stereo_indicator : 1; /* XXX */ + unsigned int agc_monitor : 1; /* XXX */ + unsigned int quality_monitor : 1; /* XXX */ + unsigned int pilot_present : 1; /* sd_ctl_PilotPresent_u1 */ + unsigned int prev_pilot_present : 1; /* XXX */ + unsigned int stereo : 1; + unsigned int active : 1; /* set when audio enabled */ + unsigned int rds_enable : 1; /* set when rds is enabled */ + unsigned int rds_present : 1; /* RDS info present */ + unsigned int rds_sync : 1; /* RDS force sync */ + unsigned int rds_demod_running : 1; /* RDS demod is running ATM */ + unsigned int rds_sdnominal_adapt : 1; /* adapt for better recept. */ + unsigned int rds_phase_pop : 1; /* enable phase pop */ + unsigned int rds_info : 1; /* print debugging info RDS */ + unsigned int tuning_grid_50KHz : 1; /* tuning grid of 50Khz */ + u32 rssi; /* rssi last decoded frame */ + u16 rssi_dc_est_log; + u16 signal_strength; /* is rssi_dc_est_log */ + u16 rds_signal_th; /* RDS threshold */ + s16 mpx_dc; /* sd_ctl_ShadowToneData_i16 */ + + u32 tune_cap_a_f; /* float! sd_ctl_TuneCapA_f */ + u32 tune_cap_b_f; /* float! sd_ctl_TuneCapB_f */ + + int monitor_period; /* period of the monitor */ + int quality_monitor_period; /* update period in ms */ + int agc_monitor_period; /* update period in ms */ + + int georegion; /* current graphical region */ + + /* last tuned frequency */ + int freq; /* 88.0 = 8800 */ + + /* weak signal processing filter state */ + struct stfm1000_filter_parms filter_parms; + + /* state of rds */ + spinlock_t rds_lock; + struct stfm1000_rds_state rds_state; + unsigned int rds_pkt_bad; + unsigned int rds_pkt_good; + unsigned int rds_pkt_recovered; + unsigned int rds_pkt_lost_sync; + unsigned int rds_bit_overruns; + + /* monitor thread */ + wait_queue_head_t thread_wait; + unsigned long thread_events; + struct task_struct *thread; +}; + +#define EVENT_RDS_BITS 0 +#define EVENT_RDS_MIXFILT 1 +#define EVENT_RDS_SDNOMINAL 2 +#define EVENT_RDS_RESET 3 + +#define STFM1000_DBGFLG_I2C (1 << 0) + +static inline struct stfm1000 *stfm1000_from_file(struct file *file) +{ + return container_of(video_devdata(file), struct stfm1000, radio); +} + +/* in stfm1000-i2c.c */ + +/* setup reg set */ +void stfm1000_setup_reg_set(struct stfm1000 *stfm1000); + +/* direct access to registers bypassing the shadow register set */ +int stfm1000_raw_read(struct stfm1000 *stfm1000, int reg, u32 *value); +int stfm1000_raw_write(struct stfm1000 *stfm1000, int reg, u32 value); + +/* access using the shadow register set */ +int stfm1000_write(struct stfm1000 *stfm1000, int reg, u32 value); +int stfm1000_read(struct stfm1000 *stfm1000, int reg, u32 *value); +int stfm1000_write_masked(struct stfm1000 *stfm1000, int reg, u32 value, + u32 mask); +int stfm1000_set_bits(struct stfm1000 *stfm1000, int reg, u32 value); +int stfm1000_clear_bits(struct stfm1000 *stfm1000, int reg, u32 value); + +struct stfm1000_reg { + unsigned int regno; + u32 value; +}; + +#define STFM1000_REG_END -1 +#define STFM1000_REG_DELAY -2 + +#define STFM1000_REG_SET_BITS_MASK 0x1000 +#define STFM1000_REG_CLEAR_BITS_MASK 0x2000 + +#define STFM1000_REG(r, v) \ + { .regno = STFM1000_ ## r , .value = (v) } + +#define STFM1000_END \ + { .regno = STFM1000_REG_END } + +#define STFM1000_DELAY(x) \ + { .regno = STFM1000_REG_DELAY, .value = (x) } + +#define STFM1000_REG_SETBITS(r, v) \ + { .regno = STFM1000_ ## r | STFM1000_REG_SET_BITS_MASK, \ + .value = (v) } + +#define STFM1000_REG_CLRBITS(r, v) \ + { .regno = STFM1000_ ## r | STFM1000_REG_CLEAR_BITS_MASK, \ + .value = (v) } + +int stfm1000_write_regs(struct stfm1000 *stfm1000, + const struct stfm1000_reg *reg); + +/* in stfm1000-precalc.c */ +extern const struct stfm1000_tune1 +stfm1000_tune1_table[STFM1000_FREQUENCY_100KHZ_RANGE]; + +/* exported for use by alsa driver */ + +struct stfm1000_dri_sample { + /* L+R */ + u16 l_plus_r; + /* L-R */ + u16 l_minus_r; + /* Rx signal strength channel */ + u16 rssi; + /* Radio data service channel */ + u16 rds; +}; + +struct stfm1000_alsa_ops { + int (*init)(struct stfm1000 *stfm1000); + void (*release)(struct stfm1000 *stfm1000); + void (*dma_irq)(struct stfm1000 *stfm1000); + void (*attn_irq)(struct stfm1000 *stfm1000); +}; + +extern struct list_head stfm1000_devlist; +extern struct stfm1000_alsa_ops *stfm1000_alsa_ops; + +/* needed for setting the interrupt handlers from alsa */ +irqreturn_t stfm1000_dri_attn_irq(int irq, void *dev_id); +irqreturn_t stfm1000_dri_dma_irq(int irq, void *dev_id); +void stfm1000_decode_block(struct stfm1000 *stfm1000, const s16 *src, s16 *dst, int count); +void stfm1000_take_down(struct stfm1000 *stfm1000); +void stfm1000_bring_up(struct stfm1000 *stfm1000); +void stfm1000_tune_current(struct stfm1000 *stfm1000); + +void stfm1000_monitor_signal(struct stfm1000 *stfm1000, int bit); + +#endif |