You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
ALSA: SB X-Fi driver merge
The Sound Blaster X-Fi driver supports Creative solutions based on 20K1 and 20K2 chipsets. Supported hardware : Creative Sound Blaster X-Fi Titanium Fatal1ty® Champion Series Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series Creative Sound Blaster X-Fi Titanium Professional Audio Creative Sound Blaster X-Fi Titanium Creative Sound Blaster X-Fi Elite Pro Creative Sound Blaster X-Fi Platinum Creative Sound Blaster X-Fi Fatal1ty Creative Sound Blaster X-Fi XtremeGamer Creative Sound Blaster X-Fi XtremeMusic Current release features: * ALSA PCM Playback * ALSA Record * ALSA Mixer Note: * External I/O modules detection not included. Signed-off-by: Wai Yew CHAY <wychay@ctl.creative.com> Singed-off-by: Ryan RICHARDS <ryan_richards@creativelabs.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
committed by
Takashi Iwai
parent
091bf7624d
commit
8cc7236148
@@ -460,6 +460,25 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-ctxfi
|
||||
----------------
|
||||
|
||||
Module for Creative Sound Blaster X-Fi boards (20k1 / 20k2 chips)
|
||||
* Creative Sound Blaster X-Fi Titanium Fatal1ty Champion Series
|
||||
* Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series
|
||||
* Creative Sound Blaster X-Fi Titanium Professional Audio
|
||||
* Creative Sound Blaster X-Fi Titanium
|
||||
* Creative Sound Blaster X-Fi Elite Pro
|
||||
* Creative Sound Blaster X-Fi Platinum
|
||||
* Creative Sound Blaster X-Fi Fatal1ty
|
||||
* Creative Sound Blaster X-Fi XtremeGamer
|
||||
* Creative Sound Blaster X-Fi XtremeMusic
|
||||
|
||||
reference_rate - reference sample rate, 44100 or 48000 (default)
|
||||
multiple - multiple to ref. sample rate, 1 or 2 (default)
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-darla20
|
||||
------------------
|
||||
|
||||
|
||||
@@ -275,6 +275,16 @@ config SND_CS5535AUDIO
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-cs5535audio.
|
||||
|
||||
config SND_CTXFI
|
||||
tristate "Creative Sound Blaster X-Fi"
|
||||
select SND_PCM
|
||||
help
|
||||
If you want to use soundcards based on Creative Sound Blastr X-Fi
|
||||
boards with 20k1 or 20k2 chips, say Y here.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-ctxfi.
|
||||
|
||||
config SND_DARLA20
|
||||
tristate "(Echoaudio) Darla20"
|
||||
select FW_LOADER
|
||||
|
||||
@@ -59,6 +59,7 @@ obj-$(CONFIG_SND) += \
|
||||
ali5451/ \
|
||||
au88x0/ \
|
||||
aw2/ \
|
||||
ctxfi/ \
|
||||
ca0106/ \
|
||||
cs46xx/ \
|
||||
cs5535audio/ \
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
snd-ctxfi-objs := xfi.o ctatc.o ctvmem.o ctpcm.o ctmixer.o ctresource.o \
|
||||
ctsrc.o ctamixer.o ctdaio.o ctimap.o cthardware.o \
|
||||
cthw20k2.o cthw20k1.o
|
||||
|
||||
obj-$(CONFIG_SND_CTXFI) += snd-ctxfi.o
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*/
|
||||
|
||||
#ifndef _20K2REGISTERS_H_
|
||||
#define _20K2REGISTERS_H_
|
||||
|
||||
|
||||
/* Timer Registers */
|
||||
#define TIMER_TIMR 0x1B7004
|
||||
#define INTERRUPT_GIP 0x1B7010
|
||||
#define INTERRUPT_GIE 0x1B7014
|
||||
|
||||
/* I2C Registers */
|
||||
#define I2C_IF_ADDRESS 0x1B9000
|
||||
#define I2C_IF_WDATA 0x1B9004
|
||||
#define I2C_IF_RDATA 0x1B9008
|
||||
#define I2C_IF_STATUS 0x1B900C
|
||||
#define I2C_IF_WLOCK 0x1B9010
|
||||
|
||||
/* Global Control Registers */
|
||||
#define GLOBAL_CNTL_GCTL 0x1B7090
|
||||
|
||||
/* PLL Registers */
|
||||
#define PLL_CTL 0x1B7080
|
||||
#define PLL_STAT 0x1B7084
|
||||
#define PLL_ENB 0x1B7088
|
||||
|
||||
/* SRC Registers */
|
||||
#define SRC_CTL 0x1A0000 /* 0x1A0000 + (256 * Chn) */
|
||||
#define SRC_CCR 0x1A0004 /* 0x1A0004 + (256 * Chn) */
|
||||
#define SRC_IMAP 0x1A0008 /* 0x1A0008 + (256 * Chn) */
|
||||
#define SRC_CA 0x1A0010 /* 0x1A0010 + (256 * Chn) */
|
||||
#define SRC_CF 0x1A0014 /* 0x1A0014 + (256 * Chn) */
|
||||
#define SRC_SA 0x1A0018 /* 0x1A0018 + (256 * Chn) */
|
||||
#define SRC_LA 0x1A001C /* 0x1A001C + (256 * Chn) */
|
||||
#define SRC_CTLSWR 0x1A0020 /* 0x1A0020 + (256 * Chn) */
|
||||
#define SRC_CD 0x1A0080 /* 0x1A0080 + (256 * Chn) + (4 * Regn) */
|
||||
#define SRC_MCTL 0x1A012C
|
||||
#define SRC_IP 0x1A102C /* 0x1A102C + (256 * Regn) */
|
||||
#define SRC_ENB 0x1A282C /* 0x1A282C + (256 * Regn) */
|
||||
#define SRC_ENBSTAT 0x1A202C
|
||||
#define SRC_ENBSA 0x1A232C
|
||||
#define SRC_DN0Z 0x1A0030
|
||||
#define SRC_DN1Z 0x1A0040
|
||||
#define SRC_UPZ 0x1A0060
|
||||
|
||||
/* GPIO Registers */
|
||||
#define GPIO_DATA 0x1B7020
|
||||
#define GPIO_CTRL 0x1B7024
|
||||
|
||||
/* Virtual memory registers */
|
||||
#define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */
|
||||
#define VMEM_PTPAH 0x1C6304 /* 0x1C6304 + (16 * Chn) */
|
||||
#define VMEM_CTL 0x1C7000
|
||||
|
||||
/* Transport Registers */
|
||||
#define TRANSPORT_ENB 0x1B6000
|
||||
#define TRANSPORT_CTL 0x1B6004
|
||||
#define TRANSPORT_INT 0x1B6008
|
||||
|
||||
/* Audio IO */
|
||||
#define AUDIO_IO_AIM 0x1B5000 /* 0x1B5000 + (0x04 * Chn) */
|
||||
#define AUDIO_IO_TX_CTL 0x1B5400 /* 0x1B5400 + (0x40 * Chn) */
|
||||
#define AUDIO_IO_TX_CSTAT_L 0x1B5408 /* 0x1B5408 + (0x40 * Chn) */
|
||||
#define AUDIO_IO_TX_CSTAT_H 0x1B540C /* 0x1B540C + (0x40 * Chn) */
|
||||
#define AUDIO_IO_RX_CTL 0x1B5410 /* 0x1B5410 + (0x40 * Chn) */
|
||||
#define AUDIO_IO_RX_SRT_CTL 0x1B5420 /* 0x1B5420 + (0x40 * Chn) */
|
||||
#define AUDIO_IO_MCLK 0x1B5600
|
||||
#define AUDIO_IO_TX_BLRCLK 0x1B5604
|
||||
#define AUDIO_IO_RX_BLRCLK 0x1B5608
|
||||
|
||||
/* Mixer */
|
||||
#define MIXER_AMOPLO 0x130000 /* 0x130000 + (8 * Chn) [4095 : 0] */
|
||||
#define MIXER_AMOPHI 0x130004 /* 0x130004 + (8 * Chn) [4095 : 0] */
|
||||
#define MIXER_PRING_LO_HI 0x188000 /* 0x188000 + (4 * Chn) [4095 : 0] */
|
||||
#define MIXER_PMOPLO 0x138000 /* 0x138000 + (8 * Chn) [4095 : 0] */
|
||||
#define MIXER_PMOPHI 0x138004 /* 0x138004 + (8 * Chn) [4095 : 0] */
|
||||
#define MIXER_AR_ENABLE 0x19000C
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,488 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File ctamixer.c
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the implementation of the Audio Mixer
|
||||
* resource management object.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date May 21 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ctamixer.h"
|
||||
#include "cthardware.h"
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define AMIXER_RESOURCE_NUM 256
|
||||
#define SUM_RESOURCE_NUM 256
|
||||
|
||||
#define AMIXER_Y_IMMEDIATE 1
|
||||
|
||||
#define BLANK_SLOT 4094
|
||||
|
||||
static int amixer_master(struct rsc *rsc)
|
||||
{
|
||||
rsc->conj = 0;
|
||||
return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0];
|
||||
}
|
||||
|
||||
static int amixer_next_conj(struct rsc *rsc)
|
||||
{
|
||||
rsc->conj++;
|
||||
return container_of(rsc, struct amixer, rsc)->idx[rsc->conj];
|
||||
}
|
||||
|
||||
static int amixer_index(const struct rsc *rsc)
|
||||
{
|
||||
return container_of(rsc, struct amixer, rsc)->idx[rsc->conj];
|
||||
}
|
||||
|
||||
static int amixer_output_slot(const struct rsc *rsc)
|
||||
{
|
||||
return (amixer_index(rsc) << 4) + 0x4;
|
||||
}
|
||||
|
||||
static struct rsc_ops amixer_basic_rsc_ops = {
|
||||
.master = amixer_master,
|
||||
.next_conj = amixer_next_conj,
|
||||
.index = amixer_index,
|
||||
.output_slot = amixer_output_slot,
|
||||
};
|
||||
|
||||
static int amixer_set_input(struct amixer *amixer, struct rsc *rsc)
|
||||
{
|
||||
struct hw *hw = NULL;
|
||||
|
||||
hw = (struct hw *)amixer->rsc.hw;
|
||||
hw->amixer_set_mode(amixer->rsc.ctrl_blk, AMIXER_Y_IMMEDIATE);
|
||||
amixer->input = rsc;
|
||||
if (NULL == rsc)
|
||||
hw->amixer_set_x(amixer->rsc.ctrl_blk, BLANK_SLOT);
|
||||
else
|
||||
hw->amixer_set_x(amixer->rsc.ctrl_blk,
|
||||
rsc->ops->output_slot(rsc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* y is a 14-bit immediate constant */
|
||||
static int amixer_set_y(struct amixer *amixer, unsigned int y)
|
||||
{
|
||||
struct hw *hw = NULL;
|
||||
|
||||
hw = (struct hw *)amixer->rsc.hw;
|
||||
hw->amixer_set_y(amixer->rsc.ctrl_blk, y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amixer_set_invalid_squash(struct amixer *amixer, unsigned int iv)
|
||||
{
|
||||
struct hw *hw = NULL;
|
||||
|
||||
hw = (struct hw *)amixer->rsc.hw;
|
||||
hw->amixer_set_iv(amixer->rsc.ctrl_blk, iv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amixer_set_sum(struct amixer *amixer, struct sum *sum)
|
||||
{
|
||||
struct hw *hw = NULL;
|
||||
|
||||
hw = (struct hw *)amixer->rsc.hw;
|
||||
amixer->sum = sum;
|
||||
if (NULL == sum) {
|
||||
hw->amixer_set_se(amixer->rsc.ctrl_blk, 0);
|
||||
} else {
|
||||
hw->amixer_set_se(amixer->rsc.ctrl_blk, 1);
|
||||
hw->amixer_set_sadr(amixer->rsc.ctrl_blk,
|
||||
sum->rsc.ops->index(&sum->rsc));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amixer_commit_write(struct amixer *amixer)
|
||||
{
|
||||
struct hw *hw = NULL;
|
||||
unsigned int index = 0;
|
||||
int i = 0;
|
||||
struct rsc *input = NULL;
|
||||
struct sum *sum = NULL;
|
||||
|
||||
hw = (struct hw *)amixer->rsc.hw;
|
||||
input = amixer->input;
|
||||
sum = amixer->sum;
|
||||
|
||||
/* Program master and conjugate resources */
|
||||
amixer->rsc.ops->master(&amixer->rsc);
|
||||
if (NULL != input)
|
||||
input->ops->master(input);
|
||||
|
||||
if (NULL != sum)
|
||||
sum->rsc.ops->master(&sum->rsc);
|
||||
|
||||
for (i = 0; i < amixer->rsc.msr; i++) {
|
||||
hw->amixer_set_dirty_all(amixer->rsc.ctrl_blk);
|
||||
if (NULL != input) {
|
||||
hw->amixer_set_x(amixer->rsc.ctrl_blk,
|
||||
input->ops->output_slot(input));
|
||||
input->ops->next_conj(input);
|
||||
}
|
||||
if (NULL != sum) {
|
||||
hw->amixer_set_sadr(amixer->rsc.ctrl_blk,
|
||||
sum->rsc.ops->index(&sum->rsc));
|
||||
sum->rsc.ops->next_conj(&sum->rsc);
|
||||
}
|
||||
index = amixer->rsc.ops->output_slot(&amixer->rsc);
|
||||
hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk);
|
||||
amixer->rsc.ops->next_conj(&amixer->rsc);
|
||||
}
|
||||
amixer->rsc.ops->master(&amixer->rsc);
|
||||
if (NULL != input)
|
||||
input->ops->master(input);
|
||||
|
||||
if (NULL != sum)
|
||||
sum->rsc.ops->master(&sum->rsc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amixer_commit_raw_write(struct amixer *amixer)
|
||||
{
|
||||
struct hw *hw = NULL;
|
||||
unsigned int index = 0;
|
||||
|
||||
hw = (struct hw *)amixer->rsc.hw;
|
||||
index = amixer->rsc.ops->output_slot(&amixer->rsc);
|
||||
hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amixer_get_y(struct amixer *amixer)
|
||||
{
|
||||
struct hw *hw = NULL;
|
||||
|
||||
hw = (struct hw *)amixer->rsc.hw;
|
||||
return hw->amixer_get_y(amixer->rsc.ctrl_blk);
|
||||
}
|
||||
|
||||
static int amixer_setup(struct amixer *amixer, struct rsc *input,
|
||||
unsigned int scale, struct sum *sum)
|
||||
{
|
||||
amixer_set_input(amixer, input);
|
||||
amixer_set_y(amixer, scale);
|
||||
amixer_set_sum(amixer, sum);
|
||||
amixer_commit_write(amixer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amixer_rsc_ops amixer_ops = {
|
||||
.set_input = amixer_set_input,
|
||||
.set_invalid_squash = amixer_set_invalid_squash,
|
||||
.set_scale = amixer_set_y,
|
||||
.set_sum = amixer_set_sum,
|
||||
.commit_write = amixer_commit_write,
|
||||
.commit_raw_write = amixer_commit_raw_write,
|
||||
.setup = amixer_setup,
|
||||
.get_scale = amixer_get_y,
|
||||
};
|
||||
|
||||
static int amixer_rsc_init(struct amixer *amixer,
|
||||
const struct amixer_desc *desc,
|
||||
struct amixer_mgr *mgr)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = rsc_init(&amixer->rsc, amixer->idx[0],
|
||||
AMIXER, desc->msr, mgr->mgr.hw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Set amixer specific operations */
|
||||
amixer->rsc.ops = &amixer_basic_rsc_ops;
|
||||
amixer->ops = &amixer_ops;
|
||||
amixer->input = NULL;
|
||||
amixer->sum = NULL;
|
||||
|
||||
amixer_setup(amixer, NULL, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amixer_rsc_uninit(struct amixer *amixer)
|
||||
{
|
||||
amixer_setup(amixer, NULL, 0, NULL);
|
||||
rsc_uninit(&amixer->rsc);
|
||||
amixer->ops = NULL;
|
||||
amixer->input = NULL;
|
||||
amixer->sum = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_amixer_rsc(struct amixer_mgr *mgr,
|
||||
const struct amixer_desc *desc,
|
||||
struct amixer **ramixer)
|
||||
{
|
||||
int err = 0, i = 0;
|
||||
unsigned int idx = 0;
|
||||
struct amixer *amixer = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
*ramixer = NULL;
|
||||
|
||||
/* Allocate mem for amixer resource */
|
||||
amixer = kzalloc(sizeof(*amixer), GFP_KERNEL);
|
||||
if (NULL == amixer) {
|
||||
err = -ENOMEM;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Check whether there are sufficient
|
||||
* amixer resources to meet request. */
|
||||
spin_lock_irqsave(&mgr->mgr_lock, flags);
|
||||
for (i = 0; i < desc->msr; i++) {
|
||||
err = mgr_get_resource(&mgr->mgr, 1, &idx);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
amixer->idx[i] = idx;
|
||||
}
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Can't meet AMIXER resource request!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = amixer_rsc_init(amixer, desc, mgr);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
*ramixer = amixer;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
spin_lock_irqsave(&mgr->mgr_lock, flags);
|
||||
for (i--; i >= 0; i--)
|
||||
mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]);
|
||||
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
kfree(amixer);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i = 0;
|
||||
|
||||
spin_lock_irqsave(&mgr->mgr_lock, flags);
|
||||
for (i = 0; i < amixer->rsc.msr; i++)
|
||||
mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]);
|
||||
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
amixer_rsc_uninit(amixer);
|
||||
kfree(amixer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr)
|
||||
{
|
||||
int err = 0;
|
||||
struct amixer_mgr *amixer_mgr;
|
||||
|
||||
*ramixer_mgr = NULL;
|
||||
amixer_mgr = kzalloc(sizeof(*amixer_mgr), GFP_KERNEL);
|
||||
if (NULL == amixer_mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
err = rsc_mgr_init(&amixer_mgr->mgr, AMIXER, AMIXER_RESOURCE_NUM, hw);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
spin_lock_init(&amixer_mgr->mgr_lock);
|
||||
|
||||
amixer_mgr->get_amixer = get_amixer_rsc;
|
||||
amixer_mgr->put_amixer = put_amixer_rsc;
|
||||
|
||||
*ramixer_mgr = amixer_mgr;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(amixer_mgr);
|
||||
return err;
|
||||
}
|
||||
|
||||
int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr)
|
||||
{
|
||||
rsc_mgr_uninit(&amixer_mgr->mgr);
|
||||
kfree(amixer_mgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SUM resource management */
|
||||
|
||||
static int sum_master(struct rsc *rsc)
|
||||
{
|
||||
rsc->conj = 0;
|
||||
return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0];
|
||||
}
|
||||
|
||||
static int sum_next_conj(struct rsc *rsc)
|
||||
{
|
||||
rsc->conj++;
|
||||
return container_of(rsc, struct sum, rsc)->idx[rsc->conj];
|
||||
}
|
||||
|
||||
static int sum_index(const struct rsc *rsc)
|
||||
{
|
||||
return container_of(rsc, struct sum, rsc)->idx[rsc->conj];
|
||||
}
|
||||
|
||||
static int sum_output_slot(const struct rsc *rsc)
|
||||
{
|
||||
return (sum_index(rsc) << 4) + 0xc;
|
||||
}
|
||||
|
||||
static struct rsc_ops sum_basic_rsc_ops = {
|
||||
.master = sum_master,
|
||||
.next_conj = sum_next_conj,
|
||||
.index = sum_index,
|
||||
.output_slot = sum_output_slot,
|
||||
};
|
||||
|
||||
static int sum_rsc_init(struct sum *sum,
|
||||
const struct sum_desc *desc,
|
||||
struct sum_mgr *mgr)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = rsc_init(&sum->rsc, sum->idx[0], SUM, desc->msr, mgr->mgr.hw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sum->rsc.ops = &sum_basic_rsc_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sum_rsc_uninit(struct sum *sum)
|
||||
{
|
||||
rsc_uninit(&sum->rsc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_sum_rsc(struct sum_mgr *mgr,
|
||||
const struct sum_desc *desc,
|
||||
struct sum **rsum)
|
||||
{
|
||||
int err = 0, i = 0;
|
||||
unsigned int idx = 0;
|
||||
struct sum *sum = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
*rsum = NULL;
|
||||
|
||||
/* Allocate mem for sum resource */
|
||||
sum = kzalloc(sizeof(*sum), GFP_KERNEL);
|
||||
if (NULL == sum) {
|
||||
err = -ENOMEM;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Check whether there are sufficient sum resources to meet request. */
|
||||
spin_lock_irqsave(&mgr->mgr_lock, flags);
|
||||
for (i = 0; i < desc->msr; i++) {
|
||||
err = mgr_get_resource(&mgr->mgr, 1, &idx);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
sum->idx[i] = idx;
|
||||
}
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Can't meet SUM resource request!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = sum_rsc_init(sum, desc, mgr);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
*rsum = sum;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
spin_lock_irqsave(&mgr->mgr_lock, flags);
|
||||
for (i--; i >= 0; i--)
|
||||
mgr_put_resource(&mgr->mgr, 1, sum->idx[i]);
|
||||
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
kfree(sum);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i = 0;
|
||||
|
||||
spin_lock_irqsave(&mgr->mgr_lock, flags);
|
||||
for (i = 0; i < sum->rsc.msr; i++)
|
||||
mgr_put_resource(&mgr->mgr, 1, sum->idx[i]);
|
||||
|
||||
spin_unlock_irqrestore(&mgr->mgr_lock, flags);
|
||||
sum_rsc_uninit(sum);
|
||||
kfree(sum);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr)
|
||||
{
|
||||
int err = 0;
|
||||
struct sum_mgr *sum_mgr;
|
||||
|
||||
*rsum_mgr = NULL;
|
||||
sum_mgr = kzalloc(sizeof(*sum_mgr), GFP_KERNEL);
|
||||
if (NULL == sum_mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
err = rsc_mgr_init(&sum_mgr->mgr, SUM, SUM_RESOURCE_NUM, hw);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
spin_lock_init(&sum_mgr->mgr_lock);
|
||||
|
||||
sum_mgr->get_sum = get_sum_rsc;
|
||||
sum_mgr->put_sum = put_sum_rsc;
|
||||
|
||||
*rsum_mgr = sum_mgr;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(sum_mgr);
|
||||
return err;
|
||||
}
|
||||
|
||||
int sum_mgr_destroy(struct sum_mgr *sum_mgr)
|
||||
{
|
||||
rsc_mgr_uninit(&sum_mgr->mgr);
|
||||
kfree(sum_mgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File ctamixer.h
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the definition of the Audio Mixer
|
||||
* resource management object.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date May 21 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CTAMIXER_H
|
||||
#define CTAMIXER_H
|
||||
|
||||
#include "ctresource.h"
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
/* Define the descriptor of a summation node resource */
|
||||
struct sum {
|
||||
struct rsc rsc; /* Basic resource info */
|
||||
unsigned char idx[8];
|
||||
};
|
||||
|
||||
/* Define sum resource request description info */
|
||||
struct sum_desc {
|
||||
unsigned int msr;
|
||||
};
|
||||
|
||||
struct sum_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
spinlock_t mgr_lock;
|
||||
|
||||
/* request one sum resource */
|
||||
int (*get_sum)(struct sum_mgr *mgr,
|
||||
const struct sum_desc *desc, struct sum **rsum);
|
||||
/* return one sum resource */
|
||||
int (*put_sum)(struct sum_mgr *mgr, struct sum *sum);
|
||||
};
|
||||
|
||||
/* Constructor and destructor of daio resource manager */
|
||||
int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr);
|
||||
int sum_mgr_destroy(struct sum_mgr *sum_mgr);
|
||||
|
||||
/* Define the descriptor of a amixer resource */
|
||||
struct amixer_rsc_ops;
|
||||
|
||||
struct amixer {
|
||||
struct rsc rsc; /* Basic resource info */
|
||||
unsigned char idx[8];
|
||||
struct rsc *input; /* pointer to a resource acting as source */
|
||||
struct sum *sum; /* Put amixer output to this summation node */
|
||||
struct amixer_rsc_ops *ops; /* AMixer specific operations */
|
||||
};
|
||||
|
||||
struct amixer_rsc_ops {
|
||||
int (*set_input)(struct amixer *amixer, struct rsc *rsc);
|
||||
int (*set_scale)(struct amixer *amixer, unsigned int scale);
|
||||
int (*set_invalid_squash)(struct amixer *amixer, unsigned int iv);
|
||||
int (*set_sum)(struct amixer *amixer, struct sum *sum);
|
||||
int (*commit_write)(struct amixer *amixer);
|
||||
/* Only for interleaved recording */
|
||||
int (*commit_raw_write)(struct amixer *amixer);
|
||||
int (*setup)(struct amixer *amixer, struct rsc *input,
|
||||
unsigned int scale, struct sum *sum);
|
||||
int (*get_scale)(struct amixer *amixer);
|
||||
};
|
||||
|
||||
/* Define amixer resource request description info */
|
||||
struct amixer_desc {
|
||||
unsigned int msr;
|
||||
};
|
||||
|
||||
struct amixer_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
spinlock_t mgr_lock;
|
||||
|
||||
/* request one amixer resource */
|
||||
int (*get_amixer)(struct amixer_mgr *mgr,
|
||||
const struct amixer_desc *desc,
|
||||
struct amixer **ramixer);
|
||||
/* return one amixer resource */
|
||||
int (*put_amixer)(struct amixer_mgr *mgr, struct amixer *amixer);
|
||||
};
|
||||
|
||||
/* Constructor and destructor of amixer resource manager */
|
||||
int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr);
|
||||
int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr);
|
||||
|
||||
#endif /* CTAMIXER_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File ctatc.h
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the definition of the device resource management object.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date Mar 28 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CTATC_H
|
||||
#define CTATC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/timer.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
#include "ctvmem.h"
|
||||
#include "ctresource.h"
|
||||
|
||||
enum CTALSADEVS { /* Types of alsa devices */
|
||||
FRONT,
|
||||
REAR,
|
||||
CLFE,
|
||||
SURROUND,
|
||||
IEC958,
|
||||
MIXER,
|
||||
NUM_CTALSADEVS /* This should always be the last */
|
||||
};
|
||||
|
||||
enum CTCARDS {
|
||||
CTSB0760,
|
||||
CTHENDRIX,
|
||||
CTSB08801,
|
||||
CTSB08802,
|
||||
CTSB08803,
|
||||
NUM_CTCARDS /* This should always be the last */
|
||||
};
|
||||
|
||||
struct ct_atc_chip_sub_details {
|
||||
u16 subsys;
|
||||
const char *nm_model;
|
||||
};
|
||||
|
||||
struct ct_atc_chip_details {
|
||||
u16 vendor;
|
||||
u16 device;
|
||||
const struct ct_atc_chip_sub_details *sub_details;
|
||||
const char *nm_card;
|
||||
};
|
||||
|
||||
struct ct_atc;
|
||||
|
||||
/* alsa pcm stream descriptor */
|
||||
struct ct_atc_pcm {
|
||||
struct snd_pcm_substream *substream;
|
||||
void (*interrupt)(struct ct_atc_pcm *apcm);
|
||||
unsigned int started:1;
|
||||
unsigned int stop_timer:1;
|
||||
struct timer_list timer;
|
||||
spinlock_t timer_lock;
|
||||
unsigned int position;
|
||||
|
||||
/* Only mono and interleaved modes are supported now. */
|
||||
struct ct_vm_block *vm_block;
|
||||
void *src; /* SRC for interacting with host memory */
|
||||
void **srccs; /* SRCs for sample rate conversion */
|
||||
void **srcimps; /* SRC Input Mappers */
|
||||
void **amixers; /* AMIXERs for routing converted data */
|
||||
void *mono; /* A SUM resource for mixing chs to one */
|
||||
unsigned char n_srcc; /* Number of converting SRCs */
|
||||
unsigned char n_srcimp; /* Number of SRC Input Mappers */
|
||||
unsigned char n_amixer; /* Number of AMIXERs */
|
||||
};
|
||||
|
||||
/* Chip resource management object */
|
||||
struct ct_atc {
|
||||
struct pci_dev *pci;
|
||||
struct snd_card *card;
|
||||
unsigned int rsr; /* reference sample rate in Hz */
|
||||
unsigned int msr; /* master sample rate in rsr */
|
||||
unsigned int pll_rate; /* current rate of Phase Lock Loop */
|
||||
|
||||
const struct ct_atc_chip_details *chip_details;
|
||||
enum CTCARDS model;
|
||||
/* Create all alsa devices */
|
||||
int (*create_alsa_devs)(struct ct_atc *atc);
|
||||
|
||||
struct ct_vm *vm; /* device virtual memory manager for this card */
|
||||
int (*map_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index);
|
||||
|
||||
spinlock_t atc_lock;
|
||||
spinlock_t vm_lock;
|
||||
|
||||
int (*pcm_playback_prepare)(struct ct_atc *atc,
|
||||
struct ct_atc_pcm *apcm);
|
||||
int (*pcm_playback_start)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
int (*pcm_playback_stop)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
int (*pcm_playback_position)(struct ct_atc *atc,
|
||||
struct ct_atc_pcm *apcm);
|
||||
int (*spdif_passthru_playback_prepare)(struct ct_atc *atc,
|
||||
struct ct_atc_pcm *apcm);
|
||||
int (*pcm_capture_prepare)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
int (*pcm_capture_start)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
int (*pcm_capture_stop)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
int (*pcm_capture_position)(struct ct_atc *atc,
|
||||
struct ct_atc_pcm *apcm);
|
||||
int (*pcm_release_resources)(struct ct_atc *atc,
|
||||
struct ct_atc_pcm *apcm);
|
||||
int (*select_line_in)(struct ct_atc *atc);
|
||||
int (*select_mic_in)(struct ct_atc *atc);
|
||||
int (*select_digit_io)(struct ct_atc *atc);
|
||||
int (*line_front_unmute)(struct ct_atc *atc, unsigned char state);
|
||||
int (*line_surround_unmute)(struct ct_atc *atc, unsigned char state);
|
||||
int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state);
|
||||
int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state);
|
||||
int (*line_in_unmute)(struct ct_atc *atc, unsigned char state);
|
||||
int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state);
|
||||
int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state);
|
||||
int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status);
|
||||
int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status);
|
||||
int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state);
|
||||
int (*have_digit_io_switch)(struct ct_atc *atc);
|
||||
|
||||
/* Don't touch! Used for internal object. */
|
||||
void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */
|
||||
void *mixer; /* internal mixer object */
|
||||
void *hw; /* chip specific hardware access object */
|
||||
void **daios; /* digital audio io resources */
|
||||
void **pcm; /* SUMs for collecting all pcm stream */
|
||||
void **srcs; /* Sample Rate Converters for input signal */
|
||||
void **srcimps; /* input mappers for SRCs */
|
||||
unsigned char n_daio;
|
||||
unsigned char n_src;
|
||||
unsigned char n_srcimp;
|
||||
unsigned char n_pcm;
|
||||
};
|
||||
|
||||
|
||||
int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
|
||||
unsigned int rsr, unsigned int msr,
|
||||
struct ct_atc **ratc);
|
||||
|
||||
#endif /* CTATC_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File ctdaio.h
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the definition of Digital Audio Input Output
|
||||
* resource management object.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date May 23 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CTDAIO_H
|
||||
#define CTDAIO_H
|
||||
|
||||
#include "ctresource.h"
|
||||
#include "ctimap.h"
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
/* Define the descriptor of a daio resource */
|
||||
enum DAIOTYP {
|
||||
LINEO1,
|
||||
LINEO2,
|
||||
LINEO3,
|
||||
LINEO4,
|
||||
SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */
|
||||
LINEIM,
|
||||
SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */
|
||||
SPDIFI1, /* S/PDIF In on internal Drive Bay */
|
||||
NUM_DAIOTYP
|
||||
};
|
||||
|
||||
struct dao_rsc_ops;
|
||||
struct dai_rsc_ops;
|
||||
struct daio_mgr;
|
||||
|
||||
struct daio {
|
||||
struct rsc rscl; /* Basic resource info for left TX/RX */
|
||||
struct rsc rscr; /* Basic resource info for right TX/RX */
|
||||
enum DAIOTYP type;
|
||||
};
|
||||
|
||||
struct dao {
|
||||
struct daio daio;
|
||||
struct dao_rsc_ops *ops; /* DAO specific operations */
|
||||
struct imapper **imappers;
|
||||
struct daio_mgr *mgr;
|
||||
void *hw;
|
||||
void *ctrl_blk;
|
||||
};
|
||||
|
||||
struct dai {
|
||||
struct daio daio;
|
||||
struct dai_rsc_ops *ops; /* DAI specific operations */
|
||||
void *hw;
|
||||
void *ctrl_blk;
|
||||
};
|
||||
|
||||
struct dao_desc {
|
||||
unsigned int msr:4;
|
||||
unsigned int passthru:1;
|
||||
};
|
||||
|
||||
struct dao_rsc_ops {
|
||||
int (*set_spos)(struct dao *dao, unsigned int spos);
|
||||
int (*commit_write)(struct dao *dao);
|
||||
int (*get_spos)(struct dao *dao, unsigned int *spos);
|
||||
int (*reinit)(struct dao *dao, const struct dao_desc *desc);
|
||||
int (*set_left_input)(struct dao *dao, struct rsc *input);
|
||||
int (*set_right_input)(struct dao *dao, struct rsc *input);
|
||||
int (*clear_left_input)(struct dao *dao);
|
||||
int (*clear_right_input)(struct dao *dao);
|
||||
};
|
||||
|
||||
struct dai_rsc_ops {
|
||||
int (*set_srt_srcl)(struct dai *dai, struct rsc *src);
|
||||
int (*set_srt_srcr)(struct dai *dai, struct rsc *src);
|
||||
int (*set_srt_msr)(struct dai *dai, unsigned int msr);
|
||||
int (*set_enb_src)(struct dai *dai, unsigned int enb);
|
||||
int (*set_enb_srt)(struct dai *dai, unsigned int enb);
|
||||
int (*commit_write)(struct dai *dai);
|
||||
};
|
||||
|
||||
/* Define daio resource request description info */
|
||||
struct daio_desc {
|
||||
unsigned int type:4;
|
||||
unsigned int msr:4;
|
||||
unsigned int passthru:1;
|
||||
};
|
||||
|
||||
struct daio_mgr {
|
||||
struct rsc_mgr mgr; /* Basic resource manager info */
|
||||
spinlock_t mgr_lock;
|
||||
spinlock_t imap_lock;
|
||||
struct list_head imappers;
|
||||
struct imapper *init_imap;
|
||||
unsigned int init_imap_added;
|
||||
|
||||
/* request one daio resource */
|
||||
int (*get_daio)(struct daio_mgr *mgr,
|
||||
const struct daio_desc *desc, struct daio **rdaio);
|
||||
/* return one daio resource */
|
||||
int (*put_daio)(struct daio_mgr *mgr, struct daio *daio);
|
||||
int (*daio_enable)(struct daio_mgr *mgr, struct daio *daio);
|
||||
int (*daio_disable)(struct daio_mgr *mgr, struct daio *daio);
|
||||
int (*imap_add)(struct daio_mgr *mgr, struct imapper *entry);
|
||||
int (*imap_delete)(struct daio_mgr *mgr, struct imapper *entry);
|
||||
int (*commit_write)(struct daio_mgr *mgr);
|
||||
};
|
||||
|
||||
/* Constructor and destructor of daio resource manager */
|
||||
int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr);
|
||||
int daio_mgr_destroy(struct daio_mgr *daio_mgr);
|
||||
|
||||
#endif /* CTDAIO_H */
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @file ctdrv.h
|
||||
*
|
||||
* @breaf
|
||||
* This file contains the definition of card IDs supported by this driver.
|
||||
*
|
||||
* @author Liu Chun
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CTDRV_H
|
||||
#define CTDRV_H
|
||||
|
||||
#define PCI_VENDOR_CREATIVE 0x1102
|
||||
#define PCI_DEVICE_CREATIVE_20K1 0x0005
|
||||
#define PCI_DEVICE_CREATIVE_20K2 0x000B
|
||||
#define PCI_SUBVENDOR_CREATIVE 0x1102
|
||||
#define PCI_SUBSYS_CREATIVE_SB0760 0x0024
|
||||
#define PCI_SUBSYS_CREATIVE_SB08801 0x0041
|
||||
#define PCI_SUBSYS_CREATIVE_SB08802 0x0042
|
||||
#define PCI_SUBSYS_CREATIVE_SB08803 0x0043
|
||||
#define PCI_SUBSYS_CREATIVE_HENDRIX 0x6000
|
||||
|
||||
#endif /* CTDRV_H */
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File cthardware.c
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the implementation of hardware access methord.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date Jun 26 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cthardware.h"
|
||||
#include "cthw20k1.h"
|
||||
#include "cthw20k2.h"
|
||||
#include <linux/bug.h>
|
||||
|
||||
static enum CHIPTYP get_chip_type(struct hw *hw)
|
||||
{
|
||||
enum CHIPTYP type = ATCNONE;
|
||||
|
||||
switch (hw->pci->device) {
|
||||
case 0x0005: /* 20k1 device */
|
||||
type = ATC20K1;
|
||||
break;
|
||||
case 0x000B: /* 20k2 device */
|
||||
type = ATC20K2;
|
||||
break;
|
||||
default:
|
||||
type = ATCNONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
int create_hw_obj(struct pci_dev *pci, struct hw **rhw)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
switch (pci->device) {
|
||||
case 0x0005: /* 20k1 device */
|
||||
err = create_20k1_hw_obj(rhw);
|
||||
break;
|
||||
case 0x000B: /* 20k2 device */
|
||||
err = create_20k2_hw_obj(rhw);
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
(*rhw)->pci = pci;
|
||||
(*rhw)->get_chip_type = get_chip_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int destroy_hw_obj(struct hw *hw)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
switch (hw->pci->device) {
|
||||
case 0x0005: /* 20k1 device */
|
||||
err = destroy_20k1_hw_obj(hw);
|
||||
break;
|
||||
case 0x000B: /* 20k2 device */
|
||||
err = destroy_20k2_hw_obj(hw);
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
unsigned int get_field(unsigned int data, unsigned int field)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUG_ON(!field);
|
||||
/* @field should always be greater than 0 */
|
||||
for (i = 0; !(field & (1 << i)); )
|
||||
i++;
|
||||
|
||||
return (data & field) >> i;
|
||||
}
|
||||
|
||||
void set_field(unsigned int *data, unsigned int field, unsigned int value)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUG_ON(!field);
|
||||
/* @field should always be greater than 0 */
|
||||
for (i = 0; !(field & (1 << i)); )
|
||||
i++;
|
||||
|
||||
*data = (*data & (~field)) | ((value << i) & field);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File cthardware.h
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the definition of hardware access methord.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date May 13 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CTHARDWARE_H
|
||||
#define CTHARDWARE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
enum CHIPTYP {
|
||||
ATC20K1,
|
||||
ATC20K2,
|
||||
ATCNONE
|
||||
};
|
||||
|
||||
/* Type of input source for ADC */
|
||||
enum ADCSRC{
|
||||
ADC_MICIN,
|
||||
ADC_LINEIN,
|
||||
ADC_VIDEO,
|
||||
ADC_AUX,
|
||||
ADC_NONE /* Switch to digital input */
|
||||
};
|
||||
|
||||
struct card_conf {
|
||||
/* device virtual mem page table page physical addr
|
||||
* (supporting one page table page now) */
|
||||
unsigned long vm_pgt_phys;
|
||||
unsigned int rsr; /* reference sample rate in Hzs*/
|
||||
unsigned int msr; /* master sample rate in rsrs */
|
||||
};
|
||||
|
||||
struct hw {
|
||||
int (*card_init)(struct hw *hw, struct card_conf *info);
|
||||
int (*card_stop)(struct hw *hw);
|
||||
int (*pll_init)(struct hw *hw, unsigned int rsr);
|
||||
enum CHIPTYP (*get_chip_type)(struct hw *hw);
|
||||
int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source);
|
||||
int (*select_adc_source)(struct hw *hw, enum ADCSRC source);
|
||||
int (*have_digit_io_switch)(struct hw *hw);
|
||||
|
||||
/* SRC operations */
|
||||
int (*src_rsc_get_ctrl_blk)(void **rblk);
|
||||
int (*src_rsc_put_ctrl_blk)(void *blk);
|
||||
int (*src_set_state)(void *blk, unsigned int state);
|
||||
int (*src_set_bm)(void *blk, unsigned int bm);
|
||||
int (*src_set_rsr)(void *blk, unsigned int rsr);
|
||||
int (*src_set_sf)(void *blk, unsigned int sf);
|
||||
int (*src_set_wr)(void *blk, unsigned int wr);
|
||||
int (*src_set_pm)(void *blk, unsigned int pm);
|
||||
int (*src_set_rom)(void *blk, unsigned int rom);
|
||||
int (*src_set_vo)(void *blk, unsigned int vo);
|
||||
int (*src_set_st)(void *blk, unsigned int st);
|
||||
int (*src_set_ie)(void *blk, unsigned int ie);
|
||||
int (*src_set_ilsz)(void *blk, unsigned int ilsz);
|
||||
int (*src_set_bp)(void *blk, unsigned int bp);
|
||||
int (*src_set_cisz)(void *blk, unsigned int cisz);
|
||||
int (*src_set_ca)(void *blk, unsigned int ca);
|
||||
int (*src_set_sa)(void *blk, unsigned int sa);
|
||||
int (*src_set_la)(void *blk, unsigned int la);
|
||||
int (*src_set_pitch)(void *blk, unsigned int pitch);
|
||||
int (*src_set_clear_zbufs)(void *blk, unsigned int clear);
|
||||
int (*src_set_dirty)(void *blk, unsigned int flags);
|
||||
int (*src_set_dirty_all)(void *blk);
|
||||
int (*src_commit_write)(struct hw *hw, unsigned int idx, void *blk);
|
||||
int (*src_get_ca)(struct hw *hw, unsigned int idx, void *blk);
|
||||
unsigned int (*src_get_dirty)(void *blk);
|
||||
unsigned int (*src_dirty_conj_mask)(void);
|
||||
int (*src_mgr_get_ctrl_blk)(void **rblk);
|
||||
int (*src_mgr_put_ctrl_blk)(void *blk);
|
||||
/* syncly enable src @idx */
|
||||
int (*src_mgr_enbs_src)(void *blk, unsigned int idx);
|
||||
/* enable src @idx */
|
||||
int (*src_mgr_enb_src)(void *blk, unsigned int idx);
|
||||
/* disable src @idx */
|
||||
int (*src_mgr_dsb_src)(void *blk, unsigned int idx);
|
||||
int (*src_mgr_commit_write)(struct hw *hw, void *blk);
|
||||
|
||||
/* SRC Input Mapper operations */
|
||||
int (*srcimp_mgr_get_ctrl_blk)(void **rblk);
|
||||
int (*srcimp_mgr_put_ctrl_blk)(void *blk);
|
||||
int (*srcimp_mgr_set_imaparc)(void *blk, unsigned int slot);
|
||||
int (*srcimp_mgr_set_imapuser)(void *blk, unsigned int user);
|
||||
int (*srcimp_mgr_set_imapnxt)(void *blk, unsigned int next);
|
||||
int (*srcimp_mgr_set_imapaddr)(void *blk, unsigned int addr);
|
||||
int (*srcimp_mgr_commit_write)(struct hw *hw, void *blk);
|
||||
|
||||
/* AMIXER operations */
|
||||
int (*amixer_rsc_get_ctrl_blk)(void **rblk);
|
||||
int (*amixer_rsc_put_ctrl_blk)(void *blk);
|
||||
int (*amixer_mgr_get_ctrl_blk)(void **rblk);
|
||||
int (*amixer_mgr_put_ctrl_blk)(void *blk);
|
||||
int (*amixer_set_mode)(void *blk, unsigned int mode);
|
||||
int (*amixer_set_iv)(void *blk, unsigned int iv);
|
||||
int (*amixer_set_x)(void *blk, unsigned int x);
|
||||
int (*amixer_set_y)(void *blk, unsigned int y);
|
||||
int (*amixer_set_sadr)(void *blk, unsigned int sadr);
|
||||
int (*amixer_set_se)(void *blk, unsigned int se);
|
||||
int (*amixer_set_dirty)(void *blk, unsigned int flags);
|
||||
int (*amixer_set_dirty_all)(void *blk);
|
||||
int (*amixer_commit_write)(struct hw *hw, unsigned int idx, void *blk);
|
||||
int (*amixer_get_y)(void *blk);
|
||||
unsigned int (*amixer_get_dirty)(void *blk);
|
||||
|
||||
/* DAIO operations */
|
||||
int (*dai_get_ctrl_blk)(void **rblk);
|
||||
int (*dai_put_ctrl_blk)(void *blk);
|
||||
int (*dai_srt_set_srco)(void *blk, unsigned int src);
|
||||
int (*dai_srt_set_srcm)(void *blk, unsigned int src);
|
||||
int (*dai_srt_set_rsr)(void *blk, unsigned int rsr);
|
||||
int (*dai_srt_set_drat)(void *blk, unsigned int drat);
|
||||
int (*dai_srt_set_ec)(void *blk, unsigned int ec);
|
||||
int (*dai_srt_set_et)(void *blk, unsigned int et);
|
||||
int (*dai_commit_write)(struct hw *hw, unsigned int idx, void *blk);
|
||||
int (*dao_get_ctrl_blk)(void **rblk);
|
||||
int (*dao_put_ctrl_blk)(void *blk);
|
||||
int (*dao_set_spos)(void *blk, unsigned int spos);
|
||||
int (*dao_commit_write)(struct hw *hw, unsigned int idx, void *blk);
|
||||
int (*dao_get_spos)(void *blk, unsigned int *spos);
|
||||
|
||||
int (*daio_mgr_get_ctrl_blk)(struct hw *hw, void **rblk);
|
||||
int (*daio_mgr_put_ctrl_blk)(void *blk);
|
||||
int (*daio_mgr_enb_dai)(void *blk, unsigned int idx);
|
||||
int (*daio_mgr_dsb_dai)(void *blk, unsigned int idx);
|
||||
int (*daio_mgr_enb_dao)(void *blk, unsigned int idx);
|
||||
int (*daio_mgr_dsb_dao)(void *blk, unsigned int idx);
|
||||
int (*daio_mgr_dao_init)(void *blk, unsigned int idx,
|
||||
unsigned int conf);
|
||||
int (*daio_mgr_set_imaparc)(void *blk, unsigned int slot);
|
||||
int (*daio_mgr_set_imapnxt)(void *blk, unsigned int next);
|
||||
int (*daio_mgr_set_imapaddr)(void *blk, unsigned int addr);
|
||||
int (*daio_mgr_commit_write)(struct hw *hw, void *blk);
|
||||
|
||||
struct pci_dev *pci; /* the pci kernel structure of this card */
|
||||
int irq;
|
||||
unsigned long io_base;
|
||||
unsigned long mem_base;
|
||||
};
|
||||
|
||||
int create_hw_obj(struct pci_dev *pci, struct hw **rhw);
|
||||
int destroy_hw_obj(struct hw *hw);
|
||||
|
||||
unsigned int get_field(unsigned int data, unsigned int field);
|
||||
void set_field(unsigned int *data, unsigned int field, unsigned int value);
|
||||
|
||||
#endif /* CTHARDWARE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File cthw20k1.h
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the definition of hardware access methord.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date May 13 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CTHW20K1_H
|
||||
#define CTHW20K1_H
|
||||
|
||||
#include "cthardware.h"
|
||||
|
||||
int create_20k1_hw_obj(struct hw **rhw);
|
||||
int destroy_20k1_hw_obj(struct hw *hw);
|
||||
|
||||
#endif /* CTHW20K1_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File cthw20k2.h
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the definition of hardware access methord.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date May 13 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CTHW20K2_H
|
||||
#define CTHW20K2_H
|
||||
|
||||
#include "cthardware.h"
|
||||
|
||||
int create_20k2_hw_obj(struct hw **rhw);
|
||||
int destroy_20k2_hw_obj(struct hw *hw);
|
||||
|
||||
#endif /* CTHW20K2_H */
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* This source file is released under GPL v2 license (no other versions).
|
||||
* See the COPYING file included in the main directory of this source
|
||||
* distribution for the license terms and conditions.
|
||||
*
|
||||
* @File ctimap.c
|
||||
*
|
||||
* @Brief
|
||||
* This file contains the implementation of generic input mapper operations
|
||||
* for input mapper management.
|
||||
*
|
||||
* @Author Liu Chun
|
||||
* @Date May 23 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ctimap.h"
|
||||
#include <linux/slab.h>
|
||||
|
||||
int input_mapper_add(struct list_head *mappers, struct imapper *entry,
|
||||
int (*map_op)(void *, struct imapper *), void *data)
|
||||
{
|
||||
struct list_head *pos, *pre, *head;
|
||||
struct imapper *pre_ent, *pos_ent;
|
||||
|
||||
head = mappers;
|
||||
|
||||
if (list_empty(head)) {
|
||||
entry->next = entry->addr;
|
||||
map_op(data, entry);
|
||||
list_add(&entry->list, head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each(pos, head) {
|
||||
pos_ent = list_entry(pos, struct imapper, list);
|
||||
if (pos_ent->slot > entry->slot) {
|
||||
/* found a position in list */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != head) {
|
||||
pre = pos->prev;
|
||||
if (pre == head)
|
||||
pre = head->prev;
|
||||
|
||||
__list_add(&entry->list, pos->prev, pos);
|
||||
} else {
|
||||
pre = head->prev;
|
||||
pos = head->next;
|
||||
list_add_tail(&entry->list, head);
|
||||
}
|
||||
|
||||
pre_ent = list_entry(pre, struct imapper, list);
|
||||
pos_ent = list_entry(pos, struct imapper, list);
|
||||
|
||||
entry->next = pos_ent->addr;
|
||||
map_op(data, entry);
|
||||
pre_ent->next = entry->addr;
|
||||
map_op(data, pre_ent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int input_mapper_delete(struct list_head *mappers, struct imapper *entry,
|
||||
int (*map_op)(void *, struct imapper *), void *data)
|
||||
{
|
||||
struct list_head *next, *pre, *head;
|
||||
struct imapper *pre_ent, *next_ent;
|
||||
|
||||
head = mappers;
|
||||
|
||||
if (list_empty(head))
|
||||
return 0;
|
||||
|
||||
pre = (entry->list.prev == head) ? head->prev : entry->list.prev;
|
||||
next = (entry->list.next == head) ? head->next : entry->list.next;
|
||||
|
||||
if (pre == &entry->list) {
|
||||
/* entry is the only one node in mappers list */
|
||||
entry->next = entry->addr = entry->user = entry->slot = 0;
|
||||
map_op(data, entry);
|
||||
list_del(&entry->list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pre_ent = list_entry(pre, struct imapper, list);
|
||||
next_ent = list_entry(next, struct imapper, list);
|
||||
|
||||
pre_ent->next = next_ent->addr;
|
||||
map_op(data, pre_ent);
|
||||
list_del(&entry->list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_input_mapper_list(struct list_head *head)
|
||||
{
|
||||
struct imapper *entry = NULL;
|
||||
struct list_head *pos = NULL;
|
||||
|
||||
while (!list_empty(head)) {
|
||||
pos = head->next;
|
||||
list_del(pos);
|
||||
entry = list_entry(pos, struct imapper, list);
|
||||
kfree(entry);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user