Commit e618a560 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/ctxfi' into for-linus

* topic/ctxfi: (35 commits)
  ALSA: ctxfi - Clear PCM resources at hw_params and hw_free
  ALSA: ctxfi - Check the presence of SRC instance in PCM pointer callbacks
  ALSA: ctxfi - Add missing start check in atc_pcm_playback_start()
  ALSA: ctxfi - Add use_system_timer module option
  ALSA: ctxfi - Fix wrong model id for UAA
  ALSA: ctxfi - Clean up probe routines
  ALSA: ctxfi - Fix / clean up hw20k2 chip code
  ALSA: ctxfi - Fix possible buffer pointer overrun
  ALSA: ctxfi - Remove useless initializations and cast
  ALSA: ctxfi - Fix DMA mask for emu20k2 chip
  ALSA: ctxfi - Make volume controls more intuitive
  ALSA: ctxfi - Optimize the native timer handling using wc counter
  ALSA: ctxfi - Add missing inclusion of linux/math64.h
  ALSA: ctxfi - Set device 0 for mixer control elements
  ALSA: ctxfi - Clean up / optimize
  ALSA: ctxfi - Set periods_min to 2
  ALSA: ctxfi - Use native timer interrupt on emu20k1
  ALSA: ctxfi - Fix previous fix for 64bit DMA
  ALSA: ctxfi - Fix endian-dependent codes
  ALSA: ctxfi - Allow 64bit DMA
  ...
