Skip to content

Commit

Permalink
Staging: Merge Ben Collins solo6x10 tree with upstream
Browse files Browse the repository at this point in the history
There were some duplicate changes that needed to be hand-merged due to
fixes needed to keep .37 building and working properly.

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Greg Kroah-Hartman committed Nov 10, 2010
2 parents 391a169 + 5bf6859 commit 050afc9
Show file tree
Hide file tree
Showing 12 changed files with 565 additions and 206 deletions.
2 changes: 1 addition & 1 deletion drivers/staging/solo6x10/Kconfig
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
config SOLO6X10
tristate "Softlogic 6x10 MPEG codec cards"
depends on PCI && VIDEO_DEV && SND
select VIDEOBUF_DMA_CONTIG
select VIDEOBUF_DMA_SG
---help---
This driver supports the Softlogic based MPEG-4 and h.264 codec
codec cards.
4 changes: 0 additions & 4 deletions drivers/staging/solo6x10/TODO
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
TODO (staging => main):

* checkpatch.pl (haven't run it yet)
* Lindent (should be clean, but check)
* Motion detection flags need to be moved to v4l2
* Some private CIDs need to be moved to v4l2

Expand All @@ -21,8 +19,6 @@ TODO (general):
- implement playback via external sound jack
- implement loopback of external sound jack with incoming audio?
- implement pause/resume
- check into jacking sound from tx28xx chips directly (to avoid
g.723/8khz limitations)

Plase send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc Ben Collins
<bcollins@bluecherry.net>
12 changes: 9 additions & 3 deletions drivers/staging/solo6x10/solo6010-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ static int __devinit solo6010_pci_probe(struct pci_dev *pdev,
int ret;
int sdram;
u8 chip_id;

solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
if (solo_dev == NULL)
return -ENOMEM;
Expand Down Expand Up @@ -261,13 +262,18 @@ static void __devexit solo6010_pci_remove(struct pci_dev *pdev)
}

static struct pci_device_id solo6010_id_table[] = {
/* 6010 based cards */
{PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_COMMSOLO_4)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_COMMSOLO_9)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_COMMSOLO_16)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16)},
/* 6110 based cards */
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8)},
{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16)},
{0,}
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/staging/solo6x10/solo6010-disp.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ static void solo_motion_config(struct solo6010_dev *solo_dev)
}

/* Default motion settings */
solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
(SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
SOLO_VI_MOTION_FRAME_COUNT(3) |
Expand Down
4 changes: 2 additions & 2 deletions drivers/staging/solo6x10/solo6010-enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ int solo_osd_print(struct solo_enc_dev *solo_enc)

solo_p2m_dma(solo_dev, 0, 1, buf, SOLO_EOSD_EXT_ADDR(solo_dev) +
(solo_enc->ch * SOLO_EOSD_EXT_SIZE), SOLO_EOSD_EXT_SIZE);
reg |= (1 << solo_enc->ch);
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
reg |= (1 << solo_enc->ch);
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);

kfree(buf);

Expand Down
14 changes: 7 additions & 7 deletions drivers/staging/solo6x10/solo6010-g723.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
snd_pcm_substream_chip(ss) = solo_pcm->solo_dev;
kfree(solo_pcm);

return 0;
return 0;
}

static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
Expand Down Expand Up @@ -197,7 +197,7 @@ static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)

static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss)
{
return 0;
return 0;
}

static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
Expand Down Expand Up @@ -271,23 +271,23 @@ static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol,

value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch);

return 0;
return 0;
}

static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value)
{
struct solo6010_dev *solo_dev = snd_kcontrol_chip(kcontrol);
u8 ch = value->id.numid - 1;
u8 old_val;
u8 old_val;

old_val = tw28_get_audio_gain(solo_dev, ch);
old_val = tw28_get_audio_gain(solo_dev, ch);
if (old_val == value->value.integer.value[0])
return 0;

tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]);

return 1;
return 1;
}

