summaryrefslogblamecommitdiffstats
path: root/include/linux/fixp-arith.h
blob: d4686fe1cac752fb17dd182d8e976ac8053afba1 (plain) (tree)
1
2
3
4
5
6


                     

                         
  





















                                                                          
                                                          



                        

















                                                                               
 










                                                             
 





                                        
 
                                 
 
                                     

 







                                                                     
 


                                              

 

































                                                               
 


                           
 



                                                                        
 

                                                
 

                                              
 
                                     
 





                                      

 




                                              
      
#ifndef _FIXP_ARITH_H
#define _FIXP_ARITH_H

#include <linux/math64.h>

/*
 * Simplistic fixed-point arithmetics.
 * Hmm, I'm probably duplicating some code :(
 *
 * Copyright (c) 2002 Johann Deneux
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Should you need to contact me, the author, you can do so by
 * e-mail - mail your message to <johann.deneux@gmail.com>
 */

#include <linux/types.h>

static const s32 sin_table[] = {
	0x00000000, 0x023be165, 0x04779632, 0x06b2f1d2, 0x08edc7b6, 0x0b27eb5c,
	0x0d61304d, 0x0f996a26, 0x11d06c96, 0x14060b67, 0x163a1a7d, 0x186c6ddd,
	0x1a9cd9ac, 0x1ccb3236, 0x1ef74bf2, 0x2120fb82, 0x234815ba, 0x256c6f9e,
	0x278dde6e, 0x29ac379f, 0x2bc750e8, 0x2ddf003f, 0x2ff31bdd, 0x32037a44,
	0x340ff241, 0x36185aee, 0x381c8bb5, 0x3a1c5c56, 0x3c17a4e7, 0x3e0e3ddb,
	0x3fffffff, 0x41ecc483, 0x43d464fa, 0x45b6bb5d, 0x4793a20f, 0x496af3e1,
	0x4b3c8c11, 0x4d084650, 0x4ecdfec6, 0x508d9210, 0x5246dd48, 0x53f9be04,
	0x55a6125a, 0x574bb8e5, 0x58ea90c2, 0x5a827999, 0x5c135399, 0x5d9cff82,
	0x5f1f5ea0, 0x609a52d1, 0x620dbe8a, 0x637984d3, 0x64dd894f, 0x6639b039,
	0x678dde6d, 0x68d9f963, 0x6a1de735, 0x6b598ea1, 0x6c8cd70a, 0x6db7a879,
	0x6ed9eba0, 0x6ff389de, 0x71046d3c, 0x720c8074, 0x730baeec, 0x7401e4bf,
	0x74ef0ebb, 0x75d31a5f, 0x76adf5e5, 0x777f903b, 0x7847d908, 0x7906c0af,
	0x79bc384c, 0x7a6831b8, 0x7b0a9f8c, 0x7ba3751c, 0x7c32a67c, 0x7cb82884,
	0x7d33f0c8, 0x7da5f5a3, 0x7e0e2e31, 0x7e6c924f, 0x7ec11aa3, 0x7f0bc095,
	0x7f4c7e52, 0x7f834ecf, 0x7fb02dc4, 0x7fd317b3, 0x7fec09e1, 0x7ffb025e,
	0x7fffffff
};

/**
 * __fixp_sin32() returns the sin of an angle in degrees
 *
 * @degrees: angle, in degrees, from 0 to 360.
 *
 * The returned value ranges from -0x7fffffff to +0x7fffffff.
 */
static inline s32 __fixp_sin32(int degrees)
{
	s32 ret;
	bool negative = false;

	if (degrees > 180) {
		negative = true;
		degrees -= 180;
	}
	if (degrees > 90)
		degrees = 180 - degrees;

	ret = sin_table[degrees];

	return negative ? -ret : ret;
}

/**
 * fixp_sin32() returns the sin of an angle in degrees
 *
 * @degrees: angle, in degrees. The angle can be positive or negative
 *
 * The returned value ranges from -0x7fffffff to +0x7fffffff.
 */
