diff options
author | Troy Kisky <troy.kisky@boundarydevices.com> | 2014-02-06 15:49:18 -0700 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2015-05-29 13:43:35 +0200 |
commit | e10688c1a1c7a35b349efb44368fb3130976493e (patch) | |
tree | a3408f2d4347e8180447be952a2c2717869ee3da /drivers/media/pci | |
parent | 1ea68186f4f9718d4b6578f01556bc7bc0264ca1 (diff) |
tw68: audio fixes
Diffstat (limited to 'drivers/media/pci')
-rw-r--r-- | drivers/media/pci/TW68/TW68-ALSA.c | 549 | ||||
-rw-r--r-- | drivers/media/pci/TW68/TW68-core.c | 145 | ||||
-rw-r--r-- | drivers/media/pci/TW68/TW68-video.c | 52 | ||||
-rw-r--r-- | drivers/media/pci/TW68/TW68_defines.h | 111 |
4 files changed, 331 insertions, 526 deletions
diff --git a/drivers/media/pci/TW68/TW68-ALSA.c b/drivers/media/pci/TW68/TW68-ALSA.c index de3c6a19051c..0ddd7f73564b 100644 --- a/drivers/media/pci/TW68/TW68-ALSA.c +++ b/drivers/media/pci/TW68/TW68-ALSA.c @@ -17,6 +17,7 @@ * Thanks to yiliang for variable audio packet length and more audio * formats support. */ +#define DEBUG #include <linux/module.h> #include <linux/vmalloc.h> #include <sound/core.h> @@ -33,36 +34,26 @@ MODULE_DESCRIPTION("alsa driver module for tw68 PCIe capture chip"); MODULE_AUTHOR("Simon Xu"); MODULE_LICENSE("GPL"); -#define audio_nCH 8 -#define DMA_page 4096 -#define MAX_BUFFER (DMA_page * 4 *audio_nCH) - - -/* - * TW PCM structure - */ -typedef struct snd_card_TW68_pcm { - - struct TW68_dev *dev; - spinlock_t lock; - struct snd_pcm_substream *substream; -} snd_card_TW68_pcm_t; - /* * Main chip structure */ -typedef struct snd_card_TW68 { +struct snd_card_tw68 { struct snd_card *card; spinlock_t mixer_lock; struct pci_dev *pci; struct TW68_dev *dev; - void *audio_ringbuffer; struct snd_pcm *TW68_pcm; struct snd_pcm_substream *substream[10]; spinlock_t lock; -} snd_card_TW68_t; + u32 audio_dma_size; + u32 audio_rate; + u32 audio_frame_bits; + u32 audio_lock_mask; + u32 last_audio_PB; + u8 period_insert[8]; +}; // static struct snd_card *snd_TW68_cards[SNDRV_CARDS]; @@ -78,17 +69,17 @@ static struct snd_pcm_hardware snd_card_tw68_pcm_hw = .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE , //| SNDRV_PCM_FMTBIT_S8, - .rates = SNDRV_PCM_RATE_8000_48000, //SNDRV_PCM_RATE_32000, // + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, + .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, .rate_max = 48000, .channels_min = 1, .channels_max = 1, - .buffer_bytes_max = 4*DMA_page, //4096, - .period_bytes_min = 256, //256, - .period_bytes_max = 4096, //1024, - .periods_min = 4, - .periods_max = 8, + .buffer_bytes_max = AUDIO_CH_BUF_SIZE, + .period_bytes_min = 64, + .period_bytes_max = 4096, + .periods_min = 4, + .periods_max = 256, }; @@ -103,67 +94,46 @@ static struct snd_pcm_hardware snd_card_tw68_pcm_hw = void TW68_alsa_irq(struct TW68_dev *dev, u32 dma_status, u32 pb_status) { + u32 dma_base = dev->m_AudioBuffer.dma; + struct snd_card_tw68 *ctw = (struct snd_card_tw68 *)dev->card->private_data; + u32 mask = ((dev->videoDMA_ID & dma_status) & 0xff00) >> 8; + u32 change = pb_status ^ ctw->last_audio_PB; + + // pr_debug("%s: card pcm %p dma_status %x pb_status %x \n", __func__, + // ctw->TW68_pcm, dma_status, pb_status); + while (mask) { + int k = __fls(mask); + u32 dma_ch = dma_base + AUDIO_CH_BUF_SIZE * k; + int period = ctw->period_insert[k]; + u32 reg_addr = DMA_CH8_CONFIG_P + k * 2; + struct snd_pcm_substream *substream = ctw->substream[k]; + u32 buffer_bytes = snd_pcm_lib_buffer_bytes(substream); + u32 smask = (1 << (k + 8)); + u32 offset = ctw->audio_dma_size * period; + + mask &= ~(1 << k); + if (!(ctw->last_audio_PB & smask)) + reg_addr++; + reg_writel(reg_addr, dma_ch + offset); + period++; + offset += ctw->audio_dma_size; + if (offset >= buffer_bytes) { + period = 0; + offset = 0; + } - struct snd_pcm_runtime *runtime; - int k; - - u32 audio_irq = (dev->videoDMA_ID & dma_status & 0xff00) >>8; - u32 audio_PB =0; - static u32 last_audio_PB =0xFFFF; - - struct TW68_pgtable p_Audio = dev ->m_AudioBuffer; - snd_card_TW68_t *card_TW68 = (snd_card_TW68_t *) dev->card->private_data; - - u8* Audioptr = (u8*)p_Audio.cpu; - u8* AudioVB = card_TW68->audio_ringbuffer; - -// pr_debug("%s() card_TW68 pcm %p dma_status %x pb_status %x \n", __func__, -// card_TW68->TW68_pcm, dma_status, pb_status); - - if (audio_irq) { - audio_PB = (pb_status >>8)& audio_irq; - ///pr_debug(" Audio irq:%d PB: %X \n", audio_irq, audio_PB); - for (k = 0; k < 8; k++) { - if (audio_irq & (1<<k)) { - runtime = card_TW68->substream[k]->runtime; - /* - pr_debug(" TW68_alsa_irq Audio CH:%d aPB: %X RUNTIME HWptr 0x%p, 0x%X, jf 0x%x Pdz 0x%x 0x%x BFz 0x%x DMA %X %X %X\n", - k, ((audio_PB >>k)& 0x1), - runtime->hw_ptr_base, runtime->hw_ptr_interrupt, runtime->hw_ptr_jiffies, - runtime->period_size, runtime->periods, runtime->buffer_size, - runtime->dma_area, runtime->dma_addr, runtime->dma_bytes - ); - */ - if (((last_audio_PB >>k)& 0x1) ^ ((audio_PB >>k)& 0x1)) { - if(((audio_PB >>k)& 0x1) ==0) { - last_audio_PB &= ~(1 <<k); - runtime->hw_ptr_base = 0; - runtime->status->hw_ptr = 0; - runtime->hw_ptr_interrupt = 0; - runtime->control->appl_ptr =0; - AudioVB += PAGE_SIZE *2 *k; - Audioptr+= PAGE_SIZE *2 *k; - memcpy(AudioVB, Audioptr, PAGE_SIZE); - } else { - last_audio_PB |= (1 <<k); - runtime->hw_ptr_base = runtime->period_size; - runtime->status->hw_ptr = 0; - runtime->hw_ptr_interrupt = 0; - runtime->control->appl_ptr = runtime->hw_ptr_base; - AudioVB += (PAGE_SIZE *2 *k + PAGE_SIZE); - Audioptr+= (PAGE_SIZE *2 *k + PAGE_SIZE); - memcpy(AudioVB, Audioptr, PAGE_SIZE); - } - snd_pcm_period_elapsed(card_TW68->substream[k]); // call pointer - } - /* - long avail = snd_pcm_capture_avail(runtime); - - pr_debug("TW68_alsa_irq: card 0x%p, substream 0x%p, runtime BD 0%d hw_ptr 0x%p, runtime->control->appl_ptr 0x%p, cap avail 0x%X\n", - card_TW68, card_TW68->substream[k], runtime->boundary, runtime->status->hw_ptr, runtime->control->appl_ptr, avail); ///runtime->xfer_align - */ - } + if (!(change & smask)) { + reg_addr ^= 1; + reg_writel(reg_addr, dma_ch + offset); + period++; + offset += ctw->audio_dma_size; + if (offset >= buffer_bytes) + period = 0; + pr_debug("%s: 2 periods elapsed\n", __func__); } + ctw->period_insert[k] = period; + ctw->last_audio_PB ^= change & smask; + snd_pcm_period_elapsed(substream); } } @@ -181,73 +151,52 @@ void TW68_alsa_irq(struct TW68_dev *dev, u32 dma_status, u32 pb_status) static int snd_card_TW68_capture_trigger(struct snd_pcm_substream *substream, int cmd) { // DMA start bit based on ss id - int nId = substream->number; - - u32 dwReg=0; - u32 dwRegF=0; - //u32 dwREGA=0; - int ret =0; - long avail =0; - snd_card_TW68_t *card_TW68 = snd_pcm_substream_chip(substream); - struct TW68_dev *dev; - struct snd_pcm_runtime *runtime = substream->runtime; - dev = card_TW68 ->dev; - - - - if (!card_TW68) { + u32 mask = (1 << (substream->number + 8)); + u32 dwReg; + u32 dwRegF; + struct snd_card_tw68 *ctw = snd_pcm_substream_chip(substream); + struct TW68_dev *dev = ctw->dev; + int start; + unsigned long flags; + + if (!ctw) { pr_err("%s: can't find device struct.\n", __func__); return -ENODEV; } - avail = snd_pcm_capture_avail(runtime); - - //pr_debug("snd_card_TW68_capture_trigger: card 0x%p, runtime BD 0%d hw_ptr 0x%p, runtime->control->appl_ptr 0x%p, Cap avail xfer_align 0x%X\n", - // card_TW68, runtime->boundary, runtime->status->hw_ptr, runtime->control->appl_ptr, avail); ///runtime->xfer_align); - - - //spin_lock(&pcm->lock); - + //pr_debug("%s: cmd=%d ctw 0x%p\n", __func__, cmd, ctw); switch (cmd) { case SNDRV_PCM_TRIGGER_START: - dev->videoDMA_ID |= (1 << (nId +8)); - dev->videoCap_ID |= (1 << (nId +8)); - - dwReg = reg_readl(DMA_CHANNEL_ENABLE); - dwReg |= (1<<(nId + 8)); - reg_writel(DMA_CHANNEL_ENABLE, dwReg); - dwReg = reg_readl(DMA_CHANNEL_ENABLE); - - dwRegF = reg_readl(DMA_CMD); - dwRegF |= (1<< (nId+8)); - dwRegF |= (1<<31); - reg_writel(DMA_CMD, dwRegF); - dwRegF = reg_readl(DMA_CMD); + start = 1; break; case SNDRV_PCM_TRIGGER_STOP: - dev->videoDMA_ID &= ~(1 << (nId +8)); - dev->videoCap_ID &= ~(1 << (nId +8)); - - dwReg = reg_readl(DMA_CHANNEL_ENABLE); - dwReg &= ~(1<<(nId + 8)); - reg_writel(DMA_CHANNEL_ENABLE, dwReg); - dwReg = reg_readl(DMA_CHANNEL_ENABLE); - - dwRegF = reg_readl(DMA_CMD); - dwRegF &= ~(1<< (nId+8)); - //dwRegF |= (1<<31); - reg_writel(DMA_CMD, dwRegF); - dwRegF = reg_readl(DMA_CMD); + start = 0; break; default: - ret = -EINVAL; + pr_debug("%s: cmd %d not supported\n", __func__, cmd); + return -EINVAL; } - - //spin_unlock(&pcm->lock); - pr_debug("%s() cmd %X ret %X DMA_CHANNEL_ENABLE 0x%X 0x%X\n", __func__, cmd, ret, dwReg, dwRegF); - return ret; + spin_lock_irqsave(&dev->slock, flags); + dwReg = reg_readl(DMA_CHANNEL_ENABLE); + dwRegF = reg_readl(DMA_CMD); + if (start) { + dev->videoDMA_ID |= mask; + dev->videoCap_ID |= mask; + dwReg |= mask; + dwRegF |= mask | (1<<31); + } else { + dev->videoDMA_ID &= ~mask; + dev->videoCap_ID &= ~mask; + dwReg &= ~mask; + dwRegF &= ~mask; + } + reg_writel(DMA_CHANNEL_ENABLE, dwReg); + reg_writel(DMA_CMD, dwRegF); + spin_unlock_irqrestore(&dev->slock, flags); +// pr_debug("%s: cmd %X DMA_CHANNEL_ENABLE 0x%x 0x%x\n", __func__, cmd, dwReg, dwRegF); + return 0; } @@ -266,49 +215,79 @@ static int snd_card_TW68_capture_trigger(struct snd_pcm_substream *substream, in static int snd_card_TW68_capture_prepare(struct snd_pcm_substream * substream) { - int nId = substream->number; - u32 dmaP; - u32 dmaB; - u32 dwREG = 0x30; ///0x38; - u32 dwREGA; - - u32 Currenrt_SAMPLE_RATE = substream->runtime->rate; - - - //struct snd_pcm_runtime *runtime = substream->runtime; - //snd_card_TW68_pcm_t *pcm; - snd_card_TW68_t *card_TW68 = snd_pcm_substream_chip(substream); + int k = substream->number; + u32 dma_ch; + u32 pb_status; + u32 mask = (1 << (k + 8)); + u32 sr = substream->runtime->rate; + u32 frame_bits = substream->runtime->frame_bits; + u32 audio_dma_size; + struct snd_card_tw68 *ctw = snd_pcm_substream_chip(substream); struct TW68_dev *dev; + __u32 __iomem *chbase; + u32 reg_addr = DMA_CH8_CONFIG_P + k * 2; - if (!card_TW68) { + if (!ctw) { pr_err("%s: can't find device struct.\n", __func__); return -ENODEV; } - dev = card_TW68 ->dev; - - dmaP = dev->m_AudioBuffer.dma + (DMA_page <<1)* nId; - dmaB = dev->m_AudioBuffer.dma + (DMA_page <<1)* nId + DMA_page; - - reg_writel(DMA_CH8_CONFIG_P + nId*2, dmaP ); - reg_writel(DMA_CH8_CONFIG_B + nId*2, dmaB ); - - - if (nId <4) { - reg_writel(AUDIO_GAIN_0 + nId, dwREG); - dwREG = reg_readl(AUDIO_GAIN_0 + nId); + dev = ctw->dev; + chbase = dev->lmmio + ((k & 4) * 0x40); + writel(readl(chbase + POWER_DOWN_CTRL) & ~0x90, chbase + POWER_DOWN_CTRL); + audio_dma_size = snd_pcm_lib_period_bytes(substream); + ctw->audio_lock_mask &= ~mask; + if (((ctw->audio_dma_size == audio_dma_size) && + (ctw->audio_rate == sr) && + (ctw->audio_frame_bits == frame_bits)) || + !ctw->audio_lock_mask) { + u64 q; + u32 ctrl1, ctrl2, ctrl3; + + ctw->audio_dma_size = audio_dma_size; + ctw->audio_rate = sr; + ctw->audio_frame_bits = frame_bits; + ctw->audio_lock_mask |= mask; + + q = (u64)125000000 << 16; + do_div(q, sr); + ctrl2 = (u32)q; + ctrl1 = (ctw->audio_dma_size << 19) | (((ctrl2 >> 16) & 0x3fff) << 5) | (1 << 0); + ctrl3 = reg_readl(AUDIO_CTRL3); + if (frame_bits == 8) + ctrl3 |= 0x100; + else + ctrl3 &= ~0x100; + reg_writel(AUDIO_CTRL1, ctrl1); + reg_writel(AUDIO_CTRL2, ctrl2); + reg_writel(AUDIO_CTRL3, ctrl3); + pr_debug("%s: AUDIO_CTRL1: 0x%x 0x%x\n", __func__, reg_readl(AUDIO_CTRL1), ctrl1); + pr_debug("%s: AUDIO_CTRL2: 0x%x 0x%x\n", __func__, reg_readl(AUDIO_CTRL2), ctrl2); + pr_debug("%s: AUDIO_CTRL3: 0x%x 0x%x\n", __func__, reg_readl(AUDIO_CTRL3), ctrl3); + pr_debug("%s: audio_dma_size=0x%x lock=0x%x\n", + __func__, ctw->audio_dma_size, ctw->audio_lock_mask); } else { - // internal decoders - reg_writel(AUDIO_GAIN_0 + 0x100 + nId, dwREG); - dwREG = reg_readl(AUDIO_GAIN_0 + 0x100 + nId); + pr_err("%s: can't change size=%x %x, rate=%d %d frame_bits %d %d lock=%x\n", + __func__, ctw->audio_dma_size, audio_dma_size, + ctw->audio_rate, sr, + ctw->audio_frame_bits, frame_bits, ctw->audio_lock_mask); + return -EINVAL; } - ///Currenrt_SAMPLE_RATE = pNewFormat->WaveFormatEx.nSamplesPerSec; - //dwREG = (u32)(((u64)(125000000) <<16)/(Currenrt_SAMPLE_RATE )); - dwREG = ((125000000 <<5)/(Currenrt_SAMPLE_RATE >>2 )) <<9; - reg_writel(AUDIO_CTRL2, dwREG); - dwREGA = reg_readl(AUDIO_CTRL2); - pr_debug("%s: AUDIO_CTRL2: 0x%x 0x%X\n", __func__, dwREGA, dwREG); - pr_debug("%s: dev %p substream->runtime->rate %d dwREG: 0x%X\n", __func__, dev, Currenrt_SAMPLE_RATE, dwREG); + dma_ch = dev->m_AudioBuffer.dma + AUDIO_CH_BUF_SIZE * k; + pb_status = reg_readl(DMA_PB_STATUS) & mask; + ctw->last_audio_PB &= ~mask; + ctw->last_audio_PB |= pb_status; + if (!pb_status) + reg_addr++; + reg_writel(reg_addr, dma_ch); + reg_addr ^= 1; + reg_writel(reg_addr, dma_ch + ctw->audio_dma_size); + ctw->period_insert[k] = 2; + + writel(0xc0, chbase + AUDIO_DET_PERIOD); + writel(0, chbase + AUDIO_DET_THRESHOLD1); + writel(0, chbase + AUDIO_DET_THRESHOLD2); + pr_debug("%s: dev %p substream->runtime->rate %d\n", __func__, dev, sr); return 0; } @@ -323,28 +302,22 @@ static int snd_card_TW68_capture_prepare(struct snd_pcm_substream * substream) * */ -static snd_pcm_uframes_t -snd_card_TW68_capture_pointer(struct snd_pcm_substream * substream) +static snd_pcm_uframes_t snd_card_TW68_capture_pointer( + struct snd_pcm_substream * substream) { - struct snd_pcm_runtime *runtime = substream->runtime; - - //snd_card_TW68_t *card_TW68 = snd_pcm_substream_chip(substream); - // 4096 byte /2 - return DMA_page *8 /runtime->frame_bits; + struct snd_card_tw68 *ctw = snd_pcm_substream_chip(substream); + int period = ctw->period_insert[substream->number]; + snd_pcm_uframes_t frames; + + period -= 2; + if (period < 0) + period += substream->runtime->periods; + frames = period * ctw->audio_dma_size; + if (ctw->audio_frame_bits != 8) + frames >>= 1; + return frames; } - - -static void snd_card_TW68_runtime_free(struct snd_pcm_runtime *runtime) -{ - snd_card_TW68_pcm_t *pcm = runtime->private_data; - //struct TW68_dev *dev = pcm->dev; - - pr_debug("%s()\n", __func__); - kfree(pcm); -} - - /* * ALSA hardware params * @@ -357,12 +330,8 @@ static void snd_card_TW68_runtime_free(struct snd_pcm_runtime *runtime) static int snd_card_TW68_hw_params(struct snd_pcm_substream * substream, struct snd_pcm_hw_params * hw_params) { - ///int err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - int err =0; - pr_debug("%s() substream->runtime->rate %d err:0x%X\n", __func__, substream->runtime->rate, err); - // return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + pr_debug("%s\n", __func__); return 0; - } /* @@ -377,7 +346,7 @@ static int snd_card_TW68_hw_params(struct snd_pcm_substream * substream, static int snd_card_TW68_hw_free(struct snd_pcm_substream * substream) { - pr_debug("%s()\n", __func__); + pr_debug("%s\n", __func__); return 0; } @@ -392,7 +361,12 @@ static int snd_card_TW68_hw_free(struct snd_pcm_substream * substream) static int snd_card_TW68_capture_close(struct snd_pcm_substream * substream) { - pr_debug("%s()\n", __func__); + int k = substream->number; + u32 mask = (1 << (k + 8)); + struct snd_card_tw68 *ctw = snd_pcm_substream_chip(substream); + + pr_debug("%s\n", __func__); + ctw->audio_lock_mask &= ~mask; return 0; } @@ -407,36 +381,33 @@ static int snd_card_TW68_capture_close(struct snd_pcm_substream * substream) static int snd_card_TW68_capture_open(struct snd_pcm_substream * substream) { + int k = substream->number; struct snd_pcm_runtime *runtime = substream->runtime; - snd_card_TW68_pcm_t *pcm; - snd_card_TW68_t *card_TW68 = snd_pcm_substream_chip(substream); + struct snd_card_tw68 *ctw = snd_pcm_substream_chip(substream); struct TW68_dev *dev; int err; - if (!card_TW68) { + if (!ctw) { pr_err("%s: can't find device struct\n", __func__); return -ENODEV; } - dev = card_TW68 ->dev; - - pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); - if (pcm == NULL) - return -ENOMEM; - - pcm->dev=dev; + dev = ctw->dev; - spin_lock_init(&pcm->lock); - - pcm->substream = substream; - runtime->private_data = pcm; - runtime->private_free = snd_card_TW68_runtime_free; runtime->hw = snd_card_tw68_pcm_hw; + runtime->dma_area = (u8 *)dev->m_AudioBuffer.cpu + k * AUDIO_CH_BUF_SIZE; + runtime->dma_bytes = AUDIO_CH_BUF_SIZE; + err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); + SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) return err; - pr_debug("%s() substream %p N:%d %s rate %d \n", __func__, + /* Align to 4 bytes */ + err = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); + if (err < 0) + return err; + pr_debug("%s: substream %p N:%d %s rate %d \n", __func__, substream, substream->number, substream->name, runtime->rate ); return 0; @@ -444,55 +415,6 @@ static int snd_card_TW68_capture_open(struct snd_pcm_substream * substream) /* - * ALSA capture start - * - * - One of the ALSA capture callbacks. - * - * Called when pcm data ready for user - * - */ - -static int snd_TW68_pcm_copy(struct snd_pcm_substream *ss, int channel, - snd_pcm_uframes_t pos, void __user *dst, - snd_pcm_uframes_t count) -{ - //struct snd_card_TW68_pcm *pcm = snd_pcm_substream_chip(ss); - //int err, i; - int nId = ss->number; - long avail =0; - struct snd_pcm_runtime *runtime = ss->runtime; - - snd_card_TW68_t *card_TW68 = snd_pcm_substream_chip(ss); - struct TW68_dev *dev = card_TW68 ->dev; - - struct TW68_pgtable p_Audio = dev ->m_AudioBuffer; - u8* Audioptr = (u8*)p_Audio.cpu + (nId * (PAGE_SIZE <<1)); - u8* AudioVB = card_TW68->audio_ringbuffer + (nId * (PAGE_SIZE <<1)); - - if (runtime->hw_ptr_base) { - Audioptr += DMA_page; - AudioVB += DMA_page; - } - /* - pr_debug("%s() nId:%d; count:%X %d AP 0X%p ", __func__, nId, count, count, Audioptr); - - pr_debug("%s() dev 0x%p A 0x%X k:%d ss:%p BF:%d P:%d S:%d F:%d \n", __func__, dev, p_Audio.size, ss->number, ss, - runtime->buffer_size, runtime->period_size, runtime->sample_bits, runtime->frame_bits ); - */ - avail = snd_pcm_capture_avail(runtime); - //pr_debug(" card 0x%p, TW68_pcm 0x%p runtime BD 0%d hw_ptr b0x%p, s0x%p, runtime->control->appl_ptr 0x%p, Cap avail xfer_align 0x%X\n", - // card_TW68, pcm, runtime->boundary, runtime->hw_ptr_base, runtime->status->hw_ptr, runtime->control->appl_ptr, avail); ///runtime->xfer_align); - - AudioVB = Audioptr + DMA_page - (avail* runtime->frame_bits/8); - - if (copy_to_user_fromio(dst, AudioVB, count*runtime->frame_bits/8)) { - pr_debug(" copy from io to user fail xxxx \n"); - return -EFAULT; - } - return 0; -} - -/* * ALSA capture callbacks definition */ @@ -505,10 +427,60 @@ static struct snd_pcm_ops snd_card_TW68_capture_ops = { .prepare = snd_card_TW68_capture_prepare, .trigger = snd_card_TW68_capture_trigger, .pointer = snd_card_TW68_capture_pointer, - .copy = snd_TW68_pcm_copy, //.page = snd_card_TW68_page, }; +/* 7 bits, 0 : .5, 127 : 2.484375, n : .5 + n/64 */ +static int gain_info(struct snd_kcontrol *ctl, + struct snd_ctl_elem_info *info) +{ + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; + info->value.integer.min = 0; + info->value.integer.max = 127; + return 0; +} + +static int gain_get(struct snd_kcontrol *ctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct TW68_dev *dev = ctl->private_data; + int k = snd_ctl_get_ioffidx(ctl, &ucontrol->id); + __u32 __iomem *chbase = dev->lmmio + ((k & 4) * 0x40); + u32 gain; + + gain = readl(chbase + AUDIO_GAIN_CH0 + (k & 3)); + ucontrol->value.integer.value[0] = gain; + pr_debug("%s: gain[%d]=%d\n", __func__, k, gain); + return 0; +} + +static int gain_put(struct snd_kcontrol *ctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct TW68_dev *dev = ctl->private_data; + int k = snd_ctl_get_ioffidx(ctl, &ucontrol->id); + __u32 __iomem *chbase = dev->lmmio + ((k & 4) * 0x40); + u32 gain; + + gain = ucontrol->value.integer.value[0]; + if (gain < 0 || gain > 127) + return -EINVAL; + pr_debug("%s: gain[%d]=%d\n", __func__, k, gain); + writel(gain, chbase + AUDIO_GAIN_CH0 + (k & 3)); + return 0; +} + +static const struct snd_kcontrol_new gain_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic Capture Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = gain_info, + .get = gain_get, + .put = gain_put, + .count = AUDIO_NCH, +}; + /* * ALSA PCM setup * @@ -517,41 +489,44 @@ static struct snd_pcm_ops snd_card_TW68_capture_ops = { * */ -static int snd_card_TW68_pcm_reg(snd_card_TW68_t *card_TW68, long idevice) +static int snd_card_TW68_pcm_reg(struct snd_card_tw68 *ctw, long idevice) { struct snd_pcm *pcm; struct snd_pcm_substream *ss; int err, i; + struct snd_kcontrol *ctl; - pr_debug("%s()\n", __func__); - if ((err = snd_pcm_new(card_TW68->card, "TW6869 PCM", idevice, 0, audio_nCH, &pcm)) < 0) //0, 1 + pr_debug("%s\n", __func__); + if ((err = snd_pcm_new(ctw->card, "TW6869 PCM", idevice, 0, AUDIO_NCH, &pcm)) < 0) //0, 1 return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_TW68_capture_ops); - pcm->private_data = card_TW68; + pcm->private_data = ctw; pcm->info_flags = 0; strcpy(pcm->id, "TW68 PCM"); strcpy(pcm->name, "TW68 Analog Audio Capture"); - card_TW68->TW68_pcm = pcm; + ctw->TW68_pcm = pcm; + for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; ss; ss = ss->next, i++) { sprintf(ss->name, "TW68 #%d Audio In ", i); - card_TW68->substream[i] = ss; - pr_debug("%s() substream[%d] %p\n", __func__, i, card_TW68->substream[i]); + ctw->substream[i] = ss; + pr_debug("%s: substream[%d] %p\n", __func__, i, ctw->substream[i]); } - return 0; + + ctl = snd_ctl_new1(&gain_control, ctw->dev); + err = snd_ctl_add(ctw->card, ctl); + return err; } static void snd_TW68_free(struct snd_card * card) { - snd_card_TW68_t *card_TW68 = (snd_card_TW68_t*)card->private_data; + struct snd_card_tw68 *ctw = (struct snd_card_tw68*)card->private_data; - if (card_TW68->audio_ringbuffer) - vfree(card_TW68->audio_ringbuffer); - pr_debug("%s: card_TW68 %p\n", __func__, card_TW68); + pr_debug("%s: ctw %p\n", __func__, ctw); } /* @@ -566,7 +541,7 @@ int TW68_alsa_create(struct TW68_dev *dev) { struct snd_card *card = NULL; - snd_card_TW68_t *card_TW68; + struct snd_card_tw68 *ctw; static struct snd_device_ops ops = { NULL }; int err; @@ -578,7 +553,7 @@ int TW68_alsa_create(struct TW68_dev *dev) err = snd_card_create(SNDRV_DEFAULT_IDX1, "TW68 SoundCard", THIS_MODULE, - sizeof(snd_card_TW68_t), &card); + sizeof(struct snd_card_tw68), &card); if (err < 0) return err; @@ -594,17 +569,18 @@ int TW68_alsa_create(struct TW68_dev *dev) return err; card->private_free = snd_TW68_free; - card_TW68 = (snd_card_TW68_t *) card->private_data; - card_TW68->dev = dev; - card_TW68->card= card; + ctw = (struct snd_card_tw68 *)card->private_data; + ctw->dev = dev; + ctw->card= card; + ctw->last_audio_PB = 0xffff00; dev->card = card; - spin_lock_init(&card_TW68->lock); + spin_lock_init(&ctw->lock); - pr_debug("alsa: %s registered as card %s card_TW68 %p err :%d \n",card->longname, card->shortname, card_TW68, err); + pr_debug("alsa: %s registered as card %s ctw %p err :%d \n", card->longname, card->shortname, ctw, err); - if ((err = snd_card_TW68_pcm_reg(card_TW68, 0)) < 0) + if ((err = snd_card_TW68_pcm_reg(ctw, 0)) < 0) goto __nodev; ///snd_card_set_dev(card, dev); @@ -617,7 +593,6 @@ int TW68_alsa_create(struct TW68_dev *dev) pr_debug("alsa: %s registered as PCM card %s :%d \n",card->longname, card->shortname, err); if ((err = snd_card_register(card)) == 0) { - card_TW68->audio_ringbuffer = vmalloc(MAX_BUFFER); TW68_audio_nPCM++; return 0; } diff --git a/drivers/media/pci/TW68/TW68-core.c b/drivers/media/pci/TW68/TW68-core.c index 6ab9165e917d..3de2889c8e37 100644 --- a/drivers/media/pci/TW68/TW68-core.c +++ b/drivers/media/pci/TW68/TW68-core.c @@ -359,29 +359,10 @@ unsigned long TW68_buffer_base(struct TW68_buf *buf) int AudioDMA_PB_alloc(struct pci_dev *pci, struct TW68_pgtable *pt) { - dma_addr_t dma_addr; - int audio_ch; - //__le32 *clean; - __le32 *pdmaP, *pdmaB; - __le32 *AudioPages; - - // for audio CH P/B - - AudioPages = pci_alloc_consistent(pci, PAGE_SIZE * MAX_NUM_DATA_DMA * 2, &dma_addr); - - if (NULL == AudioPages) { + pt->size = AUDIO_CH_BUF_SIZE * AUDIO_NCH; //pt; //2 + pt->cpu = pci_alloc_consistent(pci, pt->size, &pt->dma); + if (!pt->cpu) return -ENOMEM; - } - - pt->size = PAGE_SIZE * MAX_NUM_DATA_DMA * 2; //pt; //2 - pt->cpu = AudioPages; - pt->dma = dma_addr; - - for (audio_ch =0; audio_ch < MAX_NUM_DATA_DMA; audio_ch++) { - pdmaP = pt->cpu + (PAGE_SIZE <<1)* audio_ch /4 + 100; - pdmaB = pt->cpu + ((PAGE_SIZE <<1)* audio_ch + PAGE_SIZE)/4 + 100; - - } return 0; } @@ -1139,13 +1120,7 @@ void DecoderResize(struct TW68_dev *dev, int nId, int nHeight, int nWidth) nH = (240*256)/nH; } - if(nId >= 4) { - nAddr = (EX_VSCALE1_LO + ((nId-4)<<1) + (nId-4)) + 0x100; //EX_VSCALE1_LO + 0|3|6|9 - nAddr = VSCALE1_LO + ((nId-4)<<4) + 0x100; //6869 0x200 VSCALE1_LO + 0|0x10|0x20|0x30 - } else { - nAddr = VSCALE1_LO + (nId<<4); //VSCALE1_LO + 0|0x10|0x20|0x30 - } - + nAddr = VSCALE1_LO + ((nId & 3) << 4) + ((nId & 4) * 0x40); //VSCALE1_LO + 0|0x10|0x20|0x30 nVal = nH & 0xFF; //V /* @@ -1402,8 +1377,6 @@ int VideoDecoderDetect(struct TW68_dev *dev, unsigned int DMA_nCH) regDW = reg_readl(DECODER0_STATUS + (DMA_nCH* 0x10)); dwReg = reg_readl(DECODER0_SDT + (DMA_nCH* 0x10)); } else { // 6869 VD 5-8 - //regDW = (ULONG)DeviceRead2864(this, VIDEO_STATUS_0 + ((nID -4)* 0x10)); - //dwReg = (ULONG)DeviceRead2864(this, exVD0_SDT + ((nID -4)* 0x10)); regDW = reg_readl(DECODER0_STATUS + ((DMA_nCH -4)* 0x10) + 0x100); dwReg = reg_readl(DECODER0_SDT + ((DMA_nCH -4)* 0x10) + 0x100); //pr_debug("\n\n Decoder 0x%X VideoStandardDetect DMA_nCH %d regDW 0x%x dwReg%d \n", (DECODER0_STATUS + (DMA_nCH* 0x10) + 0x100), regDW, dwReg ); @@ -1428,7 +1401,6 @@ static irqreturn_t TW68_irq(int irq, void *dev_id) //hardware dev id for the unsigned long flags, audio_ch, k, eno, handled; u32 dwRegST, dwRegER, dwRegPB, dwRegE, dwRegF, dwRegVP, dwErrBit; static int INT1st = 1; - static u32 lastPB = 0; //__le32 *pdmaP, *pdmaB; audio_ch = 1; @@ -1436,41 +1408,32 @@ static irqreturn_t TW68_irq(int irq, void *dev_id) //hardware dev id for the spin_lock_irqsave(&dev->slock, flags); + dwRegPB = reg_readl(DMA_PB_STATUS); dwRegST = reg_readl(DMA_INT_STATUS); dwRegER = reg_readl(DMA_INT_ERROR); - dwRegPB = reg_readl(DMA_PB_STATUS); dwRegE = reg_readl(DMA_CHANNEL_ENABLE); dwRegVP = reg_readl(VIDEO_PARSER_STATUS); dwRegF = reg_readl(DMA_CMD); spin_unlock_irqrestore(&dev->slock, flags); + pr_debug("%s: PB=0x%x ST=0x%x ER=0x%x E=0x%x VP=0x%x CMD=0x%x\n", + __func__, dwRegPB, dwRegST, dwRegER, dwRegE, dwRegVP, dwRegF); if (dev->videoDMA_ID != dwRegE) { INT1st++; - if (INT1st <10) - pr_debug(" -------------Check DMA DMA_CHANNEL_ENABLE 0x%X, DMA_CMD 0x%X, DMA_INT_STATUS 0x%08X videoDMA_ID 0x%X\n", - dwRegE, dwRegF, dwRegST, dev->videoDMA_ID ); + if (INT1st < 10) + pr_debug("%s: dwRegE=0x%x, dwRegF=0x%x, dwRegST=0x%x videoDMA_ID=0x%x\n", + __func__, dwRegE, dwRegF, dwRegST, dev->videoDMA_ID); } - /* - for (audio_ch =0; audio_ch < MAX_NUM_DATA_DMA; audio_ch++) { - //pdmaP = dev->m_AudioBuffer.cpu + (PAGE_SIZE <<1)* audio_ch + 100; - //pdmaB = dev->m_AudioBuffer.cpu + (PAGE_SIZE <<1)* audio_ch + PAGE_SIZE + 100; - - pdmaP = dev->m_AudioBuffer.cpu + (PAGE_SIZE <<1)* audio_ch /4 + 100; - pdmaB = dev->m_AudioBuffer.cpu + ((PAGE_SIZE <<1)* audio_ch + PAGE_SIZE)/4 + 100; - //pr_debug("---Audio DMA 0x19-0x29 config --- CH%02d *dmaP 0X%x *dmaB 0X%x dword 0X%x 0X%x \n", - // audio_ch, pdmaP, pdmaB, *pdmaP, *pdmaB ); - } - */ - if((dwRegER &0xFF000000) && dev->video_DMA_1st_started && dev->err_times<9) { dev->video_DMA_1st_started --; if (dev->video_DMA_1st_started < 0) dev->video_DMA_1st_started = 0; dev->err_times++; - pr_debug("DeviceInterrupt: 1st startup err_times:%d ## dma_status (err) =0x%x dwRegVP (video parser)=0X%x int_status 0x%x dwRegE 0X%x \n", dev->err_times, dwRegER, dwRegVP, dwRegST, dwRegE); + pr_debug("%s: err_times:%d dwRegER=0x%x dwRegVP=0x%x dwRegST=0x%x dwRegE=0x%x\n", + __func__, dev->err_times, dwRegER, dwRegVP, dwRegST, dwRegE); } else { if((dwRegER>>16 ) || dwRegVP || (dwRegST >>24)) { //stop //err_exist, such as cpl error, tlp error, time-out @@ -1502,25 +1465,20 @@ static irqreturn_t TW68_irq(int irq, void *dev_id) //hardware dev id for the dwRegF = reg_readl(DMA_CMD); spin_unlock_irqrestore(&dev->slock, flags); - pr_debug("DeviceInterrupt: errors ## dma_status 0x%X (err) =0x%X dwRegVP (video parser)=0X%x int_status 0x%x # dwRegE 0X%x dwRegF 0X%x \n", - dwErrBit, dwRegER, dwRegVP, dwRegST, dwRegE, dwRegF); + pr_debug("%s:dwErrBit=0x%x dwRegER=0x%x dwRegVP=0x%x dwRegST=0x%x dwRegE=0x%x dwRegF=0x%x\n", + __func__, dwErrBit, dwRegER, dwRegVP, dwRegST, dwRegE, dwRegF); dev->errlog[0] = jiffies; } else { // Normal interrupt: - // pr_debug(" Normal interrupt: ++++ ## dma_status 0x%X FIFO =0x%X (video parser)=0X%x int_status 0x%x PB 0x%x # dwRegE 0X%x dwRegF 0X%x \n", - // dwRegST, dwRegER, dwRegVP, dwRegST, dwRegPB, dwRegE, dwRegF); - if (dwRegST & (0xFF00) & dev->videoDMA_ID) { TW68_alsa_irq(dev, dwRegST, dwRegPB); } - if (lastPB != dwRegPB) // skip the conflict interrupt - if ((dwRegST & (0xFF)) && (!(dwRegER >>16))) { - for(k=0; k<8; k++) { - if ((dwRegST & dev->videoDMA_ID) & (1 << k)) { //exclude inactive dev - TW68_irq_video_done(dev, k+1, dwRegPB); - - if (!dev->video_dmaq[k+1].FieldPB) { // first time after dma start + if ((dwRegST & (0xFF)) && (!(dwRegER >>16))) { + for(k=0; k<8; k++) { + if ((dwRegST & dev->videoDMA_ID) & (1 << k)) { //exclude inactive dev + TW68_irq_video_done(dev, k+1, dwRegPB); + if (!dev->video_dmaq[k+1].FieldPB) { // first time after dma start /* Reg8b <<= 16; dev->video_dmaq[k+1].FieldPB &= 0x0000FFFF; @@ -1530,23 +1488,23 @@ static irqreturn_t TW68_irq(int irq, void *dev_id) //hardware dev id for the if (Reg8b &0x10) dev->video_dmaq[k].FieldPB |= 0xF0; */ - } - - if (dev->video_dmaq[k+1].FieldPB & 0xF0) { - dev->video_dmaq[k+1].FieldPB &= 0xFFFF0000; - } else { - dev->video_dmaq[k+1].FieldPB &= 0xFFFF00FF; // clear PB - dev->video_dmaq[k+1].FieldPB |= (dwRegPB & (1<<k))<<8; - dev->video_dmaq[k+1].FCN++; - } + } + + if (dev->video_dmaq[k+1].FieldPB & 0xF0) { + dev->video_dmaq[k+1].FieldPB &= 0xFFFF0000; + } else { + dev->video_dmaq[k+1].FieldPB &= 0xFFFF00FF; // clear PB + dev->video_dmaq[k+1].FieldPB |= (dwRegPB & (1<<k))<<8; + dev->video_dmaq[k+1].FCN++; } } } + } if (dev->videoRS_ID) { dev->videoDMA_ID |= dev->videoRS_ID; - dev-> videoRS_ID =0; - dwRegE = dev ->videoDMA_ID; + dev->videoRS_ID = 0; + dwRegE = dev->videoDMA_ID; reg_writel(DMA_CHANNEL_ENABLE, dwRegE); dwRegF = reg_readl(DMA_CHANNEL_ENABLE); @@ -1590,10 +1548,10 @@ static int TW68_hwinit1(struct TW68_dev *dev) u32 m_StartIdx, m_EndIdx, m_nVideoFormat, m_dwCHConfig, dwReg; u32 m_bHorizontalDecimate=0, m_bVerticalDecimate=0, m_nDropChannelNum; u32 m_bDropMasterOrSlave, m_bDropField, m_bDropOddOrEven, m_nCurVideoChannelNum; - u32 regDW, val1, addr, k, ChannelOffset, pgn; + u32 regDW, val1, k, ChannelOffset, pgn; // Audio P int audio_ch; - u32 dmaP, dmaB; + u32 dmaP; pr_debug(" TW6869 hwinit1 \n"); mutex_init(&dev->lock); @@ -1745,28 +1703,16 @@ static int TW68_hwinit1(struct TW68_dev *dev) } // setup audio DMA - for (audio_ch =0; audio_ch < MAX_NUM_DATA_DMA; audio_ch++) { - dmaP = dev->m_AudioBuffer.dma + (PAGE_SIZE <<1)* audio_ch; - dmaB = dev->m_AudioBuffer.dma + (PAGE_SIZE <<1)* audio_ch + PAGE_SIZE; - + for (audio_ch =0; audio_ch < AUDIO_NCH; audio_ch++) { + dmaP = dev->m_AudioBuffer.dma + AUDIO_CH_BUF_SIZE * audio_ch; reg_writel(DMA_CH8_CONFIG_P + audio_ch*2, dmaP ); //Audio B = P+1 - reg_writel(DMA_CH8_CONFIG_B + audio_ch*2, dmaB ); + reg_writel(DMA_CH8_CONFIG_B + audio_ch*2, dmaP + AUDIO_DMA_PAGE); - //pr_debug("---Audio DMA 0x19-0x29 config --- CH%02d write dmaP 0X%p dmaB 0X%p read 0X%x 0X%x \n", - // audio_ch, dmaP, dmaB, reg_readl(DMA_CH8_CONFIG_P + audio_ch*2), reg_readl(DMA_CH8_CONFIG_B + audio_ch*2) ); + //pr_debug("---Audio DMA 0x19-0x29 config --- CH%02d write dmaP 0X%p read 0X%x 0X%x\n", + // audio_ch, dmaP, reg_readl(DMA_CH8_CONFIG_P + audio_ch*2), reg_readl(DMA_CH8_CONFIG_B + audio_ch*2) ); } - /* - pr_debug(" \n"); - u8 *Audioptr = (u8*)dev->m_AudioBuffer.cpu; - - for (k=0; k<(4096*16); k++) { - *(Audioptr +k)= 0xF0; - //pr_debug(" 0x%x ", (*(Audioptr +k))); - } - pr_debug(" \n"); - */ //pr_debug(" Mmio %s: CFG[0x78] cpu 0x%x dma 0x%x \n", dev->name, (unsigned int)dev->m_Page0.cpu, dev->m_Page0.dma ); regDW = reg_readl((DMA_PAGE_TABLE0_ADDR) ); @@ -1805,11 +1751,11 @@ static int TW68_hwinit1(struct TW68_dev *dev) regDW = reg_readl(DMA_CHANNEL_ENABLE ); pr_debug("DMA %s: tw DMA_CHANNEL_ENABLE %x :: 0x%x \n", dev->name, DMA_CHANNEL_ENABLE, regDW ); //reg_writel(DMA_CHANNEL_TIMEOUT, 0x180c8F88); // 860 a00 0x140c8560 0x1F0c8b08 0xF00F00 140c8E08 0x140c8D08 - reg_writel(DMA_CHANNEL_TIMEOUT, 0x3EFF0FF0); // longer timeout setting + reg_writel(DMA_CHANNEL_TIMEOUT, (0x3E << 24) | (0x7f0 << 12) | 0xff0); // longer timeout setting regDW = reg_readl(DMA_CHANNEL_TIMEOUT ); pr_debug("DMA %s: tw DMA_CHANNEL_TIMEOUT %x :: 0x%x \n", dev->name, DMA_CHANNEL_TIMEOUT, regDW ); - reg_writel(DMA_INT_REF, 0x38000); // 2a000 2b000 2c000 3932e 0x3032e + reg_writel(DMA_INT_REF, 0x1c000); // 2a000 2b000 2c000 3932e 0x3032e regDW = reg_readl(DMA_INT_REF ); pr_debug("DMA %s: tw DMA_INT_REF %x :: 0x%x \n", dev->name, DMA_INT_REF, regDW ); @@ -1866,19 +1812,6 @@ static int TW68_hwinit1(struct TW68_dev *dev) reg_writel(CSR_REG, val1); //pr_debug("2864 init CSR_REG 0x%x]= I2C 2864 val1:0X%x %x\n", CSR_REG, val1 ); - addr = CLKOCTRL | 0x100; - //val0 = DeviceRead2864(dev, addr); - val1 = 0x40 | (VIDEO_IN_MODE | (VIDEO_IN_MODE<<2) ) ; // Out enable - //DeviceWrite2864(dev, addr, (unsigned char)val1); - //val2=DeviceRead2864(dev, addr); - //pr_debug("2864[CLKOCTRL 0x%x]= I2C 2864 val0:0X%x val1:0X%x val2:0X%x\n", CLKOCTRL, val0, val1, val2 ); - - addr = NOVID | 0x100; - val1 = 0x73; // CHID with 656 Sync code, 656 output even no video input - //val0 = DeviceRead2864(dev,addr); - //DeviceWrite2864(dev,addr,val1); - //val2 = DeviceRead2864(dev,addr); - // device data structure initialization TW68_video_init1(dev); diff --git a/drivers/media/pci/TW68/TW68-video.c b/drivers/media/pci/TW68/TW68-video.c index cf1879401037..7883faa5aeca 100644 --- a/drivers/media/pci/TW68/TW68-video.c +++ b/drivers/media/pci/TW68/TW68-video.c @@ -666,9 +666,7 @@ int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *si //pr_debug(" ####%%%%%%%%%%%%%%%%%%%%%%% buffer_setup:: DECODER0_SDT %d, 0X%X \n", nId, dwReg); reg_writel(DECODER0_SDT+ (nId*0x10), 7); /// 0 NTSC } else { - ///dwReg = DeviceRead2864(dev,(exVD0_SDT + ((nId-4)*0x10))); //pr_debug(" ####%%%%%%%%%%%%%%%%%%%%%%% buffer_setup:: DECODER0_SDT %d, 0X%X \n", nId, dwReg); - ///DeviceWrite2864(dev,(exVD0_SDT + ((nId-4)*0x10)), 7); /// 7 auto detect slower } ////////////////////////////// decoder resize ////////////////////////////////////////// @@ -858,9 +856,6 @@ int TW68_g_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_c regval = reg_readl(CH1_BRIGHTNESS_REG + DMA_nCH *0x10 ); regval = (regval + 0x80) &0xFF; } else { - //regval = DeviceRead2864(dev, (EX_BRIGHTNESS1 | 0x100) +(DMA_nCH-4) *0x10); - //regval = regval * 5 /4; - //if (regval > 255) regval = 255; regval = reg_readl(CH1_BRIGHTNESS_REG + 0x100 + (DMA_nCH -4) *0x10 ); regval = (regval + 0x80) &0xFF; } @@ -871,7 +866,6 @@ int TW68_g_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_c if (DMA_nCH<4) { regval = reg_readl(CH1_HUE_REG + DMA_nCH *0x10 ); } else { - //regval = DeviceRead2864(dev, (EX_HUE1 | 0x100) +(DMA_nCH-4) *0x10); regval = reg_readl(CH1_HUE_REG + 0x100 + (DMA_nCH -4) *0x10 ); } if (regval < 0x80) @@ -884,7 +878,6 @@ int TW68_g_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_c if (DMA_nCH<4) { regval = reg_readl(CH1_CONTRAST_REG + DMA_nCH *0x10 ); } else { - // regval = DeviceRead2864(dev, (EX_CONTRAST1 | 0x100) +(DMA_nCH-4) *0x10); regval = reg_readl(CH1_CONTRAST_REG + 0x100 + (DMA_nCH -4) *0x10 ); } c->value = dev->video_param[nId].ctl_contrast = regval; @@ -894,7 +887,6 @@ int TW68_g_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_c if (DMA_nCH<4) { regval = reg_readl(CH1_SAT_U_REG + DMA_nCH *0x10 ); } else { - //regval = DeviceRead2864(dev, (EX_SAT_U1 | 0x100) +(DMA_nCH-4) *0x10); regval = reg_readl(CH1_SAT_U_REG + 0x100 + (DMA_nCH -4) *0x10 ); } c->value = dev->video_param[nId].ctl_saturation = regval /2; @@ -978,9 +970,6 @@ int TW68_s_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_ reg_writel(CH1_BRIGHTNESS_REG + DMA_nCH *0x10, regval ); } else { if (DMA_nCH<8) { - //regval = c->value &0xFF; - //regval = regval * 4 /5; - //DeviceWrite2864(dev, (EX_BRIGHTNESS1 | 0x100) +(DMA_nCH-4) *0x10, regval); reg_writel(CH1_BRIGHTNESS_REG + 0x100 +(DMA_nCH -4) *0x10, regval); } else if (DMA_nCH == 0xF) { reg_writel(CH1_BRIGHTNESS_REG, regval); @@ -996,7 +985,6 @@ int TW68_s_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_ reg_writel(CH1_CONTRAST_REG + DMA_nCH *0x10, c->value); } else { if (DMA_nCH<8) { - //DeviceWrite2864(dev, (EX_CONTRAST1 | 0x100) +(DMA_nCH-4) *0x10, c->value); reg_writel(CH1_CONTRAST_REG + 0x100 +(DMA_nCH -4) *0x10, c->value); } else if (DMA_nCH == 0xF) { reg_writel(CH1_CONTRAST_REG, c->value); @@ -1014,7 +1002,6 @@ int TW68_s_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_ reg_writel(CH1_HUE_REG + DMA_nCH *0x10, regval); } else { if (DMA_nCH<8) { - //DeviceWrite2864(dev, (EX_HUE1 | 0x100) +(DMA_nCH-4) *0x10, regval); reg_writel(CH1_HUE_REG + 0x100 +(DMA_nCH -4) *0x10, regval); } else if (DMA_nCH == 0xF) { reg_writel(CH1_HUE_REG, regval); @@ -1033,8 +1020,6 @@ int TW68_s_ctrl_internal(struct TW68_dev *dev, struct TW68_fh *fh, struct v4l2_ reg_writel(CH1_SAT_V_REG + DMA_nCH *0x10, regval); } else { if (DMA_nCH<8) { - //DeviceWrite2864(dev, (EX_SAT_U1 | 0x100) +(DMA_nCH-4) *0x10, regval); - //DeviceWrite2864(dev, (EX_SAT_V1 | 0x100) +(DMA_nCH-4) *0x10, regval); reg_writel(CH1_SAT_U_REG + 0x100 + (DMA_nCH -4)*0x10, regval); reg_writel(CH1_SAT_V_REG + 0x100 + (DMA_nCH -4)*0x10, regval); } else if (DMA_nCH == 0xF) { // write wrong addr hang @@ -1143,18 +1128,22 @@ static int video_open(struct file *file) mutex_lock(&TW686v_devlist_lock); list_for_each_entry(dev, &TW686v_devlist, devlist) { - pr_debug("%s: minor=%d type=%s openned:%X \n", + pr_debug("%s: minor=%d type=%s opened:%x\n", __func__, minor, v4l2_type_names[type], dev->video_opened); //if (dev->video_dev && (dev->video_dev->minor == minor))v->video_open //if (dev->video_device[0] && (dev->video_device[0]->minor == minor)) - for (k=0; k<9; k++) { // 8 - 9 - pr_debug("%s: search dev->video_device[k]:%p, dev->video_device[k]->minor:%d \n", - __func__, dev->video_device[k], dev->video_device[k]->minor ); + for (k=0; k < ARRAY_SIZE(dev->video_device); k++) { + struct video_device *vdev = dev->video_device[k]; - if (dev->video_device[k] && (dev->video_device[k]->minor == minor)) - goto found; + if (vdev) { + pr_debug("%s: search k=%d vdev=%p, vdev->minor:%d\n", + __func__, k, vdev, vdev->minor); + + if (vdev->minor == minor) + goto found; + } } } @@ -2360,14 +2349,6 @@ int TW68_video_init1(struct TW68_dev *dev) dev->video_param[k].ctl_hue = reg_readl(CH1_HUE_REG + (k-4) *0x10 +0x100); dev->video_param[k].ctl_saturation = reg_readl(CH1_SAT_U_REG + (k-4) *0x10 +0x100) /2; dev->video_param[k].ctl_mute = reg_readl(CH1_SAT_V_REG + (k-4) *0x10 +0x100) /2; - -#if 0 - dev->video_param[k].ctl_bright = DeviceRead2864(dev, (EX_BRIGHTNESS1 | 0x100) + (k-4) *0x10); - dev->video_param[k].ctl_contrast = DeviceRead2864(dev, (EX_CONTRAST1 | 0x100) + (k-4) *0x10); - dev->video_param[k].ctl_hue = DeviceRead2864(dev, (EX_HUE1 | 0x100) +(k-4) *0x10); - dev->video_param[k].ctl_saturation = DeviceRead2864(dev, (EX_SAT_U1 | 0x100) +(k-4) *0x10) /2; - dev->video_param[k].ctl_mute = DeviceRead2864(dev, (EX_SAT_V1 | 0x100) +(k-4) *0x10) /2; -#endif } pr_debug("%s: get decoder %d default AMP: BRIGHTNESS %d CONTRAST %d HUE_ %d SAT_U_%d SAT_V_%d\n", @@ -2429,8 +2410,6 @@ int TW68_video_init2(struct TW68_dev *dev) return 0; } - - void TW68_irq_video_done(struct TW68_dev *dev, unsigned int nId, u32 dwRegPB) { enum v4l2_field field; @@ -2440,14 +2419,14 @@ void TW68_irq_video_done(struct TW68_dev *dev, unsigned int nId, u32 dwRegPB) Fn = (dwRegPB >>24) & (1<< (nId-1)); PB = (dwRegPB ) & (1<< (nId-1)); - if ((dev->video_dmaq[0].DMA_nCH == 0xF ) && ((nId-1) <4) ) { + if ((dev->video_dmaq[0].DMA_nCH == 0xF ) && ((nId-1) < 4) ) { if ((dev->video_dmaq[0].curr)) { //if (dev->QFbit ^ (1 << nId)) { dev->video_dmaq[0].FieldPB = dwRegPB; QF_Field_Copy(dev, (nId-1), Fn, PB); dev->QFbit |= (1 << (nId-1)); //} - //pr_debug("%s: dev->QFbit 0X%X nId= 0X%x \n", __func__, dev->QFbit, nId); + pr_debug("%s: dev->QFbit=0X%x nId=0X%x\n", __func__, dev->QFbit, nId); if ((dev->QFbit & 0xF) == 0xF) { dev->QFbit =0; @@ -2459,8 +2438,7 @@ void TW68_irq_video_done(struct TW68_dev *dev, unsigned int nId, u32 dwRegPB) } - //pr_debug("%s: .curr%p nId= 0X%x dwRegPB 0X%X\n", __func__, dev->video_dmaq[nId].curr, nId, dwRegPB); - //pr_debug("%s: nId= 0X%x\n", __func__, nId); + pr_debug("%s: nId=0x%x .curr(%p) dwRegPB=0x%x\n", __func__, nId, dev->video_dmaq[nId].curr, dwRegPB); if (dev->video_dmaq[nId].curr) { dev->video_fieldcount[nId]++; field = dev->video_dmaq[nId].curr->vb.field; @@ -2540,10 +2518,6 @@ int buffer_setup_QF(struct videobuf_queue *q, unsigned int *count, unsigned int pr_debug("%s: nId %d, 0X%X nW%d nH%d nSize%d\n", __func__, nId, dwReg, nW, nH, nSize); reg_writel(DECODER0_SDT+ (nId*0x10), 7); /// 0 NTSC - } else { - //dwReg = DeviceRead2864(dev,(exVD0_SDT + ((nId-4)*0x10))); - //pr_debug("%s: DECODER0_SDT %d, 0X%X nW%d nH%d nSize%d\n", __func__, nId, dwReg, nW, nH, nSize); - // DeviceWrite2864(dev,(exVD0_SDT + ((nId-4)*0x10)), 7); /// 7 auto detect slower } ////////////////////////////// decoder resize ////////////////////////////////////////// diff --git a/drivers/media/pci/TW68/TW68_defines.h b/drivers/media/pci/TW68/TW68_defines.h index 5e06ded217a7..0fd53f071405 100644 --- a/drivers/media/pci/TW68/TW68_defines.h +++ b/drivers/media/pci/TW68/TW68_defines.h @@ -4,6 +4,11 @@ #pragma once +#define AUDIO_NCH 8 +#define AUDIO_DMA_PAGE 4096 +#define AUDIO_CH_PERIODS 4 +#define AUDIO_CH_BUF_SIZE AUDIO_DMA_PAGE * AUDIO_CH_PERIODS + #define DMA_MODE_SG_RT 0 //Scatter Gather, Real-Time #define DMA_MODE_SG_SWITCH 1 //Scatter Gather, Non-Real-Time #define DMA_MODE_BLOCK 2 //Block Memory @@ -58,8 +63,7 @@ //NO NOT CHANGE //These 3 definitions are matched with hardware #define MAX_NUM_SG_DMA 8 -#define MAX_NUM_DATA_DMA 9 -#define MAX_NUM_DMA (MAX_NUM_SG_DMA+MAX_NUM_DATA_DMA) +#define MAX_NUM_DMA (MAX_NUM_SG_DMA + AUDIO_NCH) ////////////////////////////////////////////////// @@ -70,7 +74,7 @@ #define DMA_INT_STATUS 0x00 //RO #define DMA_PB_STATUS 0x01 //RO #define DMA_CMD 0x02 -#define DMA_INT_ERROR 0x03 +#define DMA_INT_ERROR 0x03 #define DMA_FIFO_VLOSS 0x03 // B3 B2 B0 VLOSS #define VIDEO_CHID 0x04 #define VIDEO_PARSER_STATUS 0x05 @@ -80,8 +84,8 @@ #define DMA_PAGE_TABLE1_ADDR 0x09 #define DMA_CHANNEL_ENABLE 0x0a #define DMA_CONFIG 0x0b -#define DMA_INT_REF 0x0c -#define DMA_CHANNEL_TIMEOUT 0x0d +#define DMA_INT_REF 0x0c +#define DMA_CHANNEL_TIMEOUT 0x0d #define DMA_CH0_CONFIG 0x10 //DMA_CH0_CONFIG ~ DMA_CH7_CONFIG are continusly #define DMA_CH1_CONFIG 0x11 @@ -174,11 +178,12 @@ #define BDMA_ADDR_P_F2_0 0x84 #define BDMA_WHP_F2_0 0x85 #define BDMA_ADDR_B_F2_0 0x86 +#define PIN_CFG_CTRL 0xfb #define CSR_REG 0xFD #define EP_REG_ADDR 0xFE #define EP_REG_DATA 0xFF -//Part 2: Video Decoder portion +//Part 2: Video Decoder portion - ch0 - ch3, ch4 - ch7 starts at 0x200 #define DECODER0_STATUS 0x100 #define DECODER1_STATUS 0x110 #define DECODER2_STATUS 0x120 @@ -288,96 +293,14 @@ #define CH3_SHARPNESS_REG 0x123 #define CH4_SHARPNESS_REG 0x133 -////////////////////////////////////////////////// -//NO NOT CHANGE -//Register definition for external 2864 registers, See Tw2864 Spec for details -// - -#define CLK_SEL_2865 0x61 //specfic to TW2865 - -#define I2C_ADDR_2864_0 0x50 -#define I2C_ADDR_2864_1 0x52 - -#define VIDEO_STATUS_0 0x00 -#define VIDEO_STATUS_1 0x10 -#define VIDEO_STATUS_2 0x20 -#define VIDEO_STATUS_3 0x30 - -#define exVD0_SDT 0x0E -#define exVD1_SDT 0x1E -#define exVD2_SDT 0x2E -#define exVD3_SDT 0x3E - -#define VD0_SDTEN 0x0F -#define VD1_SDTEN 0x1F -#define VD2_SDTEN 0x2F -#define VD3_SDTEN 0x3F - - -#define EX_VDELAY0 0x08 -#define EX_VDELAY1 0x18 -#define EX_VDELAY2 0x28 -#define EX_VDELAY3 0x38 -#define EX_HDELAY0 0x0A -#define EX_HDELAY1 0x1A -#define EX_HDELAY2 0x2A -#define EX_HDELAY3 0x3A -#define EX_MISC_CONTROL2 0x96 -#define MPP_MODE_1 0xC8 -#define MPP_MODE_2 0xC9 -#define NOVID 0x9E -#define CLKODEL 0x9F -#define VIDEO_OUT_CTRL 0xCA -#define SMD 0xCF -#define MASTER_CTRL 0xDB -#define AUDIO_GAIN_0 0xD0 -#define AUDIO_GAIN_1 0xD1 -#define NUM_ADUIOR 0xD2 -#define SEQ_ADUIOR 0xD7 -#define MIX_OUT_SEL 0xE0 -#define EX_VSCALE1_LO 0xE4 -#define EX_VHSCALE1_HI 0xE5 -#define EX_HSCALE1_LO 0xE6 -#define EX_VSCALE2_LO 0xE7 -#define EX_VHSCALE2_HI 0xE8 -#define EX_HSCALE2_LO 0xE9 -#define EX_VSCALE3_LO 0xEA -#define EX_VHSCALE3_HI 0xEB -#define EX_HSCALE3_LO 0xEC -#define EX_VSCALE4_LO 0xED -#define EX_VHSCALE4_HI 0xEE -#define EX_HSCALE4_LO 0xEF -#define VIDEO_MISC 0xF9 -#define CLKOCTRL 0xFA -#define CLKOPOL 0xFB -#define DEV_REV 0xFE -#define EX_BRIGHTNESS1 0x01 -#define EX_BRIGHTNESS2 0x11 -#define EX_BRIGHTNESS3 0x21 -#define EX_BRIGHTNESS4 0x31 -#define EX_CONTRAST1 0x02 -#define EX_CONTRAST2 0x12 -#define EX_CONTRAST3 0x22 -#define EX_CONTRAST4 0x32 -#define EX_SHARPNESS1 0x03 -#define EX_SHARPNESS2 0x13 -#define EX_SHARPNESS3 0x23 -#define EX_SHARPNESS4 0x33 -#define EX_SAT_U1 0x04 -#define EX_SAT_U2 0x14 -#define EX_SAT_U3 0x24 -#define EX_SAT_U4 0x34 -#define EX_SAT_V1 0x05 -#define EX_SAT_V2 0x15 -#define EX_SAT_V3 0x25 -#define EX_SAT_V4 0x35 -#define EX_HUE1 0x06 -#define EX_HUE2 0x16 -#define EX_HUE3 0x26 -#define EX_HUE4 0x36 - +#define POWER_DOWN_CTRL 0x1ce +#define AUDIO_GAIN_CH0 0x1d0 +#define AUDIO_DET_PERIOD 0x1e1 +#define AUDIO_DET_THRESHOLD1 0x1e2 +#define AUDIO_DET_THRESHOLD2 0x1e3 ////////////////////////////////////////////////// +////////////////////////////////////////////////// // Constantants definitions #define DMA_STATUS_HOST_NOT_AVAIABLE 0 #define DMA_STATUS_HOST_READY 1 |