linux/sound/pci/nm256/nm256.c

// SPDX-License-Identifier: GPL-2.0-or-later
/* 
 * Driver for NeoMagic 256AV and 256ZX chipsets.
 * Copyright (c) 2000 by Takashi Iwai <[email protected]>
 *
 * Based on nm256_audio.c OSS driver in linux kernel.
 * The original author of OSS nm256 driver wishes to remain anonymous,
 * so I just put my acknoledgment to him/her here.
 * The original author's web page is found at
 *	http://www.uglx.org/sony.html
 */
  
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mutex.h>

#include <sound/core.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/initval.h>

#define CARD_NAME
#define DRIVER_NAME

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

/*
 * some compile conditions.
 */

static int index =;	/* Index */
static char *id =;	/* ID for this card */
static int playback_bufsize =;
static int capture_bufsize =;
static bool force_ac97;			/* disabled as default */
static int buffer_top;			/* not specified */
static bool use_cache;			/* disabled */
static bool vaio_hack;			/* disabled */
static bool reset_workaround;
static bool reset_workaround_2;

module_param(index, int, 0444);
MODULE_PARM_DESC();
module_param(id, charp, 0444);
MODULE_PARM_DESC();
module_param(playback_bufsize, int, 0444);
MODULE_PARM_DESC();
module_param(capture_bufsize, int, 0444);
MODULE_PARM_DESC();
module_param(force_ac97, bool, 0444);
MODULE_PARM_DESC();
module_param(buffer_top, int, 0444);
MODULE_PARM_DESC();
module_param(use_cache, bool, 0444);
MODULE_PARM_DESC();
module_param(vaio_hack, bool, 0444);
MODULE_PARM_DESC();
module_param(reset_workaround, bool, 0444);
MODULE_PARM_DESC();
module_param(reset_workaround_2, bool, 0444);
MODULE_PARM_DESC();

/* just for backward compatibility */
static bool enable;
module_param(enable, bool, 0444);



/*
 * hw definitions
 */

/* The BIOS signature. */
#define NM_SIGNATURE
/* Signature mask. */
#define NM_SIG_MASK

/* Size of the second memory area. */
#define NM_PORT2_SIZE

/* The base offset of the mixer in the second memory area. */
#define NM_MIXER_OFFSET

/* The maximum size of a coefficient entry. */
#define NM_MAX_PLAYBACK_COEF_SIZE
#define NM_MAX_RECORD_COEF_SIZE

/* The interrupt register. */
#define NM_INT_REG
/* And its bits. */
#define NM_PLAYBACK_INT
#define NM_RECORD_INT
#define NM_MISC_INT_1
#define NM_MISC_INT_2
#define NM_ACK_INT(chip, X)

/* The AV's "mixer ready" status bit and location. */
#define NM_MIXER_STATUS_OFFSET
#define NM_MIXER_READY_MASK
#define NM_MIXER_PRESENCE
#define NM_PRESENCE_MASK
#define NM_PRESENCE_VALUE

/*
 * For the ZX.  It uses the same interrupt register, but it holds 32
 * bits instead of 16.
 */
#define NM2_PLAYBACK_INT
#define NM2_RECORD_INT
#define NM2_MISC_INT_1
#define NM2_MISC_INT_2
#define NM2_ACK_INT(chip, X)

/* The ZX's "mixer ready" status bit and location. */
#define NM2_MIXER_STATUS_OFFSET
#define NM2_MIXER_READY_MASK

/* The playback registers start from here. */
#define NM_PLAYBACK_REG_OFFSET
/* The record registers start from here. */
#define NM_RECORD_REG_OFFSET

/* The rate register is located 2 bytes from the start of the register area. */
#define NM_RATE_REG_OFFSET

/* Mono/stereo flag, number of bits on playback, and rate mask. */
#define NM_RATE_STEREO
#define NM_RATE_BITS_16
#define NM_RATE_MASK

/* Playback enable register. */
#define NM_PLAYBACK_ENABLE_REG
#define NM_PLAYBACK_ENABLE_FLAG
#define NM_PLAYBACK_ONESHOT
#define NM_PLAYBACK_FREERUN

/* Mutes the audio output. */
#define NM_AUDIO_MUTE_REG
#define NM_AUDIO_MUTE_LEFT
#define NM_AUDIO_MUTE_RIGHT

/* Recording enable register. */
#define NM_RECORD_ENABLE_REG
#define NM_RECORD_ENABLE_FLAG
#define NM_RECORD_FREERUN