static inline s32 fixp_sin32(int degrees)
{
	degrees = (degrees % 360 + 360) % 360;

	return __fixp_sin32(degrees);
}

/* cos(x) = sin(x + 90 degrees) */
#define fixp_cos32(v) fixp_sin32((v) + 90)

/*
 * 16 bits variants
 *
 * The returned value ranges from -0x7fff to 0x7fff
 */

#define fixp_sin16(v) (fixp_sin32(v) >> 16)
#define fixp_cos16(v) (fixp_cos32(v) >> 16)

/**
 * fixp_sin32_rad() - calculates the sin of an angle in radians
 *
 * @radians: angle, in radians
 * @twopi: value to be used for 2*pi
 *
 * Provides a variant for the cases where just 360
 * values is not enough. This function uses linear
 * interpolation to a wider range of values given by
 * twopi var.
 *
 * Experimental tests gave a maximum difference of
 * 0.000038 between the value calculated by sin() and
 * the one produced by this function, when twopi is
 * equal to 360000. That seems to be enough precision
 * for practical purposes.
 *
 * Please notice that two high numbers for twopi could cause
 * overflows, so the routine will not allow values of twopi
 * bigger than 1^18.
 */
static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
{
	int degrees;
	s32 v1, v2, dx, dy;
	s64 tmp;

	/*
	 * Avoid too large values for twopi, as we don't want overflows.
	 */
	BUG_ON(twopi > 1 << 18);

	degrees = (radians * 360) / twopi;
	tmp = radians - (degrees * twopi) / 360;

	degrees = (degrees % 360 + 360) % 360;
	v1 = __fixp_sin32(degrees);

	v2 = fixp_sin32(degrees + 1);

	dx = twopi / 360;
	dy = v2 - v1;

	tmp *= dy;

	return v1 +  div_s64(tmp, dx);
}

/* cos(x) = sin(x + pi/2 radians) */

#define fixp_cos32_rad(rad, twopi)	\
	fixp_sin32_rad(rad + twopi / 4, twopi)

#endif
3:14 +0100 committer Dominik Brodowski 2006-01-06 00:03:10 +0100 [PATCH] pcmcia: unify detach, REMOVAL_EVENT handlers into one remove callback' href='/openslx/kernel-qcow2-linux.git/commit/drivers/parport/parport_cs.c?id=cc3b4866bee996c922e875b8c8efe9f0d8803aae'>cc3b4866bee9 ^
476835afd7fe ^
1da177e4c3f4
f23e79688c14 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196






































                                                                        





                         
                            



                             
















                                                                        





                                                                        
                                       
                             


                              
                                                        
                                                      
                                                       
 
                                                    

                         
 
                                              

                                   
                                              
                              
                      
                       
 
                                                             
 
                                

                      
                                                      
 
                                            
 
                             
 
                      

                      
                                                                             
 





                                                          

 
                                                     
 
                                      
                      
            
 
                                            
 


                                                 

                                                               
                        
 
                   
                        
                                     

                        
 

                                                       
                                                          
                                                       

                                                                    

                                                       
                          






                                                             
                   
 

             

                             
                   

                      
                                                          
 
                                          
 
                                                 





                                               
 
                                    

                          
 
                                                      
                                 
                                                                                                  




                                                

                                                 
                                       
                                        
                                         
                                      
  
                                        
/*======================================================================

    A driver for PCMCIA parallel port adapters

    (specifically, for the Quatech SPP-100 EPP card: other cards will
    probably require driver tweaks)
    
    parport_cs.c 1.29 2002/10/11 06:57:41

    The contents of this file are subject to the Mozilla Public
    License Version 1.1 (the "License"); you may not use this file
    except in compliance with the License. You may obtain a copy of
    the License at http://www.mozilla.org/MPL/

    Software distributed under the License is distributed on an "AS
    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
    implied. See the License for the specific language governing
    rights and limitations under the License.

    The initial developer of the original code is David A. Hinds
    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.

    Alternatively, the contents of this file may be used under the
    terms of the GNU General Public License version 2 (the "GPL"), in
    which case the provisions of the GPL are applicable instead of the
    above.  If you wish to allow the use of your version of this file
    only under the terms of the GPL and not to allow others to use
    your version of this file under the MPL, indicate your decision
    by deleting the provisions above and replace them with the notice
    and other provisions required by the GPL.  If you do not delete
    the provisions above, a recipient may use your version of this
    file under either the MPL or the GPL.
    
======================================================================*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/major.h>
#include <linux/interrupt.h>

#include <linux/parport.h>
#include <linux/parport_pc.h>

#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>

/*====================================================================*/

