18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * PC-Speaker driver for Linux
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 1993-1997  Michael Beck
68c2ecf20Sopenharmony_ci * Copyright (C) 1997-2001  David Woodhouse
78c2ecf20Sopenharmony_ci * Copyright (C) 2001-2008  Stas Sergeev
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#ifndef __PCSP_H__
118c2ecf20Sopenharmony_ci#define __PCSP_H__
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/hrtimer.h>
148c2ecf20Sopenharmony_ci#include <linux/i8253.h>
158c2ecf20Sopenharmony_ci#include <linux/timex.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define PCSP_SOUND_VERSION 0x400	/* read 4.00 */
188c2ecf20Sopenharmony_ci#define PCSP_DEBUG 0
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/* default timer freq for PC-Speaker: 18643 Hz */
218c2ecf20Sopenharmony_ci#define DIV_18KHZ 64
228c2ecf20Sopenharmony_ci#define MAX_DIV DIV_18KHZ
238c2ecf20Sopenharmony_ci#define CALC_DIV(d) (MAX_DIV >> (d))
248c2ecf20Sopenharmony_ci#define CUR_DIV() CALC_DIV(chip->treble)
258c2ecf20Sopenharmony_ci#define PCSP_MAX_TREBLE 1
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* unfortunately, with hrtimers 37KHz does not work very well :( */
288c2ecf20Sopenharmony_ci#define PCSP_DEFAULT_TREBLE 0
298c2ecf20Sopenharmony_ci#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE)
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* wild guess */
328c2ecf20Sopenharmony_ci#define PCSP_MIN_LPJ 1000000
338c2ecf20Sopenharmony_ci#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1)
348c2ecf20Sopenharmony_ci#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV)
358c2ecf20Sopenharmony_ci#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble))
368c2ecf20Sopenharmony_ci#define PCSP_CALC_RATE(i) (PIT_TICK_RATE / CALC_DIV(i))
378c2ecf20Sopenharmony_ci#define PCSP_RATE() PCSP_CALC_RATE(chip->treble)
388c2ecf20Sopenharmony_ci#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE
398c2ecf20Sopenharmony_ci#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE
408c2ecf20Sopenharmony_ci#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1)
418c2ecf20Sopenharmony_ci#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1)
428c2ecf20Sopenharmony_ci#define PCSP_CALC_NS(div) ({ \
438c2ecf20Sopenharmony_ci	u64 __val = 1000000000ULL * (div); \
448c2ecf20Sopenharmony_ci	do_div(__val, PIT_TICK_RATE); \
458c2ecf20Sopenharmony_ci	__val; \
468c2ecf20Sopenharmony_ci})
478c2ecf20Sopenharmony_ci#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV())
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define PCSP_MAX_PERIOD_SIZE	(64*1024)
508c2ecf20Sopenharmony_ci#define PCSP_MAX_PERIODS	512
518c2ecf20Sopenharmony_ci#define PCSP_BUFFER_SIZE	(128*1024)
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistruct snd_pcsp {
548c2ecf20Sopenharmony_ci	struct snd_card *card;
558c2ecf20Sopenharmony_ci	struct snd_pcm *pcm;
568c2ecf20Sopenharmony_ci	struct input_dev *input_dev;
578c2ecf20Sopenharmony_ci	struct hrtimer timer;
588c2ecf20Sopenharmony_ci	unsigned short port, irq, dma;
598c2ecf20Sopenharmony_ci	spinlock_t substream_lock;
608c2ecf20Sopenharmony_ci	struct snd_pcm_substream *playback_substream;
618c2ecf20Sopenharmony_ci	unsigned int fmt_size;
628c2ecf20Sopenharmony_ci	unsigned int is_signed;
638c2ecf20Sopenharmony_ci	size_t playback_ptr;
648c2ecf20Sopenharmony_ci	size_t period_ptr;
658c2ecf20Sopenharmony_ci	atomic_t timer_active;
668c2ecf20Sopenharmony_ci	int thalf;
678c2ecf20Sopenharmony_ci	u64 ns_rem;
688c2ecf20Sopenharmony_ci	unsigned char val61;
698c2ecf20Sopenharmony_ci	int enable;
708c2ecf20Sopenharmony_ci	int max_treble;
718c2ecf20Sopenharmony_ci	int treble;
728c2ecf20Sopenharmony_ci	int pcspkr;
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ciextern struct snd_pcsp pcsp_chip;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ciextern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
788c2ecf20Sopenharmony_ciextern void pcsp_sync_stop(struct snd_pcsp *chip);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ciextern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
818c2ecf20Sopenharmony_ciextern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#endif
84