/* coefficient buffer pointer */
#define NM_COEFF_START_OFFSET
#define NM_COEFF_END_OFFSET

/* DMA buffer offsets */
#define NM_RBUFFER_START
#define NM_RBUFFER_END
#define NM_RBUFFER_WMARK
#define NM_RBUFFER_CURRP

#define NM_PBUFFER_START
#define NM_PBUFFER_END
#define NM_PBUFFER_WMARK
#define NM_PBUFFER_CURRP

struct nm256_stream {};

struct nm256 {};


/*
 * include coefficient table
 */
#include "nm256_coef.c"


/*
 * PCI ids
 */
static const struct pci_device_id snd_nm256_ids[] =;

MODULE_DEVICE_TABLE(pci, snd_nm256_ids);


/*
 * lowlvel stuffs
 */

static inline u8
snd_nm256_readb(struct nm256 *chip, int offset)
{}

static inline u16
snd_nm256_readw(struct nm256 *chip, int offset)
{}

static inline u32
snd_nm256_readl(struct nm256 *chip, int offset)
{}

static inline void
snd_nm256_writeb(struct nm256 *chip, int offset, u8 val)
{}

static inline void
snd_nm256_writew(struct nm256 *chip, int offset, u16 val)
{}

static inline void
snd_nm256_writel(struct nm256 *chip, int offset, u32 val)
{}

static inline void
snd_nm256_write_buffer(struct nm256 *chip, const void *src, int offset, int size)
{}

/*
 * coefficient handlers -- what a magic!
 */

static u16
snd_nm256_get_start_offset(int which)
{}

static void
snd_nm256_load_one_coefficient(struct nm256 *chip, int stream, u32 port, int which)
{}

static void
snd_nm256_load_coefficient(struct nm256 *chip, int stream, int number)
{}


/* The actual rates supported by the card. */
static const unsigned int samplerates[8] =;
static const struct snd_pcm_hw_constraint_list constraints_rates =;

/*
 * return the index of the target rate
 */
static int
snd_nm256_fixed_rate(unsigned int rate)
{}

/*
 * set sample rate and format
 */
static void
snd_nm256_set_format(struct nm256 *chip, struct nm256_stream *s,
		     struct snd_pcm_substream *substream)
{}

/* acquire interrupt */
static int snd_nm256_acquire_irq(struct nm256 *chip)
{}

/* release interrupt */
static void snd_nm256_release_irq(struct nm256 *chip)
{}

/*
 * start / stop
 */

/* update the watermark (current period) */
static void snd_nm256_pcm_mark(struct nm256 *chip, struct nm256_stream *s, int reg)
{}

#define snd_nm256_playback_mark(chip, s)
#define snd_nm256_capture_mark(chip, s)

static void
snd_nm256_playback_start(struct nm256 *chip, struct nm256_stream *s,
			 struct snd_pcm_substream *substream)
{}

static void
snd_nm256_capture_start(struct nm256 *chip, struct nm256_stream *s,
			struct snd_pcm_substream *substream)
{}

/* Stop the play engine. */
static void
snd_nm256_playback_stop(struct nm256 *chip)
{}

static void
snd_nm256_capture_stop(struct nm256 *chip)
{}

static int
snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{}

static int
snd_nm256_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{}


/*
 * prepare playback/capture channel
 */
static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream)
{}


/*
 * get the current pointer
 */
