xref: /kernel/linux/linux-6.6/sound/drivers/pcsp/pcsp.h (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PC-Speaker driver for Linux
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 1993-1997  Michael Beck
662306a36Sopenharmony_ci * Copyright (C) 1997-2001  David Woodhouse
762306a36Sopenharmony_ci * Copyright (C) 2001-2008  Stas Sergeev
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef __PCSP_H__
1162306a36Sopenharmony_ci#define __PCSP_H__
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/hrtimer.h>
1462306a36Sopenharmony_ci#include <linux/i8253.h>
1562306a36Sopenharmony_ci#include <linux/timex.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define PCSP_SOUND_VERSION 0x400	/* read 4.00 */
1862306a36Sopenharmony_ci#define PCSP_DEBUG 0
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/* default timer freq for PC-Speaker: 18643 Hz */
2162306a36Sopenharmony_ci#define DIV_18KHZ 64
2262306a36Sopenharmony_ci#define MAX_DIV DIV_18KHZ
2362306a36Sopenharmony_ci#define CALC_DIV(d) (MAX_DIV >> (d))
2462306a36Sopenharmony_ci#define CUR_DIV() CALC_DIV(chip->treble)
2562306a36Sopenharmony_ci#define PCSP_MAX_TREBLE 1
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* unfortunately, with hrtimers 37KHz does not work very well :( */
2862306a36Sopenharmony_ci#define PCSP_DEFAULT_TREBLE 0
2962306a36Sopenharmony_ci#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/* wild guess */
3262306a36Sopenharmony_ci#define PCSP_MIN_LPJ 1000000
3362306a36Sopenharmony_ci#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1)
3462306a36Sopenharmony_ci#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV)
3562306a36Sopenharmony_ci#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble))
3662306a36Sopenharmony_ci#define PCSP_CALC_RATE(i) (PIT_TICK_RATE / CALC_DIV(i))
3762306a36Sopenharmony_ci#define PCSP_RATE() PCSP_CALC_RATE(chip->treble)
3862306a36Sopenharmony_ci#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE
3962306a36Sopenharmony_ci#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE
4062306a36Sopenharmony_ci#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1)
4162306a36Sopenharmony_ci#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1)
4262306a36Sopenharmony_ci#define PCSP_CALC_NS(div) ({ \
4362306a36Sopenharmony_ci	u64 __val = 1000000000ULL * (div); \
4462306a36Sopenharmony_ci	do_div(__val, PIT_TICK_RATE); \
4562306a36Sopenharmony_ci	__val; \
4662306a36Sopenharmony_ci})
4762306a36Sopenharmony_ci#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV())
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define PCSP_MAX_PERIOD_SIZE	(64*1024)
5062306a36Sopenharmony_ci#define PCSP_MAX_PERIODS	512
5162306a36Sopenharmony_ci#define PCSP_BUFFER_SIZE	(128*1024)
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistruct snd_pcsp {
5462306a36Sopenharmony_ci	struct snd_card *card;
5562306a36Sopenharmony_ci	struct snd_pcm *pcm;
5662306a36Sopenharmony_ci	struct input_dev *input_dev;
5762306a36Sopenharmony_ci	struct hrtimer timer;
5862306a36Sopenharmony_ci	unsigned short port, irq, dma;
5962306a36Sopenharmony_ci	spinlock_t substream_lock;
6062306a36Sopenharmony_ci	struct snd_pcm_substream *playback_substream;
6162306a36Sopenharmony_ci	unsigned int fmt_size;
6262306a36Sopenharmony_ci	unsigned int is_signed;
6362306a36Sopenharmony_ci	size_t playback_ptr;
6462306a36Sopenharmony_ci	size_t period_ptr;
6562306a36Sopenharmony_ci	atomic_t timer_active;
6662306a36Sopenharmony_ci	int thalf;
6762306a36Sopenharmony_ci	u64 ns_rem;
6862306a36Sopenharmony_ci	unsigned char val61;
6962306a36Sopenharmony_ci	int enable;
7062306a36Sopenharmony_ci	int max_treble;
7162306a36Sopenharmony_ci	int treble;
7262306a36Sopenharmony_ci	int pcspkr;
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciextern struct snd_pcsp pcsp_chip;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciextern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
7862306a36Sopenharmony_ciextern void pcsp_sync_stop(struct snd_pcsp *chip);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ciextern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
8162306a36Sopenharmony_ciextern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#endif
84