/* Module parameters */

MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA parallel port card driver");
MODULE_LICENSE("Dual MPL/GPL");

#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)

INT_MODULE_PARM(epp_mode, 1);


/*====================================================================*/

#define FORCE_EPP_MODE	0x08

typedef struct parport_info_t {
	struct pcmcia_device	*p_dev;
    int			ndev;
    struct parport	*port;
} parport_info_t;

static void parport_detach(struct pcmcia_device *p_dev);
static int parport_config(struct pcmcia_device *link);
static void parport_cs_release(struct pcmcia_device *);

static int parport_probe(struct pcmcia_device *link)
{
    parport_info_t *info;

    dev_dbg(&link->dev, "parport_attach()\n");

    /* Create new parport device */
    info = kzalloc(sizeof(*info), GFP_KERNEL);
    if (!info) return -ENOMEM;
    link->priv = info;
    info->p_dev = link;

    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;

    return parport_config(link);
} /* parport_attach */

static void parport_detach(struct pcmcia_device *link)
{
    dev_dbg(&link->dev, "parport_detach\n");

    parport_cs_release(link);

    kfree(link->priv);
} /* parport_detach */

static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;

	return pcmcia_request_io(p_dev);
}

static int parport_config(struct pcmcia_device *link)
{
    parport_info_t *info = link->priv;
    struct parport *p;
    int ret;

    dev_dbg(&link->dev, "parport_config\n");

    if (epp_mode)
	    link->config_index |= FORCE_EPP_MODE;

    ret = pcmcia_loop_config(link, parport_config_check, NULL);
    if (ret)
	    goto failed;

    if (!link->irq)
	    goto failed;
    ret = pcmcia_enable_device(link);
    if (ret)
	    goto failed;

    p = parport_pc_probe_port(link->resource[0]->start,
			      link->resource[1]->start,
			      link->irq, PARPORT_DMA_NONE,
			      &link->dev, IRQF_SHARED);
    if (p == NULL) {
	printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
	       "0x%3x, irq %u failed\n",
	       (unsigned int) link->resource[0]->start,
	       link->irq);
	goto failed;
    }

    p->modes |= PARPORT_MODE_PCSPP;
    if (epp_mode)
	p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP;
    info->ndev = 1;
    info->port = p;

    return 0;

failed:
    parport_cs_release(link);
    return -ENODEV;
} /* parport_config */

static void parport_cs_release(struct pcmcia_device *link)
{
	parport_info_t *info = link->priv;

	dev_dbg(&link->dev, "parport_release\n");

	if (info->ndev) {
		struct parport *p = info->port;
		parport_pc_unregister_port(p);
	}
	info->ndev = 0;

	pcmcia_disable_device(link);
} /* parport_cs_release */


static const struct pcmcia_device_id parport_ids[] = {
	PCMCIA_DEVICE_FUNC_ID(3),
	PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
	PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003),
	PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, parport_ids);

static struct pcmcia_driver parport_cs_driver = {
	.owner		= THIS_MODULE,
	.name		= "parport_cs",
	.probe		= parport_probe,
	.remove		= parport_detach,
	.id_table	= parport_ids,
};
module_pcmcia_driver(parport_cs_driver);