static snd_pcm_uframes_t
snd_nm256_playback_pointer(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t
snd_nm256_capture_pointer(struct snd_pcm_substream *substream)
{}

/* Remapped I/O space can be accessible as pointer on i386 */
/* This might be changed in the future */
#ifndef __i386__
/*
 * silence / copy for playback
 */
static int
snd_nm256_playback_silence(struct snd_pcm_substream *substream,
			   int channel, unsigned long pos, unsigned long count)
{}

static int
snd_nm256_playback_copy(struct snd_pcm_substream *substream,
			int channel, unsigned long pos,
			struct iov_iter *src, unsigned long count)
{}

/*
 * copy to user
 */
static int
snd_nm256_capture_copy(struct snd_pcm_substream *substream,
		       int channel, unsigned long pos,
		       struct iov_iter *dst, unsigned long count)
{}

#endif /* !__i386__ */


/*
 * update playback/capture watermarks
 */

/* spinlock held! */
static void
snd_nm256_playback_update(struct nm256 *chip)
{}

/* spinlock held! */
static void
snd_nm256_capture_update(struct nm256 *chip)
{}

/*
 * hardware info
 */
static const struct snd_pcm_hardware snd_nm256_playback =;

static const struct snd_pcm_hardware snd_nm256_capture =;


/* set dma transfer size */
static int snd_nm256_pcm_hw_params(struct snd_pcm_substream *substream,
				   struct snd_pcm_hw_params *hw_params)
{}

/*
 * open
 */
static void snd_nm256_setup_stream(struct nm256 *chip, struct nm256_stream *s,
				   struct snd_pcm_substream *substream,
				   const struct snd_pcm_hardware *hw_ptr)
{}

static int
snd_nm256_playback_open(struct snd_pcm_substream *substream)
{}

static int
snd_nm256_capture_open(struct snd_pcm_substream *substream)
{}

/*
 * close - we don't have to do special..
 */
static int
snd_nm256_playback_close(struct snd_pcm_substream *substream)
{}


static int
snd_nm256_capture_close(struct snd_pcm_substream *substream)
{}

/*
 * create a pcm instance
 */
static const struct snd_pcm_ops snd_nm256_playback_ops =;

static const struct snd_pcm_ops snd_nm256_capture_ops =;

static int
snd_nm256_pcm(struct nm256 *chip, int device)
{}


/* 
 * Initialize the hardware. 
 */
static void
snd_nm256_init_chip(struct nm256 *chip)
{}


static irqreturn_t
snd_nm256_intr_check(struct nm256 *chip)
{}

/* 
 * Handle a potential interrupt for the device referred to by DEV_ID. 
 *
 * I don't like the cut-n-paste job here either between the two routines,
 * but there are sufficient differences between the two interrupt handlers
 * that parameterizing it isn't all that great either.  (Could use a macro,
 * I suppose...yucky bleah.)
 */

static irqreturn_t
snd_nm256_interrupt(int irq, void *dev_id)
{}

/*
 * Handle a potential interrupt for the device referred to by DEV_ID.
 * This handler is for the 256ZX, and is very similar to the non-ZX
 * routine.
 */

static irqreturn_t
snd_nm256_interrupt_zx(int irq, void *dev_id)
{}

/*
 * AC97 interface
 */

/*
 * Waits for the mixer to become ready to be written; returns a zero value
 * if it timed out.
 */
static int
snd_nm256_ac97_ready(struct nm256 *chip)
{}

/* 
 * Initial register values to be written to the AC97 mixer.
 * While most of these are identical to the reset values, we do this
 * so that we have most of the register contents cached--this avoids
 * reading from the mixer directly (which seems to be problematic,
 * probably due to ignorance).
 */

struct initialValues {};

static const struct initialValues nm256_ac97_init_val[] =;

static int nm256_ac97_idx(unsigned short reg)
{}

/*
 * some nm256 easily crash when reading from mixer registers
 * thus we're treating it as a write-only mixer and cache the
 * written values
 */
static unsigned short
snd_nm256_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{}

/* 
 */
static void
snd_nm256_ac97_write(struct snd_ac97 *ac97,
		     unsigned short reg, unsigned short val)
{}

/* static resolution table */
static const struct snd_ac97_res_table nm256_res_table[] =;

/* initialize the ac97 into a known state */
static void
snd_nm256_ac97_reset(struct snd_ac97 *ac97)
{}

/* create an ac97 mixer interface */
static int
snd_nm256_mixer(struct nm256 *chip)
{}

/* 
 * See if the signature left by the NM256 BIOS is intact; if so, we use
 * the associated address as the end of our audio buffer in the video
 * RAM.
 */

static int
snd_nm256_peek_for_sig(struct nm256 *chip)
{}

/*
 * APM event handler, so the card is properly reinitialized after a power
 * event.
 */
static int nm256_suspend(struct device *dev)
{}

static int nm256_resume(struct device *dev)
{}

static DEFINE_SIMPLE_DEV_PM_OPS(nm256_pm, nm256_suspend, nm256_resume);

static void snd_nm256_free(struct snd_card *card)
{}

static int
snd_nm256_create(struct snd_card *card, struct pci_dev *pci)
{}


enum {};

static const struct snd_pci_quirk nm256_quirks[] =;


static int snd_nm256_probe(struct pci_dev *pci,
			   const struct pci_device_id *pci_id)
{}

static struct pci_driver nm256_driver =;

module_pci_driver();