static struct snd_kcontrol_new snd_solo_capture_volume = {
Expand Down Expand Up @@ -368,7 +368,7 @@ int solo_g723_init(struct solo6010_dev *solo_dev)
strcpy(card->mixername, "SOLO-6010");
kctl = snd_solo_capture_volume;
kctl.count = solo_dev->nr_chans;
ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
if (ret < 0)
return ret;

Expand Down
4 changes: 2 additions & 2 deletions drivers/staging/solo6x10/solo6010-gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ static void solo_gpio_config(struct solo6010_dev *solo_dev)

int solo_gpio_init(struct solo6010_dev *solo_dev)
{
solo_gpio_config(solo_dev);
return 0;
solo_gpio_config(solo_dev);
return 0;
}

void solo_gpio_exit(struct solo6010_dev *solo_dev)
Expand Down
8 changes: 4 additions & 4 deletions drivers/staging/solo6x10/solo6010-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ u8 solo_i2c_readbyte(struct solo6010_dev *solo_dev, int id, u8 addr, u8 off)

i2c_transfer(&solo_dev->i2c_adap[id], msgs, 2);

return data;
return data;
}

void solo_i2c_writebyte(struct solo6010_dev *solo_dev, int id, u8 addr,
Expand Down Expand Up @@ -227,7 +227,7 @@ static int solo_i2c_master_xfer(struct i2c_adapter *adap,
if (i == SOLO_I2C_ADAPTERS)
return num; // XXX Right return value for failure?

down(&solo_dev->i2c_sem);
mutex_lock(&solo_dev->i2c_mutex);
solo_dev->i2c_id = i;
solo_dev->i2c_msg = msgs;
solo_dev->i2c_msg_num = num;
Expand Down Expand Up @@ -258,7 +258,7 @@ static int solo_i2c_master_xfer(struct i2c_adapter *adap,
solo_dev->i2c_state = IIC_STATE_IDLE;
solo_dev->i2c_id = -1;

up(&solo_dev->i2c_sem);
mutex_unlock(&solo_dev->i2c_mutex);

return ret;
}
Expand All @@ -284,7 +284,7 @@ int solo_i2c_init(struct solo6010_dev *solo_dev)
solo_dev->i2c_id = -1;
solo_dev->i2c_state = IIC_STATE_IDLE;
init_waitqueue_head(&solo_dev->i2c_wait);
sema_init(&solo_dev->i2c_sem, 1);
mutex_init(&solo_dev->i2c_mutex);

for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
struct i2c_adapter *adap = &solo_dev->i2c_adap[i];
Expand Down
152 changes: 125 additions & 27 deletions drivers/staging/solo6x10/solo6010-p2m.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/kernel.h>
#include <linux/scatterlist.h>

#include "solo6010.h"

Expand All @@ -30,8 +31,9 @@ int solo_p2m_dma(struct solo6010_dev *solo_dev, u8 id, int wr,
int ret;

WARN_ON(!size);
WARN_ON(id >= SOLO_NR_P2M);
if (!size || id >= SOLO_NR_P2M)
BUG_ON(id >= SOLO_NR_P2M);

if (!size)
return -EINVAL;

dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size,
Expand All @@ -47,42 +49,137 @@ int solo_p2m_dma(struct solo6010_dev *solo_dev, u8 id, int wr,

int solo_p2m_dma_t(struct solo6010_dev *solo_dev, u8 id, int wr,
dma_addr_t dma_addr, u32 ext_addr, u32 size)
{
struct p2m_desc *desc = kzalloc(sizeof(*desc) * 2, GFP_DMA);
int ret;

if (desc == NULL)
return -ENOMEM;

solo_p2m_push_desc(&desc[1], wr, dma_addr, ext_addr, size, 0, 0);
ret = solo_p2m_dma_desc(solo_dev, id, desc, 2);
kfree(desc);

return ret;
}

void solo_p2m_push_desc(struct p2m_desc *desc, int wr, dma_addr_t dma_addr,
u32 ext_addr, u32 size, int repeat, u32 ext_size)
{
desc->ta = dma_addr;
desc->fa = ext_addr;

desc->ext = SOLO_P2M_COPY_SIZE(size >> 2);
desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
(wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON;

/* Ext size only matters when we're repeating */
if (repeat) {
desc->ext |= SOLO_P2M_EXT_INC(ext_size >> 2);
desc->ctrl |= SOLO_P2M_PCI_INC(size >> 2) |
SOLO_P2M_REPEAT(repeat);
}
}

int solo_p2m_dma_desc(struct solo6010_dev *solo_dev, u8 id,
struct p2m_desc *desc, int desc_count)
{
struct solo_p2m_dev *p2m_dev;
unsigned int timeout = 0;
unsigned int timeout;
int ret = 0;
u32 config = 0;
dma_addr_t desc_dma = 0;

WARN_ON(!size);
WARN_ON(id >= SOLO_NR_P2M);
if (!size || id >= SOLO_NR_P2M)
return -EINVAL;
BUG_ON(id >= SOLO_NR_P2M);
BUG_ON(!desc_count || desc_count > SOLO_NR_P2M_DESC);

p2m_dev = &solo_dev->p2m_dev[id];

down(&p2m_dev->sem);
mutex_lock(&p2m_dev->mutex);

solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);

start_dma:
INIT_COMPLETION(p2m_dev->completion);
p2m_dev->error = 0;
solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), dma_addr);
solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), ext_addr);
solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id),
SOLO_P2M_COPY_SIZE(size >> 2));
solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id),
SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
(wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON);

