diff options
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/cx88-alsa.c | 117 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 16 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 44 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 30 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dsp.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 181 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-i2c.c | 31 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 57 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 6 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-tvaudio.c | 43 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vbi.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 86 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vp3054-i2c.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 74 |
14 files changed, 464 insertions, 236 deletions
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 4f383cd..4aaa47c 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -40,6 +40,7 @@ #include <sound/control.h> #include <sound/initval.h> #include <sound/tlv.h> +#include <media/wm8775.h> #include "cx88.h" #include "cx88-reg.h" @@ -94,7 +95,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t; ****************************************************************************/ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(enable, bool, NULL, 0444); @@ -131,7 +132,7 @@ static int _cx88_start_audio_dma(snd_cx88_card_t *chip) { struct cx88_audio_buffer *buf = chip->buf; struct cx88_core *core=chip->core; - struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; + const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ cx_clear(MO_AUD_DMACNTRL, 0x11); @@ -197,7 +198,7 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) /* * BOARD Specific: IRQ dma bits */ -static char *cx88_aud_irqs[32] = { +static const char *cx88_aud_irqs[32] = { "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ NULL, /* reserved */ "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ @@ -308,7 +309,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) * Digital hardware definition */ #define DEFAULT_FIFO_SIZE 4096 -static struct snd_pcm_hardware snd_cx88_digital_hw = { +static const struct snd_pcm_hardware snd_cx88_digital_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -533,7 +534,7 @@ static struct snd_pcm_ops snd_cx88_pcm_ops = { /* * create a PCM device */ -static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) +static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name) { int err; struct snd_pcm *pcm; @@ -586,26 +587,47 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, int left, right, v, b; int changed = 0; u32 old; + struct v4l2_control client_ctl; + + /* Pass volume & balance onto any WM8775 */ + if (value->value.integer.value[0] >= value->value.integer.value[1]) { + v = value->value.integer.value[0] << 10; + b = value->value.integer.value[0] ? + (0x8000 * value->value.integer.value[1]) / value->value.integer.value[0] : + 0x8000; + } else { + v = value->value.integer.value[1] << 10; + b = value->value.integer.value[1] ? + 0xffff - (0x8000 * value->value.integer.value[0]) / value->value.integer.value[1] : + 0x8000; + } + client_ctl.value = v; + client_ctl.id = V4L2_CID_AUDIO_VOLUME; + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); + + client_ctl.value = b; + client_ctl.id = V4L2_CID_AUDIO_BALANCE; + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); left = value->value.integer.value[0] & 0x3f; right = value->value.integer.value[1] & 0x3f; b = right - left; if (b < 0) { - v = 0x3f - left; - b = (-b) | 0x40; + v = 0x3f - left; + b = (-b) | 0x40; } else { - v = 0x3f - right; + v = 0x3f - right; } /* Do we really know this will always be called with IRQs on? */ spin_lock_irq(&chip->reg_lock); old = cx_read(AUD_VOL_CTL); if (v != (old & 0x3f)) { - cx_write(AUD_VOL_CTL, (old & ~0x3f) | v); - changed = 1; + cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v); + changed = 1; } - if (cx_read(AUD_BAL_CTL) != b) { - cx_write(AUD_BAL_CTL, b); - changed = 1; + if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) { + cx_write(AUD_BAL_CTL, b); + changed = 1; } spin_unlock_irq(&chip->reg_lock); @@ -614,11 +636,11 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0); -static struct snd_kcontrol_new snd_cx88_volume = { +static const struct snd_kcontrol_new snd_cx88_volume = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Playback Volume", + .name = "Analog-TV Volume", .info = snd_cx88_volume_info, .get = snd_cx88_volume_get, .put = snd_cx88_volume_put, @@ -649,31 +671,74 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, vol = cx_read(AUD_VOL_CTL); if (value->value.integer.value[0] != !(vol & bit)) { vol ^= bit; - cx_write(AUD_VOL_CTL, vol); + cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); + /* Pass mute onto any WM8775 */ + if ((1<<6) == bit) { + struct v4l2_control client_ctl; + client_ctl.value = 0 != (vol & bit); + client_ctl.id = V4L2_CID_AUDIO_MUTE; + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); + } ret = 1; } spin_unlock_irq(&chip->reg_lock); return ret; } -static struct snd_kcontrol_new snd_cx88_dac_switch = { +static const struct snd_kcontrol_new snd_cx88_dac_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Playback Switch", + .name = "Audio-Out Switch", .info = snd_ctl_boolean_mono_info, .get = snd_cx88_switch_get, .put = snd_cx88_switch_put, .private_value = (1<<8), }; -static struct snd_kcontrol_new snd_cx88_source_switch = { +static const struct snd_kcontrol_new snd_cx88_source_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Switch", + .name = "Analog-TV Switch", .info = snd_ctl_boolean_mono_info, .get = snd_cx88_switch_get, .put = snd_cx88_switch_put, .private_value = (1<<6), }; +static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) +{ + snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); + struct cx88_core *core = chip->core; + struct v4l2_control client_ctl; + + client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; + call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl); + value->value.integer.value[0] = client_ctl.value ? 1 : 0; + + return 0; +} + +static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) +{ + snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); + struct cx88_core *core = chip->core; + struct v4l2_control client_ctl; + + client_ctl.value = 0 != value->value.integer.value[0]; + client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); + + return 0; +} + +static struct snd_kcontrol_new snd_cx88_alc_switch = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-In ALC Switch", + .info = snd_ctl_boolean_mono_info, + .get = snd_cx88_alc_get, + .put = snd_cx88_alc_put, +}; + /**************************************************************************** Basic Flow for Sound Devices ****************************************************************************/ @@ -683,7 +748,7 @@ static struct snd_kcontrol_new snd_cx88_source_switch = { * Only boards with eeprom and byte 1 at eeprom=1 have it */ -static struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = { +static const struct pci_device_id const cx88_audio_pci_tbl[] __devinitdata = { {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0, } @@ -795,6 +860,7 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, { struct snd_card *card; snd_cx88_card_t *chip; + struct v4l2_subdev *sd; int err; if (devno >= SNDRV_CARDS) @@ -830,6 +896,15 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, if (err < 0) goto error; + /* If there's a wm8775 then add a Line-In ALC switch */ + list_for_each_entry(sd, &chip->core->v4l2_dev.subdevs, list) { + if (WM8775_GID == sd->grp_id) { + snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, + chip)); + break; + } + } + strcpy (card->driver, "CX88x"); sprintf(card->shortname, "Conexant CX%x", pci->device); sprintf(card->longname, "%s at %#llx", diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 660b2a9..417d1d5 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1057,7 +1057,7 @@ static int mpeg_open(struct file *file) dprintk( 1, "%s\n", __func__); - lock_kernel(); + mutex_lock(&dev->core->lock); /* Make sure we can acquire the hardware */ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); @@ -1065,7 +1065,7 @@ static int mpeg_open(struct file *file) err = drv->request_acquire(drv); if(err != 0) { dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); - unlock_kernel(); + mutex_unlock(&dev->core->lock);; return err; } } @@ -1073,7 +1073,7 @@ static int mpeg_open(struct file *file) if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) { if (drv) drv->request_release(drv); - unlock_kernel(); + mutex_unlock(&dev->core->lock); return -EINVAL; } dprintk(1, "open dev=%s\n", video_device_node_name(vdev)); @@ -1083,7 +1083,7 @@ static int mpeg_open(struct file *file) if (NULL == fh) { if (drv) drv->request_release(drv); - unlock_kernel(); + mutex_unlock(&dev->core->lock); return -ENOMEM; } file->private_data = fh; @@ -1094,15 +1094,14 @@ static int mpeg_open(struct file *file) V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), - fh); + fh, NULL); /* FIXME: locking against other video device */ cx88_set_scale(dev->core, dev->width, dev->height, fh->mpegq.field); - unlock_kernel(); atomic_inc(&dev->core->mpeg_users); - + mutex_unlock(&dev->core->lock); return 0; } @@ -1120,8 +1119,11 @@ static int mpeg_release(struct file *file) videobuf_stop(&fh->mpegq); videobuf_mmap_free(&fh->mpegq); + + mutex_lock(&dev->core->lock); file->private_data = NULL; kfree(fh); + mutex_unlock(&dev->core->lock); /* Make sure we release the hardware */ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index e8416b7..b26fcba 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -970,15 +970,22 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .audio_chip = V4L2_IDENT_WM8775, .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, + /* 2: Line-In */ + .audioroute = 2, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, + /* 2: Line-In */ + .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, + /* 2: Line-In */ + .audioroute = 2, }}, .mpeg = CX88_MPEG_DVB, }, @@ -2104,6 +2111,18 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_TWINHAN_VP1027_DVBS] = { + .name = "Twinhan VP-1027 DVB-S", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2576,6 +2595,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0xb034, .subdevice = 0x3034, .card = CX88_BOARD_PROF_7301, + }, { + .subvendor = 0x1822, + .subdevice = 0x0023, + .card = CX88_BOARD_TWINHAN_VP1027_DVBS, }, }; @@ -2673,10 +2696,10 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) /* ----------------------------------------------------------------------- */ /* some GDI (was: Modular Technology) specific stuff */ -static struct { +static const struct { int id; int fm; - char *name; + const char *name; } gdi_tuner[] = { [ 0x01 ] = { .id = TUNER_ABSENT, .name = "NTSC_M" }, @@ -2710,7 +2733,7 @@ static struct { static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) { - char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner)) + const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner)) ? gdi_tuner[eeprom_data[0x0d]].name : NULL; info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown"); @@ -3070,6 +3093,13 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) cx_set(MO_GP1_IO, 0x10); mdelay(50); break; + + case CX88_BOARD_TWINHAN_VP1027_DVBS: + cx_write(MO_GP0_IO, 0x00003230); + cx_write(MO_GP0_IO, 0x00003210); + msleep(1); + cx_write(MO_GP0_IO, 0x00001230); + break; } } @@ -3485,19 +3515,19 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) later code configures a tea5767. */ v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tuner", "tuner", + NULL, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); if (has_demod) v4l2_i2c_new_subdev(&core->v4l2_dev, - &core->i2c_adap, "tuner", "tuner", + &core->i2c_adap, NULL, "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (core->board.tuner_addr == ADDR_UNSET) { v4l2_i2c_new_subdev(&core->v4l2_dev, - &core->i2c_adap, "tuner", "tuner", + &core->i2c_adap, NULL, "tuner", 0, has_demod ? tv_addrs + 4 : tv_addrs); } else { v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tuner", "tuner", core->board.tuner_addr, NULL); + NULL, "tuner", core->board.tuner_addr, NULL); } } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 85eb266f..2e145f0a 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -217,7 +217,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); BUG_ON(in_interrupt()); - videobuf_waiton(&buf->vb,0,0); + videobuf_waiton(q, &buf->vb, 0, 0); videobuf_dma_unmap(q->dev, dma); videobuf_dma_free(dma); btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); @@ -253,7 +253,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) * 0x0c00 - FIFOs */ -struct sram_channel cx88_sram_channels[] = { +const struct sram_channel const cx88_sram_channels[] = { [SRAM_CH21] = { .name = "video y / packed", .cmds_start = 0x180040, @@ -353,7 +353,7 @@ struct sram_channel cx88_sram_channels[] = { }; int cx88_sram_channel_setup(struct cx88_core *core, - struct sram_channel *ch, + const struct sram_channel *ch, unsigned int bpl, u32 risc) { unsigned int i,lines; @@ -394,7 +394,7 @@ int cx88_sram_channel_setup(struct cx88_core *core, static int cx88_risc_decode(u32 risc) { - static char *instr[16] = { + static const char * const instr[16] = { [ RISC_SYNC >> 28 ] = "sync", [ RISC_WRITE >> 28 ] = "write", [ RISC_WRITEC >> 28 ] = "writec", @@ -406,14 +406,14 @@ static int cx88_risc_decode(u32 risc) [ RISC_WRITECM >> 28 ] = "writecm", [ RISC_WRITECR >> 28 ] = "writecr", }; - static int incr[16] = { + static int const incr[16] = { [ RISC_WRITE >> 28 ] = 2, [ RISC_JUMP >> 28 ] = 2, [ RISC_WRITERM >> 28 ] = 3, [ RISC_WRITECM >> 28 ] = 3, [ RISC_WRITECR >> 28 ] = 4, }; - static char *bits[] = { + static const char * const bits[] = { "12", "13", "14", "resync", "cnt0", "cnt1", "18", "19", "20", "21", "22", "23", @@ -432,9 +432,9 @@ static int cx88_risc_decode(u32 risc) void cx88_sram_channel_dump(struct cx88_core *core, - struct sram_channel *ch) + const struct sram_channel *ch) { - static char *name[] = { + static const char * const name[] = { "initial risc", "cdt base", "cdt size", @@ -489,14 +489,14 @@ void cx88_sram_channel_dump(struct cx88_core *core, core->name,cx_read(ch->cnt2_reg)); } -static char *cx88_pci_irqs[32] = { +static const char *cx88_pci_irqs[32] = { "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1", "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err", "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err", "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1" }; -void cx88_print_irqbits(char *name, char *tag, char **strings, +void cx88_print_irqbits(const char *name, const char *tag, const char *strings[], int len, u32 bits, u32 mask) { unsigned int i; @@ -770,7 +770,7 @@ static const u32 xtal = 28636363; static int set_pll(struct cx88_core *core, int prescale, u32 ofreq) { - static u32 pre[] = { 0, 0, 0, 3, 2, 1 }; + static const u32 pre[] = { 0, 0, 0, 3, 2, 1 }; u64 pll; u32 reg; int i; @@ -879,7 +879,7 @@ static int set_tvaudio(struct cx88_core *core) } else { printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n", core->name, v4l2_norm_to_name(core->tvnorm)); - core->tvaudio = 0; + core->tvaudio = WW_NONE; return 0; } @@ -1020,15 +1020,15 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) struct video_device *cx88_vdev_init(struct cx88_core *core, struct pci_dev *pci, - struct video_device *template, - char *type) + const struct video_device *template_, + const char *type) { struct video_device *vfd; vfd = video_device_alloc(); if (NULL == vfd) return NULL; - *vfd = *template; + *vfd = *template_; vfd->v4l2_dev = &core->v4l2_dev; vfd->parent = &pci->dev; vfd->release = video_device_release; diff --git a/drivers/media/video/cx88/cx88-dsp.c b/drivers/media/video/cx88/cx88-dsp.c index a94e00a..a990726 100644 --- a/drivers/media/video/cx88/cx88-dsp.c +++ b/drivers/media/video/cx88/cx88-dsp.c @@ -230,7 +230,7 @@ static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N) static s16 *read_rds_samples(struct cx88_core *core, u32 *N) { - struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27]; + const struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27]; s16 *samples; unsigned int i; @@ -292,11 +292,20 @@ s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core) switch (core->tvaudio) { case WW_BG: case WW_DK: + case WW_EIAJ: + case WW_M: ret = detect_a2_a2m_eiaj(core, samples, N); break; case WW_BTSC: ret = detect_btsc(core, samples, N); break; + case WW_NONE: + case WW_I: + case WW_L: + case WW_I2SPT: + case WW_FM: + case WW_I2SADC: + break; } kfree(samples); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index faa8e81..367a653f 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -56,6 +56,7 @@ #include "stv0900.h" #include "stb6100.h" #include "stb6100_proc.h" +#include "mb86a16.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); @@ -105,7 +106,7 @@ static void dvb_buf_release(struct videobuf_queue *q, cx88_free_buffer(q, (struct cx88_buffer*)vb); } -static struct videobuf_queue_ops dvb_qops = { +static const struct videobuf_queue_ops dvb_qops = { .buf_setup = dvb_buf_setup, .buf_prepare = dvb_buf_prepare, .buf_queue = dvb_buf_queue, @@ -167,12 +168,12 @@ static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) { - static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; - static u8 reset [] = { RESET, 0x80 }; - static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; - static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; - static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; - static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; + static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; + static const u8 reset [] = { RESET, 0x80 }; + static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static const u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; + static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; + static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; mt352_write(fe, clock_config, sizeof(clock_config)); udelay(200); @@ -187,12 +188,12 @@ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) static int dvico_dual_demod_init(struct dvb_frontend *fe) { - static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; - static u8 reset [] = { RESET, 0x80 }; - static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; - static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; - static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; - static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; + static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; + static const u8 reset [] = { RESET, 0x80 }; + static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static const u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; + static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; + static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; mt352_write(fe, clock_config, sizeof(clock_config)); udelay(200); @@ -208,13 +209,13 @@ static int dvico_dual_demod_init(struct dvb_frontend *fe) static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) { - static u8 clock_config [] = { 0x89, 0x38, 0x39 }; - static u8 reset [] = { 0x50, 0x80 }; - static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; - static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, + static const u8 clock_config [] = { 0x89, 0x38, 0x39 }; + static const u8 reset [] = { 0x50, 0x80 }; + static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static const u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x40, 0x40 }; - static u8 dntv_extra[] = { 0xB5, 0x7A }; - static u8 capt_range_cfg[] = { 0x75, 0x32 }; + static const u8 dntv_extra[] = { 0xB5, 0x7A }; + static const u8 capt_range_cfg[] = { 0x75, 0x32 }; mt352_write(fe, clock_config, sizeof(clock_config)); udelay(2000); @@ -229,37 +230,41 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) return 0; } -static struct mt352_config dvico_fusionhdtv = { +static const struct mt352_config dvico_fusionhdtv = { .demod_address = 0x0f, .demod_init = dvico_fusionhdtv_demod_init, }; -static struct mt352_config dntv_live_dvbt_config = { +static const struct mt352_config dntv_live_dvbt_config = { .demod_address = 0x0f, .demod_init = dntv_live_dvbt_demod_init, }; -static struct mt352_config dvico_fusionhdtv_dual = { +static const struct mt352_config dvico_fusionhdtv_dual = { .demod_address = 0x0f, .demod_init = dvico_dual_demod_init, }; -static struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { +static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { .demod_address = (0x1e >> 1), .no_tuner = 1, .if2 = 45600, }; +static struct mb86a16_config twinhan_vp1027 = { + .demod_address = 0x08, +}; + #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) { - static u8 clock_config [] = { 0x89, 0x38, 0x38 }; - static u8 reset [] = { 0x50, 0x80 }; - static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; - static u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, + static const u8 clock_config [] = { 0x89, 0x38, 0x38 }; + static const u8 reset [] = { 0x50, 0x80 }; + static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static const u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x40, 0x40 }; - static u8 dntv_extra[] = { 0xB5, 0x7A }; - static u8 capt_range_cfg[] = { 0x75, 0x32 }; + static const u8 dntv_extra[] = { 0xB5, 0x7A }; + static const u8 capt_range_cfg[] = { 0x75, 0x32 }; mt352_write(fe, clock_config, sizeof(clock_config)); udelay(2000); @@ -274,41 +279,41 @@ static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) return 0; } -static struct mt352_config dntv_live_dvbt_pro_config = { +static const struct mt352_config dntv_live_dvbt_pro_config = { .demod_address = 0x0f, .no_tuner = 1, .demod_init = dntv_live_dvbt_pro_demod_init, }; #endif -static struct zl10353_config dvico_fusionhdtv_hybrid = { +static const struct zl10353_config dvico_fusionhdtv_hybrid = { .demod_address = 0x0f, .no_tuner = 1, }; -static struct zl10353_config dvico_fusionhdtv_xc3028 = { +static const struct zl10353_config dvico_fusionhdtv_xc3028 = { .demod_address = 0x0f, .if2 = 45600, .no_tuner = 1, }; -static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { +static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { .demod_address = 0x0f, .if2 = 4560, .no_tuner = 1, .demod_init = dvico_fusionhdtv_demod_init, }; -static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { +static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { .demod_address = 0x0f, }; -static struct cx22702_config connexant_refboard_config = { +static const struct cx22702_config connexant_refboard_config = { .demod_address = 0x43, .output_mode = CX22702_SERIAL_OUTPUT, }; -static struct cx22702_config hauppauge_hvr_config = { +static const struct cx22702_config hauppauge_hvr_config = { .demod_address = 0x63, .output_mode = CX22702_SERIAL_OUTPUT, }; @@ -320,7 +325,7 @@ static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) return 0; } -static struct or51132_config pchdtv_hd3000 = { +static const struct or51132_config pchdtv_hd3000 = { .demod_address = 0x15, .set_ts_params = or51132_set_ts_param, }; @@ -355,14 +360,14 @@ static struct lgdt330x_config fusionhdtv_3_gold = { .set_ts_params = lgdt330x_set_ts_param, }; -static struct lgdt330x_config fusionhdtv_5_gold = { +static const struct lgdt330x_config fusionhdtv_5_gold = { .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ .set_ts_params = lgdt330x_set_ts_param, }; -static struct lgdt330x_config pchdtv_hd5500 = { +static const struct lgdt330x_config pchdtv_hd5500 = { .demod_address = 0x59, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ @@ -376,7 +381,7 @@ static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) return 0; } -static struct nxt200x_config ati_hdtvwonder = { +static const struct nxt200x_config ati_hdtvwonder = { .demod_address = 0x0a, .set_ts_params = nxt200x_set_ts_param, }; @@ -429,15 +434,15 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, cx_set(MO_GP0_IO, 0x6040); switch (voltage) { - case SEC_VOLTAGE_13: - cx_clear(MO_GP0_IO, 0x20); - break; - case SEC_VOLTAGE_18: - cx_set(MO_GP0_IO, 0x20); - break; - case SEC_VOLTAGE_OFF: - cx_clear(MO_GP0_IO, 0x20); - break; + case SEC_VOLTAGE_13: + cx_clear(MO_GP0_IO, 0x20); + break; + case SEC_VOLTAGE_18: + cx_set(MO_GP0_IO, 0x20); + break; + case SEC_VOLTAGE_OFF: + cx_clear(MO_GP0_IO, 0x20); + break; } if (core->prev_set_voltage) @@ -445,23 +450,49 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } -static struct cx24123_config geniatech_dvbs_config = { +static int vp1027_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage) +{ + struct cx8802_dev *dev = fe->dvb->priv; + struct cx88_core *core = dev->core; + + switch (voltage) { + case SEC_VOLTAGE_13: + dprintk(1, "LNB SEC Voltage=13\n"); + cx_write(MO_GP0_IO, 0x00001220); + break; + case SEC_VOLTAGE_18: + dprintk(1, "LNB SEC Voltage=18\n"); + cx_write(MO_GP0_IO, 0x00001222); + break; + case SEC_VOLTAGE_OFF: + dprintk(1, "LNB Voltage OFF\n"); + cx_write(MO_GP0_IO, 0x00001230); + break; + } + + if (core->prev_set_voltage) + return core->prev_set_voltage(fe, voltage); + return 0; +} + +static const struct cx24123_config geniatech_dvbs_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, }; -static struct cx24123_config hauppauge_novas_config = { +static const struct cx24123_config hauppauge_novas_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, }; -static struct cx24123_config kworld_dvbs_100_config = { +static const struct cx24123_config kworld_dvbs_100_config = { .demod_address = 0x15, .set_ts_params = cx24123_set_ts_param, .lnb_polarity = 1, }; -static struct s5h1409_config pinnacle_pctv_hd_800i_config = { +static const struct s5h1409_config pinnacle_pctv_hd_800i_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_PARALLEL_OUTPUT, .gpio = S5H1409_GPIO_ON, @@ -471,7 +502,7 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = { .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, }; -static struct s5h1409_config dvico_hdtv5_pci_nano_config = { +static const struct s5h1409_config dvico_hdtv5_pci_nano_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, .gpio = S5H1409_GPIO_OFF, @@ -480,7 +511,7 @@ static struct s5h1409_config dvico_hdtv5_pci_nano_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; -static struct s5h1409_config kworld_atsc_120_config = { +static const struct s5h1409_config kworld_atsc_120_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, .gpio = S5H1409_GPIO_OFF, @@ -489,24 +520,24 @@ static struct s5h1409_config kworld_atsc_120_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; -static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { +static const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, }; -static struct zl10353_config cx88_pinnacle_hybrid_pctv = { +static const struct zl10353_config cx88_pinnacle_hybrid_pctv = { .demod_address = (0x1e >> 1), .no_tuner = 1, .if2 = 45600, }; -static struct zl10353_config cx88_geniatech_x8000_mt = { +static const struct zl10353_config cx88_geniatech_x8000_mt = { .demod_address = (0x1e >> 1), .no_tuner = 1, .disable_i2c_gate_ctrl = 1, }; -static struct s5h1411_config dvico_fusionhdtv7_config = { +static const struct s5h1411_config dvico_fusionhdtv7_config = { .output_mode = S5H1411_SERIAL_OUTPUT, .gpio = S5H1411_GPIO_ON, .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, @@ -516,7 +547,7 @@ static struct s5h1411_config dvico_fusionhdtv7_config = { .status_mode = S5H1411_DEMODLOCKING }; -static struct xc5000_config dvico_fusionhdtv7_tuner_config = { +static const struct xc5000_config dvico_fusionhdtv7_tuner_config = { .i2c_address = 0xc2 >> 1, .if_khz = 5380, }; @@ -601,19 +632,19 @@ static int cx24116_reset_device(struct dvb_frontend *fe) return 0; } -static struct cx24116_config hauppauge_hvr4000_config = { +static const struct cx24116_config hauppauge_hvr4000_config = { .demod_address = 0x05, .set_ts_params = cx24116_set_ts_param, .reset_device = cx24116_reset_device, }; -static struct cx24116_config tevii_s460_config = { +static const struct cx24116_config tevii_s460_config = { .demod_address = 0x55, .set_ts_params = cx24116_set_ts_param, .reset_device = cx24116_reset_device, }; -static struct stv0900_config prof_7301_stv0900_config = { +static const struct stv0900_config prof_7301_stv0900_config = { .demod_address = 0x6a, /* demod_mode = 0,*/ .xtal = 27000000, @@ -625,12 +656,12 @@ static struct stv0900_config prof_7301_stv0900_config = { .set_ts_params = stv0900_set_ts_param, }; -static struct stb6100_config prof_7301_stb6100_config = { +static const struct stb6100_config prof_7301_stb6100_config = { .tuner_address = 0x60, .refclock = 27000000, }; -static struct stv0299_config tevii_tuner_sharp_config = { +static const struct stv0299_config tevii_tuner_sharp_config = { .demod_address = 0x68, .inittab = sharp_z0194a_inittab, .mclk = 88000000UL, @@ -643,7 +674,7 @@ static struct stv0299_config tevii_tuner_sharp_config = { .set_ts_params = cx24116_set_ts_param, }; -static struct stv0288_config tevii_tuner_earda_config = { +static const struct stv0288_config tevii_tuner_earda_config = { .demod_address = 0x68, .min_delay_ms = 100, .set_ts_params = cx24116_set_ts_param, @@ -676,7 +707,7 @@ static int cx8802_alloc_frontends(struct cx8802_dev *dev) -static u8 samsung_smt_7020_inittab[] = { +static const u8 samsung_smt_7020_inittab[] = { 0x01, 0x15, 0x02, 0x00, 0x03, 0x00, @@ -850,7 +881,7 @@ static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, } -static struct stv0299_config samsung_stv0299_config = { +static const struct stv0299_config samsung_stv0299_config = { .demod_address = 0x68, .inittab = samsung_smt_7020_inittab, .mclk = 88000000UL, @@ -1416,6 +1447,18 @@ static int dvb_register(struct cx8802_dev *dev) } break; + case CX88_BOARD_TWINHAN_VP1027_DVBS: + dev->ts_gen_cntrl = 0x00; + fe0->dvb.frontend = dvb_attach(mb86a16_attach, + &twinhan_vp1027, + &core->i2c_adap); + if (fe0->dvb.frontend) { + core->prev_set_voltage = + fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = + vp1027_set_voltage; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", @@ -1576,7 +1619,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), - dev); + dev, NULL); /* init struct videobuf_dvb */ fe->dvb.name = dev->core->name; } diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 82db555..f53836b 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -108,7 +108,7 @@ static const struct i2c_algo_bit_data cx8800_i2c_algo_template = { /* ----------------------------------------------------------------------- */ -static char *i2c_devs[128] = { +static const char * const i2c_devs[128] = { [ 0x1c >> 1 ] = "lgdt330x", [ 0x86 >> 1 ] = "tda9887/cx22702", [ 0xa0 >> 1 ] = "eeprom", @@ -117,7 +117,7 @@ static char *i2c_devs[128] = { [ 0xc8 >> 1 ] = "xc5000", }; -static void do_i2c_scan(char *name, struct i2c_client *c) +static void do_i2c_scan(const char *name, struct i2c_client *c) { unsigned char buf; int i,rc; @@ -183,30 +183,3 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) return core->i2c_rc; } - -void cx88_i2c_init_ir(struct cx88_core *core) -{ - /* Instantiate the IR receiver device, if present */ - if (0 == core->i2c_rc) { - struct i2c_board_info info; - const unsigned short addr_list[] = { - 0x18, 0x6b, 0x71, - I2C_CLIENT_END - }; - - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - /* Use quick read command for probe, some IR chips don't - * support writes */ - i2c_new_probed_device(&core->i2c_adap, &info, addr_list, - i2c_probe_func_quick_read); - } -} - -/* ----------------------------------------------------------------------- */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index eccc5e4..fc777bc 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -405,6 +405,11 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keycode = 0x7e; ir->polling = 100; /* ms */ break; + case CX88_BOARD_TWINHAN_VP1027_DVBS: + ir_codes = RC_MAP_TWINHAN_VP1027_DVBS; + ir_type = IR_TYPE_NEC; + ir->sampling = 0xff00; /* address */ + break; } if (NULL == ir_codes) { @@ -530,6 +535,7 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_PROF_7300: case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: + case CX88_BOARD_TWINHAN_VP1027_DVBS: ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); if (ircode == 0xffffffff) { /* decoding error */ @@ -609,13 +615,54 @@ void cx88_ir_irq(struct cx88_core *core) return; } + +void cx88_i2c_init_ir(struct cx88_core *core) +{ + struct i2c_board_info info; + const unsigned short addr_list[] = { + 0x18, 0x6b, 0x71, + I2C_CLIENT_END + }; + const unsigned short *addrp; + /* Instantiate the IR receiver device, if present */ + if (0 != core->i2c_rc) + return; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + + /* + * We can't call i2c_new_probed_device() because it uses + * quick writes for probing and at least some RC receiver + * devices only reply to reads. + * Also, Hauppauge XVR needs to be specified, as address 0x71 + * conflicts with another remote type used with saa7134 + */ + for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) { + info.platform_data = NULL; + memset(&core->init_data, 0, sizeof(core->init_data)); + + if (*addrp == 0x71) { + /* Hauppauge XVR */ + core->init_data.name = "cx88 Hauppauge XVR remote"; + core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; + core->init_data.type = IR_TYPE_RC5; + core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + + info.platform_data = &core->init_data; + } + if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0, + I2C_SMBUS_READ, 0, + I2C_SMBUS_QUICK, NULL) >= 0) { + info.addr = *addrp; + i2c_new_device(&core->i2c_adap, &info); + break; + } + } +} + /* ---------------------------------------------------------------------- */ MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe"); MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls"); MODULE_LICENSE("GPL"); -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 499f8d5..f7d71ac 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -313,7 +313,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) /* ----------------------------------------------------------- */ -static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart) +static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart) { struct cx88_dmaqueue *q = &dev->mpegq; struct cx88_buffer *buf; @@ -358,7 +358,7 @@ static void cx8802_timeout(unsigned long data) do_cancel_buffers(dev,"timeout",1); } -static char *cx88_mpeg_irqs[32] = { +static const char * cx88_mpeg_irqs[32] = { "ts_risci1", NULL, NULL, NULL, "ts_risci2", NULL, NULL, NULL, "ts_oflow", NULL, NULL, NULL, @@ -849,7 +849,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) kfree(dev); } -static struct pci_device_id cx8802_pci_tbl[] = { +static const struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 2396315..08220de 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -70,7 +70,7 @@ MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, " /* ----------------------------------------------------------- */ -static char *aud_ctl_names[64] = { +static const char * const aud_ctl_names[64] = { [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO", [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO", [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP", @@ -360,7 +360,15 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) set_audio_registers(core, nicam_bgdki_common); set_audio_registers(core, nicam_i); break; - default: + case WW_NONE: + case WW_BTSC: + case WW_BG: + case WW_DK: + case WW_EIAJ: + case WW_I2SPT: + case WW_FM: + case WW_I2SADC: + case WW_M: dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__); set_audio_registers(core, nicam_bgdki_common); set_audio_registers(core, nicam_default); @@ -621,7 +629,13 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode) dprintk("%s AM-L (status: devel)\n", __func__); set_audio_registers(core, am_l); break; - default: + case WW_NONE: + case WW_BTSC: + case WW_EIAJ: + case WW_I2SPT: + case WW_FM: + case WW_I2SADC: + case WW_M: dprintk("%s Warning: wrong value\n", __func__); return; break; @@ -779,7 +793,7 @@ void cx88_set_tvaudio(struct cx88_core *core) set_audio_finish(core, EN_I2SIN_ENABLE); break; case WW_NONE: - default: + case WW_I2SPT: printk("%s/0: unknown tv audio mode [%d]\n", core->name, core->tvaudio); break; @@ -795,8 +809,8 @@ void cx88_newstation(struct cx88_core *core) void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) { - static char *m[] = { "stereo", "dual mono", "mono", "sap" }; - static char *p[] = { "no pilot", "pilot c1", "pilot c2", "?" }; + static const char * const m[] = { "stereo", "dual mono", "mono", "sap" }; + static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" }; u32 reg, mode, pilot; reg = cx_read(AUD_STATUS); @@ -840,7 +854,12 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) break; } break; - default: + case WW_NONE: + case WW_I: + case WW_L: + case WW_I2SPT: + case WW_FM: + case WW_I2SADC: /* nothing */ break; } @@ -945,6 +964,9 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) } break; case WW_I2SADC: + case WW_NONE: + case WW_EIAJ: + case WW_I2SPT: /* DO NOTHING */ break; } @@ -1000,7 +1022,12 @@ int cx88_audio_thread(void *data) /* automatically switch to best available mode */ cx88_set_stereo(core, mode, 0); break; - default: + case WW_NONE: + case WW_BTSC: + case WW_EIAJ: + case WW_I2SPT: + case WW_FM: + case WW_I2SADC: hw_autodetect: /* stereo autodetection is supported by hardware so we don't need to do it manually. Do nothing. */ diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index d9445b0..f8f8389 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -230,7 +230,7 @@ static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) cx88_free_buffer(q,buf); } -struct videobuf_queue_ops cx8800_vbi_qops = { +const struct videobuf_queue_ops cx8800_vbi_qops = { .buf_setup = vbi_setup, .buf_prepare = vbi_prepare, .buf_queue = vbi_queue, diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 0fab65c..d2f159d 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -41,6 +41,7 @@ #include "cx88.h" #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> +#include <media/wm8775.h> MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); @@ -78,7 +79,7 @@ MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); /* ------------------------------------------------------------------- */ /* static data */ -static struct cx8800_fmt formats[] = { +static const struct cx8800_fmt formats[] = { { .name = "8 bpp, gray", .fourcc = V4L2_PIX_FMT_GREY, @@ -142,7 +143,7 @@ static struct cx8800_fmt formats[] = { }, }; -static struct cx8800_fmt* format_by_fourcc(unsigned int fourcc) +static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc) { unsigned int i; @@ -159,7 +160,7 @@ static const struct v4l2_queryctrl no_ctl = { .flags = V4L2_CTRL_FLAG_DISABLED, }; -static struct cx88_ctrl cx8800_ctls[] = { +static const struct cx88_ctrl cx8800_ctls[] = { /* --- video --- */ { .v = { @@ -288,7 +289,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .shift = 0, } }; -static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls); +enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) }; /* Must be sorted from low to high control ID! */ const u32 cx88_user_ctrls[] = { @@ -306,7 +307,7 @@ const u32 cx88_user_ctrls[] = { }; EXPORT_SYMBOL(cx88_user_ctrls); -static const u32 *ctrl_classes[] = { +static const u32 * const ctrl_classes[] = { cx88_user_ctrls, NULL }; @@ -710,7 +711,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) cx88_free_buffer(q,buf); } -static struct videobuf_queue_ops cx8800_video_qops = { +static const struct videobuf_queue_ops cx8800_video_qops = { .buf_setup = buffer_setup, .buf_prepare = buffer_prepare, .buf_queue = buffer_queue, @@ -752,7 +753,7 @@ static int video_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct cx8800_dev *dev = video_drvdata(file); - struct cx88_core *core; + struct cx88_core *core = dev->core; struct cx8800_fh *fh; enum v4l2_buf_type type = 0; int radio = 0; @@ -769,19 +770,14 @@ static int video_open(struct file *file) break; } - lock_kernel(); - - core = dev->core; - dprintk(1, "open dev=%s radio=%d type=%s\n", video_device_node_name(vdev), radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (unlikely(!fh)) return -ENOMEM; - } + file->private_data = fh; fh->dev = dev; fh->radio = radio; @@ -790,18 +786,20 @@ static int video_open(struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); + mutex_lock(&core->lock); + videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), - fh); + fh, NULL); videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct cx88_buffer), - fh); + fh, NULL); if (fh->radio) { dprintk(1,"video_open: setting radio device\n"); @@ -826,9 +824,9 @@ static int video_open(struct file *file) } call_all(core, tuner, s_radio); } - unlock_kernel(); atomic_inc(&core->users); + mutex_unlock(&core->lock); return 0; } @@ -920,10 +918,11 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); videobuf_mmap_free(&fh->vbiq); + + mutex_lock(&dev->core->lock); file->private_data = NULL; kfree(fh); - mutex_lock(&dev->core->lock); if(atomic_dec_and_test(&dev->core->users)) call_all(dev->core, core, s_power, 0); mutex_unlock(&dev->core->lock); @@ -944,7 +943,7 @@ video_mmap(struct file *file, struct vm_area_struct * vma) int cx88_get_control (struct cx88_core *core, struct v4l2_control *ctl) { - struct cx88_ctrl *c = NULL; + const struct cx88_ctrl *c = NULL; u32 value; int i; @@ -976,9 +975,10 @@ EXPORT_SYMBOL(cx88_get_control); int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) { - struct cx88_ctrl *c = NULL; + const struct cx88_ctrl *c = NULL; u32 value,mask; int i; + struct v4l2_control client_ctl; for (i = 0; i < CX8800_CTLS; i++) { if (cx8800_ctls[i].v.id == ctl->id) { @@ -992,6 +992,27 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) ctl->value = c->v.minimum; if (ctl->value > c->v.maximum) ctl->value = c->v.maximum; + + /* Pass changes onto any WM8775 */ + client_ctl.id = ctl->id; + switch (ctl->id) { + case V4L2_CID_AUDIO_MUTE: + client_ctl.value = ctl->value; + break; + case V4L2_CID_AUDIO_VOLUME: + client_ctl.value = (ctl->value) ? + (0x90 + ctl->value) << 8 : 0; + break; + case V4L2_CID_AUDIO_BALANCE: + client_ctl.value = ctl->value << 9; + break; + default: + client_ctl.id = 0; + break; + } + if (client_ctl.id) + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); + mask=c->mask; switch (ctl->id) { case V4L2_CID_AUDIO_BALANCE: @@ -1072,7 +1093,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - struct cx8800_fmt *fmt; + const struct cx8800_fmt *fmt; enum v4l2_field field; unsigned int maxw, maxh; @@ -1247,7 +1268,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms) /* only one input in this sample driver */ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) { - static const char *iname[] = { + static const char * const iname[] = { [ CX88_VMUX_COMPOSITE1 ] = "Composite1", [ CX88_VMUX_COMPOSITE2 ] = "Composite2", [ CX88_VMUX_COMPOSITE3 ] = "Composite3", @@ -1267,9 +1288,10 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name,iname[INPUT(n).type]); if ((CX88_VMUX_TELEVISION == INPUT(n).type) || - (CX88_VMUX_CABLE == INPUT(n).type)) + (CX88_VMUX_CABLE == INPUT(n).type)) { i->type = V4L2_INPUT_TYPE_TUNER; i->std = CX88_NORMS; + } return 0; } EXPORT_SYMBOL(cx88_enum_input); @@ -1537,7 +1559,9 @@ static int radio_queryctrl (struct file *file, void *priv, if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) return -EINVAL; - if (c->id == V4L2_CID_AUDIO_MUTE) { + if (c->id == V4L2_CID_AUDIO_MUTE || + c->id == V4L2_CID_AUDIO_VOLUME || + c->id == V4L2_CID_AUDIO_BALANCE) { for (i = 0; i < CX8800_CTLS; i++) { if (cx8800_ctls[i].v.id == c->id) break; @@ -1578,7 +1602,7 @@ static void cx8800_vid_timeout(unsigned long data) spin_unlock_irqrestore(&dev->slock,flags); } -static char *cx88_vid_irqs[32] = { +static const char *cx88_vid_irqs[32] = { "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", "y_oflow", "u_oflow", "v_oflow", "vbi_oflow", @@ -1723,7 +1747,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { static struct video_device cx8800_vbi_template; -static struct video_device cx8800_video_template = { +static const struct video_device cx8800_video_template = { .name = "cx8800-video", .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, @@ -1758,7 +1782,7 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { #endif }; -static struct video_device cx8800_radio_template = { +static const struct video_device cx8800_radio_template = { .name = "cx8800-radio", .fops = &radio_fops, .ioctl_ops = &radio_ioctl_ops, @@ -1872,20 +1896,20 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, if (core->board.audio_chip == V4L2_IDENT_WM8775) v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "wm8775", "wm8775", 0x36 >> 1, NULL); + NULL, "wm8775", 0x36 >> 1, NULL); if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { /* This probes for a tda9874 as is used on some Pixelview Ultra boards. */ v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tvaudio", "tvaudio", 0, I2C_ADDRS(0xb0 >> 1)); + NULL, "tvaudio", 0, I2C_ADDRS(0xb0 >> 1)); } switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: { - static struct i2c_board_info rtc_info = { + static const struct i2c_board_info rtc_info = { I2C_BOARD_INFO("isl1208", 0x6f) }; @@ -2082,7 +2106,7 @@ static int cx8800_resume(struct pci_dev *pci_dev) /* ----------------------------------------------------------- */ -static struct pci_device_id cx8800_pci_tbl[] = { +static const struct pci_device_id cx8800_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8800, diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index 794f293..ec5476d 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -121,8 +121,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, sizeof(vp3054_i2c->algo)); - vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL; - vp3054_i2c->adap.dev.parent = &dev->pci->dev; strlcpy(vp3054_i2c->adap.name, core->name, sizeof(vp3054_i2c->adap.name)); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 33d161a..e8c732e 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -31,9 +31,8 @@ #include <media/videobuf-dma-sg.h> #include <media/v4l2-chip-ident.h> #include <media/cx2341x.h> -#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) #include <media/videobuf-dvb.h> -#endif +#include <media/ir-kbd-i2c.h> #include "btcx-risc.h" #include "cx88-reg.h" @@ -108,7 +107,7 @@ static unsigned int inline norm_maxh(v4l2_std_id norm) /* static data */ struct cx8800_fmt { - char *name; + const char *name; u32 fourcc; /* v4l2 format id */ int depth; int flags; @@ -138,7 +137,7 @@ struct cx88_ctrl { /* more */ struct sram_channel { - char *name; + const char *name; u32 cmds_start; u32 ctrl_start; u32 cdt; @@ -149,7 +148,7 @@ struct sram_channel { u32 cnt1_reg; u32 cnt2_reg; }; -extern struct sram_channel cx88_sram_channels[]; +extern const struct sram_channel const cx88_sram_channels[]; /* ----------------------------------------------------------- */ /* card configuration */ @@ -240,6 +239,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_WINFAST_DTV2000H_J 82 #define CX88_BOARD_PROF_7301 83 #define CX88_BOARD_SAMSUNG_SMT_7020 84 +#define CX88_BOARD_TWINHAN_VP1027_DVBS 85 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -262,7 +262,7 @@ struct cx88_input { }; struct cx88_board { - char *name; + const char *name; unsigned int tuner_type; unsigned int radio_type; unsigned char tuner_addr; @@ -281,6 +281,20 @@ struct cx88_subid { u32 card; }; +enum cx88_tvaudio { + WW_NONE = 1, + WW_BTSC, + WW_BG, + WW_DK, + WW_I, + WW_L, + WW_EIAJ, + WW_I2SPT, + WW_FM, + WW_I2SADC, + WW_M +}; + #define INPUT(nr) (core->board.input[nr]) /* ----------------------------------------------------------- */ @@ -300,7 +314,7 @@ struct cx88_buffer { /* cx88 specific */ unsigned int bpl; struct btcx_riscmem risc; - struct cx8800_fmt *fmt; + const struct cx8800_fmt *fmt; u32 count; }; @@ -352,7 +366,7 @@ struct cx88_core { /* state info */ struct task_struct *kthread; v4l2_std_id tvnorm; - u32 tvaudio; + enum cx88_tvaudio tvaudio; u32 audiomode_manual; u32 audiomode_current; u32 input; @@ -363,6 +377,9 @@ struct cx88_core { /* IR remote control state */ struct cx88_IR *ir; + /* I2C remote data */ + struct IR_i2c_init_data init_data; + struct mutex lock; /* various v4l controls */ u32 freq; @@ -381,17 +398,19 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct cx88_core, v4l2_dev); } -#define call_all(core, o, f, args...) \ +#define call_hw(core, grpid, o, f, args...) \ do { \ if (!core->i2c_rc) { \ if (core->gate_ctrl) \ core->gate_ctrl(core, 1); \ - v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \ + v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \ if (core->gate_ctrl) \ core->gate_ctrl(core, 0); \ } \ } while (0) +#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) + struct cx8800_dev; struct cx8802_dev; @@ -410,7 +429,7 @@ struct cx8800_fh { unsigned int nclips; /* video capture */ - struct cx8800_fmt *fmt; + const struct cx8800_fmt *fmt; unsigned int width,height; struct videobuf_queue vidq; @@ -565,7 +584,7 @@ struct cx8802_dev { /* ----------------------------------------------------------- */ /* cx88-core.c */ -extern void cx88_print_irqbits(char *name, char *tag, char **strings, +extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[], int len, u32 bits, u32 mask); extern int cx88_core_irq(struct cx88_core *core, u32 status); @@ -592,10 +611,10 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf); extern void cx88_risc_disasm(struct cx88_core *core, struct btcx_riscmem *risc); extern int cx88_sram_channel_setup(struct cx88_core *core, - struct sram_channel *ch, + const struct sram_channel *ch, unsigned int bpl, u32 risc); extern void cx88_sram_channel_dump(struct cx88_core *core, - struct sram_channel *ch); + const struct sram_channel *ch); extern int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, enum v4l2_field field); @@ -603,8 +622,8 @@ extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm); extern struct video_device *cx88_vdev_init(struct cx88_core *core, struct pci_dev *pci, - struct video_device *template, - char *type); + const struct video_device *template_, + const char *type); extern struct cx88_core* cx88_core_get(struct pci_dev *pci); extern void cx88_core_put(struct cx88_core *core, struct pci_dev *pci); @@ -630,13 +649,12 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q); void cx8800_vbi_timeout(unsigned long data); -extern struct videobuf_queue_ops cx8800_vbi_qops; +extern const struct videobuf_queue_ops cx8800_vbi_qops; /* ----------------------------------------------------------- */ /* cx88-i2c.c */ extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); -extern void cx88_i2c_init_ir(struct cx88_core *core); /* ----------------------------------------------------------- */ @@ -651,18 +669,6 @@ extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl); /* ----------------------------------------------------------- */ /* cx88-tvaudio.c */ -#define WW_NONE 1 -#define WW_BTSC 2 -#define WW_BG 3 -#define WW_DK 4 -#define WW_I 5 -#define WW_L 6 -#define WW_EIAJ 7 -#define WW_I2SPT 8 -#define WW_FM 9 -#define WW_I2SADC 10 -#define WW_M 11 - void cx88_set_tvaudio(struct cx88_core *core); void cx88_newstation(struct cx88_core *core); void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); @@ -686,6 +692,7 @@ int cx88_ir_fini(struct cx88_core *core); void cx88_ir_irq(struct cx88_core *core); int cx88_ir_start(struct cx88_core *core); void cx88_ir_stop(struct cx88_core *core); +extern void cx88_i2c_init_ir(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-mpeg.c */ @@ -705,10 +712,3 @@ int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl); int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl); int cx88_video_mux(struct cx88_core *core, unsigned int input); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ |