1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * PC-Speaker driver for Linux 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 1993-1997 Michael Beck 6*4882a593Smuzhiyun * Copyright (C) 1997-2001 David Woodhouse 7*4882a593Smuzhiyun * Copyright (C) 2001-2008 Stas Sergeev 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #ifndef __PCSP_H__ 11*4882a593Smuzhiyun #define __PCSP_H__ 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun #include <linux/hrtimer.h> 14*4882a593Smuzhiyun #include <linux/i8253.h> 15*4882a593Smuzhiyun #include <linux/timex.h> 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #define PCSP_SOUND_VERSION 0x400 /* read 4.00 */ 18*4882a593Smuzhiyun #define PCSP_DEBUG 0 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun /* default timer freq for PC-Speaker: 18643 Hz */ 21*4882a593Smuzhiyun #define DIV_18KHZ 64 22*4882a593Smuzhiyun #define MAX_DIV DIV_18KHZ 23*4882a593Smuzhiyun #define CALC_DIV(d) (MAX_DIV >> (d)) 24*4882a593Smuzhiyun #define CUR_DIV() CALC_DIV(chip->treble) 25*4882a593Smuzhiyun #define PCSP_MAX_TREBLE 1 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun /* unfortunately, with hrtimers 37KHz does not work very well :( */ 28*4882a593Smuzhiyun #define PCSP_DEFAULT_TREBLE 0 29*4882a593Smuzhiyun #define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE) 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun /* wild guess */ 32*4882a593Smuzhiyun #define PCSP_MIN_LPJ 1000000 33*4882a593Smuzhiyun #define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1) 34*4882a593Smuzhiyun #define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV) 35*4882a593Smuzhiyun #define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble)) 36*4882a593Smuzhiyun #define PCSP_CALC_RATE(i) (PIT_TICK_RATE / CALC_DIV(i)) 37*4882a593Smuzhiyun #define PCSP_RATE() PCSP_CALC_RATE(chip->treble) 38*4882a593Smuzhiyun #define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE 39*4882a593Smuzhiyun #define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE 40*4882a593Smuzhiyun #define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1) 41*4882a593Smuzhiyun #define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1) 42*4882a593Smuzhiyun #define PCSP_CALC_NS(div) ({ \ 43*4882a593Smuzhiyun u64 __val = 1000000000ULL * (div); \ 44*4882a593Smuzhiyun do_div(__val, PIT_TICK_RATE); \ 45*4882a593Smuzhiyun __val; \ 46*4882a593Smuzhiyun }) 47*4882a593Smuzhiyun #define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV()) 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun #define PCSP_MAX_PERIOD_SIZE (64*1024) 50*4882a593Smuzhiyun #define PCSP_MAX_PERIODS 512 51*4882a593Smuzhiyun #define PCSP_BUFFER_SIZE (128*1024) 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun struct snd_pcsp { 54*4882a593Smuzhiyun struct snd_card *card; 55*4882a593Smuzhiyun struct snd_pcm *pcm; 56*4882a593Smuzhiyun struct input_dev *input_dev; 57*4882a593Smuzhiyun struct hrtimer timer; 58*4882a593Smuzhiyun unsigned short port, irq, dma; 59*4882a593Smuzhiyun spinlock_t substream_lock; 60*4882a593Smuzhiyun struct snd_pcm_substream *playback_substream; 61*4882a593Smuzhiyun unsigned int fmt_size; 62*4882a593Smuzhiyun unsigned int is_signed; 63*4882a593Smuzhiyun size_t playback_ptr; 64*4882a593Smuzhiyun size_t period_ptr; 65*4882a593Smuzhiyun atomic_t timer_active; 66*4882a593Smuzhiyun int thalf; 67*4882a593Smuzhiyun u64 ns_rem; 68*4882a593Smuzhiyun unsigned char val61; 69*4882a593Smuzhiyun int enable; 70*4882a593Smuzhiyun int max_treble; 71*4882a593Smuzhiyun int treble; 72*4882a593Smuzhiyun int pcspkr; 73*4882a593Smuzhiyun }; 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun extern struct snd_pcsp pcsp_chip; 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); 78*4882a593Smuzhiyun extern void pcsp_sync_stop(struct snd_pcsp *chip); 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); 81*4882a593Smuzhiyun extern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm); 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun #endif 84