/* Enable the descriptors */
config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(id));
desc_dma = pci_map_single(solo_dev->pdev, desc,
desc_count * sizeof(*desc),
PCI_DMA_TODEVICE);
solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(id), desc_dma);
solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(id), desc_count - 1);
solo_reg_write(solo_dev, SOLO_P2M_CONFIG(id), config |
SOLO_P2M_DESC_MODE);

/* Should have all descriptors completed from one interrupt */
timeout = wait_for_completion_timeout(&p2m_dev->completion, HZ);

solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);

/* XXX Really looks to me like we will get stuck here if a
* real PCI P2M error occurs */
/* Reset back to non-descriptor mode */
solo_reg_write(solo_dev, SOLO_P2M_CONFIG(id), config);
solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(id), 0);
solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(id), 0);
pci_unmap_single(solo_dev->pdev, desc_dma,
desc_count * sizeof(*desc),
PCI_DMA_TODEVICE);

if (p2m_dev->error)
goto start_dma;
ret = -EIO;
else if (timeout == 0)
ret = -EAGAIN;

mutex_unlock(&p2m_dev->mutex);

WARN_ON_ONCE(ret);

up(&p2m_dev->sem);
return ret;
}

int solo_p2m_dma_sg(struct solo6010_dev *solo_dev, u8 id,
struct p2m_desc *pdesc, int wr,
struct scatterlist *sg, u32 sg_off,
u32 ext_addr, u32 size)
{
int i;
int idx;

BUG_ON(id >= SOLO_NR_P2M);

if (WARN_ON_ONCE(!size))
return -EINVAL;

memset(pdesc, 0, sizeof(*pdesc));

/* Should rewrite this to handle > SOLO_NR_P2M_DESC transactions */
for (i = 0, idx = 1; idx < SOLO_NR_P2M_DESC && sg && size > 0;
i++, sg = sg_next(sg)) {
struct p2m_desc *desc = &pdesc[idx];
u32 sg_len = sg_dma_len(sg);
u32 len;

return (timeout == 0) ? -EAGAIN : 0;
if (sg_off >= sg_len) {
sg_off -= sg_len;
continue;
}

sg_len -= sg_off;
len = min(sg_len, size);

solo_p2m_push_desc(desc, wr, sg_dma_address(sg) + sg_off,
ext_addr, len, 0, 0);

size -= len;
ext_addr += len;
idx++;

sg_off = 0;
}

WARN_ON_ONCE(size || i >= SOLO_NR_P2M_DESC);

return solo_p2m_dma_desc(solo_dev, id, pdesc, idx);
}

#ifdef SOLO_TEST_P2M
Expand Down Expand Up @@ -152,8 +249,11 @@ static void run_p2m_test(struct solo6010_dev *solo_dev)

void solo_p2m_isr(struct solo6010_dev *solo_dev, int id)
{
struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id];

solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_P2M(id));
complete(&solo_dev->p2m_dev[id].completion);

complete(&p2m_dev->completion);
}

void solo_p2m_error_isr(struct solo6010_dev *solo_dev, u32 status)
Expand Down Expand Up @@ -188,16 +288,14 @@ int solo_p2m_init(struct solo6010_dev *solo_dev)
for (i = 0; i < SOLO_NR_P2M; i++) {
p2m_dev = &solo_dev->p2m_dev[i];

sema_init(&p2m_dev->sem, 1);
mutex_init(&p2m_dev->mutex);
init_completion(&p2m_dev->completion);

solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(i),
__pa(p2m_dev->desc));

solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
SOLO_P2M_CSC_16BIT_565 |
SOLO_P2M_DMA_INTERVAL(0) |
SOLO_P2M_DMA_INTERVAL(3) |
SOLO_P2M_DESC_INTR_OPT |
SOLO_P2M_PCI_MASTER_MODE);
solo6010_irq_on(solo_dev, SOLO_IRQ_P2M(i));
}
Expand Down
Loading

0 comments on commit 050afc9

Please sign in to comment.