parents d3e37436 a5990dc5
......@@ -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
------------------
......
......@@ -1314,6 +1314,13 @@
#define PCI_VENDOR_ID_CREATIVE 0x1102 /* duplicate: ECTIVA */
#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
#define PCI_DEVICE_ID_CREATIVE_20K1 0x0005
#define PCI_DEVICE_ID_CREATIVE_20K2 0x000b
#define PCI_SUBDEVICE_ID_CREATIVE_SB0760 0x0024
#define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041
#define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042
#define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043
#define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX 0x6000
#define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */
#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
......
......@@ -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/ \
......
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 cttimer.o \
cthw20k2.o cthw20k1.o
obj-$(CONFIG_SND_CTXFI) += snd-ctxfi.o
This diff is collapsed.
/**
* 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
This diff is collapsed.
/**
* 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 */
This diff is collapsed.
/**
* 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,
SURROUND,
CLFE,
SIDE,
IEC958,
MIXER,
NUM_CTALSADEVS /* 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;
struct ct_timer;
struct ct_timer_instance;
/* alsa pcm stream descriptor */
struct ct_atc_pcm {
struct snd_pcm_substream *substream;
void (*interrupt)(struct ct_atc_pcm *apcm);
struct ct_timer_instance *timer;
unsigned int started:1;
/* 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 */
int chip_type;
int model;
const char *chip_name;
const char *model_name;
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;
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;
struct ct_timer *timer;
};
int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
unsigned int rsr, unsigned int msr, int chip_type,
struct ct_atc **ratc);
int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc);
#endif /* CTATC_H */
This diff is collapsed.
/**
* 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 */
/**
* 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>
int __devinit create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
enum CTCARDS model, struct hw **rhw)
{
int err;
switch (chip_type) {
case ATC20K1:
err = create_20k1_hw_obj(rhw);
break;
case ATC20K2:
err = create_20k2_hw_obj(rhw);
break;
default:
err = -ENODEV;
break;
}
if (err)
return err;
(*rhw)->pci = pci;
(*rhw)->chip_type = chip_type;
(*rhw)->model = model;
return 0;
}
int destroy_hw_obj(struct hw *hw)
{
int err;
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);
}
/**
* 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
};
enum CTCARDS {
/* 20k1 models */
CTSB055X,
CTSB073X,
CTUAA,
CT20K1_UNKNOWN,
/* 20k2 models */
CTSB0760,
CTHENDRIX,
CTSB0880,
NUM_CTCARDS /* This should always be the last */
};
/* 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);
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);
int (*set_timer_irq)(struct hw *hw, int enable);
int (*set_timer_tick)(struct hw *hw, unsigned int tick);
unsigned int (*get_wc)(struct hw *hw);
void (*irq_callback)(void *data, unsigned int bit);
void *irq_callback_data;
struct pci_dev *pci; /* the pci kernel structure of this card */
int irq;
unsigned long io_base;
unsigned long mem_base;
enum CHIPTYP chip_type;
enum CTCARDS model;
};
int create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
enum CTCARDS model, 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);
/* IRQ bits */
#define PLL_INT (1 << 10) /* PLL input-clock out-of-range */
#define FI_INT (1 << 9) /* forced interrupt */
#define IT_INT (1 << 8) /* timer interrupt */
#define PCI_INT (1 << 7) /* PCI bus error pending */
#define URT_INT (1 << 6) /* UART Tx/Rx */
#define GPI_INT (1 << 5) /* GPI pin */
#define MIX_INT (1 << 4) /* mixer parameter segment FIFO channels */
#define DAI_INT (1 << 3) /* DAI (SR-tracker or SPDIF-receiver) */
#define TP_INT (1 << 2) /* transport priority queue */
#define DSP_INT (1 << 1) /* DSP */
#define SRC_INT (1 << 0) /* SRC channels */
#endif /* CTHARDWARE_H */
This diff is collapsed.
/**
* 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 */
This diff is collapsed.
/**
* 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 */
/**
* 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;
struct list_head *pos;
while (!list_empty(head)) {
pos = head->next;
list_del(pos);
entry = list_entry(pos, struct imapper, list);
kfree(entry);
}
}
/**
* 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.h
*
* @Brief
* This file contains the definition of generic input mapper operations
* for input mapper management.
*
* @Author Liu Chun
* @Date May 23 2008
*
*/
#ifndef CTIMAP_H
#define CTIMAP_H
#include <linux/list.h>
struct imapper {
unsigned short slot; /* the id of the slot containing input data */
unsigned short user; /* the id of the user resource consuming data */
unsigned short addr; /* the input mapper ram id */
unsigned short next; /* the next input mapper ram id */
struct list_head list;
};
int input_mapper_add(struct list_head *mappers, struct imapper *entry,
int (*map_op)(void *, struct imapper *), void *data);
int input_mapper_delete(struct list_head *mappers, struct imapper *entry,
int (*map_op)(void *, struct imapper *), void *data);
void free_input_mapper_list(struct list_head *mappers);
#endif /* CTIMAP_H */
This diff is collapsed.
/**
* 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 ctmixer.h
*
* @Brief
* This file contains the definition of the mixer device functions.
*
* @Author Liu Chun
* @Date Mar 28 2008
*
*/
#ifndef CTMIXER_H
#define CTMIXER_H
#include "ctatc.h"
#include "ctresource.h"
#define INIT_VOL 0x1c00
enum MIXER_PORT_T {
MIX_WAVE_FRONT,
MIX_WAVE_REAR,
MIX_WAVE_CENTLFE,
MIX_WAVE_SURROUND,
MIX_SPDIF_OUT,
MIX_PCMO_FRONT,
MIX_MIC_IN,
MIX_LINE_IN,
MIX_SPDIF_IN,
MIX_PCMI_FRONT,
MIX_PCMI_REAR,
MIX_PCMI_CENTLFE,
MIX_PCMI_SURROUND,
NUM_MIX_PORTS
};
/* alsa mixer descriptor */
struct ct_mixer {
struct ct_atc *atc;
void **amixers; /* amixer resources for volume control */
void **sums; /* sum resources for signal collection */
unsigned int switch_state; /* A bit-map to indicate state of switches */
int (*get_output_ports)(struct ct_mixer *mixer, enum MIXER_PORT_T type,
struct rsc **rleft, struct rsc **rright);
int (*set_input_left)(struct ct_mixer *mixer,
enum MIXER_PORT_T type, struct rsc *rsc);
int (*set_input_right)(struct ct_mixer *mixer,
enum MIXER_PORT_T type, struct rsc *rsc);
};
int ct_alsa_mix_create(struct ct_atc *atc,
enum CTALSADEVS device,
const char *device_name);
int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer);
int ct_mixer_destroy(struct ct_mixer *mixer);
#endif /* CTMIXER_H */
This diff is collapsed.
/**
* 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 ctpcm.h
*
* @Brief
* This file contains the definition of the pcm device functions.
*
* @Author Liu Chun
* @Date Mar 28 2008
*
*/
#ifndef CTPCM_H
#define CTPCM_H
#include "ctatc.h"
int ct_alsa_pcm_create(struct ct_atc *atc,
enum CTALSADEVS device,
const char *device_name);
#endif /* CTPCM_H */
/**
* 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 ctresource.c
*
* @Brief
* This file contains the implementation of some generic helper functions.
*
* @Author Liu Chun
* @Date May 15 2008
*
*/
#include "ctresource.h"
#include "cthardware.h"
#include <linux/err.h>
#include <linux/slab.h>
#define AUDIO_SLOT_BLOCK_NUM 256
/* Resource allocation based on bit-map management mechanism */
static int
get_resource(u8 *rscs, unsigned int amount,
unsigned int multi, unsigned int *ridx)
{
int i, j, k, n;
/* Check whether there are sufficient resources to meet request. */
for (i = 0, n = multi; i < amount; i++) {
j = i / 8;
k = i % 8;
if (rscs[j] & ((u8)1 << k)) {
n = multi;
continue;
}
if (!(--n))
break; /* found sufficient contiguous resources */
}
if (i >= amount) {
/* Can not find sufficient contiguous resources */
return -ENOENT;
}
/* Mark the contiguous bits in resource bit-map as used */
for (n = multi; n > 0; n--) {
j = i / 8;
k = i % 8;
rscs[j] |= ((u8)1 << k);
i--;
}
*ridx = i + 1;
return 0;
}
static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
{
unsigned int i, j, k, n;
/* Mark the contiguous bits in resource bit-map as used */
for (n = multi, i = idx; n > 0; n--) {
j = i / 8;
k = i % 8;
rscs[j] &= ~((u8)1 << k);
i++;
}
return 0;
}
int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
{
int err;
if (n > mgr->avail)
return -ENOENT;
err = get_resource(mgr->rscs, mgr->amount, n, ridx);
if (!err)
mgr->avail -= n;
return err;
}
int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
{
put_resource(mgr->rscs, n, idx);
mgr->avail += n;
return 0;
}
static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
/* SRC channel is at Audio Ring slot 1 every 16 slots. */
[SRC] = 0x1,
[AMIXER] = 0x4,
[SUM] = 0xc,
};
static int rsc_index(const struct rsc *rsc)
{
return rsc->conj;
}
static int audio_ring_slot(const struct rsc *rsc)
{
return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
}
static int rsc_next_conj(struct rsc *rsc)
{
unsigned int i;
for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
i++;
rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
return rsc->conj;
}
static int rsc_master(struct rsc *rsc)
{
return rsc->conj = rsc->idx;
}
static struct rsc_ops rsc_generic_ops = {
.index = rsc_index,
.output_slot = audio_ring_slot,
.master = rsc_master,
.next_conj = rsc_next_conj,
};
int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
{
int err = 0;
rsc->idx = idx;
rsc->conj = idx;
rsc->type = type;
rsc->msr = msr;
rsc->hw = hw;
rsc->ops = &rsc_generic_ops;
if (NULL == hw) {
rsc->ctrl_blk = NULL;
return 0;
}
switch (type) {
case SRC:
err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
break;
case AMIXER:
err = ((struct hw *)hw)->
amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
break;
case SRCIMP:
case SUM:
case DAIO:
break;
default:
printk(KERN_ERR
"ctxfi: Invalid resource type value %d!\n", type);
return -EINVAL;
}
if (err) {
printk(KERN_ERR
"ctxfi: Failed to get resource control block!\n");
return err;
}
return 0;
}
int rsc_uninit(struct rsc *rsc)
{
if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
switch (rsc->type) {
case SRC:
((struct hw *)rsc->hw)->
src_rsc_put_ctrl_blk(rsc->ctrl_blk);
break;
case AMIXER:
((struct hw *)rsc->hw)->
amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
break;
case SUM:
case DAIO:
break;
default:
printk(KERN_ERR "ctxfi: "
"Invalid resource type value %d!\n", rsc->type);
break;
}
rsc->hw = rsc->ctrl_blk = NULL;
}
rsc->idx = rsc->conj = 0;
rsc->type = NUM_RSCTYP;
rsc->msr = 0;
return 0;
}
int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
unsigned int amount, void *hw_obj)
{
int err = 0;
struct hw *hw = hw_obj;
mgr->type = NUM_RSCTYP;
mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
if (NULL == mgr->rscs)
return -ENOMEM;
switch (type) {
case SRC:
err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
break;
case SRCIMP:
err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
break;
case AMIXER:
err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
break;
case DAIO:
err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
break;
case SUM:
break;
default:
printk(KERN_ERR
"ctxfi: Invalid resource type value %d!\n", type);
err = -EINVAL;
goto error;
}
if (err) {
printk(KERN_ERR
"ctxfi: Failed to get manager control block!\n");
goto error;
}
mgr->type = type;
mgr->avail = mgr->amount = amount;
mgr->hw = hw;
return 0;
error:
kfree(mgr->rscs);
return err;
}
int rsc_mgr_uninit(struct rsc_mgr *mgr)
{
if (NULL != mgr->rscs) {
kfree(mgr->rscs);
mgr->rscs = NULL;
}
if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
switch (mgr->type) {
case SRC:
((struct hw *)mgr->hw)->
src_mgr_put_ctrl_blk(mgr->ctrl_blk);
break;
case SRCIMP:
((struct hw *)mgr->hw)->
srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
break;
case AMIXER:
((struct hw *)mgr->hw)->
amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
break;
case DAIO:
((struct hw *)mgr->hw)->
daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
break;
case SUM:
break;
default:
printk(KERN_ERR "ctxfi: "
"Invalid resource type value %d!\n", mgr->type);
break;
}
mgr->hw = mgr->ctrl_blk = NULL;
}
mgr->type = NUM_RSCTYP;
mgr->avail = mgr->amount = 0;
return 0;
}
/**
* 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 ctresource.h
*
* @Brief
* This file contains the definition of generic hardware resources for
* resource management.
*
* @Author Liu Chun
* @Date May 13 2008
*
*/
#ifndef CTRESOURCE_H
#define CTRESOURCE_H
#include <linux/types.h>
enum RSCTYP {
SRC,
SRCIMP,
AMIXER,
SUM,
DAIO,
NUM_RSCTYP /* This must be the last one and less than 16 */
};
struct rsc_ops;
struct rsc {
u32 idx:12; /* The index of a resource */
u32 type:4; /* The type (RSCTYP) of a resource */
u32 conj:12; /* Current conjugate index */
u32 msr:4; /* The Master Sample Rate a resource working on */
void *ctrl_blk; /* Chip specific control info block for a resource */
void *hw; /* Chip specific object for hardware access means */
struct rsc_ops *ops; /* Generic resource operations */
};
struct rsc_ops {
int (*master)(struct rsc *rsc); /* Move to master resource */
int (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */
int (*index)(const struct rsc *rsc); /* Return the index of resource */
/* Return the output slot number */
int (*output_slot)(const struct rsc *rsc);
};
int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw);
int rsc_uninit(struct rsc *rsc);
struct rsc_mgr {
enum RSCTYP type; /* The type (RSCTYP) of resource to manage */
unsigned int amount; /* The total amount of a kind of resource */
unsigned int avail; /* The amount of currently available resources */
unsigned char *rscs; /* The bit-map for resource allocation */
void *ctrl_blk; /* Chip specific control info block */
void *hw; /* Chip specific object for hardware access */
};
/* Resource management is based on bit-map mechanism */
int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
unsigned int amount, void *hw);
int rsc_mgr_uninit(struct rsc_mgr *mgr);
int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx);
int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx);
#endif /* CTRESOURCE_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment