summaryrefslogtreecommitdiff
path: root/drivers/media/pci
diff options
context:
space:
mode:
authorTroy Kisky <troy.kisky@boundarydevices.com>2014-02-06 15:49:18 -0700
committerMax Krummenacher <max.krummenacher@toradex.com>2015-05-29 13:43:35 +0200
commite10688c1a1c7a35b349efb44368fb3130976493e (patch)
treea3408f2d4347e8180447be952a2c2717869ee3da /drivers/media/pci
parent1ea68186f4f9718d4b6578f01556bc7bc0264ca1 (diff)
tw68: audio fixes
Diffstat (limited to 'drivers/media/pci')
-rw-r--r--drivers/media/pci/TW68/TW68-ALSA.c549
-rw-r--r--drivers/media/pci/TW68/TW68-core.c145
-rw-r--r--drivers/media/pci/TW68/TW68-video.c52
-rw-r--r--drivers/media/pci/TW68/TW68_defines.h111
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